Day 54 Hard Human-AI Failure Visibility Verification Cost Reviewer Design

Fail Obviously — 给 AI 工作流做失效可见性设计Designing Failure Visibility into AI Workflows: The Hardest Irony of Automation

问题场景 + 需求约束

你在给一个 AI 代码生成平台做架构:每天 5000 个 LLM 补丁进流水线,人类工程师是最后一道闸。你把「明显能自动化的」都交给了 AI——补丁、单测草稿、changelog——留给人的是最难自动化的那一小撮:判断这段流畅的代码到底对不对。上线三个月指标很好看:AI 采纳率 82%、人均审查从 12 分钟降到 3 分钟。然后一个静默 bug 溜过终审进了生产:AI 把 balance -= amount 写成 balance += amount,注释、命名、测试全都自洽,reviewer 3 分钟扫过点了 approve。

这不是 reviewer 不认真,是 Lisanne Bainbridge 1983 年《Ironies of Automation》的处方在 LLM 时代变成了最难一条:你自动化了简单的 95%,把人留在监控席——可人正因不再动手而技能退化,而 LLM 的错误不像传统软件那样大声崩溃,而是「错得流畅」、不主动自曝。监控一个安静的、几乎总是对的系统,恰是人类最不擅长的任务。

核心命题:在 AI 工作流里,终审人能不能抓住错误,几乎不取决于他多聪明多认真,而取决于三件可被设计的东西——错误有多明显(失效可见性)、核验一个输出有多贵(核验成本)、真错误有多稀有(底率,Day 51)。你要设计的不是「更强的 AI」,而是一个让 AI 失效自己跳出来、并给终审席配一条比重做便宜得多的核对路径的系统

约束:吞吐 5000/天、每个终审预算 < 5 分钟、真 bug 底率约 3%、漏检率压到生产事故预算内。设计目标是固定人力下最大化「有效抓取率」,而非让 AI 少犯错(它一定会犯)。

高层架构(生成 → 可见性层 → oracle → 分诊 → 终审)

