7.3 KiB
7.3 KiB
External Query 独立主链升级计划
摘要
把外部查询从通用 AdaptiveRAG 回答链里拆出来,做成一条独立的“外部事实链”:规划 -> 取证 -> 验证 -> 呈现。这次升级的目标是让 route_mode=external 后只依赖外部证据作答,不再落到 industry_trend / external_trend prompt,也不再混入 project manifest / system snapshot / 内部检索上下文。
关键改动
1. 外部链路边界固定
- 保留现有
Query Route Gateway作为上游拍板;一旦effective_source_policy=external,后续回答链默认只走外部主链,不再回到通用 scene prompt 选择。 ExternalQueryPlanner只负责产出结构化ExternalQueryPlan;planner 的 fallback 改成保守模式:- 仅复用上游
query_semantics - 不再用硬性词语、对象词表或正则去猜
query_kind / time_range / location - 结构化 planner 失败时,默认
query_kind=generic_web、answer_contract=summary_with_sources、search_queries=[原问题]
- 仅复用上游
ExternalQueryGateway只做 provider 选择与证据收集;verifier只判断证据是否足够支撑回答,不再承担语义重判或 internal/external 二次裁决。
2. 能力选路替代固定顺序
- 在
backend/app/services/external_query_service/内把 adapter 能力声明收紧为受控合同:provider_type:fact_api | live_search | doc_searchsupported_query_kindssupports_freshnesssupports_page_fetch
- gateway 排序固定为“能力优先”而不是“注册顺序优先”:
fact_api优先处理天气/汇率/股价等结构化事实live_search处理实时网页事实doc_search只处理文档/说明类问题
- 当前没有专用天气 API 时,天气类默认优先
live_search;MCP 文档型 adapter 不再先占坑。 - MCP 和 live search 都保留“搜索结果 -> 抓目标页正文 -> chunk 打分 -> best snippet”这套正文取证链。
3. 外部证据与呈现彻底分层
- 在
schemas.py新增ExternalContextPacket,作为 external-only 的回答输入,字段固定为:questionplanadapter_attemptsverified_evidenceverifieruncertainties
- 新增
ExternalAnswerPresenter,替代_generate_answer()里对 external route 走通用_select_scene_prompt()。 - presenter 只按
answer_contract选 3 类 prompt,不再使用industry_trend / external_trend:direct_factsummary_with_sourcescompare_with_sources
- presenter 默认只喂:
- 用户问题
- 外部证据片段
- 来源摘要
- 时间/范围/不确定项
- presenter 明确禁止喂:
manifest_textproject_contextsystem_snapshotuser_snapshot- 内部 retrieval block
4. verifier 改成“证据校验器”,不是“语义裁判”
- 把当前
gateway.py里的 bundle 校验拆成独立 verifier 组件,职责只保留:- 外部来源合法性
- 目标对象一致性
- 时间范围一致性
- 多来源是否足以支撑回答
- 对象一致性继续走通用归一化和 bundle 评分,但不允许回退到硬编码对象词表、关键词探针或正则模式。
- 证据不足时统一返回
clarify / insufficient_evidence,不再误落到“行业趋势回答”这种假阳性路径。
5. 与现有 AdaptiveRAG 的接缝
mixin_answer_retrieval.py保留_execute_external_query_gateway(),但返回值从“retrieved rows + meta”扩成ExternalContextPacket所需信息。mixin_deep_guard_answer.py在effective_source_policy=external时直接走ExternalAnswerPresenter,绕过:_resolve_answer_scene_semantics()对 external 的industry_trend/external_trend映射_generate_answer()里默认注入 manifest 的逻辑
Answer Presentation Policy保持现有客户可见合同:- 正文前缀仍是
外部实时查询: - 来源只显示中文化展示字段,不暴露内部 source label/raw metadata
- 正文前缀仍是
主要接口与类型
ExternalQueryPlan保留现有字段,语义收紧为“planner 产出的结构化取证计划”,不再依赖正则推断补字段。- 新增
ExternalContextPacket作为 external presenter 的唯一输入。 - adapter 注册合同新增能力字段,供 gateway 统一排序。
- external presenter 输出仍是最终中文正文,不改上层 API 响应包络。
测试与验收
本期验收不绑定固定问句、固定 provider、固定 prompt 名或固定内部实现路径。
验收只看 route_mode=external 后,external-only 主链是否满足行为合同。
验收要求
- 一旦进入 external 主链,最终回答只能基于 external evidence 生成,不能混入
manifest_text / project_context / system_snapshot / user_snapshot / 内部 retrieval block。 - external 证据不足时,必须明确返回
insufficient_evidence或clarify,不能假装已经查实。 - 对同一 external 问题的后续追问,只要语义上仍是在继续核实,就必须继续留在 external
query.answer主链,不能误跳到 requirement-plan、draft confirm 或内部执行链。 - external source filtering 在过滤后若无合格来源,必须按空来源或证据不足处理,不能把内部来源重新塞回 external answer。
- 当前实现可以按 adapter 能力选择不同 external 取证方式,但验收不把某一种具体 provider 顺序写死为长期真源。
- 运行时必须保留清晰审计信息,至少能看出:planner 如何产出计划、gateway 如何取证、verifier 为何通过或失败、presenter 如何生成最终回答。
覆盖范围
- planner:
- 结构化 planner 失败时,不使用正则或硬词表补
weather/news/company - fallback 仍能产出可执行
search_queries
- 结构化 planner 失败时,不使用正则或硬词表补
- gateway:
- 不同类型的 external 问题都能进入受控 adapter 取证,而不是回退到旧 scene prompt 混答
- external adapter 返回搜索结果后,仍需尽量抓取目标页正文,而不是长期只依赖标题摘要
- verifier:
湛江市 / 湛江这类归一化对象不再误杀- 时间范围不匹配时明确
insufficient_evidence - 证据不足时返回
clarify,不生成假结论
- presenter:
- external route 不再命中
industry_trend / external_trend - prompt 输入中不包含
[M] 项目画像、模块规模、知识图谱、system snapshot - 最终回答只基于 external evidence 生成
- external route 不再命中
- 端到端:
- 覆盖带时间范围或地点的公开事实问题
- 覆盖一般性的外部事实或动态问题
- 覆盖证据不足后的继续核实
- 覆盖 external 来源被过滤为空的情况
- 覆盖某一种 external 取证方式不可用、需要切换备选方式的情况
- 覆盖需要多个来源交叉支撑的对比问题
假设与默认
- 这期只改“纯 external route”的主链,不在本期实现“外部事实 + 内部能力判断 + plan_mode 动作”的完整混合编排。
- 当前没有专用天气 API 时,实时公开事实默认靠
live_search + 网页正文抓取承担。 - 若后续接入专用事实 API,只需要新增 adapter,不改 planner/verifier/presenter 的边界。
- 文档同步纳入本期:至少更新
docs/architecture/RUNTIME_GUARDRAILS.md与docs/architecture/CODE_REFERENCE_INDEX.md,明确 external-only 上下文和 presenter 边界。