fix:处理模型错误添加大量文本的bug

This commit is contained in:
2026-10-14 01:08:50 -07:00
parent a80727b7a0
commit 41b769adde
35 changed files with 388 additions and 149 deletions
+1
View File
@@ -51,5 +51,6 @@ class InputNode(BaseNode):
updated_state["actions"] = None
updated_state["clarification"] = None
updated_state["answer"] = None
updated_state["suggestions"] = None
updated_state["status"] = "running"
return updated_state
+5
View File
@@ -18,6 +18,9 @@ from app.processor.summary import data_file_summary
# 模型在一次回答里分几次输出文字(例如查询前后各说一段)时,段落之间空一行
PARAGRAPH_BREAK = "\n\n"
# 带数据的问答回答完后给的后续请求:意图判断会把"展示一下 9 月销售额"这类说法分到问答,
# 用户其实想在大屏上看到;回答之后给一个按钮,点了按普通请求走大屏 agent,会话历史里有这次回答
PUT_ON_SCREEN = "把上面的结果放到大屏上"
class QANode(BaseNode):
@@ -93,4 +96,6 @@ class QANode(BaseNode):
updated_state["answer"] = answer
updated_state["status"] = "completed"
if context.data_files:
updated_state["suggestions"] = [PUT_ON_SCREEN]
return updated_state
+14 -8
View File
@@ -9,6 +9,7 @@ import json
from langchain_core.messages import HumanMessage
from app.actions.batch import mark_sample_data
from app.agent.screen_agent import (
AgentReply,
finalize_reply,
@@ -21,13 +22,19 @@ 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
from app.schemas.component_resource import ComponentCatalog
# 评测按这句话识别"草稿因最后一次提交失败没有交付",单独核对草稿本身是否满足要求
DRAFT_REJECTED = "修改没有通过校验,这次没有生效,可以换个说法再试"
def reply_update(result: dict, *, limit_hit: bool = False) -> QueryState:
"""把 agent 的运行结果转换成 QueryState 的更新"""
def reply_update(
result: dict, *, limit_hit: bool = False, catalog: ComponentCatalog | None = None
) -> QueryState:
"""把 agent 的运行结果转换成 QueryState 的更新
交付的新增组件按交付后的大屏定 sample_data:留着物料示例数据的也标为示例数据(mark_sample_data)
"""
reply: AgentReply | None = result.get("structured_response")
if reply is None:
# 收尾也没有给出合法的结论;按真实原因说明,不再一律说超出上限
@@ -44,11 +51,10 @@ def reply_update(result: dict, *, limit_hit: bool = False) -> QueryState:
if last_write_failed(result.get("messages", [])):
return {"status": "failed", "answer": DRAFT_REJECTED}
# 各次成功提交的动作按顺序拼接;clarify、unable 不交付,下次请求从原始大屏重新执行
return {
"status": "completed",
"actions": result.get("actions") or [],
"answer": reply.message,
}
actions = result.get("actions") or []
if actions:
actions = mark_sample_data(actions, result["working_screen"], catalog)
return {"status": "completed", "actions": actions, "answer": reply.message}
class ScreenAgentNode(BaseNode):
@@ -91,5 +97,5 @@ class ScreenAgentNode(BaseNode):
)
reply = await finalize_reply(result, limit_hit=limit_hit)
result = {**result, "structured_response": reply}
updated_state.update(reply_update(result, limit_hit=limit_hit))
updated_state.update(reply_update(result, limit_hit=limit_hit, catalog=catalog))
return updated_state
+1
View File
@@ -28,6 +28,7 @@ class QueryState(TypedDict):
ClarificationReply | None
] # 待合并的用户回答或取消指令
answer: NotRequired[str | None] # 问答回答,或 agent 给用户的说明
suggestions: NotRequired[list[str] | None] # 可以一键发送的后续请求,前端显示成按钮
status: NotRequired[
Literal["running", "waiting_for_input", "completed", "cancelled", "failed"]
] # 后端处理、等待补充、处理完成、用户取消或失败,完成不代表前端已执行
+6 -13
View File
@@ -3,6 +3,8 @@
只描述本次请求;会话历史由各使用方另行传入,见 history.py
"""
from app.resources.component import get_catalog_cache
from app.resources.material_fields import identifying_texts
from app.schemas.base import JsonObject
from app.schemas.data_file import RequestDataFile
from app.schemas.input_context import InputContext
@@ -14,25 +16,16 @@ SUMMARY_COLUMNS = 30
def request_summary(context: InputContext) -> JsonObject:
"""用户输入、澄清记录、编辑上下文、附件、数据文件和大屏摘要"""
nodes: list[JsonObject] = []
catalog = get_catalog_cache()
for node in context.screen.nodes:
# 画面上的标题帮助判断用户指的是哪个组件:图表在 option.title,指标卡在 props.title;
# 格式不符时按无标题处理
option = node.props.get("option")
title = option.get("title") if isinstance(option, dict) else None
titles = title if isinstance(title, list) else [title]
texts = [
item["text"]
for item in titles
if isinstance(item, dict) and isinstance(item.get("text"), str)
]
if isinstance(node.props.get("title"), str) and node.props["title"]:
texts.append(node.props["title"])
nodes.append(
{
"id": node.id,
"type": node.type,
"name": node.name,
"titles": texts,
# 画面上的名字或内容帮助判断用户指的是哪个组件;取哪个字段由字段定义的 identifies 决定,
# 新物料不用在这里加判断。物料目录没载入时为空
"titles": identifying_texts(catalog, node.model_dump(mode="json")),
"layout": node.layout.model_dump(mode="json", exclude_unset=True),
}
)