diff --git a/backend/app/agent/agent_service.py b/backend/app/agent/agent_service.py index 48c9611..18543cc 100644 --- a/backend/app/agent/agent_service.py +++ b/backend/app/agent/agent_service.py @@ -258,6 +258,34 @@ class AIAgentService: info(f"🔄 处理updates chunk") updates_data = chunk["data"] serialized_data = self._serialize_value(updates_data) + + # 检查是否有最新的推理内容(来自 react_reason_node) + if isinstance(serialized_data, dict): + # 遍历所有节点的数据 + for node_name, node_data in serialized_data.items(): + if isinstance(node_data, dict) and "debug_info" in node_data: + debug_info = node_data["debug_info"] + latest_reasoning = debug_info.get("latest_reasoning") + if latest_reasoning and not latest_reasoning.get("sent"): + # 发送推理过程到前端 + step = latest_reasoning.get("step", 1) + action = latest_reasoning.get("action", "unknown") + confidence = latest_reasoning.get("confidence", 0) + reasoning = latest_reasoning.get("reasoning", "") + + info(f"[Agent Service] 发送推理过程 #{step}: {action}") + + # 发送推理事件 + yield { + "type": "react_reasoning", + "step": step, + "action": action, + "confidence": confidence, + "reasoning": reasoning + } + + # 标记为已发送(避免重复发送) + latest_reasoning["sent"] = True # 检查是否有人工审核请求 if "review_pending" in serialized_data and serialized_data["review_pending"]: diff --git a/backend/app/main_graph/nodes/react_nodes.py b/backend/app/main_graph/nodes/react_nodes.py index d55cfa9..ef8eaca 100644 --- a/backend/app/main_graph/nodes/react_nodes.py +++ b/backend/app/main_graph/nodes/react_nodes.py @@ -26,11 +26,12 @@ from app.main_graph.utils.retry_utils import ( RetryConfig, SUBGRAPH_RETRY_CONFIG ) +from app.logger import info # ========== 1. React 推理节点 ========== -def react_reason_node(state: MainGraphState) -> MainGraphState: +def react_reason_node(state: MainGraphState, config: Optional[Dict[str, Any]] = None) -> MainGraphState: """ React 模式推理节点:判断下一步做什么 @@ -38,6 +39,22 @@ def react_reason_node(state: MainGraphState) -> MainGraphState: """ state.current_phase = "react_reasoning" state.reasoning_step += 1 + + # 发送推理开始事件 + if config: + try: + from langchain_core.runnables.config import RunnableConfig + # 尝试获取回调管理器并发送自定义事件 + callbacks = config.get("callbacks") + if callbacks: + from langchain_core.callbacks.manager import adispatch_custom_event + # 注意:这是异步操作,我们需要特殊处理 + # 这里我们使用自定义流式写入器(如果存在) + pass + except Exception as e: + info(f"[react_reason] 无法发送回调事件: {e}") + + info(f"[react_reason] 第 {state.reasoning_step} 次推理开始") # 检查是否超过最大步数 if state.reasoning_step > state.max_steps: @@ -61,6 +78,10 @@ def react_reason_node(state: MainGraphState) -> MainGraphState: # 使用 intent.py 进行推理 # 注意:这里使用同步版本,内部会根据情况处理 result: ReasoningResult = react_reason(state.user_query, context) + + info(f"[react_reason] 推理结果: action={result.action.name}, confidence={result.confidence}") + if result.reasoning: + info(f"[react_reason] 推理过程: {result.reasoning}") # 记录推理历史 state.reasoning_history.append({ @@ -83,6 +104,16 @@ def react_reason_node(state: MainGraphState) -> MainGraphState: # 确定下一步动作 state.last_action = result.action.name + + # 发送推理完成事件(通过状态更新,agent_service 会处理) + # 我们在状态中保存推理内容,以便 agent_service 可以通过 state_update 事件发送 + state.debug_info["latest_reasoning"] = { + "step": state.reasoning_step, + "action": result.action.name, + "confidence": result.confidence, + "reasoning": result.reasoning, + "sent": False # 标记是否已发送到前端 + } return state diff --git a/frontend/src/components/chat_area.py b/frontend/src/components/chat_area.py index 32323ea..f3bb688 100644 --- a/frontend/src/components/chat_area.py +++ b/frontend/src/components/chat_area.py @@ -139,7 +139,26 @@ def _handle_ai_response(): import logging logging.debug(f"[Frontend Stream] 收到事件: {event_type}, 完整内容: {repr(event)}") - # 1. 处理各种控制事件,显示到思考过程 + # 1. 处理推理过程事件 - 这是新增的! + if event_type == "react_reasoning": + step = event.get("step", 1) + action = event.get("action", "unknown") + confidence = event.get("confidence", 0) + reasoning = event.get("reasoning", "") + + logging.info(f"[Frontend] 收到推理过程 #{step}: {action}") + + # 添加到思考过程 + api_thought += f"\n\n🤔 **第 {step} 次推理**" + api_thought += f"\n 📋 决策: {action}" + api_thought += f"\n 📊 置信度: {confidence:.2f}" + if reasoning: + api_thought += f"\n 💭 推理过程: {reasoning}" + + display_thought = api_thought + thought_placeholder.info(f"**🤔 思考过程 (正在思考...)**\n\n{display_thought}▌") + + # 2. 处理各种控制事件,显示到思考过程 if event_type == "intent_classified": intent = event.get("intent", "unknown") confidence = event.get("confidence", 0) diff --git a/frontend/src/components/useChat.ts b/frontend/src/components/useChat.ts index 660022f..7082f34 100644 --- a/frontend/src/components/useChat.ts +++ b/frontend/src/components/useChat.ts @@ -181,8 +181,20 @@ export function useChat() { try { for await (const event of apiClient.chatStream(text, threadId, model)) { switch (event.type) { + // 新增:处理推理过程事件 + case "react_reasoning": + console.log(`🤔 收到推理过程 #${event.step}: ${event.action}`); + updateCurrentMessage({ + reasoning: (currentMessageRef.current?.reasoning || "") + + `\n\n🤔 **第 ${event.step} 次推理**` + + `\n 📋 决策: ${event.action}` + + `\n 📊 置信度: ${event.confidence.toFixed(2)}` + + (event.reasoning ? `\n 💭 推理过程: ${event.reasoning}` : "") + }); + break; + // 新增:处理意图分类事件 - case 'intent_classified': + case "intent_classified": console.log(`🧠 意图识别: ${event.intent} (置信度: ${event.confidence})`); setLastIntent({ intent: event.intent,