Chunking (分块): RAG 系统中无声的胜负手
当你的 RAG 系统答非所问时,问题可能出在第一步
你已经搭建了一个看似完美的 RAG 系统:拥有强大的 模型,接入了高速的 向量数据库。但当你把一篇公司财报扔给它,询问“第二季度的利润增长原因”时,它却回答得牛头不对马嘴。
问题出在哪?答案很可能藏在一个你容易忽略的环节:Chunking (分块)。
在将任何文档“喂”给 RAG 系统之前,我们必须先将其切割成小块(Chunks),然后再进行 Embedding。这个看似简单的切割动作,其策略的优劣,直接决定了 RAG 系统的上限。
让我们扮演一位情报分析师,学习如何优雅地拆解一份“机密文件”,而不是用剪 刀粗暴地将其毁掉。
情报分析师的分块手册:一分钟速览
- 核心任务: 将一本厚厚的“密码本”(你的源文档)拆解成一张张独立的“情报卡片”(Chunks),同时最大化保留每张卡片的语义完整性。
- 为什么必须分块: Embedding 模型有输入长度限制,无法一次性处理长文档。
- 关键挑战: 如何切割,才能避免将一句完整的话从中间剪开,导致上下文丢失?
- 主流策略:
- 固定大小分块 (Fixed-Size): 最简单,像切香肠一样。
- 结构化分块 (Structural): 更智能,利用文档的章节、段落等天然边界。
- 带重叠的递归分块 (Recursive with Overlap): 当前最强大、最通用的策略,它结合了结构化思想,并用“重叠”技巧解决了边界问题。
策略一:固定大小分块 (Fixed-Size Chunking)
这是最基础、最直观的分块方法。当你面对一堵巨大的、没有任何格式的“文本墙”时,这是唯一的选择。
- 工作方式: 设定一个固定的
chunk_size
(例如,500个 Token),然后从头到尾,像切香肠一样将文本切成大小完全相同的片段。 - 优点: 实现简单,计算开销小。
- 缺点: 极其“无情”。它完全不理解文本的语义,很可能会粗暴地将一个完整的句子或段落从中间切断,导致上下文信息严重丢失,从而极大地影响后续的检索和生成质量。
# 示例:固定大小分块
text = "..." # 一段很长的文本
chunk_size = 512
chunks = [text[i:i+chunk_size] for i in range(0, len(text), chunk_size)]
策略二:结构化分块 (Semantic Chunking)
作为一名优秀的情报分析师,你不会用蛮力。你会先通览全局,寻找文档本身固有的“结构”。这就是语义分块的核心思想。
-
工作方式: 我们不再依赖固定的字符数,而是利用文档的语义边界作为切割点。这些边界可以是:
- 章节标题 (Markdown 的
#
,##
) - 段落 (通过连续换行符
\n\n
识别) - 列表项 (以
-
或1.
开头) - 代码块或表格
- 章节标题 (Markdown 的
-
优点: 极大程度上保证了每一个 Chunk 的语义完整性。一个按段落切分的 Chunk,其上下文质量远高于一个被拦腰斩断的 Chunk。
策略三:带重叠的递归分块 (Recursive Chunking with Overlap)
这是目前业界最主流、最稳健的策略,它巧妙地结合了前两种方法的优点,并解决了一个核心痛点。
1. 递归 (Recursive) 它会按照一个预设的、从最重要到最次要的分隔符列表,尝试进行切割。
分隔符列表 = ["\n\n# ", "\n\n", "\n", " ", ""]
它首先尝试用最高级的分隔符(章节)切分。如果切分后的某一块依然太大(超过 chunk_size
),它就会对那一块递归地使用下一个分隔符(段落)继续切分,以此类推,直到所有块都符合大小要求。
2. 重叠 (Overlap)
这是该策略的“神来之笔”,用于解决即便是按段落切分,也可能在边界处丢失上下文的问题。它设定一个 chunk_overlap
值,让后一个 Chunk 包 含前一个 Chunk 结尾的一部分内容。
看一个例子:
原句: "...这个系统的核心优势在于其无与伦比的可扩展性..."
如果切割点恰好在“无与伦比的”之后:
-
无重叠的切割:
- Chunk 1:
...其无与伦比的
- Chunk 2:
可扩展性...
- 灾难!语义被破坏。
- Chunk 1:
-
带重叠的切割 (
overlap=2
个词):- Chunk 1:
...其无与伦比的**可扩展性**
- Chunk 2:
**无与伦比的可扩展性**...
- 完美!上下文被保留。
- Chunk 1:
当用户提问“系统的可扩展性如何?”时,无论检索到哪个 Chunk,都能获得完整的关键信息。
如何选择你的分块策略?
- 如果你的文档高度结构化 (如 Markdown, HTML),优先考虑结构化分块。
- 如果你的文档是纯文本或结构混乱,带重叠的递归分块是你的首选,它兼具了智能与鲁棒性。
- 固定大小分块应作为最后的备选方案,或用于对其他策略切分后的超大块进行最后的“硬切割”。