Files
my-v0-server/app/processor/nodes/screen_agent_node.py
T

83 lines
3.2 KiB
Python

"""调用 screen agent,按它的回复和最后一次提交的结果写回状态
kind 由模型决定;代码只在"回复 done 但最后一次提交失败"时不采纳,因为此时没有能交付的动作
"""
import json
from langchain_core.messages import HumanMessage
from app.agent.data_tools import DataContext
from app.agent.screen_agent import AgentReply, get_screen_agent
from app.agent.tools import ScreenAgentContext
from app.processor.base import BaseNode
from app.processor.history import history_messages
from app.processor.state import QueryState
from app.processor.summary import request_summary
from app.resources.component import get_catalog_cache
def reply_update(result: dict) -> QueryState:
"""把 agent 的运行结果转换成 QueryState 的更新"""
reply: AgentReply | None = result.get("structured_response")
if reply is None:
# 调用次数用尽等情况,agent 没有给出结论
return {
"status": "failed",
"answer": "处理步骤超出上限,这次没有完成,可以换个说法再试",
}
if reply.kind == "clarify":
return {"status": "waiting_for_input", "clarification": reply.clarification}
if reply.kind == "unable":
return {"status": "failed", "answer": reply.message}
if result.get("apply_error"):
return {
"status": "failed",
"answer": "修改没有通过校验,这次没有生效,可以换个说法再试",
}
return {
"status": "completed",
"actions": result.get("actions") or [],
"answer": reply.message,
}
class ScreenAgentNode(BaseNode):
name = "screen_agent_node"
async def process(self, state: QueryState) -> QueryState:
updated_state: QueryState = state.copy()
catalog = get_catalog_cache()
if catalog is None:
updated_state["status"] = "failed"
updated_state["answer"] = "物料目录未载入,暂时无法新建或修改大屏"
return updated_state
context = state["input_context"]
agent = await get_screen_agent(with_data=bool(context.data_files))
result = await agent.ainvoke(
{
# 会话历史作为此前的对话消息,本次请求是最后一条用户消息
"messages": [
*history_messages(context.history),
HumanMessage(
content=json.dumps(request_summary(context), ensure_ascii=False)
),
]
},
context=ScreenAgentContext(
screen=context.screen,
catalog=catalog,
data=DataContext(tuple(context.data_files)),
),
)
if result.get("structured_response") is None:
last = result["messages"][-1]
self.logger.warning(
f"agent 没有给出结论: {last.type} {str(last.content)[:500]} "
f"tool_calls={getattr(last, 'tool_calls', None)} "
f"metadata={getattr(last, 'response_metadata', None)}"
)
updated_state.update(reply_update(result))
return updated_state