From 1f19bb0c573f4837f983f409ecc579ac535e42f9 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 30 Apr 2026 09:49:30 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20context=5Frewrite=20=E5=92=8C=E6=99=AE?= =?UTF-8?q?=E9=80=9A=E5=B7=A5=E5=85=B7=E6=B7=B7=E8=B0=83=E5=AF=BC=E8=87=B4?= =?UTF-8?q?400=E9=94=99=E8=AF=AF=EF=BC=8C=E5=BB=B6=E8=BF=9F=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E9=98=B2=E6=AD=A2=E5=AF=B9=E8=AF=9D=E5=8E=86=E5=8F=B2?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E7=A0=B4=E5=9D=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/prompts/templates/system_prompt.md | 2 +- core/server.py | 47 ++++++++++++++----------- core/tools/memory_tools.py | 11 ++++-- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/core/prompts/templates/system_prompt.md b/core/prompts/templates/system_prompt.md index 29319a1..f19256f 100644 --- a/core/prompts/templates/system_prompt.md +++ b/core/prompts/templates/system_prompt.md @@ -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。不要和其他工具一起调 | ### 人设工具 | 工具 | 时机 | 说明 | diff --git a/core/server.py b/core/server.py index 21eff89..f356e72 100644 --- a/core/server.py +++ b/core/server.py @@ -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"\n{result_data['summary']}\n" - 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"\n{result_data['summary']}\n" + 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 diff --git a/core/tools/memory_tools.py b/core/tools/memory_tools.py index 5919ea4..61d7187 100644 --- a/core/tools/memory_tools.py +++ b/core/tools/memory_tools.py @@ -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": {