RAG 消融續集:BM25 逆轉 hybrid、chunk size 白調、reranker 兩面刃

重點摘要(TL;DR)
  • 上一篇的「hybrid 輸 dense」是冤枉了 hybrid —— 壞的是 bge-m3 的 learned sparse,不是 hybrid 這個想法本身。
  • Step 1b:把 sparse 腿換成古典 BM25(CJK bigram + 料號 token 保留完整),hybrid 反敗為勝:nDCG 0.803 → 0.876、C@3 90% → 100%,而且料號題 DN80 從「dense 完全撈不到」變成 rank 1。
  • Step 2:chunk size 2×2 網格 —— 調了等於沒調。baseline 700/120 已經是 Pareto 最好,縮 size 或減 overlap 都沒贏。這是有用的負結果:別浪費時間調它。
  • Step 4:cross-encoder reranker —— 兩面刃。Recall@5 升到全場最高 75%,但排序精度(nDCG、MRR、C@3)反而降,而且慢 16 倍。「加 reranker 一定更好」是直覺騙人。
  • 全程同一把尺、一次只動一個因子。尺仍只有 10 題,統計不顯著的部分我照實標。

這是 RAG 檢索消融系列的第二篇。上一篇我們用「一次只動一個因子」的消融規矩測了第一個因子——檢索模式,結論是 bge-m3 的 dense+sparse hybrid 在 10 題 gold 上一題都沒贏過純 dense,而且追到根因:bge-m3 的 learned sparse 把料號的數字碎片當停用詞丟掉,查 D8286 卻算出 0 分。那篇結尾留了一張路線圖。這篇,就是把路線圖真的走一遍:換一個 sparse 腿、調 chunk size、加一個 reranker,每一步都用同一把尺量,誠實記錄哪些改動真有用、哪些只是直覺騙人。

🧭 本文導覽

前情提要:上一篇卡在哪

案子是華新工廠的設備維修手冊 RAG(泵浦、空壓機、CNC、變頻器 VFD、PLC、工業爐),約 700 本混格式、掃描多、故障表多。我們負責的是 R(檢索):把原文加出處撈給下游 agent,要撈得準、撈得全、查不到要能 abstain。baseline 是 bge-m3 只用 dense

上一篇的結論很反直覺:研究共識都說「開 bge-m3 的 sparse 做 hybrid,能免費拿到料號的精確匹配」,但實測 hybrid 10 題 0 勝、還嚴格輸給純 dense。根因是——bge-m3 的 sparse 對料號無能為力。所以真正的問題不是「hybrid 這條路錯了」,而是:如果換一個真的會做精確匹配的 sparse 腿,hybrid 會不會贏回來?這就是 Step 1b。

方法沒變:同一把尺、一次一因子

消融的紀律是控制變因:每個 config 只跟 baseline 差「一個」因子,這樣命中率的變化才能歸因到某個動作,而不是一次全改然後瞎猜是誰的功勞。harness 跟上一篇同一套(ablation.py),指標都是確定性的:Content-Hit@1/3/5(相關段落命中在第幾名)、Recall@5、nDCG@5、MRR。gold 也是同一組 10 題(7 題自然語言問句 + 3 題料號 D8286 / RF008X00A / DN80)+ 1 題該 abstain。

兩個指標要分清楚:「撈得準」看 nDCG / MRR / Content-Hit@1(正解排在前面),「撈得全」看 Recall@5(前 5 名裡蒐集到多少相關段落)。下面會看到——同一個改動可能讓一個升、另一個降。

Step 1b:換古典 BM25,hybrid 反敗為勝

做法只換一件事:hybrid 的 sparse 腿,從 bge-m3 的 learned sparse 換成古典 BM25(rank_bm25)。dense 腿、RRF 融合、gold、指標全部不動。同一份 dense 快取直接重用,不重新編碼。

關鍵在 tokenizer:料號別被拆碎

