8.9 KiB
Answer Presentation Policy Design
Goal
为 query.answer 建立一层独立的“回答展示契约”,把运行时证据、审计元数据和客户可见文案彻底拆开。后续内部查询与外部查询的用户可见回复默认只展示面向客户的中文化内容,不再把 Project database / Semantic facts / Knowledge Graph / Feishu history 这类机器标签或内部术语直接暴露给客户。
Why Now
当前问题不是某一个英文 label 写得不好,而是整条回答链没有区分:
- 机器内部证据
- 后台审计证据
- 客户可见展示
现在英文和内部术语会从四个出口漏到客户侧:
- retrieval / deterministic query 分支直接写英文
source_label 来源摘要直接拼接这些source_labelcitations / evidence_pack / sources_used直接复用原始 label- 生成式回答 prompt 的 context block 里也是
来源: {item.source_label},模型会把英文来源再复述进正文
所以这不是“翻译一下来源摘要”能解决的问题,而是展示契约缺失。
Confirmed Baseline
- 客户可见回答默认走
customer_safe展示契约。 customer_safe视图只展示中文化后的来源显示名和客户可读结论。raw_source_label / source_type / source_id / chunk_id / tool_trace继续保留,但只属于 audit/debug 视图。- 不做“看到什么翻译什么”的散点补丁;统一由单点展示策略产出
display_label。 - 不强行翻译业务对象真名。项目名、产品名、人员名如果本身是英文,可以保留。
- internal / external 来源过滤都必须 fail-closed;过滤空了就不显示客户来源摘要,不允许把原始机器来源兜回来。
- 展示层整治必须覆盖正文生成 prompt、
来源摘要、payload citations/evidence pack 三层,不能只改末尾渲染。
Scope
In Scope
query.answer的客户可见回答展示- internal / external 的来源显示策略
- answer prompt 上下文里的来源显示名
- response payload 的 customer/audit 双视图拆分
来源摘要、citations、evidence_pack的客户安全化
Out Of Scope
- internal DSL / semantic facts 的查询逻辑
- external provider / MCP 执行层
- requirement-plan / draft confirm / card rendering
- 前端反馈中心、训练中心这类管理后台数据模型
Current State
1. 内部来源头是中文,但来源 label 不是
backend/app/services/adaptive_rag_service/mixin_query_route_gateway.py
- internal route 会统一加
内部知识库查询: - 但
来源摘要是直接拼label - 当前没有 customer-safe label 层
2. 多条 retrieval 分支直接写英文机器 label
例如:
Project databaseUser databaseSemantic factsKnowledge Graph
这些 label 当前分散在 deterministic query、structured db retrieval、graph retrieval 等多条分支里,不是单点控制。
3. _source_label() 也在直接产出客户可见英文 / 内部术语
backend/app/services/adaptive_rag_service/mixin_conversation_utils_a_p1.py
Document[...]Feishu historyPMFlow recordsURL[...]
这些 label 现在会被直接透传给最终回答和 citations。
4. payload 层会把原始 label 继续写进 citations / evidence pack
backend/app/services/adaptive_rag_service/mixin_answer_payload.py
_build_citations_from_sources()直接读取item.label / metadata.source_label_build_evidence_pack()再把source_label聚合进用户可见summary.evidence
5. 模型正文也会吃到原始来源 label
backend/app/services/adaptive_rag_service/mixin_deep_guard_answer.py
当前 context block 是:
[1] 来源: {item.source_label}
相关度: ...
内容: ...
这意味着即使最后渲染层不显示英文,模型正文也可能主动复述这些英文来源。
Root Cause
根因不是“英文太多”,而是运行时把一份字段同时拿去做了三种用途:
- 检索/审计定位
- 内部 debug 与治理
- 客户可见展示
只要这三种用途继续共用同一个 source_label,后面不管补多少翻译映射,都会继续漏。
Design Decision
新增单点 Answer Presentation Policy,让回答证据从一开始就分成两套字段:
- 机器字段
- 展示字段
统一数据结构建议为:
| 字段 | 用途 |
|---|---|
source_type |
机器类型 |
source_id |
机器主键/引用 |
raw_source_label |
原始 label,仅审计使用 |
display_label |
客户可见显示名 |
display_category |
如 项目数据/成员数据/文档资料/语义事实 |
target_url |
可外显链接(若允许) |
permission_scope |
可见范围 |
audience_visibility |
customer / admin_only |
后续所有客户可见回答只消费 display_* 字段,绝不直接消费 raw_source_label。
Answer Presentation Contract
建议把回答展示视图显式分成两类:
customer_safe
给客户看的默认视图,只包含:
- 中文结论
- 中文来源显示名
- 客户可读的证据摘要
- 必要时的外部 URL
不允许包含:
raw_source_labeltool_tracechunk_id- 内部表名、内部 source type
Project database / Semantic facts / Knowledge Graph / Feishu history等内部术语
admin_debug
给后台治理或排障看的视图,保留:
raw_source_labelsource_typesource_idchunk_idtool_tracereason_code- 原始 citations
Source Display Registry
新增单点 Source Display Registry,统一把机器来源映射为客户可见显示名。
示意映射:
| 机器来源 | 客户显示名 |
|---|---|
db + projects |
项目数据 |
db + users |
成员数据 |
db + semantic_facts |
语义事实 |
graph |
关联知识 |
doc |
文档资料 |
feishu |
飞书消息 |
pmflow |
系统记录 |
url |
外部网页 |
system guard |
系统校验 |
这个 registry 只负责展示,不改变检索与审计逻辑。
Mandatory Flow
回答展示主链改成:
- retrieval / deterministic query 产出机器证据
Answer Presentation Policy归一化出raw_source_label + display_label- prompt context block 只使用
display_label 来源摘要只使用display_label- response payload 拆成
customer_citations与audit_citations - 前台默认只消费
customer_safe - 治理后台按需消费
admin_debug
Prompt Hygiene Rule
生成式回答 prompt 必须改成只喂客户显示名:
从:
来源: raw_source_label
改成:
来源: display_label
否则就算前端不展示英文,模型正文仍会继续输出英文内部术语。
Failure Semantics
- 某来源无法映射 display label:客户视图不展示原始 label,只显示更高层级中文类别,或直接不列该来源
- source filter 后为空:不显示来源摘要,不回退原始机器来源
- payload 构建失败:保留最小结论,不允许把 raw audit fields 透给客户
Rollout
Phase A
先写入基线文档,不动运行时代码。
Phase B
落地 Source Display Registry + customer_safe/admin_debug 双视图。
Phase C
把 prompt context、来源摘要、citations/evidence_pack 全部切到展示契约。
Phase D
补回归测试,锁住“客户侧不再出现英文机器标签/内部术语”。
Acceptance Criteria
- internal
query.answer的客户可见回复默认纯中文展示壳 来源摘要不再出现Project database / Semantic facts / Knowledge Graph / Feishu history- 模型正文不再因为 prompt context 泄露英文来源 label
audit/debug仍可看到原始raw_source_label/source_type/source_id- external/internal 的 source filter 都是 fail-closed
Planned File Changes
新增模块
backend/app/services/adaptive_rag_service/source_presentation.py
运行时接入
backend/app/services/adaptive_rag_service/mixin_deep_guard_answer.pybackend/app/services/adaptive_rag_service/mixin_query_route_gateway.pybackend/app/services/adaptive_rag_service/mixin_answer_payload.pybackend/app/services/adaptive_rag_service/mixin_conversation_utils_a_p1.pybackend/app/services/adaptive_rag_service/mixin_retrieval_router_db.pybackend/app/services/adaptive_rag_service/mixin_retrieval_graph.pybackend/app/services/adaptive_rag_service/mixin_deterministic_query_count.pybackend/app/services/adaptive_rag_service/mixin_deterministic_query_list.py
回归测试
backend/tests/test_answer_presentation_policy.pybackend/tests/test_internal_query_source_display_contract.pybackend/tests/test_external_query_source_display_contract.pybackend/tests/test_adaptive_rag_prompt_source_hygiene.py
文档基线
AGENTS.mddocs/architecture/RUNTIME_GUARDRAILS.mddocs/architecture/ARCHITECTURE_INVENTORY.mddocs/superpowers/specs/2026-04-15-answer-presentation-policy-design.md