[CODE]

教驗證器相信一個百分比——還有當它沒辦法相信時,該怎麼放行

每份週報新增的轉換漏斗四層健檢、差點把它擋掉的反幻覺驗證器,以及為什麼一份無法驗證的報告現在會寄給維護者、而不是讓整條流程直接崩潰。

1 min read AI 生成
typescript llm analytics ci ga4

民宿自動報告裡的每一個數字,都得能追回系統真正抓到的某個值。這條規則存在的理由很簡單:語言模型在寫分析文字的時候,只要有機會,就會生出一個看起來乾乾淨淨的統計數字。這條流程裡的驗證器會掃過產出的報告、把每個數字抓出來,跟一份從 GA4 和訂房資料整理出來的可信值清單對照。只要某個數字找不到來源,整份報告就被退回、重新產生。

那套機制本身我在另一篇寫過——〈A Digital Operations Stack for Hengchun B&Bs〉——這裡不重講。這篇講的是:當我在報告裡塞進一個新的必填段落之後,哪裡壞了,以及修它的過程逼出來的兩個決定。第一個決定是怎麼讓驗證器相信一個它從沒直接看過的百分比。第二個決定是當一份報告真的沒辦法通過驗證時,該發生什麼事。

一個以前不存在的段落

週報原本已經回答了「誰來了網站」跟「廣告有沒有把人帶進來」。它沒做的,是把這兩件事接成一個業主可以從頭讀到尾的診斷:來的人裡面,有多少真的看進去了?看進去的人裡面,又有多少採取了聯絡動作?我加了一個固定的四層漏斗健檢——流量結構(新客對回訪客)、參與深度(有效 session 佔總 session)、各事件轉換率、以及聯絡意圖率——並把它定成報告必須包含的段落。少了它,報告就 fail。

聯絡意圖率需要它自己的定義。原始的轉換事件清單裡有些東西其實不算聯絡:booking_click 是興趣、不是真的傳了訊息;facebook_click 訊號比較弱;點 Google 評價是在做功課。所以我切出一個可設定的子集——電話、LINE、WeChat 的按鍵點擊——當作「這個訪客真的去找了業主」的分子,並讓每家民宿能在自己的設定檔裡覆寫。這個區分很重要:整個漏斗的意義就是要把「看過」的人和「動了」的人分開,把點評價頁混進電話裡,會悄悄地把行動率灌水。

驗證器把它自己要的百分比退回來了

有趣的地方來了。漏斗比率是用三位小數的 float 存的——0.8470.632——在前一個階段就算好,所以模型完全不用做算術。報告把它們寫成百分比:「參與率 63.2%」。合理。但驗證器的可信值清單裡放的是 0.632,不是 63.2。從它的角度看,63.2% 是一個沒有來源的數字——一個孤兒——於是它把整份報告擋了下來。

最直覺的修法,是逼報告把算式攤出來:每個百分比都寫成「有效 142 ÷ 225 = 63.2%」,讓驗證器能對上分子分母。我原本就有這條規則,而它是錯的。它把給業主看的報告推向滿是算式的雜訊——一份要給還在用紙本記帳的人看的文件,括號裡塞滿原始 session 數。這些報告的整個設計目標,就是讀的人不該需要算數學、也不該需要去核對數學。

所以我改成教驗證器去理解那層關係。當它掃資料、遇到一個大約落在 0.01 到 1 之間的 float,它現在會把這個值的 ×100 取整形式也一起塞進可信集。0.632 進清單,63.2 也跟著進。那個百分比不再是孤兒,因為驗證器懂了:一個比率和它的百分比,是同一個事實穿了兩套衣服。這是個很小的改動——掃描函式裡三行——但它把負擔搬到對的地方。報告維持乾淨;驗證器則對「什麼叫同一個數字」變聰明了。

邊界很重要。低於 0.01,×100 的形式會跟正常的小整數撞在一起;剛好等於 1.0,那是個沒必要這樣處理的退化 100%。把它嚴格限制在開區間內,可以避免讓那些會讓真正捏造的數字溜過去的值污染可信集。

當驗證沒辦法通過的時候

第二個決定比較難。在這之前,當驗證器用完它的重試次數——在最大重繪嘗試之後還是沒辦法把報告對齊——整條流程就以非零碼結束。那家民宿那一週的報告,就單純不存在。對一個跨多家民宿、每週無人值守跑 cron 的系統來說,這是個很糟的失敗方式:一個頑固的孤兒數字,就能讓一家民宿整份報告憑空消失,而我第一個察覺的方式,是它的缺席。

我把它改成 fail open。當驗證用盡,這次執行不再直接死。它把報告標成 flagged,從上一次的失敗快照裡讀出剩下的孤兒數字和術語細節,並在報告最上面加一條橫幅,明確列出哪些數字無法溯源。報告還是會被產出來。

但一份被標記的報告,絕對不能送到業主面前。一份含有可能捏造數字、又沒通過驗證的報告,比沒報告更糟——它侵蝕的,正是整套系統賴以運轉的那件事:業主能夠相信眼前的東西、不用自己去查。所以路由也跟著改。寄信那一步現在會讀執行摘要、偵測到 flagged 狀態,把寄送對象限縮到只有維護者。業主什麼都看不到;我看到的,是一份帶著警告橫幅、明確告訴我該去查什麼的報告。

這個拆分——把產物做出來、隔離它、送給能修它的人——就是「對自身瑕疵有韌性的流程」和「脆弱的流程」之間的差別。崩潰只給我一個 stack trace 和一份消失的報告。一份被標記的報告,給我的是實際內容、那些具體無法溯源的數字、外加一個保證:客戶從來沒看到它。

這一切到底為什麼存在

這些沒有一樣是誰開口要的功能。業主要的只有一件事:用我聽得懂的話,告訴我花在廣告上的錢有沒有在運作。漏斗健檢、驗證器、信任延伸、fail-open 路由——這些是把語言模型寫的分析文字,做到「可信到能據此行動」所需要的鷹架:每週一次、跨一整批小生意、迴圈裡沒有任何分析師。

對一家民宿來說,請一個工程師、加一個分析師、再加一個每週把它打包成白話的人,這筆帳從來就划不來——成本比這門生意能說服自己的數字高了一個量級。這件事之所以做得起來,是因為現在多接一家民宿進流程的邊際成本已經趨近於零,而驗證器,正是讓這個規模化變得安全的東西。沒有它,自動產出的分析文字就是個負債,而且每多接一家民宿,它就複利累積一次。

讓驗證器相信一個它只見過小數形式的百分比那天,我同時也讓它不再跟那些本來就正確的報告吵架。