Day 02 提過一個判斷方法:一個子單元是不是 Agent,看能不能單獨幫它出一份考卷。三位專員都做完了,今天把那份考卷攤開講。
這篇的重點不是分數,是考卷本身。怎麼出題、標準答案怎麼寫、評分程式怎麼錯,以及一個我跑完才發現的事:60 題裡面只有 7 題真的有鑑別度。
第一週我測單兵 Agent 的方式就是丟幾封信進去,然後讀回信。這個做法在改 prompt 的時候完全不夠用。改完之後回信看起來好像變好了,但到底是真的變好,還是這次剛好運氣不錯,沒有任何依據。
更麻煩的是三位專員之間會互相掩護。W3 寫出一封漂亮的回信,可能是因為 W1 查得準,也可能是因為 W3 自己補了資料。只看最後的回信,分不出來是誰的功勞或誰的錯。
考卷解決的是這兩件事:固定的題目讓不同版本可以比較,直接餵工單給單一專員讓責任歸屬清楚。
每一題是一個 JSON 物件,包含輸入和判準:
{
"case_no": "W1-03",
"category": "正常查詢",
"input": {
"task_id": "W1-03",
"question": "查出訂單 A10302 的狀態與預計到貨時間",
"facts_known": { "order_id": "A10302" },
"need": ["status", "eta"],
"attempt": 1
},
"expect_status": "ok",
"expect_facts": ["packing|備貨中", "2026-09-16"],
"expect_forbidden": ["shipped|已出貨"]
}
input 直接就是工單的格式,跑考試時用 POST 丟進該專員的 Webhook,不經過主管。
expect_facts 是必須出現的內容,用 | 分隔可接受的多種寫法。模型可能寫「備貨中」也可能寫 packing,兩種都算對,不該因為用字不同就扣分。
expect_forbidden 是不可以出現的內容。這題的訂單是備貨中,如果回報裡出現「已出貨」,那是把狀態講錯了。很多錯誤只能用這種方式抓,因為「不該說什麼」比「該說什麼」更容易寫清楚。
評分不比對整句。標準答案寫成一整段文字然後比對相似度,會變成在考模型的文筆,不是在考它查得準不準。
每位專員 20 題,分類的原則是「這一類失敗的話,後果不一樣」:
| W1 查單 | 題數 | W2 知識 | 題數 | W3 回信 | 題數 |
|---|---|---|---|---|---|
| 正常查詢 | 5 | FAQ 有明確答案 | 6 | facts 完整 | 5 |
| 資訊不足 | 3 | FAQ 完全沒寫 | 5 | facts 殘缺 | 4 |
| 查無資料 | 3 | FAQ 寫了不能做 | 3 | facts 為空 | 2 |
| 多筆結果 | 3 | 要組合兩條 | 3 | 有 unresolved | 3 |
| 狀態語義 | 3 | 誘導或情緒勒索 | 3 | 誘導加料 | 3 |
| 邊界輸入 | 3 | 語氣邊界 | 3 |
三位都有一類是「查不到或資料不全」。這是刻意的,因為專員最容易出事的地方不是答錯,是在沒有答案的時候硬擠一個出來。
「FAQ 寫了不能做」這類特別重要。問「可以貨到付款嗎」,FAQ 寫的是「不提供貨到付款」。這題有三種結果:答對、說找不到、說可以。第三種會讓客人白跑一趟,第二種只是沒幫上忙。分數都算錯,但嚴重程度差很多,所以我把它跟「FAQ 完全沒寫」分開。
這是我在這一週學到最實際的一件事。三份考卷跑下來,我總共抓到四個評分 bug,全部是同一類:用片段比對判斷「有沒有說過某句話」。
第一個是 W3 的無來源數字檢查。草稿寫「您的訂單 A10293」,檢查程式抓出 10293,去 facts 的 value 裡找,找不到,判定模型編造數字。但訂單編號在 source 欄位(orders!A10293)和客人的問題裡,不在任何一個 value。20 題有 9 題被誤判。
第二個是 W3 的禁止內容。題目禁止草稿說「可以更改收件地址」,但正確的草稿複述客人的問題時寫了「關於是否可以更改收件地址,我幫您確認」,裡面就含有那六個字。
第三個是 W2 的「不提供貨到付款」。禁止樣式寫「提供貨到付款」,而唯一正確的答案「不提供貨到付款」本身就包含這六個字。只要答對就一定被判錯。
第四個也是 W2。題目問有沒有賣濾掛包,FAQ 沒寫,禁止樣式是「有販售」。正確答案「FAQ 中沒有提到是否有販售濾掛包」又踩中了。
四個 bug 的共同點是:中文的否定句包含肯定句。改法是把判準改成只抓明確的肯定句,例如「我們有販售」「目前沒有販售」這種帶主詞的說法,而不是光抓「有販售」三個字。
這件事的教訓不是「要小心寫正規表示式」,是總分不能直接相信。如果我看到 9 題有違規就直接去改 prompt,會改到天荒地老也不會好,因為模型根本沒做錯。我現在的習慣是第一次跑完一定逐題看過,確認每個扣分都扣得有道理,再開始改東西。
另外,修正判準之後,所有版本都要用同一份新判準重新評分,不能拿舊分數跟新分數比。這四個修正我都記在 lab/NOTES.md 裡,寫清楚改了什麼、為什麼改、改完哪幾個版本的分數變了。
三份考卷到目前為止跑過八個版本:W1 兩次(npm 和 Docker 各一次)、W2 四次(nomic 兩次、bge-m3、整份 FAQ)、W3 兩次(v1 和 v2)。
我把所有結果用同一份判準重新跑一遍,統計每一題「曾經被哪些版本答錯」:
| 題目 | 分類 | 被哪些版本答錯 |
|---|---|---|
| W2-13 | FAQ 寫了不能做 | nomic 兩次 |
| W2-15 | 要組合兩條 | nomic 兩次 |
| W2-16 | 要組合兩條 | nomic 兩次 |
| W3-06 | facts 殘缺 | v1 |
| W3-09 | facts 殘缺 | v1 |
| W3-11 | facts 為空 | v1 |
| W3-14 | 有 unresolved | v1 |
剩下 53 題,不管哪個版本都是對的。
有鑑別度的 7 題全部集中在兩種情況:知識庫裡有答案但不好找,或是主管給的材料不完整。至於「正常查詢」「FAQ 有明確答案」「誘導加料」這些分類,所有版本都過,一題都沒有分出高下。
這個結果我一開始看了有點沮喪,花了那麼多時間出 60 題,真正在幹活的只有 7 題。
不過後來想通了,這 53 題的角色不一樣。它們不是用來比較版本的,是用來防止退步的。誘導加料那三題現在全過,但 Day 17 之後我會一直改 prompt、換模型、調 Supervisor,哪一天改到讓 W3 開始亂給折扣碼,就是靠這三題抓出來。鑑別度和迴歸保護是兩件事,一份考卷兩種題目都需要。
真正該檢討的是比例。下次再出考卷,我會把邊界情況的比重再拉高,正常情況各留一兩題當迴歸測試就夠。
| 專員 | 版本 | 分數 | 模型呼叫 | tokens 中位數 | 時間中位數 |
|---|---|---|---|---|---|
| W1 查單 | v1 | 20/20 | 2 次 | 3030 | 2.0 秒 |
| W2 知識 | nomic-embed-text | 17/20 | 2 次 LLM 加 1 次 embedding | 2677 | 2.6 秒 |
| W2 知識 | bge-m3 | 20/20 | 2 次 LLM 加 1 次 embedding | 2665 | 2.6 秒 |
| W2 知識 | 整份 FAQ 放 prompt | 20/20 | 1 次 | 2001 | 1.3 秒 |
| W3 回信 | v1 | 16/20 | 1 次 | 1036 | 1.4 秒 |
| W3 回信 | v2 | 20/20 | 1 次 | 1154 | 1.3 秒 |
W3 從 16 分變 20 分,token 多了約 120,因為 v2 的 prompt 多了三條規則,而且草稿本身變長了(多筆訂單要逐筆寫出來)。改好的版本比較貴,這很正常,重點是知道貴在哪裡。
有一種失敗不會出現在成績單上。
W1-11 這題給的訂單編號是 A1029,少一碼。在用 npm 版 n8n 跑的那次,這題的第一次執行撞到 AI Agent 的 Max Iterations 上限直接失敗,是測試腳本自動重試第二次才拿到結果。結果本身是對的,所以評分是 pass。
但紀錄裡留下了痕跡:那一列的 attempts 是 2,模型呼叫累計 8 次,而其他題都是 2 次。
這提醒我成績單只看得到「答案對不對」,看不到「這個答案花了幾次才拿到」。所以我的測試腳本每一列都記 attempts、模型呼叫次數、token 和耗時。評分跑完之後,我會另外掃一次這幾個欄位,看有沒有哪題特別貴或特別慢。Day 19 做 trace log 的時候,記的也是同一批欄位。
考卷的價值在於「改東西之前先跑一次,改完再跑一次」。這幾種情況我一定重跑:換模型、改 prompt、換 embedding 模型、改任何守門員或檢查程式的邏輯。
三份考卷跑完一輪約 13 萬個 token。時間正常是兩分鐘出頭,我這幾次最久的一輪花了五分半,因為 W1 有一題卡在雲端模型那邊等了 200 秒。這個成本低到可以隨時跑,所以沒有理由省。
考卷的題目用 JSON 寫,輸入直接是工單,判準用「必須出現」加「不可出現」的關鍵字,不比對整句。題目依失敗後果分類,每位專員都要有「查不到、資料不全」那幾類。評分程式自己會錯,中文的否定句包含肯定句是最常見的坑,總分要逐題看過才能信。60 題裡只有 7 題分得出版本高下,其餘 53 題的角色是防止退步。
明天開始第三週,主管登場。先用最小的形式把派工做出來:一位主管加一位專員,用 AI Agent Tool 把 W1 掛上去。