BM25 對中文語料的成敗全在斷詞。預設用空白切詞對中文等於廢掉。我用的規則:CJK 走 char-level bigram(免斷詞),英數字串保留成一整個 token——這樣 D8286 才不會被拆成 [D, 82, 86](那正是 bge-m3 sparse 陣亡的地方)。查詢和語料用同一把尺、都轉小寫。

def bm25_tokenize(text):
    text = text.lower(); out = []
    for m in re.finditer(r'[a-z0-9]+', text):      # 英數 run 保留成完整 token
        out.append(m.group(0))                      # D8286 → 'd8286',不拆成 82 / 86
    for run in re.findall(r'[一-鿿]+', text):        # CJK 用 char-level bigram
        out += [run] if len(run)==1 else [run[i:i+2] for i in range(len(run)-1)]
    return out

結果:hybrid_bm25 全面贏過 dense

檢索模式(chunk 700/120) C@1 C@3 C@5 Recall@5 nDCG@5 MRR
dense(baseline) 70% 90% 90% 57% 0.803 0.78
hybrid(bge-m3 sparse) 30% 30% 40% 17% 0.343 0.38
bm25 單獨 50% 80% 90% 61% 0.706 0.64
hybrid_bm25(dense + 古典 BM25) 70% 100% 100% 64% 0.876 0.83

逐題看:DN80 這題只有 exact-match 撈得到

aggregate 贏不夠,要能歸因。看料號那 3 題的相關段落排名(數字越小越好,0 = 完全沒撈到):

料號題 dense hybrid(bge-m3) bm25 hybrid_bm25
D8286(PLC 特殊暫存器) 1 8 2 1
RF008X00A(濾波器) 1 1 1 1
DN80(管徑規格) 0(未命中) 0(未命中) 1 2

DN80 是鐵證:dense 撈不到、bge-m3 hybrid 也撈不到,只有帶古典 BM25 的路線把它拉到 rank 1。這正是 dense 語意向量的死穴——「DN80」對它就是一串沒有語意的字元,而 exact-match 一擊即中。另一個副證是 D8286:bge-m3 的 sparse 噪音把它從 dense 原本的 rank 1 拖到 rank 8,而 hybrid_bm25 保住 rank 1。換對 sparse 腿,兩頭都顧到了。

一句話心法:hybrid 本身沒問題,sparse 腿選錯才是禍首。料號 / 型號的精確匹配,就該交給古典 BM25 或 exact index,不要指望 learned sparse「順便」做到。

Step 2:chunk size 網格——調了等於沒調

下一個因子:切片大小。很多 RAG 教學把「調 chunk size」當成必修的調參動作。我們做 2×2 網格:size ∈ {700, 450} × overlap ∈ {120, 60},檢索固定用 dense(隔離 chunk 這一個因子)。這一步要真的重新用 bge-m3 編碼語料(每個新配置 CPU 上約 40 分鐘)。

size / overlap C@1 C@3 C@5 Recall@5 nDCG@5 片數
700 / 120(baseline) 70% 90% 90% 57% 0.803 1525
700 / 60 60% 80% 80% 49% 0.704 1419
450 / 120 60% 80% 90% 50% 0.767 2424
450 / 60 70% 90% 90% 51% 0.790 2101

沒有一個配置贏過 baseline 700/120。它在 Recall@5(57%)和 nDCG(0.803)兩個頭牌指標上都是最高,其他配置最多在某個 @k 打平、其餘小輸。細看有一點交互作用:size 700 時 overlap 從 120 砍到 60,nDCG 掉很多(0.803 → 0.704);但 size 450 時 overlap 幾乎不影響。不過在 10 題的尺上,這些差異多半落在雜訊範圍內。

這是一個有用的負結果:在這個語料上,「調 chunk size」不會幫你,baseline 已經夠好。消融的價值不只在找到 work 的東西,也在於證明某個熱門動作是白工,讓你不要把時間花在那裡。

Step 4:reranker——兩面刃

⚠️ 更正(2026-08):本節「reranker 是兩面刃」的結論,後來被證明是 10 題小樣本的假象。把 gold 從 10 題擴到 100 題重跑後,reranker 在每個指標都最高、且統計顯著。詳見文末後記:把 gold 擴到 100 題,結論怎麼變。下面這段 10 題的分析保留原樣,正好當「小樣本會騙人」的活教材。

最被神化的一招:retrieve-then-rerank。先用 bi-encoder 撈 top-N 候選(這裡 N=20),再用 cross-encoder(bge-reranker-v2-m3)逐一讀「(問題, 段落原文)」重新打分,取重排後 top-k。我測兩種疊法:疊在純 dense 上、疊在最強的 hybrid_bm25 上。

模式 C@1 C@3 C@5 Recall@5 nDCG@5 MRR 10 題耗時
hybrid_bm25(Step 1b 冠軍) 70% 100% 100% 64% 0.876 0.83 ~21s
rerank(dense → CE) 60% 70% 90% 65% 0.727 0.68 ~327s
rerank_hybrid_bm25(hybrid_bm25 → CE) 70% 80% 100% 75% 0.831 0.78 ~330s

讀這張表要小心,因為它是兩面刃:

  • 撈得全:reranker 是全場最高。rerank_hybrid_bm25 的 Recall@5 衝到 75%(冠軍 hybrid_bm25 只有 64%)。cross-encoder 把更多相關段落拉進 top-5。
  • 撈得準:reranker 反而退步。nDCG 從 0.876 掉到 0.831、C@3 從 100% 掉到 80%、MRR 打平沒進步。它有時把原本排第一的正解往下擠。
  • 而且慢 16 倍。cross-encoder 要逐一讀 20 個候選段落,10 題從 ~21 秒變成 ~330 秒(CPU)。線上每題多花約 1.5 秒。

逐題看:reranker 只能重排「已經撈到的」

兩個關鍵細節,解釋了為什麼 reranker 沒有無腦贏:

① reranker 撈不回第一階段的 miss。 DN80 這題,疊在 dense 上的 rerank 還是 0(未命中)——因為 dense 根本沒把含 DN80 的段落放進 top-20 候選,cross-encoder 沒得重排。但疊在 hybrid_bm25 上(候選裡有 DN80)就變 rank 1。reranker 只是第二階段的排序器,救不了第一階段沒撈到的東西——所以底層檢索(召回)永遠比 reranker 重要。
② reranker 會弄糟本來對的題。「電弧爐有哪些節能做法」dense 本來 rank 1,被 reranker 擠到 rank 5;「抽水機進水管漏氣」hybrid_bm25 本來 rank 1,被擠到 rank 4。cross-encoder 的語意判斷,跟我們用「片語命中」定義的 gold 不完全一致,幾題反而被它排壞。

結論分軸:如果下游 agent 只吃前幾筆、要「撈得準」,直接用 hybrid_bm25 就好,不要加 reranker(又快又準);如果要把所有相關段落塞進一個窗口給下游 LLM、要「撈得全」,rerank_hybrid_bm25 的 recall 最高,但要付 16 倍延遲。這推翻了「加 reranker 一定更好」的直覺。

三個改動的總帳

改動 效果 值不值得
換古典 BM25 當 sparse 腿(Step 1b) nDCG 0.803→0.876、料號題救回,幾乎零成本(重用 dense 快取) ✅ 直接做
調 chunk size / overlap(Step 2) 沒有配置贏過 baseline 700/120 ⚠️ 別浪費時間
加 cross-encoder reranker(Step 4) Recall 升、排序精度降、慢 16 倍——看你要準還是要全 ⚠️ 看目標

