From e851e40763d8bb2b2d489dabaf3149f1717ecf60 Mon Sep 17 00:00:00 2001 From: root <953994191@qq.com> Date: Fri, 8 May 2026 01:45:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20finalize=20?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/main_graph/nodes/finalize.py | 54 ++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 backend/app/main_graph/nodes/finalize.py diff --git a/backend/app/main_graph/nodes/finalize.py b/backend/app/main_graph/nodes/finalize.py new file mode 100644 index 0000000..b342f71 --- /dev/null +++ b/backend/app/main_graph/nodes/finalize.py @@ -0,0 +1,54 @@ +""" +Finalize 节点 - 轻量后处理 +""" + +from typing import Dict, Any, Optional +from langchain_core.runnables.config import RunnableConfig +from langchain_core.messages import AIMessage + +from backend.app.main_graph.state import AgentState +from backend.app.logger import info + + +async def finalize_node(state: AgentState, config: Optional[RunnableConfig] = None) -> Dict[str, Any]: + """ + Finalize 节点:轻量后处理 + + 职责: + 1. 从 messages 中提取最后一条 AIMessage.content 作为最终回复 + 2. 汇总元数据:步数、使用的工具、停止原因 + 3. 如果 final_reply 为空且有 stop_reason,生成说明文本 + """ + info("[Finalize] 执行后处理") + + # 获取最终回复 + final_reply = "" + for msg in reversed(state.messages): + if isinstance(msg, AIMessage) and msg.content: + final_reply = msg.content + break + + # 获取停止原因 + stop_reason = getattr(state, "stop_reason", "") + if not final_reply and stop_reason: + # 如果没有回复但有停止原因,生成说明 + reason_messages = { + "loop_detected": "[系统] 检测到工具调用循环,已终止。", + "max_steps": "[系统] 已达到最大步数限制。", + } + final_reply = reason_messages.get(stop_reason, f"[系统] 已终止,原因: {stop_reason}") + + # 汇总元数据 + metadata = { + "steps_taken": getattr(state, "current_step", 0), + "tools_used": getattr(state, "tools_used", []), + "stop_reason": stop_reason, + "llm_calls": getattr(state, "llm_calls", 0), + } + + info(f"[Finalize] 完成 - steps: {metadata['steps_taken']}, tools: {len(metadata['tools_used'])}") + + return { + "final_reply": final_reply, + "metadata": metadata, + }