置信度门控与升级到人
上一篇说的是「阈值由代码持有」。这一篇说的是那个阈值分出来的三段 该怎么用。
三档,而不是两档
真实项目极少把决策做成「自动 / 不自动」。常见的是三档:
| 档位 | 条件 | 动作 |
|---|---|---|
| 自动 | 置信度高于上阈 且 通过附加检查 | 直接执行 |
| 升级 | 落在中间带 | 交给人 |
| 丢弃 | 置信度低于下阈 | 不执行,也不占用人的注意力 |
第三档容易被忽略,但它是三档里最省钱的一档。「不看」和「让人看一眼」的成本差着 一个人力。
一个告警分流器的实现很典型:P(SEV1) + P(SEV2) ≥ 0.80 才 page;
只有在「可操作性」这一项也不同意时才在小于 0.20 时丢弃;中间带交给人。
中间带才是真问题
三档结构一画出来,问题就全跑到中间那一条了:
它是人力资源,不是闲置容量。 中间带越宽,被升级的越多,人处理的越多。 一个 9% 的升级率听起来很低,但当基数是一天几千条时就不是了。
它需要一个兜底,否则会被静默拖死。 把决定交给人之后, 如果没有人来看,这件事就永远停在那里 —— 而这在监控面板上看起来和 「一切正常」一模一样。上面那个分流器给出的解法很硬: 人 15 分钟不 ack,照样 page。 宁可吵醒人,也不能让一条 P1 卡在待办里。
升级条件本身也会失效。 一个在 agent 里用的自主度门控是
「Choice 高于 0.6 且自主安全 Noul 高于 0.5 才继续」,否则把回合还给人类。
两个数都要过 —— 因为「我该做什么」和「这件事安全吗」是两个独立的问题,
用一个置信度同时回答它们会把风险藏起来。
阈值怎么定:先量,再定
拍一个 0.8 出来是最常见的做法,也是最容易在三个月后变成噪音的做法。 可复算的做法是:在你自己标注的数据上,量出「达到目标准确率需要多高的阈值」。
一个公开的例子:以 0.7 作低置信门槛,在 n=130 的样本上以 9% 的升级率 抓住了 3 组误判中的全部 3 组。样本很小 —— 它的价值不在于那个 0.7, 而在于说明了该这样报数:说出样本量、升级率和抓到的东西, 而不是只报「提升了准确率」。
延迟是这条链路里被低估的风险
上面那个告警分流器的实测数字值得单独看:
| 指标 | 值 |
|---|---|
| p50 | 418 ms |
| p95 | 1477 ms |
| 成本 | 约 $0.04 / 千条 |
| 最慢一次 | 距它自己设的 2 秒超时只差 151 ms |
p95 是 p50 的 3.5 倍。也就是说尾部的延迟比平均值重要得多 —— 因为超时策略会在尾部触发,而超时策略一旦触发,走的是兜底分支, 不是你以为的那个分支。最慢一次距超时只差 151 ms,说明这个系统的 「确定性」很大程度上取决于一个刚好没被触发。
门控系统的失败方式因此常常不是判断错了,而是超时了,然后走了兜底。 兜底分支要单独测,不能只测主路径。
两个兜底方向,各有各的场合
出错时该怎么办,公开的做法分成两派,而且都对:
- fail-closed(出错就拒绝):一个权限判定器在超时或报错时直接 deny。 安全门就该这样 —— 一个 fail-open 的安全门是一个静默的洞。
- fail-open(出错就放行):一个 Claude Code 的 Stop hook 在任何错误时放行。 效率门就该这样 —— 一个 fail-closed 的效率门会把整个流程卡死。
判据不是「哪个更安全」,而是错杀的代价和漏放的代价哪个更大。 而且这个取向要在写代码时想清楚,因为它决定的是异常分支, 不是主路径。
一句话
三档结构里,工作量在中间那一条上:它的宽度是成本,它的兜底是可靠性。 两样都要显式设计,不能靠默认值。