五種RAG分塊策略詳解 + LlamaIndex代碼演示

先前文章中提到,不斷優化原始文檔解析和分塊策略是控制變量法下,是提高最后檢索效果天花板的務實做法,前面已經介紹了 MinerU vs DeepDoc 在文檔解析方面的效果對比。
關于文檔解析部分簡單的結論是,MinerU 無疑是值得關注和嘗試的一個文檔解析框架,但具體效果還要結合特定項目文檔做仔細橫評。
我目前在常規項目中,主要是對照使用 DeepDoc 和 MinerU 兩個方法。后續計劃花時間再針對 PaddleOCR、Mistra OCR 等工具做進一步的測評,感興趣的可以蹲一下。
這篇試圖說清楚:
業界常用的五種 RAG 分塊策略核心思想、LlamaIndex 代碼演示以及 RAGFlow/Dify 等框架實踐思路。

本篇中 RAG 分塊相關圖示均來自https://blog.dailydoseofds.com/p/5-chunking-strategies-for-rag 下述相關圖片出處不再做單獨說明
以下,enjoy:
1、RAG 與分塊的重要性
在正式開始前,老規矩溫故知新,先來復習下傳統 RAG 出現的背景、典型 RAG 流程以及分塊的重要意義所在。
1.1典型 RAG 流程
為了讓大模型能夠回答私有知識的問題,拋開高成本的 LLM 微調方法外,我們可以選擇在提問時,直接傳入私有知識相關的參考信息,這種方法更加簡便且高效。

然而,這種方法的缺點很明顯。畢竟提示詞長度有限,當私有數據量過大時,傳入所有背景信息可能導致提示詞過長,從而影響模型的處理效率或達到長度上限。
而 RAG 巧妙地將 LLM 的生成能力與外部知識庫的信息檢索能力結合起來:

接收問題 (Query): 用戶向系統提出查詢。
信息檢索 (Retrieval): 系統在向量數據庫或搜索引擎中查找與問題相關的文檔片段。
上下文增強 (Augmentation): 將檢索到的信息片段整合進發送給 LLM 的提示 (Prompt) 中。
答案生成 (Generation): LLM 基于原始問題和增強的上下文生成最終回答。
在這個流程中,要實現高質量的檢索,需要對原始知識文檔進行有效的預處理,這也就引出了 RAG 流程中一個至關重要的準備工作——文檔分塊 (Chunking)。
1.2為啥分塊這么重要
分塊,簡單來說就是將原始文檔按照某種策略分割成更小的、語義相對完整、適合進行索引和檢索的文本單元(Chunks)的過程。 這一步通常在文檔被送入向量數據庫進行 Embedding(向量化)之前完成。分塊策略選擇和執行質量,是構建一個 RAG 應用的準確性基礎。結合以下三種情形,會更好理解些:

分塊過大: 可能導致檢索到的單個塊包含過多無關信息(噪音),增加了 LLM 理解上下文的難度,降低了答案的精確性,甚至可能超出 LLM 的上下文窗口限制。
分塊過小或切分不當: 可能破壞原文的語義連貫性,導致一個完整的知識點被拆散到多個塊中。檢索時可能只召回了部分信息,使得 LLM 無法獲得完整的背景,難以生成全面、準確的答案。
未能適應文檔結構: 不同的文檔類型(如論文、手冊、報告、網頁)具有不同的結構特點。死板的分塊方式可能無法有效利用標題、列表、表格等結構信息,影響信息提取的完整性。
2、五種分塊策略詳解
2.1固定大小分塊
核心思想
這是最直觀、最簡單的分塊方式。按照預先設定的固定長度( 最大 token 數)將文本進行切割。為了盡量減少信息損失,通常會在相鄰的塊之間保留一部分重疊內容(Overlap)。

