Decision-Relevant Evidence Gap

把缺失信息建模为会实质改变当前决策的证据缺口,使 Agent 只为真正影响判断的不确定性继续取证。

#type / concept #status / growing #tech / ai #resource / 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=safetycriticality=critical 仍然是两个不同维度:前者描述语义类别,后者描述当前决策重要性。

kindcriticality 为什么要分成两个维度

一个 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 同时:

  1. 提出 gap;
  2. 给 gap 编号;
  3. 决定能不能搜索;
  4. 声称自己搜索过;
  5. 宣布 gap 已解决;
  6. 决定是否可以 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

自测题

  1. 为什么“还有不知道的信息”不等于 EvidenceGap?
  2. Decision relevance 是怎么判断的?
  3. kindcriticality 为什么要分开?
  4. 为什么 gap identity 应由 runtime 稳定维护?
  5. UNKNOWN 为什么不能默认当 FALSE
  6. 为什么模型说 resolved 还不够?
  7. Partial evidence 为什么可能仍然不能关闭 critical gap?
  8. 为什么 external RAG 不能关闭 user-information gap?
  9. budget exhausted 和 gap resolved 为什么是两个维度?
  10. 为什么旧 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 校正/提升。
创建于 2026/8/19 更新于 2026/8/23