置信度門控與升級到人
上一篇說的是「閾值由程式碼持有」。這一篇說的是那個閾值分出來的三段 該怎麼用。
三檔,而不是兩檔
真實專案極少把決策做成「自動 / 不自動」。常見的是三檔:
| 檔位 | 條件 | 動作 |
|---|---|---|
| 自動 | 置信度高於上閾 且 通過附加檢查 | 直接執行 |
| 升級 | 落在中間帶 | 交給人 |
| 丟棄 | 置信度低於下閾 | 不執行,也不佔用人的注意力 |
第三檔容易被忽略,但它是三檔裡最省錢的一檔。「不看」和「讓人看一眼」的成本差著 一個人力。
一個告警分流器的實現很典型: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 的效率門會把整個流程卡死。
判據不是「哪個更安全」,而是錯殺的代價和漏放的代價哪個更大。 而且這個取向要在寫程式碼時想清楚,因為它決定的是異常分支, 不是主路徑。
一句話
三檔結構裡,工作量在中間那一條上:它的寬度是成本,它的兜底是可靠性。 兩樣都要顯式設計,不能靠預設值。