添加调试日志,排查Task was destroyed问题
All checks were successful
构建并部署 AI Agent 服务 / deploy (push) Successful in 6m41s

This commit is contained in:
2026-05-01 12:11:16 +08:00
parent 57a917b2c6
commit 6d300ee8b4

View File

@@ -151,123 +151,140 @@ class AIAgentService:
# ======================================== # ========================================
# ========== React 循环路径 ========== # ========== React 循环路径 ==========
info(f"🚀 开始执行 React 图,模型: {model_name}")
current_node = None current_node = None
tool_calls_in_progress = {} tool_calls_in_progress = {}
async for chunk in graph.astream( try:
input_state, info(f"📡 开始调用 graph.astream()...")
config=config, chunk_count = 0
stream_mode=["messages", "updates", "custom"], async for chunk in graph.astream(
version="v2", input_state,
subgraphs=True config=config,
): stream_mode=["messages", "updates", "custom"],
chunk_type = chunk["type"] version="v2",
processed_event = {} subgraphs=True
):
chunk_count += 1
chunk_type = chunk["type"]
info(f"📦 收到第 {chunk_count} 个chunk, type: {chunk_type}")
processed_event = {}
if chunk_type == "messages": if chunk_type == "messages":
message_chunk, metadata = chunk["data"] message_chunk, metadata = chunk["data"]
node_name = metadata.get("langgraph_node", "unknown") node_name = metadata.get("langgraph_node", "unknown")
info(f"📨 处理消息chunk, node: {node_name}")
# 检测节点变化,发送节点开始事件 # 检测节点变化,发送节点开始事件
if node_name != current_node: if node_name != current_node:
if current_node: if current_node:
yield {
"type": "node_end",
"node": current_node
}
yield {
"type": "node_start",
"node": node_name
}
current_node = node_name
# 处理消息内容
token_content = getattr(message_chunk, 'content', str(message_chunk))
reasoning_token = ""
if hasattr(message_chunk, 'additional_kwargs'):
reasoning_token = message_chunk.additional_kwargs.get("reasoning_content", "")
# 处理思考过程
if reasoning_token:
processed_event = {
"type": "llm_token",
"node": node_name,
"reasoning_token": reasoning_token
}
# 处理工具调用
elif hasattr(message_chunk, 'tool_calls') and message_chunk.tool_calls:
for tool_call in message_chunk.tool_calls:
tool_call_id = tool_call.get("id", "")
tool_name = tool_call.get("name", "")
tool_args = tool_call.get("args", {})
# 记录工具调用开始
if tool_call_id not in tool_calls_in_progress:
tool_calls_in_progress[tool_call_id] = {
"name": tool_name,
"args": tool_args
}
yield { yield {
"type": "tool_call_start", "type": "node_end",
"tool": tool_name, "node": current_node
"args": tool_args,
"id": tool_call_id
} }
# 处理普通 token yield {
elif token_content: "type": "node_start",
processed_event = { "node": node_name
"type": "llm_token", }
"node": node_name, current_node = node_name
"token": token_content,
"reasoning_token": reasoning_token
}
elif chunk_type == "updates": # 处理消息内容
updates_data = chunk["data"] token_content = getattr(message_chunk, 'content', str(message_chunk))
serialized_data = self._serialize_value(updates_data) reasoning_token = ""
if hasattr(message_chunk, 'additional_kwargs'):
reasoning_token = message_chunk.additional_kwargs.get("reasoning_content", "")
# 检查是否有人工审核请求 # 处理思考过程
if "review_pending" in serialized_data and serialized_data["review_pending"]: if reasoning_token:
review_id = serialized_data.get("review_id", "") processed_event = {
content_to_review = serialized_data.get("content_to_review", "") "type": "llm_token",
yield { "node": node_name,
"type": "human_review_request", "reasoning_token": reasoning_token
"review_id": review_id, }
"content": content_to_review # 处理工具调用
} elif hasattr(message_chunk, 'tool_calls') and message_chunk.tool_calls:
for tool_call in message_chunk.tool_calls:
tool_call_id = tool_call.get("id", "")
tool_name = tool_call.get("name", "")
tool_args = tool_call.get("args", {})
# 检查是否有工具结果 # 记录工具调用开始
if "messages" in serialized_data: if tool_call_id not in tool_calls_in_progress:
for msg in serialized_data["messages"]: tool_calls_in_progress[tool_call_id] = {
# 检测工具结果消息 "name": tool_name,
if msg.get("role") == "tool": "args": tool_args
tool_call_id = msg.get("tool_call_id", "")
tool_name = msg.get("name", "")
tool_output = msg.get("content", "")
if tool_call_id in tool_calls_in_progress:
yield {
"type": "tool_call_end",
"tool": tool_name,
"id": tool_call_id,
"result": tool_output
} }
del tool_calls_in_progress[tool_call_id] yield {
"type": "tool_call_start",
"tool": tool_name,
"args": tool_args,
"id": tool_call_id
}
# 处理普通 token
elif token_content:
processed_event = {
"type": "llm_token",
"node": node_name,
"token": token_content,
"reasoning_token": reasoning_token
}
processed_event = { elif chunk_type == "updates":
"type": "state_update", info(f"🔄 处理updates chunk")
"data": serialized_data updates_data = chunk["data"]
} serialized_data = self._serialize_value(updates_data)
elif chunk_type == "custom": # 检查是否有人工审核请求
serialized_data = self._serialize_value(chunk["data"]) if "review_pending" in serialized_data and serialized_data["review_pending"]:
processed_event = { review_id = serialized_data.get("review_id", "")
"type": "custom", content_to_review = serialized_data.get("content_to_review", "")
"data": serialized_data yield {
} "type": "human_review_request",
"review_id": review_id,
"content": content_to_review
}
if processed_event: # 检查是否有工具结果
yield processed_event if "messages" in serialized_data:
for msg in serialized_data["messages"]:
# 检测工具结果消息
if msg.get("role") == "tool":
tool_call_id = msg.get("tool_call_id", "")
tool_name = msg.get("name", "")
tool_output = msg.get("content", "")
if tool_call_id in tool_calls_in_progress:
yield {
"type": "tool_call_end",
"tool": tool_name,
"id": tool_call_id,
"result": tool_output
}
del tool_calls_in_progress[tool_call_id]
processed_event = {
"type": "state_update",
"data": serialized_data
}
elif chunk_type == "custom":
info(f"🎯 处理custom chunk")
serialized_data = self._serialize_value(chunk["data"])
processed_event = {
"type": "custom",
"data": serialized_data
}
if processed_event:
yield processed_event
info(f"✅ graph.astream() 完成,共 {chunk_count} 个chunks")
except Exception as e:
error(f"❌ 执行 React 图时出错: {e}")
import traceback
error(f"📋 堆栈: {traceback.format_exc()}")
raise
# 发送结束事件 # 发送结束事件
if current_node: if current_node: