API 開發
RAG 文本切片怎麼切?四種 chunking 策略一次講清楚
RAG 文本切片怎麼切?四種 chunking 策略一次講清楚
上一篇我們講了 RAG 為什麼存在:先把文件切成小塊,提問時只送相關的段落給模型。這篇要處理整條管線的第一道關卡:到底怎麼切。
別小看這一步。切片的方式直接決定整個系統的品質,切壞了,後面的檢索與生成做得再好也救不回來。
你將學到什麼
切不好會怎樣
一個「bug」字義誤導檢索的具體例子。
四種切法
按長度、按結構、按句子、按語意的原理與程式碼。
overlap 的作用
為什麼相鄰切塊之間要重疊一小段。
怎麼選策略
依文件給你的保證,挑出合適切法的判斷準則。
切錯一刀,整個系統跟著錯
先看一個具體情境。你有一份文件,裡面同時有醫學研究與軟體工程兩個章節。醫學章節剛好提到一種沒見過的「bug」(病菌),軟體章節則在講系統裡的臭蟲。
如果切片切得不好,使用者問「工程師今年修了幾個 bug」,檢索出來的可能是醫學研究的段落,只因為那一段也出現了 bug 這個字。
不相關的段落被塞進 prompt,模型就會拿著錯的材料,一本正經地答錯。記住這條因果鏈:檢索只能從你切出來的塊裡挑,塊本身切壞了,再聰明的檢索也只能在壞塊裡挑一個沒那麼壞的。
更麻煩的是,這種錯誤很難在事後察覺:使用者只看到答非所問,不會知道問題出在前處理的那一刀。這就是為什麼切片策略值得認真選。以下是三大類做法,外加一種實用的折衷。
按長度切:最簡單,也最不挑文件
按長度切(size-based chunking)就是把文字切成等長的字串。它最好實作、什麼文件都適用,但缺點也很直白:
- 單字或句子會在中間被硬生生切斷。
- 切塊少了前後文,脈絡不完整。
- 章節標題可能跟它的內文被切散在兩塊裡。
解法是加上 overlap:讓每個切塊多含一小段鄰居的內容。這樣邊界上的句子有機會在某一塊裡是完整的,每塊也帶著一點周圍的脈絡。代價是切塊總量會多一些、儲存與計算也跟著多一點,但換來的邊界品質通常划算。
基本實作長這樣:
def chunk_by_char(text, chunk_size=150, chunk_overlap=20):
chunks = []
start_idx = 0
while start_idx < len(text):
end_idx = min(start_idx + chunk_size, len(text))
chunk_text = text[start_idx:end_idx]
chunks.append(chunk_text)
start_idx = (
end_idx - chunk_overlap if end_idx < len(text) else len(text)
)
return chunks
按結構切:最乾淨,但要文件配合
按結構切(structure-based chunking)是順著文件的天然結構下刀:標題、段落、章節。拿 Markdown 文件來說,直接照標題符號切就行:
def chunk_by_section(document_text):
pattern = r"\n## "
return re.split(pattern, document_text)
這種切法給你最乾淨、最有意義的切塊,每一塊就是一個完整的章節。但它有個前提:你得對文件結構有把握。現實世界裡很多文件是純文字或 PDF,根本沒有清楚的結構記號,這招就使不上力。
判斷方式很簡單:你能不能對「每份進系統的文件都長這樣」打包票?公司內部的制式報告可以,使用者上傳的任意檔案就不行。
按語意切與按句子切:兩種折衷
按語意切(semantic-based chunking)是最講究的做法:先把文字拆成句子,再用自然語言處理判斷相鄰句子的關聯程度,把相關的句子聚成一塊。它產出的切塊品質最好,但計算成本高,實作也最複雜。
實務上有個好用的中間路線:按句子切。先用正規表示式把文字拆成句子,再固定幾句組成一塊,一樣可以加 overlap:
def chunk_by_sentence(text, max_sentences_per_chunk=5, overlap_sentences=1):
sentences = re.split(r"(?<=[.!?])\s+", text)
chunks = []
start_idx = 0
while start_idx < len(sentences):
end_idx = min(start_idx + max_sentences_per_chunk, len(sentences))
current_chunk = sentences[start_idx:end_idx]
chunks.append(" ".join(current_chunk))
start_idx += max_sentences_per_chunk - overlap_sentences
if start_idx < 0:
start_idx = 0
return chunks
怎麼選:看你的文件給了什麼保證
選策略的關鍵不是哪招最炫,而是你的文件能給你什麼保證:
| 策略 | 適合的情境 | 取捨 |
|---|---|---|
| 按結構切 | 格式有把握的文件,例如公司內部的制式報告 | 品質最好,但文件沒結構就不能用 |
| 按句子切 | 大多數一般的文字文件 | 折衷之選,實作與品質都中等 |
| 按長度切 | 任何內容,包含程式碼與格式混亂的文件 | 最可靠的保底,品質不完美但穩定 |
| 按語意切 | 願意投入計算成本追求檢索品質的場景 | 切塊最準,但最貴也最複雜 |
我自己的習慣是把這個決定當成可以回頭改的假設:先用最穩的切法讓整條管線跑通,再拿真實提問的檢索結果回頭調整。切片不是一次定生死的決定,而是一個可以迭代的參數。
記住:沒有唯一最佳的切片策略。答案取決於你的文件長相、使用情境,以及你願意在實作複雜度與切塊品質之間怎麼交換。下一篇,我們來看切好的塊要怎麼被「找到」:embedding 與向量檢索。
延伸學習
ChatGPT 很強,但真正讓你下班的是 Google
六小時完整實錄。從「AI 很厲害,為什麼你還是每天加班」這個問題出發,把 Google Workspace 當成真正的工作平台重新設計一次流程 ── Sheets 的資料結構、Drive 與 Docs 的文件流、Gmail 與 Calendar 的通知系統,再用 Apps Script 讓它自己跑起來,最後收斂成一張屬於你自己的 AI 工作能力地圖。
NT$ 4,599
寫給升國一的你的筆記術
寫給剛升上國中的你:筆記不是寫給老師看的,是寫給考前的自己看的。18 章 85 課圖文,從「為什麼要寫」講到七科各自怎麼記,附 78 份可以印出來寫的練習單,以及 80 課家長專區與 34 張三年筆記養成路徑圖。沒有閱讀期限,國一買、國三還在。
NT$ 3,599