優點
實現簡單,處理速度快。
塊大小統一,便于批量處理和管理,能精確控制輸入 LLM 的 token 數量。
缺點
容易在句子或語義完整的表達中間被“攔腰斬斷”,破壞文本的語義連貫性。
可能將關聯緊密的關鍵信息分散到不同的塊中,影響后續檢索和理解的完整性。
適用場景
處理結構簡單、對語義連貫性要求不高的文本。
需要快速實現或作為基線對比策略時。
對塊大小有嚴格限制的應用。
2.2語義分塊
核心思想
嘗試根據文本的語義含義進行切分,將語義關聯緊密的句子或段落聚合在一起。通常做法是先將文本分成基礎單元(如句子),然后計算相鄰單元的語義相似度(例如通過嵌入向量的余弦相似度),如果相似度高于某個閾值,則合并這些單元,直到相似度顯著下降時才創建一個新的塊。

優點
能更好地保持文本的語義連貫性和上下文的完整性。
生成的塊通常包含更集中的信息,有助于提升檢索精度。
為 LLM 提供更高質量的上下文,有助于生成更連貫、相關的回答。
缺點
實現相對復雜,依賴于嵌入模型的質量和相似度閾值的設定。
閾值可能需要根據不同的文檔類型進行調整和優化。
計算成本通常高于固定大小分塊。

適用場景
對上下文理解和語義連貫性要求較高的場景,如問答系統、聊天機器人、文檔摘要等。
處理敘事性或論述性較強的長文本。
2.3遞歸分塊
核心思想
采用“分而治之”的策略。首先嘗試使用一組優先級較高的、較大的文本分隔符(如段落、章節標記)來分割文本。然后,檢查分割出的每個塊的大小。如果某個塊仍然超過預設的大小限制,就換用下一組優先級更低、更細粒度的分隔符(如句子結束符、換行符)對其進行再次分割,此過程遞歸進行,直到所有塊都滿足大小要求。

優點
在保持一定語義結構的同時,能靈活地控制塊的大小。
比固定大小分塊更能尊重原文的自然結構。
適應性較好,是一種常用的通用分塊策略。
缺點
實現比固定大小分塊更復雜一些。
需要預先定義好一組有效的分隔符及其優先級順序。

注:兩個段落(紫色)被識別為初始塊,接著第一個段落再被拆成更小的塊。這種方式既保留了語義完整性,又能靈活控制分塊大小。
適用場景
適用于大多數類型的文檔,特別是那些具有一定層次結構(如章節、段落、列表)但又不完全規整的文檔。
是許多 RAG 框架(如 LangChain)中推薦的默認策略之一。
2.4基于文檔結構的分塊
核心思想
直接利用文檔本身固有的、明確的結構元素(如標題層級、章節、列表項、表格、代碼塊、Markdown 標記等)來定義塊的邊界。目標是使每個塊盡可能對應文檔中的一個邏輯組成部分。

優點
能最大程度地保留文檔的原始邏輯結構和上下文信息。
塊的劃分方式自然,符合人類的閱讀和理解習慣。
缺點
強依賴于文檔本身具有清晰、一致的結構,這在現實世界的文檔中并非總是得到滿足。
生成的塊大小可能差異巨大,某些塊可能非常長,超出 LLM 的處理限制。
通常需要結合遞歸分塊等方法來處理過大的塊。

適用場景
特別適合處理結構化或半結構化特征明顯的文檔,如技術手冊、法律合同、API 文檔、教程、帶有章節的書籍、格式良好的 Markdown 文件等。
注:某些結構下的分塊長度差異較大,可能會超出模型支持的 token 限制。可以考慮結合遞歸切分法來處理。
2.5基于 LLM 的分塊
核心思想
不再依賴固定的規則或啟發式方法,而是利用大型語言模型 (LLM) 自身的理解能力來判斷文本的最佳分割點??梢酝ㄟ^設計合適的提示 (Prompt),讓 LLM 將文本分割成語義上內聚且與其他部分相對獨立的塊。