如果只能挑一個當生產預設:hybrid_bm25(dense + 古典 BM25,RRF 融合,chunk 700/120,不加 reranker)。它在「撈得準」的三個指標上都是冠軍,料號題也顧到了,而且快。

誠實的坑:沒做的與尺的極限

路線圖裡還有一個 Step 3:表格 row 前綴(把表格每列前面補上表頭/情境,讓檢索有語意錨點)。這一步原本我沒做——因為做了也測不了(後來還是補做了,見文末 Step 3 補做)。這個語料裡唯一的表格是通用的 Excel 月份 demo 和一份技巧清單,不是設備規格表;而且 gold 10 題裡沒有一題是表格查詢。沒有量表格的尺,跑 Step 3 只是空轉。誠實地標記為「等有真實表格文件 + 表格 gold 再做」。

還有一個貫穿兩篇的殘酷現實:這把尺只有 10 題,統計上證明不了什麼。10 題的 McNemar 檢定幾乎測不出顯著。上面看到的差異,方向性是可信的(尤其 DN80 這種「一路撈到、其他撈不到」的鐵證),但小數點的高低不要當真。所以下一個真正的高優先項,不是再加檢索花招,而是把 gold 從 10 題擴到上百題,讓尺變準——在壞尺上調參,只會追到幻影(這個教訓,更早那篇 27% 假象的除錯記錄已經踩過一次)。

下一步與心法

  • 檢索技術的 hype,要用自己的尺量。「bge-m3 免費料號匹配」「加 reranker 一定更好」「調 chunk size 能救命」——三個熱門說法,在這個真實語料上一個假、一個看目標、一個白工。
  • 一次只動一個因子。不然你分不清是誰的功勞、誰的鍋。
  • 召回 > 重排。reranker 救不了第一階段沒撈到的段落,先把底層檢索的召回做好。
  • 先修尺,再調參。下一篇會是把 gold set 擴到上百題,把統計力補起來,再回頭重驗這三個結論。

所有結果都來自同一個開源風格的消融 harness(ablation.py),CPU 可跑、快取可重用、一行指令換一個因子。方法比單一數字重要——尺對了,結論才站得住。

後記:把 gold 擴到 100 題,結論怎麼變

整篇文章反覆講一句話:10 題 gold 幾乎證明不了任何事。寫完之後我決定實踐它——把評估的尺從 10 題擴到 100 題可量測(62 題自然語言 + 28 題料號 + 10 題原題),再加 8 題該 abstain。做法:料號題從語料自動挖掘(gold 片語=料號本身,存活保證);自然語言題請多個 agent 讀真實手冊段落、寫現場工人問句 + 從段落取一段逐字的答案錨點片語;每一題的片語都用程式驗過「真的存在於某個 chunk」且「只出現在少數幾片」(夠獨特、不是泛用詞),0 幽靈片語。然後同一套 harness 重跑三個關鍵對照。

結果很有教育意義——一個結論被坐實,一個被推翻,而被推翻的正是我自己在上面 Step 4 寫的。

模式(100 題) Hit@5 全體 料號題 自然語言題 nDCG@5
dense78%54%87%0.670
hybrid_bm2589%86%89%0.792
rerank_hybrid_bm2597%96%97%0.880

McNemar 配對顯著性檢定(hit@5,精確二項雙尾):

