feat: 新增 react_reason 循环思考过程的流式显示
All checks were successful
构建并部署 AI Agent 服务 / deploy (push) Successful in 5m38s
All checks were successful
构建并部署 AI Agent 服务 / deploy (push) Successful in 5m38s
- 修改 react_nodes.py,在推理时保存推理过程到状态 - 修改 agent_service.py,检测并发送推理过程事件到前端 - 修改 chat_area.py,接收并显示推理过程 - 修改 useChat.ts,添加对推理过程事件的支持
This commit is contained in:
@@ -259,6 +259,34 @@ class AIAgentService:
|
||||
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"]:
|
||||
review_id = serialized_data.get("review_id", "")
|
||||
|
||||
@@ -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 模式推理节点:判断下一步做什么
|
||||
|
||||
@@ -39,6 +40,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:
|
||||
state.current_phase = "max_steps_exceeded"
|
||||
@@ -62,6 +79,10 @@ def react_reason_node(state: MainGraphState) -> MainGraphState:
|
||||
# 注意:这里使用同步版本,内部会根据情况处理
|
||||
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({
|
||||
"step": state.reasoning_step,
|
||||
@@ -84,6 +105,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
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user