文檔太長模型“吃不下”?試試這15種Chunking策略,輕松搞定RAG! 原創 精華
RAG系統也能“切塊”?15種Chunking技巧讓你的檢索生成更聰明!
你知道嗎?在構建一個強大的RAG(Retrieval-Augmented Generation)系統時,決定其“聰明程度”的,可能不是模型本身,而是——你怎么“切塊”你的文檔。
在NLP領域,RAG系統已經成為處理復雜問答、文檔摘要、知識庫檢索等任務的利器。但面對動輒上萬字的文檔,如何在不丟失上下文的前提下,把它們“切”成模型能消化的“小塊”,就成了關鍵。
今天這篇文章,我們就來系統聊聊:15種Chunking技巧,幫你打造一個既快又準的RAG系統。無論你是做問答系統、文檔檢索,還是構建企業知識庫,這篇文章都值得你收藏。
01|什么是Chunking?為什么它這么重要?
在RAG系統中,Chunking(切塊)指的是:把大文檔拆分成小塊,以便模型更好地理解和檢索信息。
你可能會問:為什么不能直接把整篇文檔丟給模型?原因很簡單:
- 大模型有token限制(比如GPT-4最多支持8K tokens);
- 文檔太長,模型容易“看漏”關鍵信息;
- 不切塊,檢索系統很難精準定位答案。
所以,Chunking不是簡單的“切”,而是要在“保留上下文”和“適配模型能力”之間找到平衡。
02|Chunking的三大核心考量
在正式介紹15種技巧之前,我們先來理解Chunking的三個關鍵因素:
1. 塊的大小(Chunk Size)
- 太大:容易超token限制,檢索慢;
- 太小:上下文丟失,生成質量差;
- 建議:根據模型token上限,控制在100~500 tokens之間。
2. 上下文保留(Context Preservation)
- 切塊不能“斷句斷意”,否則模型會“看不懂”;
- 使用滑動窗口、語義切塊等方式,能有效保留上下文。
3. 多模態處理(Modality Handling)
- 文檔中可能包含表格、圖片、代碼塊;
- 不同內容類型需要不同的切塊策略。
03|15種Chunking技巧全解析(附代碼)
接下來,我們進入正題:15種Chunking技巧,每種都配有使用場景、優缺點和代碼示例,建議收藏!
1. 固定大小切塊(Fixed-Size Chunking)
原理:按固定詞數或token數切分。
適用場景:結構簡單的小文檔。
優點:實現簡單,速度快。
缺點:可能切斷句子,丟失語義。
def fixed_size_chunk(text, max_words=100):
words = text.split()
return [' '.join(words[i:i + max_words]) for i in range(0, len(words), max_words)]
2. 句子切塊(Sentence-Based Chunking)
原理:按句子邊界切分。
適用場景:需要保留語義完整性的文檔。
優點:語義清晰,上下文連貫。
缺點:句子長度不一,chunk大小不穩定。
import spacy
nlp = spacy.load("en_core_web_sm")
def sentence_chunk(text):
doc = nlp(text)
return [sent.text for sent in doc.sents]
3. 段落切塊(Paragraph-Based Chunking)
原理:按段落切分。
適用場景:結構清晰的文檔,如論文、報告。
優點:自然分段,語義完整。
缺點:段落長度不一,可能超token限制。
def paragraph_chunk(text):
return text.split('\n\n')
4. 語義切塊(Semantic Chunking)
原理:基于語義相似度進行切塊。
適用場景:技術文檔、復雜文本。
優點:上下文保留好。
缺點:實現復雜,需依賴模型。
def semantic_chunk(text, max_len=200):
doc = nlp(text)
chunks = []
current_chunk = []
for sent in doc.sents:
current_chunk.append(sent.text)
if len(' '.join(current_chunk)) > max_len:
chunks.append(' '.join(current_chunk))
current_chunk = []
if current_chunk:
chunks.append(' '.join(current_chunk))
return chunks
5. 模態感知切塊(Modality-Specific Chunking)
原理:文本、表格、圖片分別處理。
適用場景:PDF、技術手冊等混合內容文檔。
優點:保留多種模態信息。
缺點:實現復雜。
def modality_chunk(text, images=None, tables=None):
text_chunks = paragraph_chunk(text)
return {'text_chunks': text_chunks, 'images': images, 'tables': tables}
6. 滑動窗口切塊(Sliding Window Chunking)
原理:相鄰chunk之間有重疊。
適用場景:法律、學術文檔。
優點:上下文連貫。
缺點:內容重復,處理量大。
def sliding_window_chunk(text, chunk_size=100, overlap=20):
tokens = text.split()
chunks = []
for i in range(0, len(tokens), chunk_size - overlap):
chunk = ' '.join(tokens[i:i + chunk_size])
chunks.append(chunk)
return chunks
7. 層級切塊(Hierarchical Chunking)
原理:按章節、段落、子段落分層切塊。
適用場景:結構化文檔,如論文、合同。
優點:保留文檔結構。
缺點:實現復雜。
def hierarchical_chunk(text, section_keywords):
sections = []
current_section = []
for line in text.splitlines():
if any(keyword in line for keyword in section_keywords):
if current_section:
sections.append("\n".join(current_section))
current_section = [line]
else:
current_section.append(line)
if current_section:
sections.append("\n".join(current_section))
return sections
8. 內容感知切塊(Content-Aware Chunking)
原理:根據內容特征動態調整切塊策略。
適用場景:電子書、技術文檔。
優點:靈活適應不同內容。
缺點:邏輯復雜。
def content_aware_chunk(text):
chunks = []
current_chunk = []
for line in text.splitlines():
if line.startswith(('##', '###', 'Introduction', 'Conclusion')):
if current_chunk:
chunks.append('\n'.join(current_chunk))
current_chunk = [line]
else:
current_chunk.append(line)
if current_chunk:
chunks.append('\n'.join(current_chunk))
return chunks
9. 表格感知切塊(Table-Aware Chunking)
原理:將表格獨立切塊。
適用場景:財務報表、技術文檔。
優點:保留表格結構。
缺點:格式可能丟失。
import pandas as pd
def table_aware_chunk(table):
return table.to_markdown()
10. Token級切塊(Token-Based Chunking)
原理:按token數切塊,適配Transformer模型。
適用場景:GPT、BERT等模型。
優點:適配模型限制。
缺點:可能切斷句子。
from transformers import GPT2Tokenizer
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
def token_based_chunk(text, max_tokens=200):
tokens = tokenizer(text)["input_ids"]
chunks = [tokens[i:i + max_tokens] for i in range(0, len(tokens), max_tokens)]
return [tokenizer.decode(chunk) for chunk in chunks]
11. 實體感知切塊(Entity-Based Chunking)
原理:基于NER識別實體進行切塊。
適用場景:簡歷、合同、法律文檔。
優點:保留實體信息。
缺點:需訓練NER模型。
def entity_based_chunk(text):
doc = nlp(text)
return [ent.text for ent in doc.ents]
12. 主題切塊(Topic-Based Chunking)
原理:使用LDA等主題模型進行切塊。
適用場景:新聞、研究論文等多主題文檔。
優點:按主題聚合信息。
缺點:需額外建模。
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.decomposition import LatentDirichletAllocation
def topic_based_chunk(text, num_topics=3):
sentences = text.split('. ')
vectorizer = CountVectorizer()
sentence_vectors = vectorizer.fit_transform(sentences)
lda = LatentDirichletAllocation(n_components=num_topics, random_state=42)
lda.fit(sentence_vectors)
# 省略主題分配邏輯
return sentences
13. 頁面切塊(Page-Based Chunking)
原理:按PDF頁面切塊。
適用場景:PDF文檔。
優點:實現簡單。
缺點:可能斷句。
def page_based_chunk(pages):
return pages
14. 關鍵詞切塊(Keyword-Based Chunking)
原理:按關鍵詞切分。
適用場景:結構清晰的文檔。
優點:符合文檔結構。
缺點:需預定義關鍵詞。
def keyword_based_chunk(text, keywords):
chunks = []
current_chunk = []
for line in text.splitlines():
if any(keyword in line for keyword in keywords):
if current_chunk:
chunks.append('\n'.join(current_chunk))
current_chunk = [line]
else:
current_chunk.append(line)
if current_chunk:
chunks.append('\n'.join(current_chunk))
return chunks
15. 混合切塊(Hybrid Chunking)
原理:結合多種策略。
適用場景:復雜文檔。
優點:靈活強大。
缺點:實現復雜。
def hybrid_chunk(text):
paragraphs = paragraph_chunk(text)
hybrid_chunks = []
for paragraph in paragraphs:
hybrid_chunks += sentence_chunk(paragraph)
return hybrid_chunks
04|不同場景下如何選擇Chunking策略?
場景類型 | 推薦策略 |
FAQ、客服系統 | 句子切塊、關鍵詞切塊 |
學術論文 | 層級切塊、語義切塊 |
技術文檔 | 表格感知切塊、內容感知切塊 |
多模態文檔 | 模態感知切塊、混合切塊 |
法律文檔 | 滑動窗口切塊、實體感知切塊 |
05|結語:Chunking不是“切”,是“設計”
Chunking不是簡單的“把文檔切碎”,而是一種信息架構設計。不同的切塊策略,直接決定了RAG系統的檢索精度、生成質量和響應速度。
希望這篇文章能幫你找到最適合你業務的Chunking策略。如果你正在構建RAG系統,不妨從這些小技巧開始,逐步優化你的文檔處理流程。
本文轉載自??Halo咯咯?? 作者:基咯咯