對照 誰贏幾題 p 值 10 題時
hybrid_bm25 vs bge-m3 hybrid
(只換 sparse 腿,最乾淨的隔離)
36 : 1<1e-910 題也 0 勝
hybrid_bm25 vs dense14 : 30.013p≈0.06 不顯著
rerank_hybrid_bm25 vs hybrid_bm259 : 10.022看似兩面刃
rerank_hybrid_bm25 vs dense20 : 1<0.0001
補一個更乾淨的對照(有讀者問我為什麼沒做):要證明「sparse 腿選錯」,最該比的不是 hybrid_bm25 vs dense(那混了「要不要加 sparse 腿」和「換哪條腿」兩件事),而是兩個 hybrid 直接對打——固定 dense 腿 + RRF 融合不變,只換 sparse 來源。100 題實測 hybrid_bm25 贏 36 題、只輸 1 題(p≈5×10⁻¹⁰),sparse 腿就是禍首,鐵證。更關鍵:這個對照揭露了 dense 對照藏住的真相——bge-m3 hybrid 不是「沒幫忙」,是主動有害:全體從 dense 的 78% 掉到 54%,傷害集中在自然語言題(87%→56%,bge-m3 的 sparse 把 NL 查詢拉去表面字匹配的不相關段落),料號題則跟 dense 一樣 54%(零貢獻)。古典 BM25 換上去,NL 和料號兩頭都贏。——我一開始為了省時間、假設「bge-m3 hybrid 反正還是爛」就沒在 100 題重跑它,這正是本文一直在罵的偷懶,被讀者抓到了。

坐實的:hybrid_bm25 > dense

10 題時這個結論的 McNemar 只有 p≈0.06(測不出顯著);100 題後變 p=0.013,正式顯著。料號軸尤其鐵:dense 在料號題只有 54%(語意向量對料號無能為力),hybrid_bm25 拉到 86%。這條路是對的。

被推翻的:reranker 不是兩面刃,是清楚的贏

上面 Step 4 我根據 10 題下結論:reranker 犧牲排序精度換 recall、「要準就別加」。100 題打臉了我:rerank_hybrid_bm25 在 C@1/3/5、Recall、nDCG 每一個指標都是最高,McNemar 對 hybrid_bm25 也顯著(p=0.022)。為什麼會反轉?10 題時,reranker 把兩題自然語言(電弧爐、抽水機)往下擠的雜訊,主導了那個小到不行的樣本,害 nDCG 看起來降;放大到 100 題,reranker 對絕大多數題的普遍拉抬壓過那兩題,真相才顯出來。唯一不變的 caveat:reranker 在 CPU 上慢 37 倍(100 題從 90 秒變 55 分鐘;我先前這裡誤植為「16 倍」——那是 10 題的比值,100 題實測是 3295s/90s≈37×),延遲成本是真的,要準到極致才值得付。

真正的心法:「先修尺、再調參」不是口號。我在同一篇文章裡一邊喊「10 題證明不了什麼」,一邊還是根據 10 題對 reranker 下了錯的結論——直到把尺擴到 100 題才抓到。評估集的統計力,比任何一個檢索花招都先決。下一次想調 RAG?先問你的尺夠不夠大。

走完最後一步:表格前綴 + 完整路線圖總表

前面 Step 3(表格 row 前綴)我標記為「測不了」跳過了。既然要把路線圖走完,還是把它補上——用語料裡僅有的兩個 Excel 表格檔(一份月份表 + 一份產品清單)當測試對象,誠實說明它的侷限。

Step 3:表格 row 前綴——救孤兒 row

痛點:xls/xlsx 抽出來後每一列各自切成一片。其中一份檔案更慘——產品「名稱」和「描述」被拆成不同的孤兒 chunk,像「Make instant backups, sort sheets」這行單獨被撈出時,完全不知道它在講哪個產品、屬哪個類別。技術很單純:給每個表格行前綴「《檔名》|最近的類別表頭|」,原文保留在後面(片語仍存活)。做 A/B:同一組表格行,baseline(原樣)vs prefixed(加前綴),只重編這 51 個表格 chunk,其餘 1474 片沿用,dense 檢索測 6 題表格 gold。

6 題表格 gold(dense)Content-Hit@1@3@5
baseline(每列各自切)4/66/66/6
prefixed(加類別前綴)5/66/66/6

