PMFlow/mdproject/PLAN.md

129 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 边界。