RAG分块策略完全指南:为什么你的知识库总是答非所问?

📅 2026/9/21 ✍️ 小文 📖 约 1 分钟

RAG效果差八成出在分块上。本文用原理加代码讲透固定长度、语义分块、父子分块、上下文增强等策略的取舍,并给出选型决策表。

做过 RAG 知识库的人几乎都踩过同一个坑:明明文档里写着答案,模型却答不上来,或者答得牛头不对马嘴。 大多数人第一反应是换个更强的模型,或者调高检索 top-k,结果收效甚微。真相往往更朴素——问题出在**分块(chunking)**上。

一、分块为什么是 RAG 的命门

RAG 的链路是:文档 → 分块 → 向量化 → 检索 → 拼进提示 → 生成。分块处在最上游,它决定了什么信息被”打包”成一个检索单元。分块一旦切错,后面再好的模型也救不回来:

  • 切得太碎:单块信息不完整,模型拿到的是”半句话”,无法推理。
  • 切得太大:一块里塞了多个主题,向量被平均化,检索时匹配度下降。
  • 切在错误位置:把”结论”和”支撑它的条件”切到两个块里,检索到结论却缺前提。

二、主流分块策略逐一拆解

1. 固定长度分块(Fixed-size) 按字符或 token 数硬切,通常带一点重叠(overlap)。优点是简单、快、可控;缺点是经常在一句话中间切断,语义破碎。 适用:日志、结构化程度低的短文本、快速原型。

2. 递归分块(Recursive Character) 按”段落 → 句子 → 词”的优先级递归切分,尽量在自然边界断开。这是 LangChain 默认策略,也是最稳妥的基线。 适用:绝大多数通用文档。

3. 语义分块(Semantic Chunking) 计算相邻句子的 embedding 相似度,在相似度骤降处切分——那里往往是话题转折点。效果通常优于固定分块,但成本高(要先算向量)。

4. 结构感知分块(Markdown/HTML Aware) 按标题层级切分,让每个 chunk 携带所属的标题路径。对技术文档、法律合同、说明书尤其有效。

5. 父子分块(Parent-Child) 用小块做检索(精准匹配),但把小块所在的”父块”(更大上下文)喂给模型。这解决了”检索要小、生成要大”的矛盾,是目前召回质量最高的方案之一。

6. 上下文增强分块(Contextual Retrieval) 给每个 chunk 前面补一段由模型生成的”这段在整篇文档中的位置和主题”说明,再去做向量。据公开测试可显著降低检索失败率。

三、按文档类型选策略(决策表)

文档类型推荐策略块大小重叠
技术文档/API手册结构感知 + 父子300~600 token10%
法律合同结构感知(按条款)500~8000
通用文章/百科递归400~60015%
会议纪要/FAQ语义分块200~40020%
表格/报表按行组 + 表头注入视行数—

四、三个常被忽略的细节

1. 给每个块加上元数据。 标题路径、来源文件、页码、时间戳。检索时可以按元数据过滤,也能在生成时给模型提供出处。

2. 保留表格和代码的完整性。 表格一旦被跨块切开就彻底失效。预处理时应把表格转成 Markdown 并作为独立块。

3. 分块要为检索反推。 问自己:“用户会用什么话提问?我的块里有没有对应这句话的语义锚点?“如果答案是否定的,就该考虑改写或增强块内容。

五、一个可复用的递归分块示例

from langchain_text_splitters import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=75,
    separators=["\n## ", "\n### ", "\n\n", "\n", "。", "!", "?", " ", ""],
)
chunks = splitter.split_text(doc)

注意中文场景要显式把中文标点加进 separators,否则会退化成按空格硬切。

结语

RAG 效果的提升,往往不靠换模型,而靠把上游的分块做对。先做对分块,再谈检索优化,最后才是生成调优。 如果你的知识库今天答非所问,别急着骂模型,先去看看你的 chunk 长什么样。

📤 分享到