BodySense Targeted RAG 与 Evidence Provenance
把 BodySense 的 EvidenceGap、targeted retrieval、normalized Evidence、admissibility、citation 与 provenance 放进同一条取证链,解释为什么外部 RAG 不能补成用户事实,以及 retrieved/admissible/resolved 必须分层。
[!info] related notes
- 所属 MOC:
- 相关概念:
- 易混淆概念:
- 相关资源:
BodySense Targeted RAG 与 Evidence Provenance
核心结论
BodySense 更成熟的 RAG 心智不是:
“用户问了问题
→ 先搜几条知识
→ 全塞进 Prompt”
而是:
当前决策出现明确 uncertainty
→ typed EvidenceGap
→ policy 选择 acquisition channel
→ targeted retrieval
→ runtime 记录 EvidenceAttempt
→ normalized Evidence
→ provenance / admissibility
→ gap resolved or unresolved
这把 RAG 从“Prompt 增强技巧”升级成一个有原因、有预算、有 identity、有 provenance、有停止条件的证据获取过程。
Broad Preloaded RAG 为什么在决策 Agent 中不够好
传统 RAG:
request
→ search(query)
→ top 5 docs
→ concatenate rag_context
→ LLM
在普通问答里完全可以工作,但 Diagnosis/Treatment 这种 decision system 会遇到几个问题。
1. 不知道为什么搜
结果里有 citation,但无法回答:
“这条 Evidence 是为哪个 decision-relevant uncertainty 获取的?”
2. 不知道不搜是否合理
如果已有信息足够,继续 broad search 只会增加:
- latency;
- token;
- irrelevant context;
- conflicting facts。
3. User Fact 与 External Knowledge 容易混淆
外部 RAG 能告诉系统:
“某类症状通常与哪些机制相关?”
不能告诉系统:
“这个用户本人是否有该症状?”
4. 无法定义停止原因
只写:
search until model feels enough
不能审计:
- 为什么继续;
- 为什么停止;
- budget 是否越界;
- gap 是否真的解决。
5. Replay 难解释
如果只保存最终 prompt/citation,未来很难恢复:
当时缺什么
→ 为什么搜
→ 搜了什么
→ 哪些结果可用
→ 为什么最后仍 ABSTAIN
Targeted RAG 就是为这些生产问题增加控制面。
EvidenceGap 是 Retrieval 的上游语义
一个真正可执行的 Gap 至少表达:
EvidenceGap
├─ stable identity
├─ kind / source kind
├─ missing fact/question
├─ rationale
├─ criticality
└─ targeted query(只有 external knowledge 适用)
重点是:
先知道为什么缺,再决定怎么找。
不是先有一个 search tool,再让模型所有不确定性都扔进去。
user_information 与 external_knowledge 必须分开
User Information Gap
“这个用户是否出现进行性肌力下降?”
合适来源:
- ask_user;
- measurement;
- user-owned durable record;
- observation。
External Knowledge Gap
“进行性肌力下降在当前风险判断里意味着什么?”
合适来源:
- RAG;
- guideline;
- domain knowledge tool。
这两个问题看起来相关,但 epistemic role 完全不同。
为什么 External RAG 绝不能补成 User Fact
知识库:
“C6 神经根受累可能伴随拇指感觉异常。”
用户只说:
“右肩痛。”
错误:
RAG says C6 often has thumb numbness
→ user has thumb numbness
正确:
External Evidence:
thumb numbness would be informative for C6
Current User Fact:
UNKNOWN
Gap:
ask whether this user actually has thumb numbness
这是一个非常重要的 epistemic invariant:
population/general knowledge
≠
individual observed fact
LLM、Runtime、Policy 三种角色
成熟 Targeted RAG 可以分:
LLM
= proposer / semantic reasoner
→ identify a useful Gap
→ formulate a targeted query
→ interpret semantic support
Runtime
= recorder / verifier
→ execute actual retrieval
→ assign attempt identity
→ record returned evidence IDs
→ enforce budget
Policy
= authority
→ which channel/source is allowed
→ admissibility
→ consequence of unresolved critical gap
压缩成一句:
LLM proposes; Runtime records; Policy authorizes.
如果 LLM 同时负责“说自己搜过”“说这条证据能用”“说 gap 已解决”“说可以 AUTO”,就失去了独立控制面。
EvidenceAttempt:为什么 Tool Log 还不够
普通 tool trace:
search_knowledge(query="...")
→ 200 OK
缺少业务信息:
为哪个 Gap?
当时预算多少?
返回哪些 Evidence?
是否 admissible?
是否真正解决 Gap?
为什么之后停止?
所以可以有:
EvidenceAttempt
├─ attempt_id
├─ gap_id
├─ channel
├─ query
├─ requested_top_k
├─ returned_evidence_ids
├─ outcome
├─ stopping_reason
├─ latency
└─ budget before/after
它把一个低层 ToolCall 提升成 decision-relevant execution fact。
EvidenceBudget 只控制资源,不证明知识充分
例如:
max_searches = 2
max_results_per_search = 5
只表示:
最多允许消耗多少 retrieval resource
它不表示:
两次搜索后 Gap 一定 resolved
完全可能:
budget exhausted
+
critical Gap unresolved
→ ABSTAIN / ESCALATE
所以:
budget exhausted
≠ evidence sufficient
Targeted Query 的真正价值
Broad query:
“颈椎 神经 症状 治疗 训练 风险”
很容易返回:
- definition;
- exercise;
- warning;
- unrelated body region;
- general education。
Targeted Gap:
G7:
“某 intervention 在神经症状加重时的 stop condition 是什么?”
query 就可以围绕:
specific intervention + stop condition + relevant context
这样:
Gap → Attempt → Evidence
的因果关系更清晰,context pollution 更少。
Retrieved、Admissible、Resolved 三层
Retrieved Evidence
含义:
Retriever 返回了它
Admissible Evidence
含义:
当前 source/version/fact-type/policy 允许用于这次 decision
可能检查:
- source status;
- source version;
- run/source set;
- gap kind;
- evidence identity;
- review/quality status。
Gap Resolved
含义:
可采纳 Evidence 在语义上已经足够消除这条 uncertainty
所以必须直接记住:
retrieved
≠ admissible
≠ sufficient
≠ resolved
Partial Support
Gap:
“这个 intervention 的动作、剂量和 stop condition 是否都有支持?”
Evidence:
action supported ✅
dosage supported ✅
stop condition absent ❌
这条 Evidence 完全可以:
admissible = true
但 Gap 仍:
partial / unresolved
不要为了状态简单,把“有一篇相关文章”自动压成 resolved=true。
Conflicting Evidence
可能:
E31 admissible → supports A
E32 admissible → contradicts A
这不是 admissibility failure;相反,系统得到了合法冲突证据。
后续可能需要:
- source hierarchy;
- recency;
- evidence quality;
- conflict policy;
- keep Gap unresolved;
- human review。
不要因为系统想要一个确定答案,就静默丢掉不喜欢的 Evidence。
Normalized Evidence Contract
Raw SearchResult 服务 retrieval/UI,可以有:
title
summary
body_markdown
similarity
source title/author
clips
但治理层更需要稳定 Evidence:
Evidence
├─ evidence_id
├─ source_id / source key
├─ source version/snapshot
├─ kind
├─ observed excerpt/content
├─ acquired_for_gap_id
├─ attempt_id
├─ retrieval score/rank(若需要)
└─ policy metadata
Normalized 的价值在于隔离 retriever 实现。
未来即使从:
pgvector
→ hybrid BM25 + vector + reranker
上层仍然消费同一个 Evidence contract。
Runtime-known Facts 不应该让模型重新抄
Tool 实际返回:
E31@v7
模型最终 output 里又写:
used_evidence = [E31]
只能证明:
model claims it used E31
不能替代:
runtime actually observed E31
模型可能:
- 忘抄;
- 抄错;
- hallucinate E99;
- 引用另一个 run 的 evidence。
所以:
Runtime Evidence Trail
≠
Model Evidence Claim
二者可以比较,但不能合并。
Cross-run Evidence 为什么危险
Run A retrieved E31
Run B did not
Run B 模型/缓存却引用:
supporting_evidence_ids = [E31]
如果 validator 只检查:
database contains E31
就会错误通过。
真正应该检查:
E31 ∈ Run B observed/admissible evidence set ?
如果不是:
invalid provenance
这属于 deterministic check,不需要 LLM Judge。
Citation 与 Provenance
Citation
面向用户/解释:
“这条建议参考了哪里?”
可以展示:
- source title;
- timestamp;
- excerpt;
- clip。
Provenance
面向 audit/replay/governance:
“这次 run 实际观察了哪个版本的哪条 Evidence?为哪个 Gap?来自哪个 Attempt?”
漂亮 citation UI 不自动意味着 provenance 足够。
Query 也属于 Acquisition Provenance
同一 Evidence 可能被不同 query 召回。
Q1: “梨状肌 坐骨神经 禁忌”
Q2: “小腿放射痛 怎么训练”
它们代表不同 acquisition intent。
保存 query / gap relation 有助于:
- retriever debugging;
- query eval;
- replay;
- 发现模型搜索方向错误;
- 评估 context engineering。
这不要求保存所有私有 chain-of-thought,只保存 decision-relevant acquisition fact。
Knowledge Snapshot 与 Evidence Version
知识库持续更新时,同一个 source key 的内容可能变化。
Historical Replay 需要回答:
当时模型看到的是 E31@v3,还是今天的 E31@v8?
所以真正影响 decision 的 Evidence 应有:
- stable ID;
- version/snapshot; -必要 excerpt。
如果历史版本找不到,replay 应标记:
fidelity degraded
不能偷偷替换成最新版并称为 exact historical replay。
Targeted RAG 与 Top-k Vector Search 并不冲突
Targeted RAG 没有否定底层:
query embedding
→ pgvector cosine search
→ filters
→ intent boost
→ top_k
变化的是上层 orchestration:
Traditional:
每次都搜,因为“这是 RAG 应用”
Targeted:
只有 explicit decision-relevant external gap 时搜,
并把 search 绑定 gap/budget/provenance
所以它是Evidence acquisition policy 的升级,不一定要求换向量数据库。
RAG Infrastructure Failure 为什么必须进入 Attempt Provenance
假设:
Gap G7 correct
query correct
但:
sync DB blocks loop
→ query timeout
或:
local embedding executor saturated
→ acquisition timeout
最终:
Gap unresolved
如果 Attempt 只记录:
no evidence
会把 infrastructure failure 误认为 knowledge absence。
所以要区分:
success-empty
infrastructure-error
inadmissible-result
insufficient-result
budget-denied
permission-denied
这直接连接 L4 Async 与 L1 Failure Attribution。
Grounding 是 Acquisition 之后的下一道门
即使 targeted retrieval 正确返回 Evidence,还要问:
最终 Diagnosis/Treatment material claim
真的被这些 admissible Evidence 支持吗?
所以:
Evidence acquisition
→ Evidence set
→ Model claim
→ Grounding evaluator
不能简化成:
有 citation
→ faithful
详见 RAG Grounding / Faithfulness 校验。
一个完整 BodySense 例子
用户已确认:
久坐后臀部紧张,偶有向小腿后外侧放射感
Treatment 前出现:
G17
kind = external_knowledge
question = 某个神经相关动作的 stop conditions 是什么?
critical = true
Attempt A1
query = targeted stop-condition query
→ E41, E42
Policy:
E41 reviewed source / approved version
→ admissible
E42 unpublished draft
→ inadmissible
Semantic support:
E41 mentions action
but not all stop conditions
→ partial
最终:
retrieved = 2
admissible = 1
resolved = false
criticalGapCount = 1
DecisionAuthority → ABSTAIN / ESCALATE / safer path
整个过程中,没有因为 external article 写了某症状,就偷偷给用户新增 user fact。
测试 Targeted RAG 应覆盖什么
No-gap
信息充分:
no unnecessary retrieval
User-fact Gap
kind=user_information
→ generic RAG forbidden
External Gap
kind=external_knowledge
→ targeted search allowed
Budget
max searches reached
→ later attempt denied
→ gap does not auto-resolve
Provenance
returned Evidence IDs = runtime observed set
Cross-run
model references E31 not observed in this run
→ invalid
Inadmissible
retrieved unapproved source
→ gap remains unresolved
Partial support
some subclaims supported
→ critical gap still open if required subclaim missing
Infrastructure error
DB/Embedding failure:
must not be represented as successful empty retrieval
Historical version
replay 使用 exact source version;缺失则显式 degraded fidelity。
自测题
- 为什么 broad preloaded RAG 在 decision Agent 中不够可治理?
- EvidenceGap 为什么应该在 search 之前出现?
- User-information 与 external-knowledge gap 的 acquisition channel 有什么根本区别?
- Tool log 为什么不能替代 EvidenceAttempt?
- Budget exhausted 为什么不能把 Gap 自动标 resolved?
retrieved / admissible / resolved分别是哪一层事实?- Runtime Evidence Trail 与模型
used_evidence声明有什么区别? - Cross-run Evidence 为什么可以 deterministic 拦截?
- Citation 与 Provenance 分别回答什么?
- 为什么 knowledge source version 对 Historical Replay 很重要?
- Targeted RAG 是否要求放弃 pgvector top-k?为什么?
- 为什么 DB timeout 必须和“0 search result”区分?
最终不变量
Gap decides WHY to acquire
Kind decides WHERE to acquire
Budget limits HOW MUCH
Runtime records WHAT happened
Evidence identity tells WHICH evidence
Admissibility decides CAN it be used
Resolution decides DID uncertainty disappear
Citation explains WHERE it came from to users
Provenance makes it replayable/auditable
Targeted RAG 的本质,是把“搜索知识”从一个无上下文 tool call,升级成 production Agent 的受控证据获取过程。