優點
理論上具有最高的潛力,能實現最符合語義邏輯的分割效果,因為 LLM 能更深入地理解文本內容、上下文和細微差別。
缺點
計算成本最高昂,處理速度最慢,因為涉及到多次調用 LLM。
需要精心設計有效的 Prompt 來指導 LLM 完成分塊任務。
同樣受到 LLM 本身上下文窗口大小的限制。
適用場景場景:
對分塊質量有極致要求,并且能夠承擔高昂計算成本和較慢處理速度的場景。
用于處理語義關系特別復雜、傳統方法難以處理的文本。
也可能作為更復雜策略(如生成摘要樹、構建知識圖譜)的一部分。
3、LlamaIndex 分塊策略演示
為了更好的理解五種不同的分塊策略原理和實現細節,下面以 LlamaIndex 為例,展示五種策略對應的示例 python 代碼。
在具體介紹前,先補充說明兩個問題:LlamaIndex 是什么?以及為什么不選擇 RAGFlow/Dify 等框架來進行分塊策略的演示?
3.1LlamaIndex 掃盲介紹
LlamaIndex 也是一個非常流行的開源數據框架,與 Ragflow 不同,LlamaIndex 更像是一個靈活的工具箱或庫,提供了豐富、模塊化的組件來處理 RAG 流程中的各個階段,特別是數據加載、轉換(包括分塊/節點解析)、索引和查詢。
主要組件特點
數據連接器 (Data Connectors): 支持從各種來源(文件、API、數據庫等)加載數據。
數據索引 (Data Indexes): 提供多種索引結構(如向量存儲索引、列表索引、關鍵詞表索引、樹狀索引、知識圖譜索引等)來組織數據,以適應不同的查詢需求。
節點解析/文本分割 (Node Parsing / Text Splitting): 這是 LlamaIndex 處理分塊的核心部分。它提供了多種可配置的文本分割器 (Text Splitters),讓開發者可以精細地控制文檔如何被分割成“節點 (Nodes)”(LlamaIndex 中對“塊/Chunk”的稱呼)。
檢索器 (Retrievers): 基于索引,提供不同的方式來檢索與查詢相關的節點。
查詢引擎 (Query Engines): 結合檢索器和 LLM,構建端到端的查詢和響應能力。
代理 (Agents): 構建更復雜的、可以自主規劃和使用工具的 LLM 應用。
模塊化和可擴展性: 開發者可以方便地組合、替換或自定義各個組件。
演示底層機制的優勢
LlamaIndex 的設計哲學就是提供明確的、可編程的接口。對于分塊(節點解析),我們可以直接在代碼中:
導入特定的 TextSplitter 類: LlamaIndex 提供了與多種分塊策略對應的類。
實例化分割器并配置參數: 顯式地設置塊大小、重疊大小、分隔符、模型(用于語義分割)、結構解析規則等。
調用分割器的 split_text 或類似方法: 將原始文本輸入,直接獲得分割后的節點列表。
下文會通過具體的 Python 代碼清晰和直接地展示五種分塊策略的實現。
3.2高集成度的局限
像 Ragflow、Dify 這樣封裝度較高的框架,提供的開箱即用的端到端解決方案,必然會通過 UI 或 API 參數將底層的實現細節抽象化。
這雖然方便用戶快速搭建應用,但對于希望理解“引擎蓋”下面發生了什么的用戶來說會不夠透明,難以窺見不同策略的具體代碼實現和細微差別。具體來說:
抽象層級的差異: Ragflow/Dify 等平臺為了易用性,會將底層的分塊邏輯封裝在更高級的選項(如 Ragflow 的 chunk_method 下拉菜單和相關配置)。用戶無法直接編寫或修改 LlamaIndex 那樣的底層分塊代碼。
平臺特定實現: 即便 Ragflow 提供了一個名為 "Paper" 的分塊方法,其內部的具體實現邏輯、使用的分隔符、遞歸策略等細節,與 LlamaIndex 的 MarkdownNodeParser 組合有所不同。
配置而非編碼: 在這些平臺上,用戶更多的是通過圖形界面 (UI) 或平臺的 Python API 來配置分塊選項,而不是直接編寫分塊算法的代碼。
3.3LlamaIndex 五種分塊策略代碼參考
固定大小分塊:
可以使用SentenceSplitter(設置 chunk_size控制token數,chunk_overlap 控制重疊) 或 TokenTextSplitter。代碼會清晰展示如何設置大小和重疊。
from llama_index.core.node_parser import SentenceSplitter
splitter = SentenceSplitter(chunk_size=128, chunk_overlap=20)
nodes = splitter.get_nodes_from_documents(documents) # 'documents' 是加載后的文檔對象
# 可以打印 nodes[0].get_content() 查看第一個塊的內容語義分塊:
LlamaIndex 提供了 SemanticSplitterNodeParser。需要配置一個嵌入模型,并設定相似度閾值 (breakpoint_percentile_threshold)。
from llama_index.core.node_parser import SemanticSplitterNodeParser
from llama_index.embeddings.openai import OpenAIEmbedding # 或其他嵌入模型
embed_model = OpenAIEmbedding()
splitter = SemanticSplitterNodeParser(
buffer_size=1, breakpoint_percentile_threshold=95, embed_model=embed_model
)
nodes = splitter.get_nodes_from_documents(documents)遞歸分塊
SentenceSplitter 本身就具有一定遞歸特性,它會按順序嘗試使用不同的分隔符(默認從 \n\n 到 . 到 等)??梢宰远x paragraph_separator 等參數。更復雜的遞歸(如構建摘要樹)可能涉及 HierarchicalNodeParser。
from llama_index.core.node_parser import SentenceSplitter
# 默認行為就是遞歸的,可以定制分隔符
splitter = SentenceSplitter(
separator=" ", # 可以簡化分隔符用于演示
chunk_size=256,
chunk_overlap=30,
paragraph_separator="\n\n\n", # 示例:自定義段落分隔符
)
nodes = splitter.get_nodes_from_documents(documents)基于文檔結構的分塊
LlamaIndex 有專門的 MarkdownNodeParser 或 JSONNodeParser。對于 PDF 中提取的 Markdown,MarkdownNodeParser 能很好地利用標題、列表等結構。
from llama_index.core.node_parser import MarkdownNodeParser
parser = MarkdownNodeParser()
nodes = parser.get_nodes_from_documents(documents) # 假設 documents 是加載的 Markdown 內容
# 對于從 PDF 解析得到的 Markdown 尤其有效基于 LLM 的分塊
雖然沒有一個現成的 LLMTextSplitter,但 LlamaIndex 的靈活性允許我們構建自定義的 NodeParser,在其中調用 LLM 來決定分割點或生成摘要塊。例如結合 LLM 進行章節總結或主題劃分,或者利用 LLM 對元數據進行分析來指導分割。這部分后續我結合具體案例再做演示。
4、寫在最后
4.1如何在 Ragflow/Dify 中應用不同分塊策略
上述 LlamaIndex 的演示只是提供了評估的思路和方向,不能替代在目標平臺上的實際驗證。各位可以利用上述LlamaIndex 演示中的原理,去解讀 Ragflow/Dify等框架提供的分塊選項。
以RAGFlow為例,相關分塊選項和上述的五種分塊策略很難一一映射,結合官方的python api解讀參考如下:
固定大小分塊: Ragflow 的 "naive" 方法最接近這個概念,尤其是當配置了 chunk_token_num 時。它可能也結合了 delimiter 進行分割。
語義分塊: API 文檔中沒有直接命名為 "semantic" 的選項。然而,某些高級方法(像 "qa"、"knowledge_graph" 某種程度上)可能隱含了語義理解。但 API 沒有提供一個像 LangChain 那樣明確的 Semantic Splitter 選項。
遞歸分塊: 像 "book" 或 "paper" 這樣的方法內部猜測是采用了遞歸或基于結構的分塊邏輯,會先嘗試按大綱(章節、標題)分割,如果塊太大再按段落或句子遞歸分割。但API 文檔沒有明確說明其內部遞歸邏輯。
基于文檔結構的分塊: "paper", "book", "laws", "presentation", "table" 這些方法明顯是針對特定文檔結構的,它們會優先利用文檔的固有結構(標題、章節、表格結構、幻燈片等)來定義塊邊界。
基于 LLM 的分塊:API 中沒有通用的、直接讓 LLM 決定分塊邊界的選項。

