iT邦幫忙

2026 iThome 鐵人賽

DAY 25
0
AI 自動化

從單一 Agent 到 Supervisor 架構:用 n8n 實作會自己分工的 Multi-Agent AI 部門系列 第 25 篇

Day 25|寄信前的人工審批:規則攔不住的那一封,是隨機抽樣接到的

  • 分享至 

  • xImage
  •  

把完整的流程拿去跑 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 封信跑出來的樣子

50 封信的審批分流,以及 6 封有問題的信各自落在哪裡,整理成下圖。

https://ithelp.ithome.com.tw/upload/images/20261009/20183868NpsLRHUI4s.png

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 直接進了「寄出」那一堆。

一成的抽樣不是為了「攔住這一封」,它是為了讓你有機會知道這類錯誤存在。真正把它修掉要靠別的手段——事實上今天後半段就是從這張卡片追下去的。

誤報 11 封,但這不是 bug

被規則攔下來的 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 留下的缺口

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 整理評估集時一起處理。

關於 68%

人要看 34 封、自動寄 16 封,自動化比例三分之一。

這個數字會讓人想砍規則,但拆開看就知道不該砍。17 封轉人工是客訴、優惠、其他——這三類我從 Day 09 就決定不讓 AI 自己回。15 封規則攔截裡有 9 封是退貨類,也是政策決定。真正「因為系統不確定」而被攔下來的只有 6 封。

所以 68% 裡面大部分不是 AI 不行,是我不讓它自己做。 這兩件事要分開算。

如果哪天決定退貨類可以自動回,審核量立刻降到 50 封裡的 25 封。但那是一個商業決定,不是技術決定——一封寫錯的退款回覆的代價,跟審一封信的三十秒,是兩個量級的東西。

小結

  • 分流規則接在自動回覆那條路上,八條規則加一成隨機抽樣。50 封信的結果:17 封本來就轉人工、15 封規則攔下、2 封抽樣、16 封直接寄出。
  • 自動回覆路徑的 33 封裡有 6 封有問題。規則攔到 4 封,抽樣撈到 1 封,漏掉 1 封。
  • 抽樣撈到的那封(EV12)是三個危險錯誤之一,而八條規則一條都沒響:事實有來源、狀態 ok、零違規、信心 1。它錯在「沒把濾杯對應到哪一筆訂單」,這是系統沒辦法自己發現的錯。前七條規則都依賴系統先舉手,不舉手的案件在規則裡是隱形的。
  • 抽到它是運氣。後面改派工規則重跑同一批信時就沒抽到。一成抽樣的價值不是攔住某一封,是讓你有機會知道這類錯誤存在。
  • 誤報 11/15 看起來很差,但大部分是政策造成的——退貨類一律人審是我自己寫的規則,不是誤判。
  • 分類信心值幾乎沒有鑑別力:33 封裡 32 封填 1。有用的訊號全部來自程式可以驗證的東西。
  • 補上 Day 24 的缺口:合併專員回報時用 try/catch 讀降級節點,案件紀錄多一個 component_failed,一半壞掉的案件現在會被攔下來。
  • 從那張審批卡片追到一個真的上游問題:查單類的派工沒有要 items。修了之後 EV10 修好,但總分 42/50 沒動(另一封是雜訊抖動),而 EV12 拿到品項之後還是把兩筆都列出來請客人選——缺的不是資料,是比對那一步。

明天處理錢的問題:主管加三個專員的 token 到底花在哪,以及把小模型放進去會發生什麼事。


上一篇
Day 24|容錯實測:壞得大聲的慢一百倍,壞得安靜的考卷剩 6/20
下一篇
Day 26|成本實測:最貴的是查單專員不是主管,三個省錢手段全部更貴
系列文
從單一 Agent 到 Supervisor 架構:用 n8n 實作會自己分工的 Multi-Agent AI 部門 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言