feat(roundtable): xdfx 行动名喂入 summary/抽取 + 第三步意图理解增强
- xdfx:把本次「行动名称」喂进 summary 材料(buildMaterials 加 actionName) 与结构化抽取 材料(flow_extract._material 加【本次行动】抬头),让报告/流程图都贴着该行动展开 - 第三步意图识别(classify_flow_intent)增强:新增 can_ingest 上下文 + ingest 意图;重写 _INTENT_SYS 走语义理解——「介绍/解释/为什么/总结一下」等对内容的提问→qa(文字答); 「帮我入库」(可入库时)→ingest→直接入库;能判断就给具体意图不轻易 unclear; 不可入库时误判 ingest 自动降级 qa。前端 classifyFlowIntent 传 canIngest,ask 新增 ingest 分支 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
fba417918f
commit
ae2706dad3
3 files changed
+73
-21
No files matched your search
@@ -78,11 +78,14 @@ class FlowIntentRequest(BaseModel):
|
||||
message: str = ""
|
||||
has_report: bool = False
|
||||
has_flow: bool = False
|
||||
# 当前是否可入库(结构化抽取智能体已判定有适配本场景的入库技能、入库按钮已出现且未入库)。
|
||||
# 为真时才允许识别出 ingest 意图——否则「帮我入库」回退为 qa/unclear。
|
||||
can_ingest: bool = False
|
||||
model: str | None = Field(default=None)
|
||||
|
||||
|
||||
# 意图枚举(与前端路由一一对应)。
|
||||
_INTENTS = {"regenerate_report", "modify_flow", "regenerate_flow", "qa", "unclear"}
|
||||
# 意图枚举(与前端路由一一对应)。ingest 仅在 can_ingest=true 时可用。
|
||||
_INTENTS = {"regenerate_report", "modify_flow", "regenerate_flow", "ingest", "qa", "unclear"}
|
||||
|
||||
|
||||
# ── flow-json 容错解析(Python 版,对齐前端 lib/flow-graph.ts)──────────────
|
||||
@@ -434,13 +437,16 @@ _STRUCTURE = (
|
||||
|
||||
|
||||
def _material(req: FlowExtractRequest) -> str:
|
||||
# xdfx:把本次「行动名称」作为材料抬头喂进去(根节点就是它),让抽取贴着这条行动展开。
|
||||
action = (req.root_label or "").strip()
|
||||
prefix = f"【本次行动】{action}\n\n" if action else ""
|
||||
report = (req.report_md or "").strip()
|
||||
if report:
|
||||
return "===== 方案总结报告全文(数据来源,逐条抽取,勿改写)=====\n" + report + "\n===== 报告结束 ====="
|
||||
return prefix + "===== 方案总结报告全文(数据来源,逐条抽取,勿改写)=====\n" + report + "\n===== 报告结束 ====="
|
||||
seats = [s for s in req.seat_deliveries if (s.content or "").strip()]
|
||||
if seats:
|
||||
body = "\n\n".join(f"## 席位{i + 1}:{s.sender or '(未具名席位)'}\n{s.content.strip()}" for i, s in enumerate(seats))
|
||||
return "===== 各席位交付产物(数据来源,逐条抽取,勿改写)=====\n" + body + "\n===== 交付结束 ====="
|
||||
return prefix + "===== 各席位交付产物(数据来源,逐条抽取,勿改写)=====\n" + body + "\n===== 交付结束 ====="
|
||||
return ""
|
||||
|
||||
|
||||
@@ -703,23 +709,33 @@ def _parse_intent_json(text: str) -> dict[str, Any] | None:
|
||||
|
||||
|
||||
_INTENT_SYS = (
|
||||
"你是圆桌「方案总结」第三步输入框的**意图识别器**。第三步有两类产物:方案总结报告(Markdown) 和 结构化流程图。"
|
||||
"用户在输入框发了一条消息,请判断他的**真实意图**,只输出一个 JSON 对象(不要解释、不要 markdown 代码块、用英文双引号):\n"
|
||||
"你是圆桌「方案总结」第三步对话的**意图识别器**,也是个能帮用户的助手。第三步已产出:方案总结报告(Markdown)、"
|
||||
"结构化流程图,可能还可把成果入库到知识库。用户在对话框发了一条消息,请**按语义理解他真正想干什么**"
|
||||
"(不要只做关键词匹配),只输出一个 JSON 对象(不要解释、不要 markdown 代码块、用英文双引号):\n"
|
||||
'{"intent":"<枚举>","reason":"<一句话依据>"}\n'
|
||||
"intent 只能取其一:\n"
|
||||
"- regenerate_report:想重新分析 / 重写【方案总结报告】(如「重新生成报告」「报告再写一版」「重新分析一下」);\n"
|
||||
"- modify_flow:想修改**当前流程图**的某些节点/连线(如「把目的1改成X」「删掉第3个行为体」「加个验收节点」「流程图这里调整下」);\n"
|
||||
"intent 取值:\n"
|
||||
"- regenerate_report:想**重做/重写整份**方案总结报告(如「重新生成报告」「报告再写一版」「重新分析一下」);\n"
|
||||
"- modify_flow:想**修改当前流程图**的节点/连线(如「把目的1改成X」「删掉第3个行为体」「加个验收节点」「这一层调整下」);\n"
|
||||
"- regenerate_flow:想**重新生成整张**流程图(如「重新画流程图」「流程图重来」「重新结构化输出」);\n"
|
||||
"- qa:只是提问 / 咨询,不需要改任何产物(如「为什么选 OTA 平台」「这个目的什么意思」);\n"
|
||||
"- unclear:意图不明确、无法判断要改报告还是改流程图还是提问(如只说「改一下」「不对」「重来」而没指明对象)。\n"
|
||||
"判断要点:结合下面给出的上下文(是否已有报告 / 是否已有流程图);当前已有流程图时,含「节点/连线/这一层/这个目的/行为体…改/删/加」之类多半是 modify_flow;"
|
||||
"明确提到「报告」才是 regenerate_report;只有完全无法判断对象时才用 unclear。\n"
|
||||
"- ingest:想把本次成果**入库/沉淀/存进知识库**(如「帮我入库」「入库吧」「把方案存进知识库」「沉淀一下」);\n"
|
||||
"- qa:**提问 / 要求解释、介绍、概述、答疑**,只需用文字回答、不改任何产物(如「介绍一下这报告的内容」"
|
||||
"「这方案主要讲了啥」「为什么选 OTA 平台」「风险最高的是哪条」「帮我看看有没有遗漏」「总结成几句话」);\n"
|
||||
"- unclear:**实在**判断不出他想做哪件事(如只说「改一下」「不对」「重来」「再说」且无任何指向)。\n"
|
||||
"判断要点:\n"
|
||||
"1. **优先识别出明确意图,不要动不动就 unclear**——只要能合理判断就给具体意图;尤其『介绍/讲讲/解释/说明/"
|
||||
"为什么/是什么/有没有/帮我看/概述/总结一下』这类是**对内容的提问** → 一律 qa(用文字答),不要误判成重做报告。\n"
|
||||
"2. 含『节点/连线/这一层/这个目的/行为体/流程图…的 改/删/加/换』 → modify_flow(前提是已有流程图)。\n"
|
||||
"3. 明确说『报告』要重写/重做才是 regenerate_report;只是问报告内容是 qa。\n"
|
||||
"4. **入库类意图只有在下文上下文标注「可入库=是」时才允许返回 ingest**;若标注不可入库,用户提入库就归 qa"
|
||||
"(用文字说明当前不可入库/无适配技能)。\n"
|
||||
"示例:\n"
|
||||
'「再帮我生成一次报告」→ {"intent":"regenerate_report","reason":"明确要求重新生成报告"}\n'
|
||||
'「把目的1的名称改短点」→ {"intent":"modify_flow","reason":"要求修改流程图某节点"}\n'
|
||||
'「流程图重新画一张」→ {"intent":"regenerate_flow","reason":"要求重画整张流程图"}\n'
|
||||
'「OTA 平台为什么是直接行为体」→ {"intent":"qa","reason":"纯提问不改产物"}\n'
|
||||
'「改一下」→ {"intent":"unclear","reason":"没说改报告还是流程图"}'
|
||||
'「帮我介绍一下这报告中的内容」→ {"intent":"qa","reason":"要求介绍报告内容,属提问答疑"}\n'
|
||||
'「这方案为什么这么定」→ {"intent":"qa","reason":"询问方案理由"}\n'
|
||||
'「帮我入库」(可入库=是) → {"intent":"ingest","reason":"明确要求入库且当前可入库"}\n'
|
||||
'「再帮我生成一次报告」→ {"intent":"regenerate_report","reason":"明确要求重做报告"}\n'
|
||||
'「把目的1的名称改短点」→ {"intent":"modify_flow","reason":"修改流程图某节点"}\n'
|
||||
'「流程图重新画一张」→ {"intent":"regenerate_flow","reason":"重画整张流程图"}\n'
|
||||
'「改一下」→ {"intent":"unclear","reason":"没说改什么"}'
|
||||
)
|
||||
|
||||
|
||||
@@ -729,7 +745,11 @@ async def classify_flow_intent(request: Request, payload: FlowIntentRequest = Bo
|
||||
msg = (payload.message or "").strip()
|
||||
if not msg:
|
||||
return {"intent": "unclear", "reason": "空消息"}
|
||||
ctx = f"当前上下文:{'已生成报告' if payload.has_report else '尚无报告'};{'已生成流程图' if payload.has_flow else '尚无流程图'}。"
|
||||
ctx = (
|
||||
f"当前上下文:{'已生成报告' if payload.has_report else '尚无报告'};"
|
||||
f"{'已生成流程图' if payload.has_flow else '尚无流程图'};"
|
||||
f"可入库={'是' if payload.can_ingest else '否'}。"
|
||||
)
|
||||
try:
|
||||
model = create_chat_model(name=_resolve_model(payload.model), thinking_enabled=False)
|
||||
res = await model.ainvoke(
|
||||
@@ -740,6 +760,9 @@ async def classify_flow_intent(request: Request, payload: FlowIntentRequest = Bo
|
||||
intent = _as_str(obj.get("intent")).lower()
|
||||
if intent not in _INTENTS:
|
||||
intent = "unclear"
|
||||
# 不可入库时模型若误判 ingest → 降级为 qa(用文字说明当前不可入库),不要触发入库。
|
||||
if intent == "ingest" and not payload.can_ingest:
|
||||
intent = "qa"
|
||||
return {"intent": intent, "reason": _as_str(obj.get("reason"))}
|
||||
except Exception: # noqa: BLE001 — 分类失败不致命,回退澄清让用户自己定
|
||||
logger.warning("flow intent classify failed", exc_info=True)
|
||||
|
||||
Reference in new issue
Block a user