对应:Stanford CS224V Fall 2026 Lecture 4(10/5 Accountable AI: SMT;系统 SatIR、VERDICT)。 关于材料来源:这次课的幻灯片尚未公开。本讲依据:第 1 讲幻灯片里关于临床决策、VERDICT 和 SatIR 的部分;两篇论文——VERDICT(Zhou 等,Accountable AI with Grounded, Faithful, Consistent, Actionable Rationales,EMNLP 2026,arXiv 2609.03366)和 SatIR(Zhou 等,Scalable High-Recall Constraint-Satisfaction-Based Information Retrieval for Clinical Trials Matching,COLM 2026,arXiv 2604.08849);课程表的描述;阅读清单的”Formal Reasoning”部分。 配套代码:
code/lecture04/(只用 Python 标准库,数据库用自带的sqlite3;05 号文件可选,需要anthropic包和 API 密钥) 预计阅读时间:3~4 小时(含运行代码)
0. 本讲导航
0.1 学完本讲,你应该能够
- 说明临床试验匹配为什么是一个高风险决策问题,以及只给”是 / 否”为什么不够。
- 解释可问责的四个要求:可验证、忠实、一致、可行动;以及”自我忠实性”这个自动检验。
- 用自己的话解释命题逻辑、可满足性(SAT)、DPLL、三值逻辑、SMT、不可满足核心和 MaxSAT。
- 画出 VERDICT 的流程:LLM 只负责翻译,求解器负责决策;说出它怎样得到证据、假设和关键条件。
- 解释 SatIR 为什么把约束”投影”到数据库,以及这种投影为什么保留召回率、只牺牲一点精确率。
- 说出形式化方法的边界:翻译的质量是天花板;政策是人的决定;SQL 的 NULL 也是三值逻辑。
0.2 先修知识
| 知识点 | 用在哪里 | 最低要求 |
|---|---|---|
| 第 1 讲 | 全讲 | “把问题分解成可靠的 LLM 任务”;核查比生成可靠 |
| 第 3 讲 | 第 4、5 节 | 工具的输出要校验;计算思维:LLM 是程序里的一个组件 |
| 布尔逻辑 | 第 3 节 | 与、或、非(讲义里从头讲) |
| SQL | 第 5 节 | 知道 SELECT ... FROM ... WHERE ...(第 6 讲会系统地讲;代码注释里也有解释) |
0.3 本讲地图
第1节 高风险决策:临床试验匹配
第2节 可问责的四个要求与"自我忠实性"
第3节 逻辑与求解器入门:SAT、DPLL、三值逻辑、SMT、MaxSAT ← 代码 01
第4节 VERDICT:LLM 翻译,求解器决策 ← 代码 02、03、05
第5节 SatIR:把约束投影到数据库,高召回地检索 ← 代码 04
第6节 形式化方法的边界与相关工作
第7–11节 小结、与项目的关系、练习、延伸阅读、下一讲预告
0.4 本讲的玩具世界:虚构的临床试验和病人
代码 trial_world.py 生成一个可以精确评估的玩具版本:
- 一个很小的医学本体:概念之间的上下位关系,例如”局灶性癫痫”是一种”癫痫”,“肺癌”是一种”癌症”。特别设计了一个容易引起歧义的概念:**“控制良好的高血压”**不在”心血管疾病”之下(真实的 SNOMED CT 有几十万个概念)。
- 试验:目标疾病 + 若干条入组 / 排除条件(年龄、诊断、ECOG 体能状态、肌酐、HbA1c、怀孕、HIV、有临床意义的心血管疾病、既往治疗)。有些癌症试验的条件是跨变量的:“ECOG 0–1,或者 70 岁以下 ECOG 2”。每条条件既有自然语言的写法,也有对应的形式化公式。
- 病人:结构化的事实,其中一部分缺失(病历里没写 ECOG、肌酐、HIV 状态……);以及几种不同措辞的病历文字。例如:
试验:Trial T0010 for lung cancer. Inclusion criteria: Age 18 to 65 years; Diagnosis of lung cancer;
ECOG performance status 0-2; Serum creatinine at most 1.5 mg/dL. Exclusion criteria: Clinically
significant cardiovascular disease; Prior treatment with chemotherapy.
病历:A man of 14 years with lung cancer. Previously treated with chemotherapy. ECOG performance status
not reported. Serum creatinine 1.5 mg/dL.
- 决策政策:P1 缺失的值视为”未知”——只要存在一种可能的取值让病人合格,就判为”可能合格”(进入下一步筛查),并把这些取值作为明确的假设列出来;P2 控制良好的高血压不算有临床意义的心血管疾病。标准答案就是在这套政策下,求解器给出的判定。
关于本讲的数字:论文和幻灯片里的真实数字会注明出处;模拟实验的数字都来自 01~04 号代码的实际输出(固定随机种子,每个脚本几秒钟)。模拟的”LLM 匹配器”会犯哪几类错误、犯错的概率多大,都是设定的参数——它展示的是论文描述的那几类问题的机制。05 号代码需要 API 密钥,编写讲义时没有用真实的 API 运行过。
1. 高风险决策:临床试验匹配
1.1 背景
临床试验是循证医学的核心:新药、新疗法要通过临床试验才能证明有效。第 1 讲幻灯片给出了两个数字:登记在案的临床试验超过 50 万个;然而 80% 的临床试验因为招不到足够的病人而失败。另一边,数以百万计的病人可能从某个试验中获益,却不知道它的存在。
把病人和试验匹配起来,难在入组条件:每个试验有一长串纳入条件和排除条件,涉及诊断、分期、化验值、体能状态、既往治疗、合并症、时间窗……医生逐条核对一个病人和一个试验,就要花不少时间;面对几千个试验,人工根本做不完。
1.2 以往的做法与它们的不足
第 1 讲幻灯片总结了以往的最好做法:
- 检索可能合格的试验:基于嵌入的检索。精确率低(返回大量不合格的试验,浪费医生的时间);召回率低(漏掉可能救命的试验)。原因是嵌入衡量的是”话题相关”,把入组条件当成”软信号”而不是必须满足的要求。
- 基于 LLM 的匹配:约 90% 的准确率。但这意味着 10% 的决策仍然是错的。更重要的是:
- 医生要的不只是一个”是 / 否”,他们需要后续诊疗所需的信息;
- 他们需要可问责(accountability)。
1.3 什么是”可问责”
VERDICT 论文的定义是:一个决策可以被检查、被论证、被质疑。LLM 让这件事变得困难:流畅的输出可能没有依据、不完整,或者不忠实于决策过程本身——它说的理由,并不是它实际做出决定的原因。
举个直观的例子:一个 LLM 说”这位病人不符合条件,因为他的 ECOG 评分大于 1”。医生据此去改善病人的体能状态,几周后病人的 ECOG 降到了 0——结果病人还是不符合,因为他还有另一条排除条件。LLM 的理由不完整,误导了医生。
2. 可问责的四个要求
第 1 讲幻灯片用临床试验匹配的例子,列出了可问责的四个要求:
| 要求 | 含义 | LLM 的反例(幻灯片) | 要回答的问题 |
|---|---|---|---|
| 可验证(verified) | 理由经过验证 | LLM:“病人不符合入组条件”(没有可验证的推导) | 判断准吗?能信任它吗? |
| 忠实(faithful) | 明确写出所做的假设 | LLM 默认”控制良好的高血压”满足”无有临床意义的心血管疾病”——这是一个没说出来的假设 | 病历缺了很多数据:它做了错误的假设吗? |
| 一致(consistent) | 遵守决策政策 | 政策规定”缺失的 HIV 状态应保持未知”,LLM 却自行假设 | 歧义需要决策政策:所有病人被平等对待了吗? |
| 可行动(actionable) | 指出关键条件 | LLM:“因为 ECOG > 1 所以不合格”——但即使 ECOG 变成 0,病人也会因为别的条件不合格 | 能保证:采取了这些行动,结论就会翻转吗? |
VERDICT 论文把它们表述为四样东西:经过验证的理由(决策是怎样得出的)、假设(哪些是假设的而不是已知的)、政策一致性(同样的事实得到同样的对待)、关键条件(什么会改变结果)。
论文还提出了一个自动检验:自我忠实性(self-faithfulness)。如果一个系统说”这个决策取决于这几个关键条件”,那么改掉这几个条件,决策就应该改变。这个检验不需要人工标注:构造一个反事实的病人(把关键条件改掉),让系统再判断一次,看结论有没有翻转。
3. 逻辑与求解器入门
VERDICT 的核心想法是”LLM 负责语言理解,定理证明器负责决策”。在看 VERDICT 之前,先弄清楚”定理证明器 / 求解器”到底在做什么。
3.1 命题逻辑:一条规则就是一个公式
规则”18 岁以上,且(有癫痫或偏头痛),且没有怀孕”可以写成公式 ,其中 、、 是三个布尔变量。 个变量有 种取值组合,真值表把每一种都列出来(代码 01 演示 1)——最笨,但绝对正确。
把自然语言的规则写成公式以后,“合格吗?“就变成了”这组取值让公式为真吗?“——一个纯粹的计算问题,任何人用任何程序算,答案都一样。这就是”可验证”的来源。
3.2 可满足性(SAT)与 DPLL
可满足性问题(SAT):给一个公式,问是否存在一组取值让它为真。如果存在,这组取值叫一个模型;如果不存在,公式不可满足。
SAT 求解器通常处理合取范式(CNF):整个公式是若干”子句”的”与”,每个子句是若干”文字”(变量或变量的否定)的”或”。
最朴素的算法是枚举全部 种取值。DPLL 算法(Davis–Putnam–Logemann–Loveland,1962)快得多,关键是单元传播:如果某个子句只剩一个没赋值的文字,这个文字必须为真——不用猜,直接赋值。一次赋值往往引发一连串”被迫”的赋值,矛盾很早就暴露出来,整棵子树都不用搜索。
代码 01 演示 2 用随机 3-SAT(子句数 = 4.26 × 变量数,这个比例附近的问题最难)比较:
| 变量数 | 可满足 | 暴力枚举检查的取值 | DPLL 的搜索节点 |
|---|---|---|---|
| 8 | 是 | 65 | 16 |
| 8 | 否 | 256 | 25 |
| 12 | 是 | 2,382 | 20 |
| 12 | 否 | 4,096 | 60 |
| 16 | 是 | 5,870 | 29 |
| 16 | 否 | 65,536 | 80 |
不可满足时,暴力枚举必须检查全部 种取值;DPLL 只搜索了很小的一部分。SAT 是 NP 完全问题,最坏情况下没有已知的高效算法;但现代求解器(CDCL:在 DPLL 的基础上加入”从冲突中学习”)在实际问题上能处理几百万个变量。
3.3 三值逻辑:“不知道”不等于”假”
病历里常常缺数据。一个变量的取值未知时,公式的值也可能未知。Kleene 三值逻辑的规则:
| 真 | 未知 | 未知 | 真 |
| 假 | 未知 | 假 | 未知 |
| 未知 | 未知 | 未知 | 未知 |
(其余组合和普通逻辑一样。)关键是第二行:只要有一个”假”,“与”的结果就是”假”,不需要知道其他值。代码 01 演示 3 的三个病人(规则:年龄 ≥ 18 且 ECOG ≤ 1 且不是 HIV 阳性):
| 病人 | 三值求值 | 判定 |
|---|---|---|
| 全部已知 | 真 | 合格 |
| HIV 状态未知 | 未知 | 可能合格,前提是假设 HIV 阴性 |
| ECOG = 2,HIV 未知 | 假 | 不合格(ECOG 已经足以判定) |
第二个病人:如果把”未知”当成”假”(默认没有 HIV),就悄悄地做了一个假设;如果当成”真”,就悄悄地把他排除了。三值逻辑让”未知”显式地留下来,求解器再找出”让他合格需要什么假设”——假设被明确地写了出来。这正是”忠实”的要求。
3.4 SMT:SAT + 理论
真实的条件不只有布尔变量,还有”ECOG ≤ 1""肌酐 ≤ 1.5 mg/dL”这样的算术约束。可满足性模理论(Satisfiability Modulo Theories,SMT)= SAT + “理论”:布尔的骨架交给 SAT 求解器,原子条件的含义交给专门的理论求解器(整数和实数的线性算术、位向量、数组、字符串……)。常用的 SMT 求解器有 Z3、cvc5。
代码 01 演示 4 说明了一个直觉:整数有无穷多个,但条件”ECOG 0–1,或者 70 岁以下 ECOG 2”只拿 ECOG 和 1、2 比较,所以只需要试 0、1、2、3 这几个”关键点”——每个点代表一个区间(≤ 1、= 2、≥ 3)。代码 logic.py 的小求解器就是这样为未知的整数变量挑选候选值的。
3.5 不可满足核心与 MaxSAT
两个和”解释”有关的概念:
- 不可满足核心(unsat core):公式不可满足时,找出一个最小的子集——单凭这几条约束就足以不可满足,去掉任何一条就不再不可满足。在匹配问题里,它回答”为什么不合格”:单凭病人的这几条事实,就足以推出不合格。代码里用”逐个删除”算法求最小冲突集:依次尝试把每条事实改成未知,如果仍然不可满足就真的删掉它。
- MaxSAT:把约束分成硬约束(必须满足)和带权重的软约束(尽量满足),求一组取值,在满足所有硬约束的前提下,违反的软约束权重最小。在匹配问题里,把试验条件当硬约束、把病人的每条事实当权重为 1 的软约束,MaxSAT 就回答”最少改变哪几条事实,结论就会翻转”——这就是关键条件。
4. VERDICT:LLM 翻译,求解器决策
4.1 核心想法
第 1 讲幻灯片上 VERDICT 的核心想法图可以这样画:
临床试验 ──┐
├─► LLM(语言理解)──► SMT 约束 ──► SMT + MaxSAT 求解器(决策)──► 可问责的决策
病历 ──┘
分工的依据是第 1 讲的计算思维:
| 部件 | 负责 | 保证什么 |
|---|---|---|
| LLM | 功能:把自然语言翻译成形式化的约束 | 翻译未必 100% 忠实,但它是可解释的——每一条都可以和原文对照 |
| 定理证明器 | 正确性:在约束上做决策 | 相对于 SMT 约束,决策是可证明正确的 |
幻灯片列出了这样做的好处:
- 形式化迫使系统暴露歧义和缺失的值——用自然语言推理时,这些很容易被悄悄带过;
- 是 / 否的决策附带一份推导的证明;
- 假设:所有剩余的约束(未知的变量需要满足什么);
- 对政策的遵守是有保证的;
- 关键条件由 MaxSAT 给出。
4.2 流程的细节
根据论文:
- 试验的形式化:每条条件写成带类型的原子条件(类型:诊断、用药、化验值、时间……;取值范围;文字描述;原文中的位置——用于追溯),条件之间用逻辑连接起来。
- 病人的解析:对每个病人和一套政策,为每个变量生成一条”解析记录”:解析出的值;值的来源——观察到的(来自病历的证据)、由政策补上的(例如”缺失的某项化验视为正常”),或者未解析的(保持未知);支持它的证据;补上它的理由。未解析的条件用一个”未知”值表示。
- 决策:把试验的约束和病人的事实(观察到的、由政策补上的)合在一起交给 SMT 求解器——可满足则合格,不可满足则不合格;求解器的推导过程就是可以验证的理由。可能的话,求解器为未解析的变量找一组让约束可满足的取值——这就是假设。
- 关键条件:把病人的每条事实当作权重为 1 的软约束,试验的约束当作硬约束,用 MaxSMT 求出”最少要改变哪些事实,才能变成合格”;对合格的病人,在加上假设之后,求出”最少改变哪些事实就会不合格”。
- 定理:在 VERDICT 的形式化表示下,如果把一个病例的关键条件翻转,决策也一定会翻转——自我忠实性由构造保证。
4.3 模拟实验:LLM 匹配器 vs VERDICT
代码 02 让两个系统处理 300 个”试验—病人”对(病人都有试验的目标疾病)。
模拟的 LLM 匹配器会犯论文描述的那几类错误:遇到缺失值,这次当作满足、下次当作不满足;对”控制良好的高血压算不算心血管疾病”判断摇摆;条件多时漏看一条;跨变量的条件只看了一半;偶尔判断错一条已知的条件;理由只说出它注意到的第一条不满足的条件。模拟的 VERDICT 只在翻译时出错(每条条件 6% 的概率阈值翻译错、每个数值 4% 的概率读错)。
演示 1:一个病例(就是第 0.4 节的那个 14 岁的肺癌病人)。LLM 匹配器:“不合格,因为年龄 18–65 岁”。VERDICT 的过程:
① 翻译成的公式:
Age 18 to 65 years ⇒ (age ≥ 18 AND age ≤ 65)
Diagnosis of lung cancer ⇒ dx:lung cancer
ECOG performance status 0-2 ⇒ ecog ≤ 2
Serum creatinine at most 1.5 mg/dL ⇒ creatinine ≤ 18 ← 翻译错了!
Clinically significant cardiovascular disease ⇒ NOT (dx:cardiovascular disease)
Prior treatment with chemotherapy ⇒ NOT (prior:chemotherapy)
翻译核对:Serum creatinine at most 1.5 mg/dL:翻译成了 creatinine ≤ 18,应为 creatinine ≤ 15
② 抽取的事实:age=14, creatinine=15, ecog=None(病历里没写), prior:chemotherapy=True, ...
③ 判定:不合格
不满足的条件:年龄、既往化疗
最小冲突集:['prior:chemotherapy']
关键条件:age 14 → 18,且 prior:chemotherapy True → False
这个例子很能说明问题:
- VERDICT 也会出错——肌酐的阈值被翻译错了。但错误摆在那里,可以逐条核对出来(这里恰好不影响判定)。LLM 匹配器的错误藏在它的”推理”里,看不见。
- 有两条条件不满足:最小冲突集只需要其中一条就足以推出不合格;而关键条件是两处都要改。LLM 匹配器只说了”年龄”——如果医生以为等病人满 18 岁就行,就被误导了。
- ECOG 没写,保持”未知”,没有被悄悄当成满足或不满足。
演示 2:准确率
| 方法 | 准确率 | F1(合格) |
|---|---|---|
| LLM 匹配器 | 80.3% | 0.720 |
| VERDICT | 98.7% | 0.985 |
LLM 匹配器判错的 59 个病例里,各类错误出现的次数:缺失值没有按政策处理 35 次;判断错了一条已知条件 20 次;把控制良好的高血压当成心血管疾病 8 次;漏看了一条条件 1 次。
演示 3:政策一致性。同一个病人换三种写法(顺序、措辞、缺失值的说法不同),三次判定完全相同的比例:LLM 匹配器 68.7%,VERDICT 99.0%。只看”决定取决于政策”的病例:
| 病例 | LLM 匹配器 | VERDICT |
|---|---|---|
| 有缺失值且缺失值会影响判定(75 例) | 46.7% | 97.3% |
| 病人只有控制良好的高血压,试验排除心血管疾病(36 例) | 63.9% | 100.0% |
LLM 匹配器每次遇到缺失值、遇到含糊的概念,都重新”决定”一次怎么办——同样的病人,可能得到不同的对待。VERDICT 把政策写成公式的一部分,求解器每次都严格执行(剩下的少数不一致来自偶尔读错数值)。
演示 4:自我忠实性。对每个”不合格”的判定,按系统自己给出的关键条件构造反事实的病人,再判定一次:
| 方法 | 翻转的比例 |
|---|---|
| LLM 匹配器(改掉它说的那条理由) | 111/219(50.7%) |
| VERDICT(改掉 MaxSAT 算出的关键条件) | 163/170(95.9%) |
一个没有翻转的例子:LLM 说不合格是因为年龄,把年龄改成满足以后,病人仍然不合格——他还有”用过胰岛素""有临床意义的心血管疾病”两条不满足。VERDICT 不到 100% 的部分来自”读病历”:反事实的病历被重新读了一遍,读错数值的位置可能不同。形式化保证的是”从公式到决策”这一段;“从文字到公式”这一段仍然要靠翻译的质量。
4.4 可问责的理由(代码 03)
不合格的病人:例如一位 79 岁、患 1 型糖尿病和未控制的高血压、用过胰岛素的病人,申请一个糖尿病试验。三条条件不满足(年龄、用过胰岛素、心血管疾病);最小冲突集是 ['prior:insulin']——单凭这一条就足以判定不合格;关键条件却是三处都要改(年龄 79 → 65、心血管疾病、胰岛素)。有些关键条件是改不了的(年龄),有些可以改变(停用某种药、等化验指标好转)——把它们列出来,由医生判断哪些现实可行。
可能合格的病人:例如一位 29 岁、局灶性癫痫、病历里没有肌酐和 HIV 检测记录的病人,申请一个癫痫试验。判定”可能合格”,假设是”肌酐正常、HIV 阴性”;而”任何一条单独改变(或者记录有误)就会让他不合格”的事实里,属于假设、需要优先核实的是肌酐和 HIV。“可能合格”不是”合格”:把假设写出来,医生就知道下一步要做哪些检查。
假设的汇总:300 个病例里,130 个可能合格,其中 75 个依赖至少一条假设;最常被假设的信息是肌酐(41 次)、HIV(28 次)、ECOG(21 次)。对一家医院来说,这说明哪些信息最常缺失、最影响入组判断——“可行动”在系统层面的意义。
可调的决策政策:
| 处理缺失值的政策 | 合格的病例数 |
|---|---|
| 可能合格(存在一种取值让他合格就算) | 130 |
| 必定合格(不管缺失的值是什么都合格才算) | 55 |
| 必须有 HIV 检测记录(HIV 缺失按阳性处理) | 102 |
从”可能合格”换成”必定合格”,判定改变的 75 个病例全部是依赖假设的那些;换成”必须有 HIV 检测记录”,改变的 28 个全部是试验排除 HIV、而病历里没有检测记录的病人(代码用断言保证了这两句话)。用哪种政策是人的决定(医院、试验方、伦理委员会):筛查阶段可能倾向”可能合格”(不漏掉人),正式入组前必须”必定合格”。政策写成公式的一部分以后,换政策就是换一行规则,所有病人按同一个规则一起改变——这就是幻灯片说的”可引导、且公平”(steerable and fair)。
4.5 论文的结果
以下数字来自 VERDICT 论文和第 1 讲幻灯片:
- 准确率:在从 SIGIR 2016 派生的数据集上,VERDICT 的 F1 是 0.900(用 GPT-4.1 翻译)、0.836(GPT-4o)、0.754(GPT-4o-mini),在所有系统中最高;在 TREC 2021 上,F1 是 0.828(GPT-5-mini)、0.800(Claude Haiku 4.5)、0.738(Qwen2.5-7B),比神经符号的基线 DLSC 高 0.10~0.27。幻灯片报告经过蒸馏的 Qwen2.5-7B 在 TREC 2021 上达到 0.830。同一个系统,用不同的 LLM 翻译,F1 相差很大:翻译的质量就是系统的天花板。
- 政策一致性:用自然语言逐条应用政策的基线(LlmMatch、ZSPM),只在约 71%~81% 的病例上遵循了政策;VERDICT 由构造保证完全一致。
- 自我忠实性(关键条件翻转后决策翻转的比例):VERDICT 为 100%(由构造保证);最强的基线只有 65.0%;LLM 匹配器 LlmMatch 为 48.9%,即使明确要求它列出”变成合格需要哪些改变”,也只提高到 57.7%;ZSPM 为 26.6%。
- 医生研究:在两两比较中,VERDICT 对 ZSPM 的胜率(平局按半场计)是 90.6%(16 次比较赢 13 次、平 3 次),对 LlmMatch 是 75.0%(赢 11、平 2、输 3);在可验证性、忠实性、一致性、可行动性四个维度上,医生给 VERDICT 的评分都高于 LLM。
5. SatIR:把约束投影到数据库
5.1 检索也要讲约束
VERDICT 判断”一个病人 × 一个试验”。但要从几十万个试验里找出一个病人可能符合的那些,逐对运行 SMT 求解器的代价太高(第 1 讲幻灯片:“对所有的配对都用 SMT 匹配,成本太高”)。以往的检索方法(关键词、嵌入相似度)又把入组条件当成软信号。SatIR 论文的第一句话点出了问题的本质:很多真实的检索问题需要的不只是话题相关——候选必须满足某个具体的人的约束,而不只是和他相关。
5.2 方法
- 借助已有的医学本体(SNOMED CT),用 LLM 把非形式化的推理——关于歧义、隐含的临床假设、不完整的病历——转换成明确、精确、可控、可解释的 SMT 约束。
- 离线:把每个试验的条件解析、转换成试验一侧的约束,存进数据库。
- 在线:把每个新病人的病历解析成病人一侧的约束;一个数据库查询执行器同时评估两边,检索出满足匹配目标的候选试验,并解释每个试验为什么被检索到或没有被检索到。
- 投影:为了规模和效率,把 SMT 匹配问题投影到关系代数上,用数据库实现——保留高召回,只牺牲一点精确率。
为什么投影能保留召回率?可以这样理解:数据库的一行只能存”每个变量的上下限""每种排除条件的开关”这样的简单约束;复杂的跨变量逻辑放不进去,只能放宽(取最宽松的情况)。放宽只会让数据库多返回一些试验,绝不会漏掉合格的试验——召回率不降,精确率略降;多返回的那些,再交给 VERDICT 逐条验证。
5.3 模拟实验
代码 04 生成 3600 个试验和 50 个病人(每个病人平均有 218.9 个可能合格的试验,标准答案由求解器逐对算出)。
投影(演示 1):一个肺癌试验投影成数据库的一行:age_min=40, age_max=80, ecog_max=2, creat_max=15, excl_preg=1, excl_hiv=1, relaxed=1——“ECOG 0–1,或者 70 岁以下 ECOG 2”被放宽成了 ECOG ≤ 2。一个病人变成一条 SQL 查询:
SELECT tid FROM trials
WHERE target IN (:t0, :t1, ...) -- 病人的诊断,按本体展开成所有上位概念
AND :age BETWEEN age_min AND age_max
AND (ecog_max IS NULL OR :ecog IS NULL OR :ecog <= ecog_max) -- 试验没要求 / 病人未知 / 满足
AND (creat_max IS NULL OR :creat IS NULL OR :creat <= creat_max)
AND NOT (excl_hiv = 1 AND COALESCE(:hiv, 0) = 1) -- 未知的 HIV 状态不排除(政策 P1)
AND ...
比较(演示 2):
| 方法 | 召回率 | 精确率 | 返回个数 | 每个病人(毫秒) |
|---|---|---|---|---|
| BM25(病历全文),前 100 | 31.0% | 27.8% | 100.0 | 4.0 |
| 关键词检索(诊断),前 100 | 38.4% | 52.6% | 92.0 | 0.4 |
| BM25(病历全文),前 400 | 58.8% | 26.1% | 400.0 | 4.0 |
| 关键词检索(诊断),前 400 | 81.0% | 48.9% | 350.3 | 0.5 |
| SatIR(数据库投影) | 100.0% | 100.0% | 218.9 | 0.2 |
| SatIR + 逐条验证(VERDICT) | 100.0% | 100.0% | 218.9 | 2.6 |
| (对照)逐对求解全部试验 | 100.0% | 100.0% | 218.9 | 24.3 |
- BM25 和关键词检索衡量的是”话题相关”:返回的大多是讲同一种病的试验,但不管年龄、化验、排除条件,精确率很低;要提高召回率只能多返回——医生要看的也越多。
- SatIR 把约束当作必须满足的要求:召回率 100%,返回的个数和标准答案一样。
- 放宽的代价是集中的。这 50 个病人里,没有一个恰好落在被放宽的区域里,所以精确率也是 100%。但专门构造一个 75 岁、ECOG 2 的肺癌病人:SatIR 返回 330 个试验,其中 191 个在逐条验证时被剔除——对这个病人,精确率只有 42%。“平均只牺牲一点精确率”不等于”对每个病人都只牺牲一点”——所以检索之后还要逐条验证。
- 速度:在这个玩具世界里逐对求解也不算慢;真实系统里逐对运行 SMT 求解器(加上本体推理)要贵得多,这才是投影的动机。
本体的作用(演示 3):用本体把病人的诊断展开成所有上位概念,召回率 100%;只用病人的具体诊断,召回率降到 68.7%——目标写成”癫痫""癌症”的试验,对”局灶性癫痫""肺癌”的病人全部漏掉。
5.4 SQL 也是三值逻辑:NULL 的陷阱
代码 04 演示 4 是一个值得记住的教训。在 SQL 里,NULL(未知)参与比较的结果是”未知”;NOT(未知) 还是”未知”;而 WHERE 子句把”未知”当成不满足,过滤掉这一行——和第 3.3 节的 Kleene 三值逻辑一模一样。
| 排除条件的写法 | 召回率 |
|---|---|
NOT (excl_hiv = 1 AND COALESCE(:hiv, 0) = 1) | 100.0% |
NOT (excl_hiv = 1 AND :hiv = 1) | 87.1% |
第二种写法看起来没错,却让所有”HIV 状态未知”的病人被所有排除 HIV 的试验悄悄过滤掉了:它实际执行的政策是”未知就当作阳性”,和规定的”缺失值保持未知”不一致。用 COALESCE(“如果是 NULL 就取 0”)显式地写出政策,结果才对。形式化的好处是政策写在明处;但写错了,形式化系统也会一丝不苟地执行错误的政策——翻译出的约束和查询本身也要核对。
5.5 论文的结果
据 SatIR 论文:在 SIGIR 2016 数据集和一个从 TREC 2022 派生的基准上,SatIR 都稳定地优于基于相似度的基线。和基于相似度的检索相比,SatIR 在 SIGIR 2016 上每个病人多检索到 32%72% 的”相关且合格”的试验,在 TREC 基准上合格试验的召回率是它们的 1.83.2 倍(幻灯片上对比的是 BM25 和 TrialGPT)。检索很快:在 SIGIR 的 3,621 个试验上,每个病人只需 146 毫秒(幻灯片上写的是 0.15 秒)。研究组和梅奥诊所(Mayo Clinic)合作,把 SatIR(检索)和 VERDICT(判定)组合成了一个临床试验匹配系统,代码开源在 github.com/stanford-oval/clinical-trial-matching。
6. 形式化方法的边界与相关工作
6.1 边界
- 翻译的质量是天花板。求解器只保证”从公式到决策”是对的;“从文字到公式”仍然靠 LLM。VERDICT 用不同的 LLM 翻译,F1 从 0.738 到 0.900 不等。好在翻译错误是可以逐条核对的(代码 02 演示 1 自动发现了一个阈值翻译错误),而且可以针对翻译这个小任务专门改进(例如蒸馏)。
- 本体的覆盖面。上下位关系、同义词、隐含的临床知识(“控制良好的高血压不算有临床意义的心血管疾病”)都要靠本体和政策写清楚。本体没覆盖到的概念,形式化系统同样会出错。
- 政策是人的决定。系统能保证政策被一致地执行,但”该用哪套政策”不是技术问题。
- 表达能力与成本。真实的入组条件涉及时间(“过去 6 个月内”)、剂量、序列、不确定的表述;形式化越完整,求解越贵——这正是 SatIR 要投影、VERDICT 只用于最终验证的原因。
- 形式化系统也会一丝不苟地执行错误(第 5.4 节的 NULL 陷阱)。
6.2 相关工作(课程阅读清单)
- SatLM(Ye 等 2024):把自然语言问题翻译成 SAT 公式,交给定理证明器求解。
- Logic-LM(Pan 等 2023):用符号求解器增强 LLM,实现忠实的逻辑推理。
- Lang2LTL(Liu 等 2022):把自然语言命令翻译成时序逻辑(LTL)规格,用于机器人。
它们和 VERDICT 共享同一个模式:LLM 负责翻译,求解器负责推理。项目页还列出了把这种可问责性推广到其他领域的方向:医学里的罕见病诊断和指南遵循、金融里的治理合规。
7. 本讲小结
- 高风险决策不只要准确,还要可问责:可以被检查、被论证、被质疑。四个要求:可验证(理由经过验证)、忠实(明确写出假设)、一致(遵守决策政策)、可行动(指出关键条件)。自我忠实性提供了一个自动检验:改掉关键条件,决策应该翻转。
- 求解器的基础:SAT 问”是否存在让公式为真的取值”;DPLL 靠单元传播剪枝;三值逻辑让”未知”显式地留下来;SMT = SAT + 理论;不可满足核心回答”为什么不合格”,MaxSAT 回答”最少改变什么就会翻转”。
- VERDICT:LLM 只负责把试验、病历、政策翻译成 SMT;求解器做决策,并推导出证据、假设、关键条件。政策一致性和自我忠实性由构造保证;翻译的质量是天花板,但翻译错误是看得见、可核对的。
- SatIR:把约束投影到关系代数,用数据库查询高召回地检索;借助本体处理上下位关系;放宽只牺牲一点精确率(但代价集中在少数病人身上),检索之后再逐条验证。
- 形式化让政策写在明处,也会一丝不苟地执行写错的政策:SQL 的 NULL 也是三值逻辑。
8. 与项目的关系
- 项目页把 VERDICT 推广到其他领域列为技术驱动的项目方向:罕见病诊断、指南遵循、金融治理合规。思考你的领域里:决策规则能不能写成约束?哪些部分需要 LLM 翻译?决策政策由谁制定?
- 第 4 讲的方法论适用于任何高风险决策:先问”可问责”需要什么(证据、假设、一致性、关键条件),再设计系统让这些东西由构造保证,而不是指望 LLM 自己说对。
- 评估时别忘了自我忠实性这类不需要人工标注的自动检验,以及一致性检验(同样的事实换种写法)。
9. 练习
练习 1(三值逻辑)。规则:(年龄 ≥ 18) ∧ (ECOG ≤ 1 ∨ 肌酐 ≤ 1.5) ∧ ¬怀孕。对下面三个病人,写出三值求值的结果;如果是”未知”,写出让他合格所需的假设。 (a) 年龄 30,ECOG 2,肌酐未知,怀孕未知;(b) 年龄 30,ECOG 0,肌酐 2.0,怀孕 = 是;(c) 年龄 16,其余全部未知。
参考答案
(a) 未知。ECOG ≤ 1 为假,所以”或”取决于肌酐;怀孕也未知。可能合格,假设:肌酐 ≤ 1.5 且没有怀孕。 (b) 假。怀孕 = 是,排除条件成立(“与”里有一个假就是假)。 (c) 假。年龄 < 18 已经足以判定,其他未知的值无关紧要。
练习 2(不可满足核心 vs 关键条件)。一个试验要求:年龄 18–65、ECOG ≤ 1、未用过化疗。病人:70 岁、ECOG 2、用过化疗。 (a) 有几个大小为 1 的最小冲突集? (b) 关键条件(变成合格最少要改几处)是什么? (c) 如果一个系统只回答”因为 ECOG > 1 所以不合格”,它违反了可问责的哪个要求?
参考答案
(a) 三个:{年龄}、{ECOG}、{化疗}——任何一条单独都足以推出不合格。(“逐个删除”算法只返回其中一个,取决于删除的顺序。) (b) 三处都要改:年龄 ≤ 65、ECOG ≤ 1、未用过化疗。其中年龄改不了——这位病人实际上不可能入组这个试验,这也是有用的信息。 (c) 可行动:它没有保证”采取行动后结论会翻转”——即使 ECOG 降到 1 也没用。同时也不够忠实(没说出全部原因)。
练习 3(政策)。为什么说”缺失值怎么处理”是一个政策问题,而不是一个技术问题?举一个例子说明,在筛查阶段和正式入组阶段,合适的政策为什么不一样。
参考思路
缺失值没有”正确”的处理方式:当作满足,可能让不合格的病人进入试验(安全风险);当作不满足,可能让合格的病人错过治疗(机会成本)。这是在两种错误之间权衡,需要医院、试验方、伦理委员会根据风险来定。筛查阶段的目的是”不漏掉”,可以用”可能合格”并列出假设,让医生补做检查;正式入组前必须”必定合格”,所有关键信息都要有记录。系统能做的是:把政策写清楚,并保证对所有病人一致地执行(代码 03 演示 4)。
练习 4(自我忠实性)。设计一个自动检验,判断一个”贷款审批”系统给出的拒绝理由是否忠实。需要什么?可能有什么困难?
参考思路
对每个被拒绝的申请,取系统给出的关键条件(例如”收入低于 X""负债率高于 Y”),构造一个反事实的申请(把这些条件改成满足),让系统再判断一次,统计翻转的比例。困难:(1) 反事实要现实(改收入时,负债率等相关变量也许要一起变);(2) 系统可能是随机的,要多次运行;(3) 理由可能是含糊的文字,先要把它解析成具体的条件——这本身是一个翻译任务;(4) 还要检查”一致性”:同样条件的申请人是否得到同样的对待(公平)。
练习 5(投影)。一个试验的条件是”肌酐 ≤ 1.5,除非病人正在透析”。
(a) 写出它的公式。
(b) 如果数据库表只有一列 creat_max,怎样投影才能保证召回率不降?代价是什么?
参考答案
(a) (肌酐 ≤ 15) ∨ 透析(用代码里 ×10 的单位)。
(b) 放宽:creat_max = NULL(不限制肌酐),或者加一个标记列 creat_unless_dialysis,查询时写 (creat_max IS NULL OR :creat <= creat_max OR (creat_unless_dialysis = 1 AND :dialysis = 1))。前者最简单,代价是肌酐高、又不透析的病人也会被返回(精确率下降),需要后续逐条验证;后者更精确,但表结构更复杂。这正是 SatIR”保留召回、牺牲一点精确率”的取舍。
练习 6(动手改代码)。在 02_verdict.py 里,把 Verdict 的 p_translate 从 0.06 调到 0.2,重新运行演示 2 和演示 3。VERDICT 的准确率和一致性分别怎样变化?为什么一致性几乎不受影响?
参考思路
实测:VERDICT 的准确率从 98.7% 降到 96.0%(F1 从 0.985 降到 0.953),三种写法下判定一致的比例仍是 99.0%。准确率下降是因为翻译错误更多了;而一致性不受影响,是因为翻译错误由试验决定(代码里翻译用的随机数只由试验编号决定:同一个试验总是被同样地翻译),换一种病历写法并不会改变公式;只有”读病历”那一步受写法影响。这说明:形式化系统的错误是系统性的、可复现的——错就错得一致,便于发现和修正;而 LLM 匹配器的不一致是随机的。(注意:“政策遵循率”会下降——缺失值那一组从 97.3% 降到 96.0%,高血压那一组从 100% 降到 94.4%——因为它衡量的是判定和政策规定的结果是否一致,翻译错了,结果自然就错了;但”错得一致”。)
练习 7(动手改代码)。在 04_satir_retrieval.py 的 project 里,把跨变量的 ECOG 条件改成投影为 ecog_max = 1(取最严格的分支,而不是最宽松的),重新运行演示 2。召回率和精确率怎样变化?这说明了什么?
参考思路
实测:SatIR 的召回率从 100% 降到 98.2%(平均返回 211.6 个,标准答案 218.9 个),加上逐条验证仍是 98.2%——70 岁以下、ECOG 2 的病人本来合格,却被数据库过滤掉了,后续的逐条验证无法挽回,因为它们根本没有被检索出来。精确率呢?这 50 个病人本来就是 100%;那个构造的 75 岁、ECOG 2 的病人,返回的个数从 330 降到 139,一个都不用剔除——收紧换来的精确率,恰恰集中在被放宽的区域。检索阶段宁可放宽(多返回、后面再剔除),不能收紧(漏掉就永远找不回来)。
10. 延伸阅读
本讲的核心论文
- Zhou, Jin, Xu, Wang, Chao, Lam. Accountable AI with Grounded, Faithful, Consistent, Actionable Rationales: A Case Study in Clinical Trial Matching with VERDICT. EMNLP 2026. arXiv 2609.03366.
- Zhou, Jin, Xu, Wang, Chao, Lam. SatIR: Scalable High-Recall Constraint-Satisfaction-Based Information Retrieval for Clinical Trials Matching. COLM 2026. arXiv 2604.08849.
- 代码:github.com/stanford-oval/clinical-trial-matching;在线演示:satir.genie.stanford.edu
LLM + 符号求解器(课程阅读清单)
- Ye 等. SatLM: Satisfiability-Aided Language Models Using Declarative Prompting. NeurIPS 2023.
- Pan 等. Logic-LM: Empowering Large Language Models with Symbolic Solvers for Faithful Logical Reasoning. Findings of EMNLP 2023.
- Liu 等. Lang2LTL: Translating Natural Language Commands to Temporal Specification with Large Language Models. 2022–2023.
求解器
- de Moura & Bjørner. Z3: An Efficient SMT Solver. TACAS 2008.
- Davis, Logemann, Loveland. A Machine Program for Theorem-Proving. Communications of the ACM 1962.(DPLL)
11. 下一讲预告
第 1 讲介绍了 WikiChat 的 7 个阶段。第 5 讲把它拆开来细看,回答几个本讲没有涉及的问题:
- 早期的知识对话系统(BlenderBot-3、Atlas)在众包评估里得分很高,为什么在真实的长尾话题上一塌糊涂?“事实性”之外,对话还需要哪些指标?
- 为什么说 LLM 带来了 NLP 研究方法的”范式转变”——不再”建数据集、训练、测试”,而是”设计指标、用关键例子调试、系统地评估”?
- 每个阶段在细节上要解决什么问题:时间(“今年”是哪一年?)、声明的去语境化、“部分正确”的声明、什么时候该说”我不知道”?
- 怎样评估一个不幻觉的聊天机器人:模拟用户、头部 / 长尾 / 新近话题、LLM 评委与人工核查;以及怎样检测语料库内部的不一致。