高级分块策略:语义分割、父子索引与多级检索
RAG 的第一步是切片 (Chunking)。 如果你把一篇文章切得乱七八糟(比如按固定字符数 512 切割),那么语义就会断裂。 一个句子被切成了两半,一个表格被腰斩。 这样的 Chunk 即使被检索到了,模型也看不懂。 高质量的 Chunking 是 RAG 成功的基石。
1. 语义分割 (Semantic Chunking)
1.1 什么是语义分割?
与其按固定长度切割,不如按语义边界切割。 段落、句子、标题都是天然的语义边界。
- RecursiveCharacterTextSplitter:LangChain 默认的分隔符是
\n\n,\n,, ``。 - MarkdownHeaderTextSplitter:按 Markdown 的标题层级切割,保留层级结构。
1.2 基于 Embedding 的分割
更高级的做法是:计算相邻句子的 Embedding 相似度。 如果相似度骤降(比如从 0.8 降到 0.3),说明话题切换了,就在这里切一刀。 这种方法能保证每个 Chunk 内部的话题是连贯的。
2. 父子索引 (Parent-Child Indexing)
2.1 痛点:小块易检索,大块含语义
- 小块 (Small Chunk):比如 100 Token。容易被 Embedding 匹配到,但缺乏上下文,模型看不懂。
- 大块 (Large Chunk):比如 1000 Token。包含完整语义,但 Embedding 容易被稀释,检索不到。
2.2 解决方案
同时存储小块和大块。
- Index:将大块切分成小块,计算小块的 Embedding,存入向量库。
- Mapping:记录小块与大块的父子关系(Parent ID)。
- Retrieve:用户搜索时,匹配到小块。
- Fetch:通过 Parent ID,找到对应的大块。
- Generate:把大块(包含完整上下文)喂给 LLM。
这种策略兼顾了检索的精准度和生成的上下文完整性。
3. 多级检索 (Multi-Level Retrieval)
3.1 摘要索引 (Summary Indexing)
对于长文档(如一本书),先生成每一章的摘要。
- Level 1: 用户搜索,先匹配摘要。
- Level 2: 找到相关章节后,再在该章节内部进行详细检索。 这种方法适合处理层级结构明显的文档。
3.2 句子窗口检索 (Sentence Window Retrieval)
检索时只匹配单个句子(极小粒度),但在生成时,自动扩展出该句子前后的 3-5 个句子(Window)。 这也是一种变相的父子索引。
4. 架构选型指南
| 场景 | 推荐策略 |
|---|---|
| 通用文档 | RecursiveCharacterTextSplitter (Chunk Size 512, Overlap 50) |
| 结构化文档 (Markdown/HTML) | MarkdownHeaderTextSplitter / HTMLSectionSplitter |
| 长难句/法律文档 | Parent-Child Indexing (Child: 200, Parent: 1000) |
| 多主题长文 | Semantic Chunking (基于 Embedding 变化) |
| 精准问答 | Sentence Window Retrieval |
Chunking 没有银弹。 你需要根据你的数据特点(长短、结构、领域)来选择最合适的策略。 多做实验,多看 Bad Case。 也许你会发现,仅仅把 Chunk Size 从 500 改成 200,RAG 的效果就能提升 10 个点。 这,就是工程的魅力。