Fix Bedrock tool history and add upload limit config
This commit is contained in:
+94
-1
@@ -91,6 +91,99 @@ def _parse_tool_arguments(raw_arguments: Any) -> dict[str, Any]:
|
||||
)
|
||||
|
||||
|
||||
def _tool_call_ids(message: dict[str, Any]) -> list[str]:
|
||||
raw_tool_calls = message.get('tool_calls')
|
||||
if not isinstance(raw_tool_calls, list):
|
||||
return []
|
||||
ids: list[str] = []
|
||||
for index, raw_call in enumerate(raw_tool_calls):
|
||||
if not isinstance(raw_call, dict):
|
||||
continue
|
||||
call_id = raw_call.get('id')
|
||||
ids.append(call_id if isinstance(call_id, str) and call_id else f'call_{index}')
|
||||
return ids
|
||||
|
||||
|
||||
def _contiguous_tool_result_ids(
|
||||
messages: list[dict[str, Any]],
|
||||
start_index: int,
|
||||
) -> set[str]:
|
||||
ids: set[str] = set()
|
||||
index = start_index
|
||||
while index < len(messages) and messages[index].get('role') == 'tool':
|
||||
tool_call_id = messages[index].get('tool_call_id')
|
||||
if isinstance(tool_call_id, str) and tool_call_id:
|
||||
ids.add(tool_call_id)
|
||||
index += 1
|
||||
return ids
|
||||
|
||||
|
||||
def _filter_tool_calls_by_ids(
|
||||
message: dict[str, Any],
|
||||
valid_ids: set[str],
|
||||
) -> dict[str, Any]:
|
||||
raw_tool_calls = message.get('tool_calls')
|
||||
if not isinstance(raw_tool_calls, list):
|
||||
return message
|
||||
filtered: list[dict[str, Any]] = []
|
||||
for index, raw_call in enumerate(raw_tool_calls):
|
||||
if not isinstance(raw_call, dict):
|
||||
continue
|
||||
call_id = raw_call.get('id')
|
||||
normalized_id = (
|
||||
call_id if isinstance(call_id, str) and call_id else f'call_{index}'
|
||||
)
|
||||
if normalized_id in valid_ids:
|
||||
filtered.append(raw_call)
|
||||
if len(filtered) == len(raw_tool_calls):
|
||||
return message
|
||||
next_message = dict(message)
|
||||
if filtered:
|
||||
next_message['tool_calls'] = filtered
|
||||
else:
|
||||
next_message.pop('tool_calls', None)
|
||||
return next_message
|
||||
|
||||
|
||||
def _sanitize_anthropic_tool_messages(
|
||||
messages: list[dict[str, Any]],
|
||||
) -> list[dict[str, Any]]:
|
||||
"""清理 Anthropic/Bedrock 严格要求的 tool_use/tool_result 邻接关系。
|
||||
|
||||
OpenAI 风格历史在异常中断、裁剪或前端恢复时可能留下 assistant tool_calls,
|
||||
但下一条消息不再紧跟对应 tool 结果。Anthropic Messages API 会直接拒绝
|
||||
这种历史。这里在出网关前删除缺失结果的 tool_call,并跳过没有前置
|
||||
tool_use 的孤儿 tool 结果,保留普通文本上下文继续对话。
|
||||
"""
|
||||
sanitized: list[dict[str, Any]] = []
|
||||
pending_tool_ids: set[str] = set()
|
||||
|
||||
for index, message in enumerate(messages):
|
||||
role = message.get('role')
|
||||
if role == 'assistant':
|
||||
tool_ids = _tool_call_ids(message)
|
||||
if tool_ids:
|
||||
result_ids = _contiguous_tool_result_ids(messages, index + 1)
|
||||
valid_ids = set(tool_ids).intersection(result_ids)
|
||||
message = _filter_tool_calls_by_ids(message, valid_ids)
|
||||
pending_tool_ids = valid_ids
|
||||
else:
|
||||
pending_tool_ids = set()
|
||||
sanitized.append(message)
|
||||
continue
|
||||
|
||||
if role == 'tool':
|
||||
tool_call_id = message.get('tool_call_id')
|
||||
if isinstance(tool_call_id, str) and tool_call_id in pending_tool_ids:
|
||||
sanitized.append(message)
|
||||
continue
|
||||
|
||||
pending_tool_ids = set()
|
||||
sanitized.append(message)
|
||||
|
||||
return sanitized
|
||||
|
||||
|
||||
def _optional_int(value: Any) -> int:
|
||||
if isinstance(value, bool):
|
||||
return 0
|
||||
@@ -341,7 +434,7 @@ class OpenAICompatClient:
|
||||
) -> dict[str, Any]:
|
||||
system_parts: list[str] = []
|
||||
anthropic_messages: list[dict[str, Any]] = []
|
||||
for message in messages:
|
||||
for message in _sanitize_anthropic_tool_messages(messages):
|
||||
role = message.get('role')
|
||||
if role == 'system':
|
||||
content = _normalize_content(message.get('content')).strip()
|
||||
|
||||
Reference in New Issue
Block a user