> 发现自带的"修法"和"理由"是一份可测的规格——而逃生门实现之后,它的召回率是新问题
一条检查报告通常有三部分:结论(哪里有问题)、理由(为什么这是问题)、 修法(怎么办,常常还给一个"或者……"的替代路径)。 后两部分是写给人看的散文,所以没人测它们。它们是规格,而且不需要任何语料就能测。
// TABLE_OF_CONTENTS
结论先行¶
一条检查报告通常有三部分:结论(哪里有问题)、理由(为什么这是问题)、 修法(怎么办,常常还给一个"或者……"的替代路径)。 后两部分是写给人看的散文,所以没人测它们。它们是规格,而且不需要任何语料就能测。
两个方向,都很便宜:
① 照修法做一遍,看发现是否消失。 三条现场回报,三次做完了而警报没走:
| 修法原文 | 作者做了 | 结果 |
|---|---|---|
| "或者在 caption 里说明为什么没有要标的赢家" | caption 改成 "Nothing is marked best: the table records what each arm is shown, not how it scores" | 仍然报 |
| 术语检查要求"解释这个词" | two deterministic trace pipelines (…) 改成 two deterministic NETWORK-INTRUSION trace pipelines (…) |
四条 STOPS 一条没掉 |
| 重述检测,"按文档里的修法改完" | 用破折号和括号各写了一遍意译 | 仍报"只标记了一次然后用了 8 次" |
做完了警报还在,作者得到的结论不是"我改得不对",而是"这个工具不可信"—— 或者更糟,把那句诚实的 caption 删掉,因为它既没用又占行。
② 把理由句当谓词去读,看实现是否更宽。 摘要里的行内数学检查,理由写的是
"摘要里的记号是还没有指称的符号,每一个都是非专家停下来的地方"——
而它当时会在 $+32.1$pp、$+23.1$pp 上触发。那些是数字,不是符号。
理由句已经把正确的谓词写出来了,实现没照着做。
为什么¶
这两条都已经被修了,而修法本身就是最好的例证。
行内数学那条的修补直接从理由句抄来,连注释都写成了理由的复述:
# $+0.3$ to $+1.8$ nats is a number that happens to be typeset in math mode.
# Notation is what costs the reader: a symbol with no referent yet.
inline_math = len([m for m in re.finditer(r"(?<!\\)\$([^$]+)\$", text)
if not re.fullmatch(r"[\s\d.,+\-%$()\\]*|...", m.group(1).strip())])
理由句是现成的规格。它已经写好了,而且通常比实现更准确—— 因为写理由的时候人在想问题,写正则的时候人在想字符串。
caption 那条也实现了。但这里有一层只有做了测量才看得到的东西: 逃生门装好之后,它的召回率成了新的缺陷面。现在的判据是 "否定词 + 0–3 个词 + 六个名词之一":
cap_explains = re.search(r"(?i)(no|nothing|not)\s+(?:\w+\s+){0,3}"
r"(best|winner|marked|bold|highlighted|declared)", inner)
我把同一个意思写了八种,拿它过了一遍:
| caption | 结果 |
|---|---|
| Nothing is marked best: … | ✅ 开门 |
| No column has a winner. | ✅ 开门 |
| The table records what each arm is shown, not how it scores. | ❌ 仍然报 |
| We deliberately leave the winner unmarked. | ❌ 仍然报 |
| There is nothing to rank here; the rows are configurations, not results. | ❌ 仍然报 |
| Bolding is omitted on purpose: no arm is a baseline. | ❌ 仍然报 |
| Nothing wins; this is an inventory. | ❌ 仍然报 |
| This table is descriptive rather than comparative. | ❌ 仍然报 |
八种写法,两种开门。 修法的原话是"在 caption 里说明为什么"—— 那是一句邀请人去写句子的话,而实现接受的是一个短语族。 对剩下六种写法的作者来说,体验和逃生门不存在时一模一样:做了工作,警报还在。
逃生门的召回率低,后果比普通假阳性重:它的受害者恰好是听话的那些人。 不理警报的人不受影响;照着修法做了的人被罚一次,而且他唯一的反馈是"没用"。
怎么用¶
- 每条发现写完之后,照自己的修法做一遍,确认它真的会消失。这是一个测试用例, 和"这条发现会在坏例子上触发"同等重要——对抗夹具测的是前者,几乎没人测后者。
- 把理由句当谓词去读。 理由比实现窄的地方就是假阳性的位置, 而这个对比不需要语料、不需要跑工具,读两行就行。
- 逃生门装好之后,把同一个意思写五到八遍去过它。几分钟的事, 直接给出"听话的作者里有多大比例仍然被罚"。
- 逃生门宁可宽:它的假阴性是"少报一条本该报的",它的假阳性是 "惩罚一个照做了的人"。这两者的代价不对称(同类的代价不对称, 见 会产生"指控"的工具,误报代价不对称——先归一化再开口)。
- 更一般的:一条规则只写在提示/文档里而不在代码里执行,就只是个请求, 见 只活在 prompt 里的规则,会在模型状态不好的那一周失效——而那正是它最该生效的一周; "写了指令不等于指令被核对"见 指令写进 prompt 不等于它生效了——加一道"引文必须在原文里"的机械核验。
出处¶
~/Tools/nonexpert-review:三条"照修法做了但警报仍在"的现场回报在 feedback/;
行内数学的理由与修后实现、caption 逃生门的正则,都在 nonexpert_review.py 当前版本里。
八种 caption 写法的测试是我这次跑的。