微信扫码
添加专属顾问
我要投稿
RAG系统的性能关键在分块技术,本文详解8种策略助你优化检索效果。 核心内容: 1. 分块技术对RAG系统性能的决定性影响 2. 8种主流分块策略的优缺点对比 3. 选择分块技术的实战决策框架
在人工智能领域迅猛发展的今天,检索增强生成(RAG)系统已成为构建可靠且上下文感知应用的基石,这些应用由大型语言模型(LLM)驱动。RAG 系统通过检索外部知识库(如向量数据库)中的相关信息,来弥合 LLM 与外部知识之间的差距,从而提升模型的响应质量。然而,在实现高效 RAG 系统时,一个最关键却常常被忽略的步骤是“分块”(chunking)——即将大型文档分解成更小、更易消化的片段的过程。
为什么分块如此重要?LLM 的上下文窗口有限,通常限制了一次能处理的文本量。糟糕的分块策略可能导致上下文不完整、检索无关信息,甚至生成幻觉输出。相反,精心选择的分块策略能显著提升检索准确性、响应相关性和整体系统性能。事实上,分块对 RAG 效果的影响往往大于嵌入模型或向量存储的选择。
本文将探讨八种流行的分块策略,借鉴行业最佳实践。我们将涵盖每种策略的描述、优缺点、理想使用场景,以及适用的代码示例。最后,我们提供一个决策框架,帮助您为 RAG 系统选择合适的技术。
固定大小分块是最简单的方法,将文本分割成预定义长度的块(例如 512 个令牌),并可选地添加重叠(10-20%)以保持边界间的上下文连续性。
优点:实现简单、计算高效,适合快速原型开发。
缺点:忽略语义结构,可能在句子或想法中间截断,导致上下文碎片化。
何时使用:适用于统一的无结构数据,如日志、短笔记,或在实时应用中优先考虑速度而非精度。
代码示例(Python):
from typing import List
import re
def word_splitter(source_text: str) -> List[str]:
source_text = re.sub("\s+", " ", source_text)
return re.split("\s", source_text)
def get_chunks_fixed_size_with_overlap(text: str, chunk_size: int, overlap_fraction: float = 0.2) -> List[str]:
text_words = word_splitter(text)
overlap_int = int(chunk_size * overlap_fraction)
chunks = []
for i in range(0, len(text_words), chunk_size):
chunk_words = text_words[max(i - overlap_int, 0): i + chunk_size]
chunk = " ".join(chunk_words)
chunks.append(chunk)
return chunks
这种方法使用分隔符的层次结构(例如,双换行符分段落,然后单换行符分句子),递归地分割文本,直到块符合所需大小。
优点:比固定大小更尊重文档结构,减少了不自然的断点。
缺点:仍基于规则,可能无法捕捉深层语义;编码稍复杂。
何时使用:适用于半结构化文本,如博客文章、新闻或研究论文,这些文本存在逻辑断点。
代码示例(Python):
from typing import List
def recursive_chunking(text: str, max_chunk_size: int = 1000) -> List[str]:
if len(text) <= max_chunk_size:
return [text.strip()] if text.strip() else []
separators = ["\n\n", "\n", ". ", " "]
for separator in separators:
if separator in text:
parts = text.split(separator)
chunks = []
current_chunk = ""
for part in parts:
test_chunk = current_chunk + separator + part if current_chunk else part
if len(test_chunk) <= max_chunk_size:
current_chunk = test_chunk
else:
if current_chunk:
chunks.append(current_chunk.strip())
current_chunk = part
if current_chunk:
chunks.append(current_chunk.strip())
final_chunks = []
for chunk in chunks:
if len(chunk) > max_chunk_size:
final_chunks.extend(recursive_chunking(chunk, max_chunk_size))
else:
final_chunks.append(chunk)
return [chunk for chunk in final_chunks if chunk]
return [text[i:i + max_chunk_size] for i in range(0, len(text), max_chunk_size)]
内容感知分块基于自然内容单元(如句子、段落或章节)进行分割,使用分隔符或 NLP 工具。
优点:保持逻辑完整性,提升检索相关性。
缺点:依赖一致的格式;对结构不良的数据无效。
何时使用:适用于格式化文档,如报告、书籍或法律文本。
代码示例:使用 NLTK 库进行句子分割:
import nltk
nltk.download('punkt')
def sentence_chunking(text: str) -> List[str]:
sentences = nltk.sent_tokenize(text)
return sentences # 如需进一步组合以达到所需大小
这种高级技术使用嵌入来分组语义相似的句子或段落,通常通过余弦相似度阈值实现。
优点:确保块在上下文中连贯,提升 RAG 准确性。
缺点:嵌入计算导致高计算成本。
何时使用:适用于密集的技术内容,如科学论文或代码库,其中含义优先于结构。
代码示例:使用 sentence-transformers:
from sentence_transformers import SentenceTransformer, util
model = SentenceTransformer('all-MiniLM-L6-v2')
def semantic_chunking(sentences: List[str], similarity_threshold: float = 0.7) -> List[str]:
embeddings = model.encode(sentences)
chunks = []
current_chunk = [sentences[0]]
for i in range(1, len(sentences)):
sim = util.cos_sim(embeddings[i-1], embeddings[i])
if sim > similarity_threshold:
current_chunk.append(sentences[i])
else:
chunks.append(' '.join(current_chunk))
current_chunk = [sentences[i]]
chunks.append(' '.join(current_chunk))
return chunks
利用 LLM 作为“代理”来智能确定块边界,基于提示进行操作。
优点:高度适应性且语义感知,无需固定规则。
缺点:因 LLM 调用而昂贵且缓慢;可能不一致。
何时使用:高价值场景,如自定义企业数据,精度至关重要。
代码示例:通过 OpenAI API 提示 LLM:
import openai
def Agentic_chunking(text: str, max_chunk_size: int) -> List[str]:
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[{"role": "user", "content": f"将此文本分割成不超过 {max_chunk_size} 个字符的连贯块:{text}"}]
)
chunks = response.choices[0].message.content.split('\n\n') # 假设块由双换行符分隔
return chunks
通过在文本上滑动窗口创建重叠块,确保连续上下文。
优点:捕捉边界间信息,减少信息丢失。
缺点:因冗余而增加存储和检索开销。
何时使用:叙事或序列数据,如故事、转录或时间序列日志。
代码示例:类似于固定大小,但步长可调:
def sliding_window_chunking(text: str, window_size: int, step: int) -> List[str]:
words = text.split()
chunks = []
for i in range(0, len(words), step):
chunk = ' '.join(words[i:i + window_size])
if chunk:
chunks.append(chunk)
return chunks
构建多级结构(例如,文档 > 章节 > 段落 > 句子),用于分层检索。
优点:启用灵活的多分辨率搜索。
缺点:设置和索引复杂。
何时使用:大型层次文档,如手册、维基或学术论文。
代码示例:表示为树状结构(简化):
# 使用 BeautifulSoup 等库解析 HTML 或自定义解析器处理层次
def hierarchical_chunking(document: dict) -> dict:
# 假设文档已解析成章节
hierarchy = {'sections': []}
for section in document['sections']:
chunks = {'title': section['title'], 'paragraphs': [p for p in section['content'].split('\n\n')]}
hierarchy['sections'].append(chunks)
return hierarchy
一种新颖方法,首先在长上下文中生成嵌入,然后在嵌入后派生块,以保留完整上下文。
优点:更好地处理长依赖;对某些模型成本效益高。
缺点:需要兼容的嵌入模型;不普遍适用。
何时使用:与长上下文 LLM 一起使用,或处理相互连接的叙事,如小说或法律合同。
代码示例:使用专用 API(例如 Cohere):
import cohere
co = cohere.Client('your-api-key')
def late_chunking(text: str) -> List[str]:
# 嵌入长文本,然后基于嵌入簇进行分割
response = co.embed(texts=[text], model='embed-english-v3.0')
embeddings = response.embeddings[0]
# 使用聚类(例如 KMeans)定义块
# 简化:假设后处理分割
return [text] # 实际实现的占位符
选择合适的分块策略取决于几个因素:
总之,没有一种分块技术适用于所有场景——最佳选择取决于您的数据和用例。通过理解这些策略并应用决策框架,您可以优化 RAG 系统以实现卓越性能。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2025-09-10
关于多模态应用的几个疑问,以及多模态应该怎么应用于RAG?
2025-09-10
MiniMax RAG 技术:从推理、记忆到多模态的演进与优化
2025-09-09
告别新手级RAG!一文掌握专业级后检索优化流水线
2025-09-09
切块、清洗、烹饪:RAG知识库构建的三步曲
2025-09-09
终结 “闭卷考试”:RAG 如何从根源上构建可信的AI应用
2025-09-09
你的RAG应用为什么总“胡说八道”?这份21项优化自查清单,帮你根治AI幻觉
2025-09-08
万字长文详解腾讯优图RAG技术的架构设计与创新实践
2025-09-08
运用 Elasticsearch 进行向量搜索及创建 RAG 应用
2025-06-20
2025-06-20
2025-07-15
2025-06-24
2025-06-24
2025-07-16
2025-06-23
2025-07-09
2025-06-15
2025-06-20
2025-09-10
2025-09-10
2025-09-03
2025-08-28
2025-08-25
2025-08-20
2025-08-11
2025-08-05