fix: context_rewrite 和普通工具混调导致400错误,延迟执行防止对话历史结构破坏

This commit is contained in:
root
2026-04-30 09:49:30 +08:00
parent 69a79ac86d
commit 1f19bb0c57
3 changed files with 36 additions and 24 deletions

View File

@ -102,7 +102,7 @@ subject, relation, object 每个字段必须是一个**短关键字**1~5个
| `memory_archive` | 信息过期需保留历史 | 将旧记忆归档而非删除,保留历史轨迹 |
| `memory_cleanup` | 确认数据异常 | 清理冗余/孤立节点dry_run可预览 |
| `memory_query_archived` | 回顾归档历史 | 查询已归档的原始关系记录status=archived支持天数/关键词过滤 |
| `context_rewrite` | 单轮调用了 5 次及以上查询类工具 | 压缩本轮工具调用的 JSON 参数和返回结果,剔除工具噪声,节省上下文 token。**必须是回复前的最后一步** |
| `context_rewrite` | 单轮调用了 5 次及以上查询类工具 | 压缩本轮工具调用的 JSON 参数和返回结果,剔除工具噪声,节省上下文 token。**⚠️ 必须单独调用**:先调完其他所有工具并收到结果 → 再单独调 context_rewrite。不要和其他工具一起调 |
### 人设工具
| 工具 | 时机 | 说明 |

View File

@ -345,6 +345,8 @@ class BackendServer:
messages_history.append(assistant_msg)
current_tool_results = []
deferred_rewrite = None # 延迟处理 context_rewrite
for tool_call in message.tool_calls:
args = json.loads(tool_call.function.arguments)
@ -364,26 +366,9 @@ class BackendServer:
self._tool_limiter.record_call(tool_call.function.name, args)
if tool_call.function.name == "context_rewrite":
result = execute_tool(self._graph, tool_call.function.name, args)
result_data = json.loads(result)
# 记录到 tool_calls让 TUI 显示这个工具调用
tool_calls.append({
"name": tool_call.function.name,
"arguments": args,
"result": result
})
if result_data.get("status") == "success":
user_msg = messages_history[0]
# 添加特殊标记,让 AI 知道这是上下文压缩的结果
compressed_content = f"<context_compressed>\n{result_data['summary']}\n</context_compressed>"
messages_history[:] = [
user_msg,
{"role": "assistant", "content": compressed_content}
]
# context_rewrite 压缩上下文后,不需要添加 tool 结果消息
# 因为 messages_history 已经被重写为压缩后的状态
# 延迟执行 context_rewrite先处理完其他所有工具
# 避免在迭代中途重写 messages_history 导致 tool 结果丢失对应的 tool_calls
deferred_rewrite = (tool_call.id, args)
continue
result = execute_tool(self._graph, tool_call.function.name, args)
@ -400,8 +385,30 @@ class BackendServer:
}
current_tool_results.append(tool_result_msg)
# 先添加所有非 context_rewrite 工具的结果到消息历史
messages_history.extend(current_tool_results)
# 再处理延迟的 context_rewrite作为本轮最后一步
if deferred_rewrite:
tool_call_id, args = deferred_rewrite
result = execute_tool(self._graph, "context_rewrite", args)
result_data = json.loads(result)
tool_calls.append({
"name": "context_rewrite",
"arguments": args,
"result": result
})
if result_data.get("status") == "success":
user_msg = messages_history[0]
compressed_content = f"<context_compressed>\n{result_data['summary']}\n</context_compressed>"
messages_history[:] = [
user_msg,
{"role": "assistant", "content": compressed_content}
]
# 不添加 context_rewrite 的 tool 结果到历史(压缩后的历史已替代)
response = self._client.send_message_with_history(messages_history)
message = response.choices[0].message

View File

@ -299,11 +299,16 @@ memory_query_archived({"days": 30, "keyword": "配置"})
"description": """压缩本轮对话的工具调用上下文。将冗长的JSON工具结果提炼为简洁摘要。
【使用场景】
- 已执行多次工具调用JSON细节已理解不再需要原始格式
- 本轮已执行 ≥5 次查询类工具调用JSON细节已理解不再需要原始格式
- 但需保留"我调用了什么工具、得到了什么结论"的元认知
- 继续携带原始JSON会干扰后续推理
【⚠️ 强制格式要求】
【⚠️ 强制要求】
**context_rewrite 必须单独调用,不能和其他工具在同一轮一起调!**
- 正确方式:先调其他所有工具 → 收到工具结果 → 单独调 context_rewrite
- 错误方式:和其他工具一起调(会破坏对话历史结构)
【格式要求】
1. 必须标注调用了哪些工具
2. 必须标注是对几次工具调用的总结
3. 必须保留关键语义信息
@ -316,7 +321,7 @@ memory_query_archived({"days": 30, "keyword": "配置"})
【注意事项】
- 不可删除用户原始消息
- 不可歪曲工具返回的关键事实
- 仅在工具调用 ≥ 2 次后使用""",
- 仅在调用 ≥5 次查询类工具后使用""",
"parameters": {
"type": "object",
"properties": {