這里需要特別說明的是,在RAGFlow中創建知識庫環節,自動關鍵詞/問題提取不是LLM-based Chunking,而是分塊后的 LLM 增強。但RAPTOR(遞歸摘要樹,多粒度檢索) 策略涉及對初始塊進行聚類,并使用 LLM 對聚類進行摘要,生成新的、更高層次的“摘要塊”。 這個策略可以被認為是“基于 LLM 的分塊”的一種高級形式或應用。雖然它可能建立在初始分塊之上,但它確實利用 LLM 生成了新的、語義層級更高的塊(摘要),這些新塊是文檔內容的一種 LLM 驅動的重新組織和分割。它不僅僅是分析現有塊,而是創造了新的塊邊界和內容。
4.2成熟框架的分塊策略定制問題
如果你想實現的功能(例如一種非常特定的、Ragflow 沒有內置或通過 API 參數暴露的分塊方法,或者你想徹底改變其檢索邏輯)超出了 Ragflow 提供的 API 和配置選項的范疇,理論上唯一的途徑就是修改 Ragflow 的源代碼。
但像 Ragflow 這樣的框架通常有復雜的內部結構和依賴關系,理解并安全地修改其核心代碼需要投入大量時間和精力。而且鑒于 RAGFlow 在常態化更新中,創建一個 Ragflow 的“定制分支”意味著官方的更新、補丁或新功能無法直接合并,需要自己手動同步或重新應用你的修改,維護成本很高。
類似Dify 支持編寫插件來添加自定義功能,而無需修改核心代碼。RAGFlow 等類似框架后續預期都會陸續支持更加靈活的擴展機制,建議短期內不要在二開上耗費精力。
4.3使用 LlamaIndex 替代 Ragflow/Dify?
這是我近期被問到比較多的一個問題,我在實施或咨詢的一些項目中,部分企業選擇直接基于 LlamaIndex(或 LangChain 等類似庫)來構建自己的企業級 RAG 應用,而不是使用封裝好的平臺。
除了可以更好的與現有技術棧集成外,企業可以完全掌控 RAG 流程的每一個環節,選擇最適合需求的模型(嵌入、LLM、重排)、向量數據庫、索引策略、檢索邏輯等,并進行深度定制和優化。
但問題也隨著而來,這需要開發或集成幾乎所有“外圍”組件,包括 UI、API、數據庫、部署運維在內的所有周邊系統。 畢竟LlamaIndex 雖然提供了 RAG 的核心“引擎”和“管道”,但它本身不是一個可以直接部署給最終用戶的完整應用。
一般的建議是,針對企業級知識庫項目落地,如果需求與某個成熟框架的功能高度匹配,且對定制化要求不高,或者時間緊迫需要快速驗證,那么選擇 Ragflow/Dify 顯然更高效。但如果企業對 RAG 的性能、邏輯有深度定制的需求,希望完全掌控技術棧,擁有較強的內部研發能力,或者需要將 RAG 深度嵌入現有復雜系統,那么基于 LlamaIndex 自建通常是更長遠、更靈活的選擇,盡管前期投入更大。


































