iT邦幫忙

2026 iThome 鐵人賽

DAY 17
0
AI Engineering

30 天打造 AI 後端:從 LLM、RAG 到 AI Agent系列 第 17

[Day 17] 聯集 recall 從 62% 爬到 88%,答對率從 5/8 掉到 3/8

  • 分享至 

  • xImage
  •  

Day 14~16 的題目有一個我一直沒講的共同點:每一題都只要一條條文就答得完。
在那個前提下,Day 15 的結論成立得很漂亮——「答對率的天花板就是 recall@k」,
撈得到就答得對。

今天把題組換成 8 題缺一條就算不出來的綜合題。第一張表就把那個結論推翻了。

k 單條 recall 聯集 recall 答對率 輸入 tokens
1 50% 0% 1/8 2,239
3 81% 62% 5/8 4,863
5 81% 62% 4/8 7,579
10 88% 75% 5/8 14,334
15 94% 88% 3/8 20,791
  • 單條 recall:必要條文中撈到幾條(Day 15 用的那把尺,撈到一半也算 50%)
  • 聯集 recall所有必要條文都進 top-k 才算命中——今天的新尺

k 從 3 開到 15,聯集 recall 多了 26 個百分點,輸入 token 貴了 4.3 倍,
答對率掉了兩題。把更多正確的條文塞進 context,不等於模型會用它們。

(語料:虛構的《員工工作規則》59 條,同 Day 9~16。生成用 gpt-4o-mini
temperature=0、prompt 全程固定在 P1 基本版——今天唯一的變因在檢索側,
跟 Day 16 剛好相反。)

一、反轉長什麼樣子

第 301 題「平日加班 3 小時,加班費怎麼算?」,第 19 條在每個 k 都是第 1 名。

  • k=3 ✅:「前 2 小時按每小時工資額加給三分之一以上,第三小時按加給
    三分之二以上。具體加班費計算基準為本薪加計經常性給與。」
  • k=15 ❌:「您加班 3 小時的加班費應按平日每小時工資額加給三分之二以上計算。」

同一條條文、同一個模型、同一句 prompt。多給了 12 條,答案從「分段算」塌成
一個錯的比例,計算基準整句消失。第 304 題也一樣:k=3 答得清楚,k=15 縮成一句。

Day 16 量到「加一句引用要求,答案會擠掉限制條件」。今天量到的是同一個現象的
另一個觸發源:context 變長,輸出也會縮——k=15 的輸出 token(377)比 k=3
(387)還少。你付了 4.3 倍的輸入,買到的是更短的答案。

二、然後我去逐題讀了答案原文

反轉是真的。但我把 8 題的答案原文逐字讀過一遍之後,發現更難堪的事:
這 8 題裡,我的尺判錯了 5 題。

第 308 題是最糟的一個。問「颱風停班我改在家上班,要不要簽到?算不算出勤?」
正確答案要兩條:第 16 條(改居家辦公以正常出勤論)+ 第 15 條
(遠距工作日仍應完成線上簽到)。

第 15 條五個 k 值全部沒撈到,聯集 recall 是 0%。而模型五次都回答:

該日以正常出勤論,因此當天不需要簽到

facts 是「正常出勤」「簽到」,兩個關鍵詞都在句子裡。我的尺五次都判它對。
規章的答案是「要簽到」,模型答的是「不用簽到」,中間只差一個「不」字,
而子字串比對看不見否定。

這不是新發現。Day 14 的 README 就寫著這把尺「只看有沒有講到,不看有沒有講錯」,
forbid 欄位就是用來補這個洞的——而我這 8 題的 forbid 全部留空。

三、另外四題,錯法各不相同

題號 判定 實際情況
304 k=5、k=15 ❌ 模型寫「無需發給資遣費」,我的 fact 是「發給資遣費」。差一個字
305 五個 k 全 ❌ k=3 答「尚未滿六個月,因此沒有特休假」——這是全場最好的答案,被判錯
306 五個 k 全 ❌ 答「會被書面提醒,但不會直接記過」。完全正確,但沒說出「申誡」兩個字
307 五個 k 全 ❌ 答「公司得暫緩發給」。正確,但沒講「七個工作日」——因為問題根本沒問時限

