Decision-Relevant Evidence Gap
把缺失信息建模为会实质改变当前决策的证据缺口,使 Agent 只为真正影响判断的不确定性继续取证。
[!info] related notes
Decision-Relevant Evidence Gap
一句话定义
Decision-Relevant Evidence Gap 是当前缺失、且一旦补齐可能实质改变候选、风险等级或最终动作的证据缺口;它不是所有“还可以知道更多”的信息。
[!important] 核心问题 不是“还有什么不知道?”,而是:这个未知信息如果得到不同答案,会不会改变当前决策?
如果不会,它通常不是当前 decision-relevant gap。
为什么“未知”本身不是一个充分模型
Agent 永远不知道很多事情。
用户说“肩痛”时,系统还不知道:
- 今天早餐吃了什么;
- 最近喜欢看什么电影;
- 左手握力具体是多少;
- 是否有严重创伤;
- 是否有进行性肌力下降;
- 哪个动作会加重症状。
显然不能把所有未知都变成:
EvidenceGap
否则 Agent 会陷入无限信息收集。
Decision-Relevant 的意义就是做一次“价值过滤”:
Unknown Information
↓
Would different answers materially change:
- candidate ranking?
- safety/risk?
- authority outcome?
- intervention choice?
↓
Yes → Decision-Relevant Gap
No → ignore for current decision
这实际上是在问信息的边际决策价值,而不是追求“知道得越多越好”。
为什么要把 Gap 做成一等结构,而不是一串字符串
简单的:
information_gaps = ["还需要知道肌力情况"]
只能描述文本,无法稳定控制:
- 这个 gap 是用户事实还是外部知识?
- 是否 critical?
- 允许使用什么 acquisition channel?
- 是否正在取证?
- 哪一次 EvidenceAttempt 属于它?
- 为什么最终仍 unresolved?
更成熟的结构可以是:
EvidenceGap
├─ gap_id
├─ kind
├─ missing_fact
├─ why_needed
├─ criticality
├─ related_concern_key
├─ acquisition_strategy
└─ status
其中 gap_id、实际状态转换和真实 attempt identity 应由 runtime 持有,而不是依赖 LLM 自己在自由文本里维持一致。
“Gap Identity”为什么重要
如果只保留文本:
“还需要知道肌力情况”
第二轮模型可能写:
“需要确认是否存在进行性无力”
第三轮又写:
“需要补充 motor weakness 信息”
语义上可能是同一个 gap,但系统很难知道:
- 是同一个 gap 被持续追踪;
- 还是三个不同 gap;
- 哪些 attempts 属于它;
- budget 是否已经耗过;
- 是否已经 resolved。
因此 runtime-owned stable gap_id 可以把语义描述与执行历史绑定起来:
G17
├─ proposed description v1
├─ Attempt A1
├─ Attempt A2
├─ Evidence E31
└─ final status = unresolved
这和数据库主键的价值类似:稳定 identity 让生命周期可追踪。
四种常见 Gap 类型
1. user_information
缺少这个用户本人的事实,例如:
“这个用户是否存在进行性肌力下降?”
常见获取方式:
- ask_user;
- structured clarification;
- measurement;
- observation;
- 后续真实业务数据。
一般知识库不能直接关闭这类 gap。
2. external_knowledge
缺少一般领域知识,例如:
“C6 神经根受累通常是否与拇指感觉异常相关?”
这类 gap 才适合:
- targeted retrieval;
- knowledge base;
- read-only domain tool。
3. conflict
系统已经有多个事实,但它们互相矛盾,例如:
当前输入:无麻木
历史结构化观察:持续麻木
这不是“多搜一篇文献”可以解决的问题。通常需要:
- 明确时间关系;
- 请求用户澄清;
- 重新测量;
- 建立 conflict resolution policy。
4. safety
缺少的信息本身直接决定是否可以继续自动化处理,例如:
“是否存在新的进行性神经功能缺失?”
Safety gap 往往是 critical,但 kind=safety 与 criticality=critical 仍然是两个不同维度:前者描述语义类别,后者描述当前决策重要性。
kind 与 criticality 为什么要分成两个维度
一个 external knowledge gap 也可能是 critical:
“某个 intervention 在当前高风险条件下是否有明确 contraindication?”
一个 user information gap 也可能不 critical:
“用户更喜欢上午还是晚上训练?”
所以不要把:
kind=safety
等价为:
critical=true
更合理是:
kind
= 这是什么类型的未知?
criticality
= 如果当前不知道它,对当前决策有多严重?
两个维度一起决定 acquisition 与 authority。
Gap 的状态模型
一个 gap 可以显式拥有状态:
OPEN
↓
SEARCHING / ACQUIRING
↓
RESOLVED
或者:
OPEN
↓
ACQUIRING
↓
UNRESOLVABLE
UNKNOWN 不等于失败,它表示系统尚没有足够证据完成某项判断,因此应进入信息获取或受控降级路径。
状态模型最好区分“为什么没有解决”
只有:
status = unresolved
还不够解释。
可以额外保留 stopping/resolution reason:
unresolved_reason
├─ budget_exhausted
├─ user_fact_unavailable
├─ source_unavailable
├─ contradictory_evidence
├─ inadmissible_evidence_only
├─ semantic_support_insufficient
└─ permission_boundary
这样未来可以知道:
“系统不知道”
到底是因为:
- 没去找;
- 找不到;
- 找到了但不能用;
- 找到了合法 Evidence 但证据不够;
- 当前产品根本没有权限继续获取。
这些在 incident/debug 中是完全不同的问题。
谁拥有 Gap?LLM、Runtime 与 Policy 要分工
一个很容易出错的设计是让 LLM 同时:
- 提出 gap;
- 给 gap 编号;
- 决定能不能搜索;
- 声称自己搜索过;
- 宣布 gap 已解决;
- 决定是否可以 AUTO。
这把 proposal、事实和 authority 全部混在一个随机组件里。
更稳健的 ownership 是:
LLM
→ propose semantic gap
→ explain why it matters
Runtime
→ validate schema
→ assign/maintain gap identity
→ record actual attempts/evidence/budget
→ verify factual observations
Domain / Acquisition Policy
→ authorize acquisition channel
→ determine hard consequences
可以压缩成:
LLM = proposer / reasoner
Runtime = recorder / verifier
Policy = authority
为什么“模型说我还缺信息”本身也需要结构化约束
如果完全自由文本,模型可能提出:
“我需要更多信息”
但没有说明:
缺什么?
为什么会改变决策?
来自哪里?
是否 critical?
这类 gap 很难执行。
更好的 output schema 会要求模型至少表达:
missing_fact
kind
rationale
criticality
然后 runtime 再验证:
user_information不得携带 external search query;- criticality enum 合法;
- rationale 非空;
- gap 不能引用不存在的 concern/candidate identity。
这叫semantic proposal typed boundary。
RESOLVED 不是模型一句话就能成立
模型可以做语义判断:
“E31 看起来回答了 G1。”
但 Runtime 至少还应该确认:
- E31 真的被本轮 tool 返回;
- evidence identity 真实;
- source/version 满足 policy;
- evidence 类型与 gap 类型兼容;
- 它被合法关联到这个 gap。
也就是先经过 Evidence Admissibility。
所以:
LLM says “resolved”
≠
Gap is factually resolved
Resolution 也可能是“部分解决”
很多真实问题不是二元的。
例如 Gap:
“这个 intervention 是否有充分 evidence 支持其动作、剂量和 stop condition?”
Evidence 可能:
动作支持 ✅
剂量支持 ✅
stop condition 没提 ❌
那么最诚实的状态可能是:
PARTIAL
或:
UNRESOLVED with supported_subclaims
不要为了让状态机简单,把“部分证据”强行压成 resolved=true。
对于 critical gap,通常应以关键子问题全部满足为关闭条件。
Critical Gap
并不是所有 gap 的优先级都一样。若某个 gap 关系到:
- 是否存在高风险情况;
- 是否允许 AUTO;
- 某候选是否会发生实质改变;
- 是否需要转人工;
它可以被标记为 critical gap,并参与 hard policy gate。
例如:
critical gap unresolved
→ outside normal SafetyEnvelope
→ policy may ABSTAIN / ESCALATE / BLOCK
即使 candidate confidence 很高,也不能把缺失证据“算没了”。
“Critical”最好来自 Policy,而不是只由模型决定
模型可以提出:
“我认为 G7 很重要”
但某些 criticality 本身属于稳定业务规则:
progressive neurological deficit
new severe trauma
loss of bowel/bladder control
如果这些是明确安全边界,就不应该完全依赖 LLM 每次自己想起。
更成熟的结构是:
LLM proposes Gap + semantic importance
↓
Runtime / Policy validates or upgrades criticality
↓
Final governed Gap
甚至某些 hard safety gaps 可以由 deterministic detector 直接产生,而不是等 LLM proposal。
Absence of Evidence ≠ Evidence of Absence
检索没有找到结果,只能说明:
本次 acquisition 没有找到足以回答 gap 的 evidence
不能自动推导:
该情况不存在
例如:
没有搜到“某风险一定存在”的证据
并不等于:
该风险已被排除
这是 critical gap 场景中非常重要的 epistemic boundary。
这个原则在 User Fact 中更加明显
问:
“用户是否夜间痛醒?”
数据库/历史记录没有相关信息,只能得到:
UNKNOWN
不能得到:
FALSE
这和数据库三值逻辑很像:
missing
≠
negative
如果产品把“没记录”默认解释成“没有”,会产生隐蔽的数据偏差。
Gap 与 Longitudinal History
如果一个 EvidenceGap 影响了历史 Decision,它的当时状态应成为 durable audit artifact。
例如:
D100 / BodyState R42
G8 = unresolved
Decision = ESCALATE
第二天 R43 获得新信息,并不能回去把 D100.G8 改成 resolved。
因为:
Past knowledge ≠ current knowledge
新的事实应进入新的 BodyState revision 和新的 Analysis。详见 BodySense Diagnosis 的 Durable Domain Model。
为什么 Gap 的历史状态本身就是业务事实
很多人会觉得:
“最后都知道答案了,还保存以前不知道什么干嘛?”
但 DecisionTrace 要解释的是:
“当时为什么这么做?”
假设 D100 当时:
G8 unresolved
→ ESCALATE
如果后来把 G8 更新成 resolved,历史记录会变成:
G8 resolved
但 Decision 仍是 ESCALATE
看起来像系统做了错误决策。
因此“当时不知道什么”与“后来知道什么”都是独立事实。
Gap 与 Tool Selection 的关系
Gap kind 可以直接限制工具空间:
user_information
→ ask_user / measurement / user-owned state
external_knowledge
→ search_knowledge / guideline lookup
conflict
→ clarification / compare revisions / human review
safety
→ deterministic safety workflow / escalation / targeted evidence
这比让模型面对 20 个 tools 自由决定更安全,也更高效。
可以把 tool routing 看成:
Gap Type
→ Allowed Acquisition Capability Set
→ LLM chooses within allowed set
而不是:
LLM sees every tool
→ prompt says “please be careful”
Gap 与 EvidenceBudget 的关系
每个 Gap 可以有局部 budget,整个 run 也有全局 budget。
例如:
Run Budget
max_searches = 2
G1
used_searches = 1
G2
used_searches = 1
当 global budget 用完:
G3 remains open
这只是 resource state,不是 epistemic state。
所以:
Budget exhausted
≠
Gap resolved
这条不等式值得直接记忆。
一个完整例子:从 Gap Proposal 到 Authority
用户输入:
颈肩不适,右手偶尔麻,但没有说明是否出现进行性无力
模型提出:
G1
kind = user_information
missing_fact = progressive motor weakness?
criticality = critical
Runtime:
assign gap_id = G17
validate kind
forbid generic RAG query
Acquisition:
ask_user unavailable / user did not answer
Gap final state:
G17 unresolved
reason = required_user_fact_unavailable
DecisionFacts:
unresolved_critical_gap_count = 1
DecisionAuthority:
ABSTAIN / ESCALATE
注意这里模型甚至可能已经有一个语义上很合理的 candidate,但系统仍然不授权 normal AUTO。
Gap 设计常见反模式
反模式 1:所有 unknown 都列成 Gap
后果:无限追问、成本高、用户体验差。
反模式 2:Gap 只是自由文本
后果:无法绑定 attempt、budget、source policy、status。
反模式 3:模型自己宣布 resolved=true
后果:execution fact 与 semantic proposal 混在一起。
反模式 4:所有 Gap 都允许 RAG
后果:external knowledge 被错误升级成 user fact。
反模式 5:budget 用完自动关闭 Gap
后果:资源耗尽被误解释成知识充分。
反模式 6:后来获得信息后回写旧 Gap
后果:历史 DecisionTrace 被篡改。
如何测试 EvidenceGap Contract
至少覆盖:
No-gap case
信息充分:
no unnecessary acquisition
User-fact case
kind=user_information
→ no generic RAG
External-knowledge case
kind=external_knowledge
→ targeted search allowed
Critical + zero budget
budget=0
critical gap remains unresolved
→ authority must not normal AUTO
Budget exhausted
first critical gap uses search
second critical gap cannot silently search past budget
Inadmissible evidence
retrieved but invalid source/version
→ gap remains unresolved
Historical immutability
新 BodyState 获得答案后:
old Analysis gap state unchanged
自测题
- 为什么“还有不知道的信息”不等于 EvidenceGap?
- Decision relevance 是怎么判断的?
kind和criticality为什么要分开?- 为什么 gap identity 应由 runtime 稳定维护?
UNKNOWN为什么不能默认当FALSE?- 为什么模型说 resolved 还不够?
- Partial evidence 为什么可能仍然不能关闭 critical gap?
- 为什么 external RAG 不能关闭 user-information gap?
- budget exhausted 和 gap resolved 为什么是两个维度?
- 为什么旧 Gap 的 unresolved 状态不能被未来知识回写?
最小例子
用户说“肩痛”,但没有说明是否发生明显创伤。
缺少喜欢的运动
→ 可能不影响当前安全判断
缺少近期严重创伤信息
→ 可能改变风险与处置路径
→ decision-relevant / potentially critical
再比如:
Gap A:
“颈神经根问题通常是否影响拇指感觉?”
→ external_knowledge
→ targeted retrieval may help
Gap B:
“这个用户的肱二头肌反射是否减弱?”
→ user_information
→ generic RAG cannot answer
常见误解
- gap 越多,模型就越差:gap 描述的是证据状态,不是模型质量评分。
- confidence 高就说明 gap 可以忽略:模型自信不能补足缺失证据。
- 搜索能关闭所有 gap:用户事实、知识、冲突与安全 gap 需要不同 acquisition channel。
- budget exhausted 就等于 gap 已解决:预算耗尽只代表停止当前获取方式。
- 模型说 resolved 就一定 resolved:还要经过 runtime factual validation 与 evidence admissibility。
- 后来知道答案就应该更新旧 gap:这会篡改当时的历史知识状态。
- 所有缺失信息都应该问用户:只有 decision-relevant 的信息值得增加用户负担。
- criticality 完全由模型决定:安全关键规则可以由 deterministic policy 校正/提升。