graph LR
    G["AI 生成器
LLM 补丁/agent"] V["失效可见性层
结构化断言 / 自检 / diff 高亮"] O["独立 oracle
编译·测试·参照路径"] T["分诊层
按 风险 × 未验证度 排序"] H["终审席
人类最后一道闸"] G --> V V --> O O --> T T --> H H -->|校准反馈 + 注入已知错例| G

职责失效可见性层要求 AI 输出的不只是补丁,还有可被机器核验的结构化断言(「不改变对外契约」「余额单调递减」);独立 oracle(承 Day 52 差分正确性 oracle)用与生成路径无关的手段——编译、跑测试、跟参照实现比对——去证伪断言,把「静默错结果」变成「被标红的断言未通过」;分诊层(承 Day 51)按风险与残余不确定性排序,只把值得看的推给终审;终审席是 slow-loop 最后闸,靠注入错例保持手感。关键:可见性和 oracle 在人之前,不是在人之后。

关键技术点

1. 为什么「错得流畅」是最难的失效模式 — 传统软件 fail loud,LLM fail fluent

【原理】传统软件的失效响亮:空指针抛异常、类型不匹配编译不过、断言失败进程崩溃——错误自带信号,"fail fast" 是几十年攒下的哲学。LLM 相反:语法永远合法、命名永远合理、解释永远自洽,它把「不知道」和「知道」渲染成同一种流畅的自信。人脑对流畅性有根深蒂固的信任偏差(fluency = truth heuristic),于是最危险的不是 AI 犯错,而是它自信且流畅地犯错。叠加 Bainbridge 悖论:终审人因长期只点 approve 而技能退化,恰好在最需要他的那 3% 上最弱。

Trade-off:三种应对。(a) 让 AI 更准——底率从 3% 压到 1%,但绝对量还在、且 reviewer 更松懈(越准越不看);(b) 让人更努力——加审查时长,与 5000/天吞吐冲突、且违反 Bainbridge(疲劳监控是人类最差的任务);(c) 让失效可见——不改准确率,把错误从「流畅隐藏」变成「结构化自曝」。只有 (c) 随吞吐线性扩展,工程重心应压在这里。
现实案例:Bainbridge《Ironies of Automation》(Automatica, 1983) 早在核电与航空就指出:自动化越好,留给人的越是「小概率但致命」的干预,人越没机会练习。2018–19 737 MAX MCAS 事故复盘反复回到这条:系统安静地做错事、飞行员来不及建立心智模型。LLM 工作流是同一悖论的软件版。

2. 失效可见性工程 — 结构化断言 / 可执行自检 / 差异高亮,让错误自曝

【原理】核心动作:把 AI 输出从「自然语言 + 代码」升级为「代码 + 一组可独立核验的断言」。断言必须机器可判定(能编译、能跑、能 diff),而非「我认为对」的自然语言自评。再用一条与生成路径独立的 oracle 去证伪它——关键在独立:让同一个 LLM 自评,失效是相关的(correlated failure),生成错了自评往往同样错,等于没查(承 Day 51)。可见性 = 让错误在到达人眼前就已被标红。

sequenceDiagram
    participant AI as LLM 生成器
    participant SC as 自检(同模型)
    participant OR as 独立 oracle
    participant H as 终审席
    AI->>SC: "我检查过了,没问题"
    Note over SC: 相关失效:自评与生成同源同错
    AI->>OR: 补丁 + 结构化断言
    OR->>OR: 编译 / 跑测试 / 参照路径比对
    OR-->>H: 断言#3 未通过 ⚠️ 红色高亮
    Note over H: 只看被标红的 1 处
核验成本骤降
# pseudo-code:让 AI 输出可核验断言,独立 oracle 证伪
patch, claims = llm_generate(task)
#   claims = [
#     Assertion(kind="tests_pass",   spec="pytest tests/billing"),
#     Assertion(kind="invariant",    spec="balance monotonic non-increasing"),
#     Assertion(kind="no_api_change",spec="public signatures unchanged"),
#   ]
flags = []
for c in claims:
    verdict = independent_oracle.check(c, patch)   # 编译/测试/AST diff/参照跑
    if verdict.status != PASS:
        flags.append(highlight(c, verdict.evidence))  # 定位到具体行 + 反例
# 只有带 flag 的、或高风险且断言覆盖不足的,才进人类队列
route_to_human(patch, flags, coverage=assertion_coverage(claims, patch))
Trade-off:LLM 自检——零基建,但相关失效使有效性存疑;独立 oracle(编译/测试/参照实现)——能抓真错,但只覆盖「可判定」属性,语义意图仍需人;形式化断言(类型/契约/property test)——最强保证,但写断言有成本、覆盖面窄。务实组合:可判定属性交给 oracle 自动标红,语义意图留给人,人只看 oracle 没覆盖的残余
现实案例:Meta 的 SapFix 用自动测试作 oracle,AI 生成的修复必须先过可执行核验再给人;Google 的大规模自动化改动(Rosie)强制 presubmit 测试 + 结构化 diff 才进 code review;差分 oracle 思路见 Day 52。共同点:人看到的每个输出,都已被一条独立路径审过一遍。

3. 核验成本工程 — 解释只在真降核验成本时才降过度依赖(Vasconcelos/Zhang 边界)

【原理】直觉是「让 AI 多解释、人就能更好判断」——错。Vasconcelos 等 (CSCW 2023) 用成本-收益框架证明:人是否真去核验,取决于核验成本 vs 采纳收益的权衡;解释只有真正降低了「核验这个输出对不对」的成本时才减少过度依赖,若只是又一段流畅叙述,反而提高流畅性信任、加重过度依赖。Zhang 等 (FAT* 2020) 补上另一半:置信度/解释能否改善判断,取决于人能否据此校准信任、区分该信与不该信。所以目标不是「多给信息」,而是给终审席一条比自己重做便宜得多、且直接指向对错的核验路径

Trade-off:给自然语言解释——成本低,但常常只增流畅信任、不降核验成本(Vasconcelos 的 null 效应多源于此);给可执行核验(反例、失败测试、参照输出 diff)——真降核验成本,但需要 oracle 基建;给 diff 高亮 + 定位——把「读全文找错」变成「看被标红的 3 行」,性价比最高。判据:一条辅助信息若不能让「核验」变得比「重做」便宜,它就是在制造过度依赖而非减少。
# 核验成本的直观模型:终审席的理性行为
# 人会核验 ⟺  C_verify < benefit_of_catching_error
#          ⟺  C_verify < base_rate × cost_of_miss
# 降低漏检有两条杠杆:
#   1) 抬右边:把高后果项排到前面(分诊按 风险 排序)
#   2) 压左边:C_verify ↓  ← 失效可见性层的全部意义
# 反直觉:解释若只加长阅读,C_verify ↑,理性的人反而更少核验
现实案例:代码补全类工具的经验:并排 diff + inline 测试结果比大段 rationale 更能让人抓错;Day 50「Code Review 当信号检测」讲的降噪层(nitpick 过滤、注意力留给高信号项)本质就是核验成本工程——reviewer 注意力是稀缺资源,每条低价值提示都在抬高真错误的核验成本。

4. 终审席位设计四参数 — 底率 · 核验成本 · 练习剂量 · 失效可见性

【原理】把终审席当可调系统,其有效抓取率由四个参数决定,缺一个都塌:

参数含义调节手段不管它的后果
底率 (base rate)真错误频率分诊排序、高风险前置过低 → 长期只见对的,警惕性崩塌(Day 51)
核验成本核对一个输出多贵oracle 标红、diff 定位、反例过高 → 理性的人直接采纳(Vasconcelos)
练习剂量保持判断力的手感注入错例、轮岗动手、校准题为零 → 技能退化,关键时刻抓不住(Bainbridge)
失效可见性错误自曝的程度结构化断言、独立 oracle、高亮为零 → 错得流畅全部溜过

练习剂量最反直觉、最常被砍:一个几乎总是对的系统会让人失去练习机会,于是要主动注入已知错例(seeded faults / calibration items),像混沌工程给人类注入故障——既维持警惕性,又量出终审席的真实抓取率。呼应 Day 44 与 Day 51。

Trade-off:注入错例 降低通过效率(人多花时间在假错上)却 买到可观测的抓取率和不退化的技能——「先护栏后规模」(Day 41)在人机协同上的翻版。不注入 = 省眼前成本、赌上尾部事故。
现实案例:航空模拟机的定期 recurrent training 是给飞行员「注入错例、维持手感」的制度化版本;TSA 安检的 TIP(Threat Image Projection)往 X 光流里随机插入虚拟危险品图像,正是「底率过低时人工插高底率练习信号」——AI 终审席可照搬。

扩展与优化

演进方向:(1) 断言覆盖率驱动——把「哪些属性有独立 oracle 覆盖、哪些只能靠人」做成指标,优先给高后果模块补 oracle;(2) 分级终审——低风险高覆盖走轻量抽检,高后果低覆盖走双人复核(bulkhead,Day 23);(3) 校准闭环——用注入错例的抓取率反哺分诊阈值,抓取率下滑就自动收紧;(4) 可见性下沉到生成端——AI 生成时即产出可核验断言与自证据。瓶颈通常不在 AI 准确率,而在oracle 覆盖面终审席注意力预算——这两者才是要花钱扩的地方。

常见陷阱 + 面试问题

面试追问:① 怎么量一个「人类终审席」当前的漏检率?(注入错例测抓取率)② 底率从 3% 降到 0.3%,设计要改哪?(可见性与练习剂量加码,纯靠人更不可靠)③ 为什么让 AI 多写解释有时更危险?④ 独立 oracle 覆盖不到语义意图时剩下怎么办?⑤ 这套设计和 Day 41「把人移出快回路」矛盾吗?(不——快回路止血靠自动化,慢回路正确性终审保住人并给他可见性)

深入资源

深入思考(点击展开答案)

底率从 3% 降到 0.3%,为什么「靠更认真的人」是错误答案?

这是 Day 51 基率谬误在人机协同的直接后果。底率越低,连续「对的」样本越长,警惕性衰减(vigilance decrement)越严重——人监控极稀有信号本就差,几百个 approve 之后碰到第一个真错,心智已默认「都是对的」;同时真错变少 = 手感更差。所以底率下降同时恶化了可见性依赖、警惕性和练习剂量三条。正确做法:把省下的确定性预算投到失效可见性(更多 oracle 标红)和练习剂量(注入错例,把「人感知到的底率」抬回可工作区间,像 TSA 的 TIP)。反直觉结论:你要人为地让终审席「多看到错」,哪怕那些错是你埋的。

为什么「让 AI 生成更详细的解释」有时会让漏检率上升?

Vasconcelos 的成本-收益框架:人是否真去核验,取决于「核验成本 vs 采纳收益」。解释若降低了核验成本(如「改了 X 行、可能影响 Y 契约、这里是反例测试」),过度依赖下降。但若只是又一段流畅自洽的叙述,它做两件坏事:(1) 没降核验成本(读它还花时间);(2) 抬高流畅性信任(fluency heuristic)。净效果是理性的人核验更少、漏检上升。判据很干脆:一条辅助信息若不能让「核验对错」比「自己重做」更便宜,它就是在制造过度依赖。可执行反例 > diff 高亮 > 结构化断言 > 自然语言 rationale。

同一个 LLM 做生成又做自检,失效为什么「相关」?数量上意味着什么?

独立性是 oracle 有效的前提。若生成器和检查器是同一模型(或同族、同数据、同 prompt),错误高度相关:模型生成时把 += 当成 -=,自检时同样的语义盲点会让它确认「对的」。数量上:设单次错误率 p,两次独立则漏检率 ≈ p²(3% → 0.09%);但相关系数接近 1 时漏检率 ≈ p(几乎没改善,还烧一倍算力制造「已核验」假象)。这正是 Day 51「Argus 消融证明器 0/20 vs LLM 自任裁判 20/20」的机理。所以 oracle 必须走独立路径:编译器、真实测试、参照实现,或至少不同模型/信息源的交叉验证。独立性决定 oracle 是真查还是自我安慰。

这套「保住人类终审席」的设计,和 Day 41「把人移出快回路」矛盾吗?

不矛盾,它们管两个回路。快回路(止血):故障时毫秒级的自动检测、熔断、回滚——人太慢,必须移出交给自动化(Day 41 Knight Capital 教训)。慢回路(正确性终审):判断一个 AI 补丁的语义意图对不对,不需要毫秒级,需要判断力和可见性——这里人是最后一道价值闸,要保住并给他弹药。混淆两者会犯双向错误:把慢回路判断塞进快回路(人来不及),或把快回路止血交给人(Bainbridge:人连建立心智模型的时间都没有)。正确架构是快回路全自动 + 慢回路人在环且高可见性。判据:瓶颈是速度还是正确性判断?速度归自动化,判断留人并降其核验成本。

如果给你固定人力,你会先投「更强 oracle」还是「更好分诊」?怎么判断?

用有效抓取率的分解判断:≈ (进入人类队列的真错比例) × (人对队列内真错的抓取率)。若队列里真错太少(底率被稀释)→ 投分诊,按「风险 × 未验证度」把高信号前置。若真错进了队列人却没抓住(可见性差、核验成本高)→ 投 oracle 和 diff 高亮。注入错例的 A/B 就能量出是哪种:埋一批已知错例,看它们(a)有没有进人类队列(分诊问题),(b)进了有没有被抓(可见性/成本问题),先补漏在前面的那一环。早期常两个都缺,但 oracle 边际收益更陡——它同时降核验成本、又反哺分诊,一份投入两处受益。