文檔太長(zhǎng)模型“吃不下”?試試這15種Chunking策略,輕松搞定RAG! 原創(chuàng) 精華
RAG系統(tǒng)也能“切塊”?15種Chunking技巧讓你的檢索生成更聰明!
你知道嗎?在構(gòu)建一個(gè)強(qiáng)大的RAG(Retrieval-Augmented Generation)系統(tǒng)時(shí),決定其“聰明程度”的,可能不是模型本身,而是——你怎么“切塊”你的文檔。
在NLP領(lǐng)域,RAG系統(tǒng)已經(jīng)成為處理復(fù)雜問答、文檔摘要、知識(shí)庫(kù)檢索等任務(wù)的利器。但面對(duì)動(dòng)輒上萬(wàn)字的文檔,如何在不丟失上下文的前提下,把它們“切”成模型能消化的“小塊”,就成了關(guān)鍵。
今天這篇文章,我們就來(lái)系統(tǒng)聊聊:15種Chunking技巧,幫你打造一個(gè)既快又準(zhǔn)的RAG系統(tǒng)。無(wú)論你是做問答系統(tǒng)、文檔檢索,還是構(gòu)建企業(yè)知識(shí)庫(kù),這篇文章都值得你收藏。
01|什么是Chunking?為什么它這么重要?
在RAG系統(tǒng)中,Chunking(切塊)指的是:把大文檔拆分成小塊,以便模型更好地理解和檢索信息。
你可能會(huì)問:為什么不能直接把整篇文檔丟給模型?原因很簡(jiǎn)單:
- 大模型有token限制(比如GPT-4最多支持8K tokens);
- 文檔太長(zhǎng),模型容易“看漏”關(guān)鍵信息;
- 不切塊,檢索系統(tǒng)很難精準(zhǔn)定位答案。
所以,Chunking不是簡(jiǎn)單的“切”,而是要在“保留上下文”和“適配模型能力”之間找到平衡。
02|Chunking的三大核心考量
在正式介紹15種技巧之前,我們先來(lái)理解Chunking的三個(gè)關(guān)鍵因素:
1. 塊的大?。–hunk Size)
- 太大:容易超token限制,檢索慢;
- 太小:上下文丟失,生成質(zhì)量差;
- 建議:根據(jù)模型token上限,控制在100~500 tokens之間。
2. 上下文保留(Context Preservation)
- 切塊不能“斷句斷意”,否則模型會(huì)“看不懂”;
- 使用滑動(dòng)窗口、語(yǔ)義切塊等方式,能有效保留上下文。
3. 多模態(tài)處理(Modality Handling)
- 文檔中可能包含表格、圖片、代碼塊;
- 不同內(nèi)容類型需要不同的切塊策略。
03|15種Chunking技巧全解析(附代碼)
接下來(lái),我們進(jìn)入正題:15種Chunking技巧,每種都配有使用場(chǎng)景、優(yōu)缺點(diǎn)和代碼示例,建議收藏!
1. 固定大小切塊(Fixed-Size Chunking)
原理:按固定詞數(shù)或token數(shù)切分。
適用場(chǎng)景:結(jié)構(gòu)簡(jiǎn)單的小文檔。
優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,速度快。
缺點(diǎn):可能切斷句子,丟失語(yǔ)義。
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)
原理:按句子邊界切分。
適用場(chǎng)景:需要保留語(yǔ)義完整性的文檔。
優(yōu)點(diǎn):語(yǔ)義清晰,上下文連貫。
缺點(diǎn):句子長(zhǎng)度不一,chunk大小不穩(wěn)定。
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)
原理:按段落切分。
適用場(chǎng)景:結(jié)構(gòu)清晰的文檔,如論文、報(bào)告。
優(yōu)點(diǎn):自然分段,語(yǔ)義完整。
缺點(diǎn):段落長(zhǎng)度不一,可能超token限制。
def paragraph_chunk(text):
return text.split('\n\n')
4. 語(yǔ)義切塊(Semantic Chunking)
原理:基于語(yǔ)義相似度進(jìn)行切塊。
適用場(chǎng)景:技術(shù)文檔、復(fù)雜文本。
優(yōu)點(diǎn):上下文保留好。
缺點(diǎn):實(shí)現(xiàn)復(fù)雜,需依賴模型。
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. 模態(tài)感知切塊(Modality-Specific Chunking)
原理:文本、表格、圖片分別處理。
適用場(chǎng)景:PDF、技術(shù)手冊(cè)等混合內(nèi)容文檔。
優(yōu)點(diǎn):保留多種模態(tài)信息。
缺點(diǎn):實(shí)現(xiàn)復(fù)雜。
def modality_chunk(text, images=None, tables=None):
text_chunks = paragraph_chunk(text)
return {'text_chunks': text_chunks, 'images': images, 'tables': tables}
6. 滑動(dòng)窗口切塊(Sliding Window Chunking)
原理:相鄰chunk之間有重疊。
適用場(chǎng)景:法律、學(xué)術(shù)文檔。
優(yōu)點(diǎn):上下文連貫。
缺點(diǎn):內(nèi)容重復(fù),處理量大。
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. 層級(jí)切塊(Hierarchical Chunking)
原理:按章節(jié)、段落、子段落分層切塊。
適用場(chǎng)景:結(jié)構(gòu)化文檔,如論文、合同。
優(yōu)點(diǎn):保留文檔結(jié)構(gòu)。
缺點(diǎn):實(shí)現(xiàn)復(fù)雜。
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. 內(nèi)容感知切塊(Content-Aware Chunking)
原理:根據(jù)內(nèi)容特征動(dòng)態(tài)調(diào)整切塊策略。
適用場(chǎng)景:電子書、技術(shù)文檔。
優(yōu)點(diǎn):靈活適應(yīng)不同內(nèi)容。
缺點(diǎn):邏輯復(fù)雜。
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)
原理:將表格獨(dú)立切塊。
適用場(chǎng)景:財(cái)務(wù)報(bào)表、技術(shù)文檔。
優(yōu)點(diǎn):保留表格結(jié)構(gòu)。
缺點(diǎn):格式可能丟失。
import pandas as pd
def table_aware_chunk(table):
return table.to_markdown()
10. Token級(jí)切塊(Token-Based Chunking)
原理:按token數(shù)切塊,適配Transformer模型。
適用場(chǎng)景:GPT、BERT等模型。
優(yōu)點(diǎn):適配模型限制。
缺點(diǎn):可能切斷句子。
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. 實(shí)體感知切塊(Entity-Based Chunking)
原理:基于NER識(shí)別實(shí)體進(jìn)行切塊。
適用場(chǎng)景:簡(jiǎn)歷、合同、法律文檔。
優(yōu)點(diǎn):保留實(shí)體信息。
缺點(diǎn):需訓(xùn)練NER模型。
def entity_based_chunk(text):
doc = nlp(text)
return [ent.text for ent in doc.ents]
12. 主題切塊(Topic-Based Chunking)
原理:使用LDA等主題模型進(jìn)行切塊。
適用場(chǎng)景:新聞、研究論文等多主題文檔。
優(yōu)點(diǎn):按主題聚合信息。
缺點(diǎn):需額外建模。
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. 頁(yè)面切塊(Page-Based Chunking)
原理:按PDF頁(yè)面切塊。
適用場(chǎng)景:PDF文檔。
優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單。
缺點(diǎn):可能斷句。
def page_based_chunk(pages):
return pages
14. 關(guān)鍵詞切塊(Keyword-Based Chunking)
原理:按關(guān)鍵詞切分。
適用場(chǎng)景:結(jié)構(gòu)清晰的文檔。
優(yōu)點(diǎn):符合文檔結(jié)構(gòu)。
缺點(diǎn):需預(yù)定義關(guān)鍵詞。
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)
原理:結(jié)合多種策略。
適用場(chǎng)景:復(fù)雜文檔。
優(yōu)點(diǎn):靈活強(qiáng)大。
缺點(diǎn):實(shí)現(xiàn)復(fù)雜。
def hybrid_chunk(text):
paragraphs = paragraph_chunk(text)
hybrid_chunks = []
for paragraph in paragraphs:
hybrid_chunks += sentence_chunk(paragraph)
return hybrid_chunks
04|不同場(chǎng)景下如何選擇Chunking策略?
場(chǎng)景類型 | 推薦策略 |
FAQ、客服系統(tǒng) | 句子切塊、關(guān)鍵詞切塊 |
學(xué)術(shù)論文 | 層級(jí)切塊、語(yǔ)義切塊 |
技術(shù)文檔 | 表格感知切塊、內(nèi)容感知切塊 |
多模態(tài)文檔 | 模態(tài)感知切塊、混合切塊 |
法律文檔 | 滑動(dòng)窗口切塊、實(shí)體感知切塊 |
05|結(jié)語(yǔ):Chunking不是“切”,是“設(shè)計(jì)”
Chunking不是簡(jiǎn)單的“把文檔切碎”,而是一種信息架構(gòu)設(shè)計(jì)。不同的切塊策略,直接決定了RAG系統(tǒng)的檢索精度、生成質(zhì)量和響應(yīng)速度。
希望這篇文章能幫你找到最適合你業(yè)務(wù)的Chunking策略。如果你正在構(gòu)建RAG系統(tǒng),不妨從這些小技巧開始,逐步優(yōu)化你的文檔處理流程。
本文轉(zhuǎn)載自??Halo咯咯?? 作者:基咯咯