小幅有用、大致中性。前綴把一題邊界案例從 rank 2 拉到 rank 1(C@1 4→5),@3/@5 沒變。誠實解讀:這份語料的描述文字本身就夠「自描述」,dense 靠描述內容就找得到,前綴只救了一個邊界。前綴的價值取決於你的表格 cell 自不自描述——如果 cell 是「80」這種光禿數字(需要「DN|80」才有意義),前綴會差很多;本語料剛好沒有這種硬表格。這也是為什麼一開始說「測不了」——沒有真正的規格硬表 + 表格 gold,只能給一個有侷限的結論。

完整路線圖總表:哪些改動真有用

⚠️ 這張表下方部分判定經事後審查修正——尤其「chunk size 白調」被一個 factorial 交叉實驗推翻(700/120 其實顯著優於 450)。完整修正見文末補課
步驟改動100 題實測結論判定
1dense → bge-m3 hybridhybrid 全輸(sparse 腿選錯)🚫 別用 bge-m3 sparse
1bsparse 腿換古典 BM25hybrid_bm25 顯著贏 dense(p=0.013),料號題 54%→86%✅ 一定做
2調 chunk size / overlap無配置贏過 baseline 700/120⚠️ 白調
3表格 row 前綴小幅有用(C@1 4→5/6),看 cell 自不自描述⚠️ 視表格而定
4cross-encoder reranker100 題下每指標最高、顯著(p=0.022),Hit@5 97%✅ 準確優先就做
gold 10 → 100 題讓上面所有結論從「測不出」變「顯著」;還推翻了 Step 4✅ 最先做

最終建議:生產要怎麼配

① 有 GPU / 能吃延遲、要最高準確 → rerank_hybrid_bm25
dense + 古典 BM25 用 RRF 融合出候選,再用 cross-encoder 重排。100 題 Hit@5 = 97%。代價:CPU 上慢 37 倍(100 題實測;有 GPU 就不痛)。
② 純 CPU / 要快、又要顧料號 → hybrid_bm25(不加 reranker)
Hit@5 = 89%、料號 86%,10 題只要 21 秒。CP 值最高的預設。
③ 別做的:別開 bge-m3 的 learned sparse 做料號、別花時間調 chunk size。表格前綴只在你有「光禿 cell 硬表」時才值得。

路線圖到這裡走完了。回頭看,最大的收穫不是任何單一個檢索技巧,而是那把尺:從 10 題擴到 100 題,才讓「哪個改動真有用」這個問題有了可信的答案——甚至推翻了我自己中途下的結論。先修尺,再調參。

補課:審查團隊抓出的方法論漏洞,與 factorial 修正

這篇發出去後,我請幾個獨立審查者專門挑一個毛病:整篇的消融是「貪婪串接」——每一步都疊在上一步的贏家頭上、而且全部鎖死在 chunk 700/120——不是真正的「因子交叉」。三個審查者獨立咬到同一條:最刺的就是「chunk size 白調」這個結論,它只在 dense、只在 10 題 上測過,卻被寫成跨所有檢索模式的生產通則。而我自己在文章裡明明喊著「10 題證明不了什麼」——等於拿我自己判死刑的樣本量,去替 chunk size 定罪。這是公平的批評,我接受。

所以補一個真正的 factorial:retrieval{dense, hybrid_bm25, rerank_hybrid_bm25} × size{700, 450},全跑在 100 題上(先驗過 gold 片語在兩種切法下都 90/90 全存活,所以差異是真檢索效果,不是片語被切斷的假象)。

