把完整的流程拿去跑 50 封評估信,結果是 42 封完全通過、5 封部分通過、3 封錯得有風險。
3 封聽起來不多。但這 3 封如果直接寄出去了,就是 3 個收到錯誤資訊的客人,而寄信是收不回來的。所以今天的問題不是「怎麼讓它更準」,是哪些信要人看過再寄。
這件事可以寫成程式。寫完之後我把它套回那 50 封信,想知道一件事:它攔不攔得住那 3 封。
答案是攔得住兩封。第三封,也就是唯一一封八條規則全部沒響的,是靠一成的隨機抽樣撈到的。
先講清楚它接在哪裡。Day 18 的流程最後會分成兩條路:一條是轉人工(客訴、優惠、其他,主管直接擋下),一條是自動回覆。轉人工的本來就是人在處理,不需要審批,所以分流規則只接在自動回覆那條路的最後面:
const r = $input.first().json;
const reasons = [];
// 1. 錯了會很貴的類別,一律人審
if (['return_refund', 'complaint', 'promo_coupon'].includes(r.intent)) reasons.push(`類別 ${r.intent}`);
// 2. 主管自己說要人看
if (r.needs_human === true) reasons.push('主管標了 needs_human');
// 3. 有元件掛掉(Day 24 留下的缺口)
if (r.component_failed) reasons.push(`元件故障 ${r.component_failed}`);
// 4. 專員沒有乾淨地回報
if ((r.worker_statuses ?? []).some((s) => !/:ok$/.test(s))) reasons.push(`專員狀態 ${r.worker_statuses.join(',')}`);
// 5. 有查不到、答不完的部分
if ((r.unresolved ?? []).length) reasons.push('有未解決項');
// 6. 程式層的合規檢查有話說
if ((r.w3_violations ?? []).length) reasons.push('合規違規');
// 7. 回覆專員自己提出疑慮
if ((r.w3_concerns ?? []).length) reasons.push('W3 提出疑慮');
// 8. 分類信心低
if (typeof r.intent_confidence === 'number' && r.intent_confidence < 0.85) reasons.push('分類信心低');
// 規則都沒中的,抽一成出來看
const sampled = reasons.length === 0 && Math.random() < 0.1;
八條規則加一個隨機抽樣。前面七條都是「系統自己知道有事」的訊號——這些資訊本來就在案件紀錄裡,前面二十幾天陸續做出來的。
第三條是今天才補上的,等一下講。
50 封信的審批分流,以及 6 封有問題的信各自落在哪裡,整理成下圖。

