跳到主要内容

ADR-018 — 真算切片 LLM 输出抖动鲁棒性强制验收

§0 决策简述

决议:凡引入或修改「LLM 真算」输出解析的切片(真算切片:把确定性 stub / 占位换成真实 LLM 产出并解析进 schema 的工程,如 MCA / s1 / posterior,以及未来任何同类),必须满足 §3 五条强制验收项才算完成。其中两条是硬门:(a) 离线 fake 必须注入真实格式抖动样本,仅含规范 JSON 的离线全绿不构成验收;(b) 合并 / 送外部评测前必须跑真 provider live 烟测

本 ADR 是 SVA-9(ADR-012)L2/L5 在「真实输入分布鲁棒性」维上的补强,retroactively 由 R7 回归修复(FinBayes 217af19)满足。

§1 触发:R7 P0 回归(M1.5 真算 21/21 零输出)

M1.5 三块真算(MCA/s1/posterior)离线 125 测试全绿,但 FinTecEval R7 用真实 gpt-5.5 评测21/21 题全部零输出(同一 harness 入口在 M0 的 R4/R5/R6 全过 → 回归坐实在 M1.5)。双独立确认根因(FinTecEval 代码判读 + Codex 只读评审):

  • MCA(致命 20/21):gpt-5.5 返回 "L3 散户或量化高敏感"(裸码 + 自然语言注解),_axis_levelint(value[-1]) 取中文末字符抛 ValueError,且未纳入重试/主循环的 except单点解析失败击穿整条认知链
  • s1(live 续暴露)falsification_ref 返回 dict、backtrigger 返回单 dict、s1_mode 返回单 str —— parser 的 setdefault 只管「字段缺失」不管「字段在但类型错」→ pydantic 类型校验崩。

元根因(比单 bug 更重要):离线 fake/stub 全部返回开发者手写的"理想规范 JSON",与真实 LLM 输出分布有系统性偏差——真 LLM 的格式抖动(枚举带注解、list 字段返回单 object、optional 返回 object 而非 string-or-null、大小写/空白噪声)是常态而非异常。离线全绿因此对真算切片不具备验收效力

§2 理由(第一性原理)

  • 真算 = 把确定性产出换成概率性自然语言产出。确定性 stub 的输出空间是单点;真 LLM 的输出空间是一个带长尾的分布。把"schema 合法"当验收,只覆盖了分布的众数附近,长尾抖动必然在生产/评测暴露。
  • fake 是开发者的"自我应答",天然偏向自己设计的规范形态,无法代表真实分布——这是结构性盲点,不是写得不够仔细。
  • 单点解析失败击穿全链 = 脆性架构。认知链由多个 LLM 解析阶段串联,任一阶段对单字段抖动零容忍,则整链可用性 = 各阶段可用性之积,在真实分布下迅速塌为零。
  • 稳健 > 完美:宁可诚实降级到"未评估"并产出可用骨架,不可因单字段抖动零输出。但降级必须诚实可识别,不得退化为假填常量(否则违反 M1.5 内核「真值随输入变化、非常量」与评测边界)。

§3 强制验收项(真算切片 done 的充要清单)