305、306、307 是同一個病:我把「條文裡有的事實」當成「正確答案必須包含的事實」。
問「會不會被記過」,正確答案是「不會,先書面提醒」,它沒有義務背出懲處清單。

而第 301 題的病更根本:它根本不是多條文題。第 19 條原文寫著
「加班費之計算基準為第 33 條所定之本薪加計經常性給與」——
條文自己把答案交叉引用過來了。所以 k=3 沒撈到第 33 條也答得對。

順帶更正 Day 15 補充實驗的一句話:我當時寫這題「k=3 沒撈到第 33 條卻答對」是
判定寬鬆造成的僥倖。那句是錯的。真正的原因是條文互相引用,
而我出題時沒有去讀第 19 條的最後一句。

四、我的自我檢查為什麼沒抓到

腳本裡有一節「判定自我檢查」:把每題必要條文的原文送進 grader,8 題全過。
我以為這證明了尺沒問題。

它只證明了一件事:尺不會誤殺照抄原文的答案。
它完全沒有檢查「一個簡短而正確的答案會不會被誤殺」——而那才是模型實際會寫的東西。

單條文題可以用關鍵事實比對,因為正確答案幾乎就是條文本身。
多條文題的正確答案是一段推理(「兩條合起來所以三個月還沒有特休」),
推理的表達方式有無限多種,關鍵詞只抓得到其中一種。

所以第一張表要打個折來看:判定沒有爭議的只有 301、302、303,
其中只有 301 是 k=15 掉的。反轉看得到,但有多少是真的、多少是尺的雜訊,
今天答不出來。

題目變難的時候,先壞掉的不是模型,是你的判定。

五、順序與 reranker:兩個沒買到東西的變因

固定 k=10,同一批 context 只換排列順序,輸入 token 三組完全相同(14,334):

排法 答對率
相似度序(預設) 5/8
反序(最相關放最後) 3/8
必要條文塞中間 3/8

掉的是第 303、304 題,而且掉法很具體:303 反序時把「超過部分自行負擔
整句丟了,304 塞中間時連「三日」都不見了。同樣的資訊、同樣的 token,
只換位置就掉兩題。8 題太小不足以下定論,但這個變因你在自己的系統上值得測一次

reranker(候選 15 → gpt-4o-mini listwise 重排取 3):

組別 聯集 recall 答對率 生成成本 重排成本
純向量 k=3 62% 5/8 0.030 元
純向量 k=15 88% 3/8 0.104 元
rerank 15→3 75% 4/8 0.030 元 0.101 元

重排挑得比向量準(聯集 recall 62% → 75%),答得比 k=3 差。
而且那筆帳:重排本身比它省下來的生成貴 3.4 倍,加總後比直接 k=15 還貴一點。
因為它要先把 15 條完整讀一遍才能排序——候選池的 token 一樣要付,
只是換到另一行帳上
。8 次重排的輸出總共只有 40 個 token(就是「1,3,7」),
這是一筆幾乎全是輸入的帳單。

最諷刺的是第 301 題:重排把第 33 條(候選第 9 名)丟掉了,
挑進來的第 20、26 條是補休規定,跟算錢無關。然後它把加成比例答反了。

小結

今天三個變因——加大 k、換條文順序、加 reranker——沒有一個買到更高的答對率。
但真正的收穫是第二節:我在單條文題上用了三天的那把尺,換成多條文題就壞了,
而且我的自我檢查設計成看不見這件事。

成本:首跑計費 embedding 258 + 生成輸入 99,739/輸出 2,838 tokens
新台幣 0.517 元(72 次生成 + 8 次重排)。全部從零跑約 0.622 元。

如果你的 RAG 評估只有一個「答對率」數字,去把 20 個答案原文逐字讀一遍。
你會找到你的 308。

明天 Day 18:換判定方式。關鍵事實比對從 Day 14 撐到今天,八題壞五題,
該退休了。要換成逐項 rubric、還是終於請 LLM 當裁判(本系列前四天一直拒絕的
那個選項)——以及裁判自己要怎麼驗。

GitHub:https://github.com/wp900622/TrustRAGday17_rag/


上一篇
[Day 16] 最危險的答案是「規章沒寫,但國內是三千元」
下一篇
[Day 18] 我寫了一個自動改考卷的程式,今天發現它 40 題改錯 25 題
系列文
30 天打造 AI 後端:從 LLM、RAG 到 AI Agent26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言