17 封在主管那一步就轉人工了。剩下 33 封走自動回覆路徑,分流規則攔下 15 封,隨機抽樣抽到 2 封,16 封直接寄出。
加起來人要看 34 封,佔 68%。 自動化的比例只有三分之一。這比我原本想的差很多,後面會說為什麼我接受這個數字。
這 33 封裡,端到端評分判定有問題的有 6 封(其中 3 封是危險錯誤)。它們的落點是:
| 落在哪 | 幾封 |
|---|---|
| 被規則攔下來 | 4 |
| 被隨機抽樣撈到 | 1 |
| 直接寄出去了 | 1 |
被隨機抽樣撈到的是 EV12,三封危險錯誤之一。客人只寫了一句話:
我的濾杯什麼時候寄?
我把案件紀錄排成審批卡片的樣子,這是它實際長的樣子:
[待審] 李小美 order_status 隨機抽樣
需要注意
- 隨機抽樣
客人問什麼
客戶詢問濾杯的寄送時間。
查到的事實(8 筆)
- order_id:A10294 (orders!A10294)
- status:備貨中(packing) (orders!A10294)
- eta:2026-09-17 (orders!A10294)
- order_id:A10310 (orders!A10310)
- status:已送達(delivered) (orders!A10310)
- carrier:黑貓宅急便 (orders!A10310)
- tracking_no:8891234850 (orders!A10310)
- eta:2026-09-05 (orders!A10310)
草稿
李小美 您好
感謝您的來信。我為您確認到兩筆訂單:
訂單 A10294 目前狀態為備貨中(packing),預計到達時間為 2026-09-17。
訂單 A10310 目前狀態為已送達(delivered)。
請您確認您詢問的是哪一筆訂單。
祝您有個美好的一天,
好豆選物 客服小豆
濾杯是 A10294,還在備貨。A10310 是咖啡豆,已經送達了。這封信把兩筆都報出來,等於跟一個問「我的濾杯什麼時候寄」的客人說「你有一筆已經送達了」。
而八條規則一條都沒響。 看那張卡片就知道為什麼:八筆事實每一筆都有 source、專員狀態是 ok、沒有未解決項、合規檢查零違規、W3 沒有提出任何疑慮、分類信心 1。從系統的角度看,這是一次完美的執行。
它錯在一個系統沒有辦法自己發現的地方:它沒有把「濾杯」對應到哪一筆訂單。
這跟 Day 23 那個「濾杯那筆」是同一件事。當時我的結論是主管的記憶裡沒有品項資訊,所以解不出代詞。今天看到的是同一個缺口在另一個位置發作。
前七條規則有一個共同前提:系統得先知道自己有狀況。 查不到、狀態不是 ok、合規有違規、W3 有疑慮——這些都是「系統自己舉手」。
EV12 沒有舉手,因為它不知道自己錯了。這種案件在規則裡是隱形的,唯一能看到它們的辦法就是隨機抽。
我要誠實說一件事:這次抽到 EV12 是運氣。 兩封沒被規則攔到的問題信,抽樣抽到了其中一封,機率上完全可能一封都沒抽到。本文後半段改了派工規則之後又跑了一次同一批信,那一次就沒抽到它,EV12 直接進了「寄出」那一堆。
一成的抽樣不是為了「攔住這一封」,它是為了讓你有機會知道這類錯誤存在。真正把它修掉要靠別的手段——事實上今天後半段就是從這張卡片追下去的。
被規則攔下來的 15 封裡,只有 4 封真的有問題,另外 11 封其實寫得好好的。誤報率 73%。
看一下這 11 封的理由就會發現,大部分不是規則不準:
EV27 ["類別 return_refund", "主管標了 needs_human"]
EV28 ["類別 return_refund", "主管標了 needs_human"]
EV29 ["類別 return_refund", "主管標了 needs_human"]
EV30 ["類別 return_refund", "主管標了 needs_human"]
退貨類一律人審,是我在 Day 17 寫進分類規則的決定。它們被攔下來不是誤判,是規則就是這樣寫的:不管 AI 寫得多好,牽涉到退款的信我都要人看過。
剩下幾筆是「專員狀態不是 ok」或「有未解決項」。這些案件通常是誠實地說「這部分我幫您確認後回覆」——草稿沒錯,但它確實有沒答完的部分,讓人看一眼不過分。
所以每條規則的攔截效率長這樣:
| 規則 | 攔下 | 其中真的有問題 |
|---|---|---|
| 主管標了 needs_human | 11 | 3 |
| 類別(退貨/客訴/優惠) | 9 | 2 |
| 專員狀態不是 ok | 7 | 3 |
| 有未解決項 | 7 | 3 |
| W3 提出疑慮 | 3 | 1 |
| 分類信心低 | 1 | 1 |
(同一封信會踩中多條規則,所以加起來超過 15。)
第八條規則「分類信心低於 0.85」只攔到 1 封。不是因為分類很準,是因為模型幾乎總是填 1。
33 封自動回覆路徑的案件裡,32 封的 intent_confidence 是 1,只有 1 封低於 1——而那一封確實錯了(EV49,該轉人工卻自己回)。
所以這個欄位的方向是對的,問題是它幾乎不出聲。讓模型自己評估信心,在這個規模下沒有鑑別力。真正有用的訊號全部來自程式可以驗證的事實:工具回報的狀態、合規檢查的結果、有沒有未解決項。
這跟 Day 21 的結論是同一件事:能寫成規則的交給程式,模型的自我評估拿來參考就好。
Day 24 發現一個問題:一信兩問的案件,W1 掛掉走了錯誤輸出、W2 還活著,流程照常往下走產出回覆,但案件紀錄裡沒有任何欄位說明有元件掛掉。
修法是在合併專員回報的那個 Code 節點裡補一句:
// Day 24 留下的缺口:有專員走了錯誤輸出的話,主線上要留下紀錄
let componentFailed = null;
try { componentFailed = $('Degrade').first().json?.failed_node ?? null; } catch { componentFailed = null; }
$('節點名稱') 在該節點沒有執行過的時候會丟例外,所以要 try/catch——沒掛掉就是 null。
重跑 Day 24 的那個故障案例驗證:
final_action=reply component_failed="Execute W1 (both)"
review_required=true
reasons=["元件故障 Execute W1 (both)", "專員狀態 knowledge:partial", "有未解決項"]
案件還是照常回覆,但它現在會被攔下來給人看。這一條規則在正常的 50 封信裡一次都沒觸發,它是專門給那種「一半壞掉」的情況準備的。
EV12 那張卡片上,八筆事實裡有訂單編號、狀態、物流、預計到貨——沒有品項。
回去看派工規則就找到了:
need_csv: {{ $json.intent === 'return_refund' ? 'status,items,delivered_at'
: 'status,carrier,tracking_no,eta' }}
退貨類要 items,查單類不要。所以客人問「我的濾杯什麼時候寄」的時候,W1 根本沒被要求回報品項,底下的人就算想分辨也分辨不出來。
這跟 Day 22 抓到的是同一種錯:派工時寫死的欄位清單,會在某個意圖上剛好少一欄,而且不會報錯。
我把查單類也加上 items,重跑 50 封:
| 原本 | 加上 items | |
|---|---|---|
| 完全通過 | 42/50 | 42/50 |
| 危險錯誤 | 3 | 3 |
| token 總和 | 243933 | 245810 |
總分沒有動。拆開看是兩件事抵銷了:
EV10 修好了。 客人寫「我今天早上下單兩包豆子(A10314),想確認你們有收到訂單嗎」,標準答案要求講出買了什麼。原本只回「備貨中、預計 9/18 送達」,加上 items 之後變成:
您的訂單 A10314 目前狀態為備貨中(packing),內容包含肯亞 AA 中淺焙 200g 與
瓜地馬拉 安提瓜 中焙 200g,預計於 2026-09-18 送達。
EV13 掉了一分,但那是雜訊。 兩次跑的 facts 裡都有 status=備貨中(packing),但第二次 W3 莫名其妙寫成「關於訂單 A10294 的出貨狀態,我這邊幫您確認後回覆您」。同樣的輸入、同樣的 prompt,寫出不一樣的東西——這就是 Day 22 量過的那個一題上下的抖動。
而 EV12 沒有修好。 加上 items 之後,W1 確實把「V60 濾杯 01 + 濾紙 100入」和「哥倫比亞 慧蘭 中深焙 200g」都報上來了,草稿也把品項寫進去了:
關於您的訂單,我這邊查到兩筆紀錄:
訂單 A10294(V60 濾杯 01 + 濾紙 100入):目前為備貨中,預計 2026-09-17 送達。
訂單 A10310(哥倫比亞 慧蘭 中深焙 200g):已送達。
請您確認您詢問的是哪一筆訂單。
資訊全都在手上了,「濾杯」對得上 A10294,它還是把兩筆都列出來、請客人自己選。
缺的不是資料,是那一步比對。 這也解釋了 Day 23 的 C3-R2 為什麼是同樣的行為:這個系統遇到兩筆訂單的習慣就是「都講出來、請你確認」,它沒有被要求先挑。
這件事今天不修,因為它要改的是 W3 或主管的 prompt,而我手上沒有足夠多的「同信箱多筆訂單」案例來驗證改完有沒有用——50 封裡只有 3 封。Day 27 整理評估集時一起處理。
人要看 34 封、自動寄 16 封,自動化比例三分之一。
這個數字會讓人想砍規則,但拆開看就知道不該砍。17 封轉人工是客訴、優惠、其他——這三類我從 Day 09 就決定不讓 AI 自己回。15 封規則攔截裡有 9 封是退貨類,也是政策決定。真正「因為系統不確定」而被攔下來的只有 6 封。
所以 68% 裡面大部分不是 AI 不行,是我不讓它自己做。 這兩件事要分開算。
如果哪天決定退貨類可以自動回,審核量立刻降到 50 封裡的 25 封。但那是一個商業決定,不是技術決定——一封寫錯的退款回覆的代價,跟審一封信的三十秒,是兩個量級的東西。
component_failed,一半壞掉的案件現在會被攔下來。items。修了之後 EV10 修好,但總分 42/50 沒動(另一封是雜訊抖動),而 EV12 拿到品項之後還是把兩筆都列出來請客人選——缺的不是資料,是比對那一步。明天處理錢的問題:主管加三個專員的 token 到底花在哪,以及把小模型放進去會發生什麼事。