模式(nDCG@5, 100 題)chunk 700/120chunk 450/120700 vs 450
McNemar
dense0.6700.603p=0.092 不顯著
hybrid_bm250.7920.748p=0.344 不顯著
rerank_hybrid_bm250.8800.820p=0.039 顯著
  • 「chunk size 白調」錯了,要修正。在真正要上線的頂堆疊(rerank_hybrid_bm25)上,700/120 顯著優於 450(p=0.039)——縮小 chunk 會顯著受傷。正確結論是:700/120 是最佳、別往小縮;只是往上調不出更好的,不等於 chunk size 不重要。之前的「白調」是 dense@10 題那個弱樣本的產物。
  • 好消息:沒有交互作用。三個模式偏好 700/120,而且模式排序在 700 和 450 上完全一致(rerank > hybrid_bm25 > dense)。所以「hybrid_bm25 贏 dense」「reranker 有用」這兩個結論跨 chunk size 穩定,反而更站得住。
  • 其他誠實補正:(a) reranker 的延遲我先前寫「16×」是 10 題的比值,100 題實測是 ~37×(90s→3295s),已改;(b) 招牌「料號 54%→86%」該比的對照組是 bge-m3 hybrid(見後記直接對照 36:1),不是 dense;(c) 表格前綴(6 題)、bge-m3 hybrid 全輸(部分 10 題)這些判定樣本仍小,屬「暫定」,別跟 100 題+顯著性的結論等量齊觀;(d) reranker 的候選深度 RR_N=20 尚未 ablate,「reranker 就做」嚴格說只在這個深度成立。
這才是最大的一課,而且是雙重的。第一課:消融要做因子交叉(縱向:固定一軸、掃另一軸),不是貪婪串接(每步疊在上一步贏家上)——否則早期被淘汰的組合永遠不再回來驗,交互作用被系統性丟光。第二課更謙卑:我在一篇通篇講「先修尺、別被小樣本騙」的文章裡,自己既串接又混用不同樣本量,還是被一組獨立審查者抓包。再嚴謹的自我要求,都比不上讓別人來挑。

放大來看:這一切優化的是「資料」,不是 AI

退一步看,這整個系列在調的,其實不是那顆 LLM,而是「AI 回答之前的資料處理」。這是很多人做 RAG 一直搞錯的地方:以為換一顆更貴、更聰明的模型就會變好。不會。RAG 答得好不好,大約 80% 決定在「資料怎麼進來、怎麼撈出來」這兩段,不是模型多聰明。換更強的 LLM,救不了「進來是亂碼」或「撈錯片」——垃圾進、垃圾出。

一條 RAG 管線的骨架:PDF → ①讀進來(解析)→ 切片 → 索引 → ②撈出來(檢索)→ 重排 → 餵 AI → 答案。本系列從頭到尾在調的是 ②撈出來(檢索):dense vs BM25、hybrid、reranker、chunk size。另一半 ①讀進來(解析) 同樣關鍵——把爛掃描件、故障表變成乾淨結構化文字(這是另一個工具的戰場,例如把規格表的欄列保住,而不是拍扁成一排對不回型號的數字)。兩段都是「資料」,都不是 AI 本身。

鐵三角:一台把每一格收斂到最佳的機器

把整套方法收斂成三個角,湊齊就是一台「收斂機器」:

是什麼
可換零件管線每一格都有候選工具(解析 / 切片 / embedding / sparse / 融合 / reranker),可插拔
黃金尺(gold set)客觀量「對我的語料,哪個零件好」——本系列反覆強調:先修尺,再調參
消融法一次只換一格、配對顯著性檢定,決定每格的贏家(還要因子交叉,別貪婪串接)

這三個湊齊,就是一台自動把管線每一格收斂到「對你這批語料的最佳解」的機器。本系列的每一步(檢索模式、BM25、chunk size、reranker、擴 gold、factorial)都是這台機器在轉。

最後一個心法,也是這台機器真正值錢的地方:「最佳工具」會隨語料變——我們親眼看到 chunk size 在這語料白調、reranker 要 100 題才顯出價值。所以真正的資產不是一套「凍結的最佳配置」,而是這台「黃金尺 + 消融」的收斂機器:換一批新語料(別的廠、別的文件),它能重新量、重新選最佳零件。別人賣你固定的 RAG;你要有的是「能對任何語料自己收斂到最佳」的機器。這,才是護城河。

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *