文件導航

程式碼持有閾值,模型只給機率

如果把幾百個真實專案放在一起看,最穩定的一條共同點是:

模型只負責回答「有多可能」,程式碼負責回答「夠了沒有」。

這不是風格偏好。它是從模型自報的置信度不可信這個事實裡推出來的唯一穩妥做法 —— 而這一點在置信度到底可不可信那篇裡有獨立的實測證據。

具體長什麼樣

Choice 與 Score 返回答案時附帶一個 confidence,Noul 直接返回 0 到 1 的機率。 介面本身不替你做任何判斷,閾值是你的。真實專案裡這句話落實成了很具體的形態:

  • 一個跑在 Cloudflare Worker 上的髒話過濾器,閾值、max() 的聚合策略、以及 對外的 OpenAPI schema 全都寫在 Worker 程式碼裡,模型只是其中一個被呼叫的函式。
  • 一個瀏覽器擴充套件用它判斷評論是否要遮起來,擴充套件自己釘著 0.85 / 0.7 / 0.5 三檔, 並且檢查失敗時保持遮住(寧可多遮,不可漏遮)—— 這也是閾值策略的一部分。
  • 一個工單告警分流器把「要 page」定義成 P(SEV1) + P(SEV2) ≥ 0.80, 這個 0.80 寫在它自己的配置裡,不在模型裡。

三者的共同點是同一個:換模型時閾值不動,換閾值時模型不動。 把閾值交給模型去「決定」的話,這兩件事就綁在一起了 —— 而你要調閾值的時候, 會發現自己在改一個提示詞。

為什麼這條原則這麼重要

因為它把兩種失敗分開了:

  • 模型回答得不好 —— 去改問題、改 state、換模型。
  • 閾值定得不好 —— 去改程式碼裡那個數。

混在一起之後,一個「準確率不夠」的問題既可能是模型的問題也可能是閾值的問題, 而你沒有任何辦法把它們分開。上一條的告警分流器之所以敢把 0.80 直接寫進配置, 正是因為那個數可以被單獨拿出來復盤、單獨拿出來調。

反例:置信度不總是它看起來的那個東西

這條原則有一個必須知道的前提:你拿到的那個數,未必是校準過的機率。

有獨立復算發現,Score 題返回的 confidence 經常正好等於分數的小數部分, 而且這類輸出高度集中(在 121 個這樣的輸出裡)。這不是「模型很自信」, 更像這個欄位是從分數本身推匯出來的一個值。

區別很大:

  • 如果它是校準過的機率,那麼 0.85 可以用在「85% 的情況下我會是對的」這種推理裡。
  • 如果它是分數的函式,那麼 0.85 只表示「這一題得了高分」,和「我有多大機率對」 沒有關係 —— 拿它去定閾值,是在給一個沒有機率含義的數設門檻。

同樣地,有一篇獨立的測量報告直接去核對模型自報的欄位與真值是否相符, 結論是那些欄位的取值遠沒有描述裡寫的那麼細(詳見公開質疑)。

怎麼辦

實踐裡的做法可以歸納成三步,而且順序不能反:

  1. 先用閾值做事,別信它的含義。 0.8 這個數是不是「80% 正確」不重要 —— 重要的是在你的資料上,0.8 以上的那些是不是明顯更準。這是可以用留出集驗的。
  2. 用你自己的標註擬合閾值。 有工具專門做這件事:拿你自己的標註資料, 為每個問題擬合出「達到目標準確率所需的閾值」,用留出集驗證, 並且當模型更新破壞了已鎖定的閾值時讓 CI 失敗。
  3. 把閾值鎖進程式碼,並給它一個複核日期。 閾值會隨著模型版本過期 —— 和價格一樣,是要有人定期回頭看的東西,不是一次定終身。

一句話

模型的可信度應該體現在你的閾值上,而不是體現在它的自報數字上。 你可以在自己的資料上度量前者,沒法度量後者。