任何真算切片(新增或修改 LLM 真算字段解析)完成前,逐条满足

  1. 抖动 fixture 强制:离线 fake/stub 对每个真算字段至少注入 1 个真实抖动样本(枚举带自然语言注解 / list 字段返回单 object / optional 返回 object 而非 string|null / 大小写与空白噪声等),并有断言「抖动样本经归一化 / coerce 后校验通过」。仅含规范 JSON 的离线全绿不构成验收。
  2. 容错解析:解析层对真算字段做归一化 / 类型 coerce(提取裸码、单值包成 list、object→紧凑串等),不假设 LLM 返回规范形态。
  3. 单点不击穿 + 诚实降级:任一字段解析失败不得零输出整条认知链;每个真算阶段 = 容错解析 + 重试 + 诚实降级兜底。降级输出必须可被下游 / 评测识别为「未评估 / 降级」(显式 tag 如 *-degraded、或空值 + 置信度 0),绝不伪装成真实结果常量(违反 = 假填回归)。
  4. 异常类型纪律(F-2026-06-01-a 后扩展)任何因处理 raw LLM 结构(解析 / 归一化 / 哈希 / 去重 / 成员判断)而抛的异常,都必须在该阶段的消费边界被捕获并路由到 重试 / 诚实降级——不仅是解析失败,也包括 TypeError(如 list 进 set/in {}/dict 键)/ KeyError / AttributeError。实现上:阶段边界 except 应覆盖 (CognitionSynthesisError, ValidationError, TypeError, KeyError, AttributeError)(即 _LLM_STRUCTURE_EXCEPTIONS)。但编程契约校验(如 max_attempts < 1、明确内部 bug)须留在 try 之外、继续直接暴露,不得被吞。理由:F-2026-06-01-a(C2 间歇 TypeError: unhashable type: 'list')证明——只为"解析失败/ValueError"补击穿不够,同一架构缺陷(裸异常击穿 retry/degrade)会在任何 raw-LLM 处理点复发;通则必须覆盖处理全程,而非只覆盖 parse。
  5. 真 provider live 烟测 = 合并 / 送评前硬门:离线测试不可替代真实 LLM 验证。真算切片合并入 main 或触发外部评测前,必须跑真 provider live 烟测覆盖代表性 task_type,确认非零输出 + 走真实(非降级)路径。降级触发率应≈0。

主控(Claude)独立 verify 真算切片时,§3 是 checklist;Codex 工单的「验收测试」节须显式包含第 1、3 条;主控负责执行第 5 条 live 烟测(凭据走 keychain,密钥不落盘)。

§3.6 R7' 补强(抖动覆盖面 + live 烟测必含 held-out 式新格式)

R7' 暴露:s1 修复在 R7 已见格式上全绿(4 题 live 烟测 + 离线),但 held-out 上 8/11 降级——抖动 coerce 只做到「顶层字段存在性 + 顶层类型」是不够的。实证两类更深抖动:① 语义类型错位coupling_strength 返回定性词 "weak" 而非 float);② 嵌套对象缺必填子字段backtrigger 元素缺 reason)。据此补强 §3:

  • §3.1 的"抖动 fixture"须多样化/对抗化,至少覆盖:(a) 枚举带自然语言注解;(b) 集合字段返回单 object;(c) 数值字段返回定性词/数字串;(d) 嵌套对象缺必填子字段;(e) optional 返回 object 而非 string|null。仅 1 个样本或只覆盖 (a)(b) 不足。
  • §3.5 的 live 烟测必须含 held-out 式新格式题(不能只跑开发者熟悉的题面)——R7' 证明"已见格式 live 全绿"会漏掉过拟合;主控烟测应取评测会话风格的、自己没调过的新题。
  • 容错解析须到"语义类型 + 嵌套必填"深度:数值字段定性词→有损归一化(带映射表注释);嵌套元素缺必填→显式占位或丢弃(不杜撰内容、保留模型真给的信号)。
  • retroactively:s1 held-out 鲁棒化(FinBayes fix/m1_5-s1-heldout-robustness,主控记录型 provider 探针诊断)按本节执行。

§4 影响(下位同步)

  • m1_5 engineering-pack:加「工程纪律:真算切片鲁棒性(ADR-018)」指针节。
  • 未来真算切片工单模板:必须内含 §3 五条作为验收项(尤其抖动 fixture + live 烟测)。
  • SVA-9(ADR-012):本 ADR 补强 L2(contract test 扩到真实分布抖动)+ L5(D 维评测须含 live);不新增防御层,只把既有层的覆盖面从"schema 合法"扩到"真实分布鲁棒"。
  • 不溯及非真算切片:纯确定性状态化 / 文档 / 编排切片不受 §3 第 1、5 条约束(无 LLM 真算解析面)。

§5 现状

  • R7 回归修复已满足本 ADR(FinBayes 916e599 + merge 217af19):MCA/s1 容错解析 + 双诚实降级 + 抖动 fixture(注解 MCA 轴值 / 单 dict backtrigger)+ 主控真 gpt-5.5 live 烟测 4 题全绿。
  • ⏳ R7' 复跑将独立验证修复在 21 题全集上的有效性(同 21 题纵向可比)。