27 個公式都過了,為什麼還是不能交付?
上週看到一個很典型的案例:一份表格宣稱通過 27 個公式檢查,匯入 Google Sheets 之後卻還是損壞。有人會把它歸類成格式小問題,我不會。這其實是在提醒大家,AI 產出的驗證邊界畫錯了。
模型答對 27 題,跟交付一份下游系統可以安全消費的 artifact,是兩件不同的事。前者測的是答案看起來對不對,後者測的是它進入真實 consumer 之後,整條流程能不能維持契約。小店不需要一個很會做 demo 的 AI 工具,小店需要的是月底結帳不會把資料弄爛的工具。
我以前做過對帳和付款相關的 backend。那時候最常見的事故,不是核心計算公式寫錯,而是輸出在邊界上出了問題,例如欄位名稱被改了、日期時區被轉掉、空值被寫成字串,或同一批資料重跑兩次後產生重複紀錄。單看產出 JSON 的 unit test,全部都是綠燈。接到 Google Sheets、資料庫和報表服務,才發現每一層對「有效」的定義不一樣。
所以我現在看 AI 工具,會把 artifact validation 拆成五層。
第一層是 schema。欄位、型別、必要性、允許值都要明確。不要只驗證「有 12 個欄位」,還要驗證欄位順序是否被 consumer 依賴,日期是不是 RFC 3339,金額是不是 decimal 而不是浮點數,空白欄位是 null 還是空字串。Google Sheets 很寬容,寬容到會把看似合法的內容自動轉型。00123 可能變成 123,2026-10-03 可能依照試算表 locale 顯示成另一種日期。寬容不是相容性,很多事故就是這樣開始的。
第二層是引用完整性。表格裡的 customer_id、invoice_id、工作表名稱和外部連結,都要能在下游找到對應對象。AI 很容易產生格式正確但不存在的 ID,也容易在複製範本時留下上一個客戶的引用。測試不能只比對欄位值長得像不像,應該拿測試資料庫做 foreign key lookup,確認每一個引用都存在,而且沒有跨租戶。
第三層是 idempotency。相同輸入送兩次,結果應該是同一份結果,或至少第二次不會重複寫入。這點對小店特別重要,因為很多自動化會靠排程、人工重試和 webhook 重送維持運作。
我會要求每個 AI workflow 都帶一個穩定的 run_id 和業務層 idempotency_key,寫入時用唯一索引保護,而不是在 prompt 裡提醒模型「請勿重複」。prompt 不是交易鎖。曾經有一個匯入流程,模型產出的資料完全正確,但 API timeout 後工作者重試,結果同一張發票寫進去兩次。監控看到的只是兩次成功 HTTP response,財務月底才看到金額翻倍。
第四層是 replay。你能不能拿同一份原始輸入,在隔離環境重播,得到可比較的結果?AI 有非決定性,不能迷信每次文字完全相同,但 schema、引用集合、筆數、金額總和和副作用數量必須符合可接受範圍。輸出最好保留原始輸入、模型版本、prompt 版本、工具呼叫紀錄和驗證結果。沒有這些,出了事故只能說「當時 AI 好像這樣回答」,那不叫可維運。
第五層是失敗恢復。驗證失敗時,系統要停在哪裡,哪些副作用已經發生,能否 rollback,人工修正後能不能從中間階段繼續?把檔案產出到一半、建立了部分資料列,最後才發現一個欄位錯誤,這時候顯示紅色錯誤訊息沒有用。要有 staging、commit 和補償策略。對 Google Sheets 這類不一定支援完整交易的 consumer,我會先寫入暫存工作表,完成檢查後再 publish,並且保留上一版快照。
團隊要落地,其實可以先寫一份很無聊但很有用的驗收契約。我通常會要求至少包含這些欄位:
- Input fixture,固定一組正常資料、空值資料、亂序資料和重複資料。
- Output schema,逐欄寫型別、格式、nullable 規則和版本。
- Consumer test,真的呼叫 Google Sheets API、下游 API 或 migration,不接受只測中間 JSON。
- Invariant,列數、金額總和、主鍵唯一性、foreign key 完整性等不可違反的條件。
- Retry test,同一個
idempotency_key重送 3 次,副作用仍只能有 1 次。 - Replay test,使用保存的輸入和工具回應重播,確認結果可追溯。
- Recovery test,在第 N 個步驟故意 timeout 或斷線,確認能恢復、重試或安全停機。
測試階段也不要一次全壓在最後。我會分成四道門。先做內容檢查,確認模型抽取和計算邏輯符合規則。接著做 a
rtifact 檢查,把產出交給真正 consumer,檢查 schema 和引用。再做流程檢查,測重試、重跑、併發和部分失敗。最後才是小流量 shadow 或人工核准。每道門都要有明確的 fail closed 行為,不能驗證失敗後還自動發布。
有人會覺得這樣太重,小店哪有時間做完整測試。我的看法是,測試不需要一開始就做成大型平台,但契約不能省。拿一個 20 筆資料的 fixture,加上一次真實 API 測試,通常已經能抓到很多「模型答對、匯入損壞」的問題。真正昂貴的是沒有測試,讓老闆在結帳日手動找出 3000 筆資料中哪一列被轉型。
還有一個常被忽略的點:驗收標準必須由 consumer 的擁有者定義。做報表的人、維護資料庫的人、負責 CI 的人,看到的風險不同。AI 工具供應商說通過 27 個公式檢查,只能證明它通過那 27 個檢查,不能替你的資料管線背書。把分數當 SLA,是採購上最危險的偷換。
我對「AI 工具能不能交付」的最低判斷很簡單。把它放到真實 consumer,餵一組包含空值、重複、亂序和邊界日期的資料,故意讓一次網路呼叫失敗,再完整重跑一次。如果團隊說不清楚哪裡會停、怎麼恢復、重跑會不會重複,就先別急著用,看看 benchmark 以外的驗收結果再說。
27 個公式全數通過,卻在 Google Sheets 裡損壞,這個畫面應該被記住。它說明模型評估的終點,往往只是系統交付測試的起點。
作者:鍵盤工人