From 02904f711e37328beeec207e6af0c1c0eb5463c4 Mon Sep 17 00:00:00 2001 From: qing <1776177662@qq.com> Date: Mon, 3 Aug 2026 23:05:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(aibox):=20=E4=BF=AE=E5=A4=8D=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E8=B0=83=E7=94=A8=E9=85=8D=E5=AF=B9=E7=BC=BA=E5=A4=B1?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=9A=84=20insufficient=20tool=20messages=20?= =?UTF-8?q?400?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当 assistant 携带 tool_calls 但对应 tool 响应缺失(工具被中断/压缩丢弃)时, 下一次请求报 400。新增 _repair_tool_pairs 在构建请求前补齐缺失的 tool 响应。 --- aibox/aibox.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/aibox/aibox.py b/aibox/aibox.py index bc6f710..6642dee 100644 --- a/aibox/aibox.py +++ b/aibox/aibox.py @@ -7003,6 +7003,10 @@ class DeepSeekChat: if self.history_manager: self.history_manager.add_message("user", enhanced_input, "用户") + # 修复工具调用配对:确保每个 assistant 的 tool_calls 都有对应 tool 响应, + # 防止因工具被中断/压缩导致 "insufficient tool messages" 报 400 + self._repair_tool_pairs() + # 构建消息列表,确保包含 reasoning_content enhanced_messages = [] @@ -7296,6 +7300,48 @@ class DeepSeekChat: except Exception as e: self.logger.error(f"消息回滚失败: {e}") + def _repair_tool_pairs(self): + """修复消息历史中的工具调用配对,保证 API 消息结构合法。 + + 场景:assistant 消息携带 tool_calls,但对应的 tool 响应缺失(工具被中断、 + 压缩算法丢弃、端对话提前 break 等),下一次请求会因 + "insufficient tool messages following tool_calls" 返回 400。 + 修复策略:为每个缺失响应的 tool_call_id 补一条占位 tool 消息,使其配对完整。 + """ + if not self.messages: + return + repaired = [] + i = 0 + n = len(self.messages) + while i < n: + msg = self.messages[i] + role = msg.get("role") + tool_calls = msg.get("tool_calls") if role == "assistant" else None + if not tool_calls: + repaired.append(msg) + i += 1 + continue + # 收集紧随其后的 tool 消息 + needed = [tc.get("id") for tc in tool_calls if tc.get("id")] + j = i + 1 + tool_msgs = [] + while j < n and self.messages[j].get("role") == "tool": + tool_msgs.append(self.messages[j]) + j += 1 + have = {tm.get("tool_call_id") for tm in tool_msgs if tm.get("tool_call_id")} + # 补齐缺失的 tool 响应 + for tid in needed: + if tid not in have: + tool_msgs.append({ + "role": "tool", + "tool_call_id": tid, + "content": "⚠️ 该工具调用未返回结果(可能被中断)。", + }) + repaired.append(msg) # 保留 assistant 消息本身 + repaired.extend(tool_msgs) + i = j + self.messages = repaired + def reset_conversation(self, reload_prompts: bool = True): """ 重置对话状态 - 清除所有对话记忆,可选择是否重新加载系统提示词