129 lines
7.3 KiB
Markdown
129 lines
7.3 KiB
Markdown
# 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_search`
|
||
- `supported_query_kinds`
|
||
- `supports_freshness`
|
||
- `supports_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 的回答输入,字段固定为:
|
||
- `question`
|
||
- `plan`
|
||
- `adapter_attempts`
|
||
- `verified_evidence`
|
||
- `verifier`
|
||
- `uncertainties`
|
||
- 新增 `ExternalAnswerPresenter`,替代 `_generate_answer()` 里对 external route 走通用 `_select_scene_prompt()`。
|
||
- presenter 只按 `answer_contract` 选 3 类 prompt,不再使用 `industry_trend / external_trend`:
|
||
- `direct_fact`
|
||
- `summary_with_sources`
|
||
- `compare_with_sources`
|
||
- presenter 默认只喂:
|
||
- 用户问题
|
||
- 外部证据片段
|
||
- 来源摘要
|
||
- 时间/范围/不确定项
|
||
- presenter 明确禁止喂:
|
||
- `manifest_text`
|
||
- `project_context`
|
||
- `system_snapshot`
|
||
- `user_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`
|
||
- 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 来源被过滤为空的情况
|
||
- 覆盖某一种 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 边界。
|