feat:优化增量执行、工具调用容错与评测体系
This commit is contained in:
@@ -1,39 +1,49 @@
|
||||
"""调用 screen agent,按它的回复和最后一次提交的结果写回状态
|
||||
"""调用 screen agent,按它的回复和成功提交的动作写回状态
|
||||
|
||||
kind 由模型决定;代码只在"回复 done 但最后一次提交失败"时不采纳,因为此时没有能交付的动作
|
||||
kind 由模型决定;代码只在"回复 done 但最后一次提交失败"时不采纳:最后想做的修改没有写入草稿,
|
||||
模型却说已完成。这是保守做法,last_write_failed 只看工具结果,任务是否完成仍以模型的结论和评测为准
|
||||
agent 正常结束却没有结论时(调用次数用尽、只回了文本或空回复)补一次只读收尾;取消和异常照常抛出,不收尾
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
from langchain_core.messages import HumanMessage
|
||||
|
||||
from app.agent.screen_agent import AgentReply, get_screen_agent
|
||||
from app.agent.tools import ScreenAgentContext
|
||||
from app.agent.screen_agent import (
|
||||
AgentReply,
|
||||
finalize_reply,
|
||||
get_screen_agent,
|
||||
reached_call_limit,
|
||||
)
|
||||
from app.agent.tools import ScreenAgentContext, last_write_failed
|
||||
from app.processor.base import BaseNode
|
||||
from app.processor.history import history_messages
|
||||
from app.processor.state import QueryState, run_data
|
||||
from app.processor.summary import request_summary
|
||||
from app.resources.component import get_catalog_cache
|
||||
|
||||
# 评测按这句话识别"草稿因最后一次提交失败没有交付",单独核对草稿本身是否满足要求
|
||||
DRAFT_REJECTED = "修改没有通过校验,这次没有生效,可以换个说法再试"
|
||||
|
||||
def reply_update(result: dict) -> QueryState:
|
||||
|
||||
def reply_update(result: dict, *, limit_hit: bool = False) -> QueryState:
|
||||
"""把 agent 的运行结果转换成 QueryState 的更新"""
|
||||
reply: AgentReply | None = result.get("structured_response")
|
||||
if reply is None:
|
||||
# 调用次数用尽等情况,agent 没有给出结论
|
||||
return {
|
||||
"status": "failed",
|
||||
"answer": "处理步骤超出上限,这次没有完成,可以换个说法再试",
|
||||
}
|
||||
# 收尾也没有给出合法的结论;按真实原因说明,不再一律说超出上限
|
||||
answer = (
|
||||
"处理步骤超出上限,这次没有完成,修改没有生效,可以换个说法再试"
|
||||
if limit_hit
|
||||
else "这次没有得出结论,修改没有生效,可以换个说法再试"
|
||||
)
|
||||
return {"status": "failed", "answer": 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": "修改没有通过校验,这次没有生效,可以换个说法再试",
|
||||
}
|
||||
if last_write_failed(result.get("messages", [])):
|
||||
return {"status": "failed", "answer": DRAFT_REJECTED}
|
||||
# 各次成功提交的动作按顺序拼接;clarify、unable 不交付,下次请求从原始大屏重新执行
|
||||
return {
|
||||
"status": "completed",
|
||||
"actions": result.get("actions") or [],
|
||||
@@ -70,12 +80,16 @@ class ScreenAgentNode(BaseNode):
|
||||
data=run_data(),
|
||||
),
|
||||
)
|
||||
limit_hit = False
|
||||
if result.get("structured_response") is None:
|
||||
limit_hit = reached_call_limit(result["messages"])
|
||||
last = result["messages"][-1]
|
||||
self.logger.warning(
|
||||
f"agent 没有给出结论: {last.type} {str(last.content)[:500]} "
|
||||
f"tool_calls={getattr(last, 'tool_calls', None)} "
|
||||
f"agent 没有给出结论({'调用次数用尽' if limit_hit else '没有调用 AgentReply'}),收尾一次: "
|
||||
f"{last.type} {str(last.content)[:500]} "
|
||||
f"metadata={getattr(last, 'response_metadata', None)}"
|
||||
)
|
||||
updated_state.update(reply_update(result))
|
||||
reply = await finalize_reply(result, limit_hit=limit_hit)
|
||||
result = {**result, "structured_response": reply}
|
||||
updated_state.update(reply_update(result, limit_hit=limit_hit))
|
||||
return updated_state
|
||||
|
||||
@@ -20,7 +20,9 @@ class QueryState(TypedDict):
|
||||
input_context: NotRequired[InputContext] # 校验后的上下文,包含最新大屏和澄清历史
|
||||
intent_decision: NotRequired[DecisionResponse | None] # Jev 原始意图判断及分数
|
||||
intent: NotRequired[Route | None] # 门控后的去向
|
||||
actions: NotRequired[list[Action] | None] # screen agent 最后一次成功提交的动作
|
||||
actions: NotRequired[
|
||||
list[Action] | None
|
||||
] # screen agent 各次成功提交的动作,按执行顺序拼接
|
||||
clarification: NotRequired[Clarification | None] # 当前澄清问题及选项
|
||||
clarification_reply: NotRequired[
|
||||
ClarificationReply | None
|
||||
|
||||
Reference in New Issue
Block a user