一般功能要測,通常可以先把輸入和預期輸出寫清楚。
例如:
expect(calculateTax(100)).toBe(5)
程式只要沒有照規格執行,測試就會失敗。
AI 會多一種比較麻煩的情況。
假設我們把問題送給 LLM:
const response = await llm.generate({
input: '0.9 和 0.11 哪一個比較大?'
})
Request 成功送出,Provider 回傳 HTTP 200,Response Schema 也完全正確,最後卻得到:
0.11 比較大,因為 11 大於 9。
從程式的角度來看,這次 Request 沒有任何問題;從使用者的角度來看,結果就是錯的。
所以 AI 功能並不是不需要原本的 Test。API Integration、Schema、Authentication、Permission、Tool 本身的邏輯,還是可以照原本的方法測。
只是除此之外,我們還要回答另一個問題:
AI 有沒有真的把任務做好?
如果只是比較兩個數字,成功條件很容易定義。
實際產品通常沒這麼單純。假設我們做的是退款 Agent,使用者說:
幫我把昨天的訂單退款。
Agent 最後回答:
已經替你完成退款。
這句話本身不能證明退款真的完成。
我們可能還需要確認身份有沒有驗證、退款 API 有沒有成功、資料庫裡的訂單狀態有沒有改變,以及最後的回答有沒有把結果說清楚。
Anthropic 在 Agent Evaluation 的整理裡,特別把 Transcript / Trace 和 Outcome 分開。Trace 是這次執行中發生了什麼;Outcome 則是執行結束後,環境真正留下了什麼結果。
例如:
Task:替指定訂單退款
Trace:
驗證身份
→ 查詢訂單
→ 呼叫退款 Tool
→ 回覆使用者
Outcome:
refund.status = completed
order.status = refunded
如果 Outcome 沒有成立,就算 Agent 的最後一句話寫得再漂亮,這個 Task 還是失敗。
這也是設計 AI 測試時最先要決定的事情:不要先問要用哪個 Model 當 Judge,而是先把成功條件定義清楚。
把成功條件定義出來後,就可以開始做 Eval。
Anthropic 用幾個滿直觀的名詞描述一個 Eval:
例如退款 Agent 的一個 Task,可以同時有幾個 Grader:
退款狀態真的變成 completed
身份驗證有成功
退款金額沒有超過可退款金額
回答沒有捏造政策
這裡沒有規定一定只能得到一個 Pass / Fail。實際任務常常同時包含「有沒有完成」和「做得好不好」兩種問題。
Grader 不一定是 LLM。
很多條件其實可以直接用程式確認,例如:
這些條件通常便宜、穩定,也比較容易 Debug。
只有像「回答有沒有真正回應問題」、「摘要是否保留重要資訊」、「語氣是否符合要求」這類比較難寫成 deterministic rule 的條件,才比較適合用 Model-based Grader 或 Human Review。
Anthropic 也把常見 Grader 分成 Code-based、Model-based 和 Human Grader,並建議能直接驗證 Outcome 時,優先驗證 Outcome,而不是把 Agent 經過的每一步寫死。
這點對 Agent 特別重要。假設我們要求它一定要:
get_order()
→ check_policy()
→ refund()
但它其實找到另一條同樣正確的做法,如果 Outcome 和安全條件都成立,過度限制執行路徑反而可能讓測試變得很脆弱。
Eval 告訴我們這次 Task 有沒有通過,Trace 則告訴我們為什麼。
假設退款測試失敗,最後狀態沒有變成 refunded。只知道 Grader 回傳 Fail 還不夠,我們還會想知道:
這些都不是 Grader 本身要解決的問題,而是 Observability / Trace 要處理的事情。
所以可以把兩者理解成:
Evaluation:結果好不好?
Observability:剛才發生了什麼?
兩個缺一個都很難長期維護 AI 功能。只有 Trace 沒有 Eval,最後還是要人工一筆一筆判斷好壞;只有 Eval 沒有 Trace,看到分數下降時又很難知道要改哪裡。
一般的 deterministic test,在同一份 Code 和 Input 下,我們通常預期結果固定。
LLM 不一定。
同一個 Task 重複執行,可能一次成功、下一次失敗。Anthropic 把每次執行稱為一個 Trial,也是因為單次結果很容易誤導。
假設我們剛修正 0.9 和 0.11 的問題,重新跑一次後答案正確,只能證明這一次正確。
更實際的做法是保留一組 Task,在 Prompt、Model、Tool 或 Context 改動後重新跑。這裡通常會有兩種目的:
這其實和我們熟悉的 Regression Test 很接近,只是判斷的對象從 deterministic software behavior,延伸到了 AI 的行為品質。
再完整的 Eval Suite,也不可能在上線前把真實使用者的所有情境想完。
使用者會問我們沒預期過的問題、用奇怪的方式組合功能,也可能碰到只有 Production 資料才會出現的狀況。
所以 AI 的測試不太像「上線前把 Test 寫完就結束」,而比較像一個持續的 Loop:
先定義 Success Criteria
→ 建立 Eval Tasks
→ 修改 Prompt / Model / Tool
→ 跑 Eval
→ Deploy
→ 觀察 Production
→ 找到新的 Failure
→ 把 Failure 加回 Eval Suite
Anthropic 也建議已經上線的產品直接從 Bug Tracker、Support Queue 和真實失敗案例建立 Eval Task,因為這些案例最接近使用者真的在做的事情。
同時也要注意,Offline Eval 通過不代表產品一定成功。Eval 可以告訴我們 Agent 是否符合預先定義的品質標準,真正的 Product Outcome 還是要回到 Production 看:使用者有沒有完成任務、有沒有轉人工、有沒有重複詢問,甚至修改後的 Retention 或 Conversion 有沒有變化。
因此 AI 功能的測試可以整理成三個問題:
程式有沒有正常執行?
→ Test / Error Tracking
AI 有沒有把任務做好?
→ Evaluation
Production 裡實際發生了什麼?
→ Observability / Trace
理論上知道這三件事後,接下來的問題就很工程化了:Production 裡要留下哪些資料,才能把使用者、Task、Trace 和最後的 Product Outcome 串起來?
下一篇就直接用 PostHog AI Observability 把這件事接起來。
如果你願意花 30 秒留下回饋,我會用這些意見來調整後續文章:分享你的意見
