跳转至

第四章:Chunking 策略与粒度选择

4.1 为什么必须切分

切分通常有三个直接原因:

理由 说明
窗口限制 一篇长文档可能远超模型上下文预算,无法整篇塞入
检索精度 整篇文档的向量是全文语义的平均,会把具体细节稀释掉
成本与延迟 只把相关片段送进 Prompt,而不是整本手册

其中更直接影响检索质量的是第二条。

一个 Embedding 向量的表达能力是有限的。把一篇涵盖十个主题的长文压成一个向量,得到的是这十个主题的"平均语义"——它对任何一个具体问题都不够相似。

切分的目的,不只是为了装得下,而是为了让每个向量表达一个足够聚焦的语义单元。

4.2 粒度的核心矛盾

flowchart TB
    G[chunk 粒度] --> S[切得太小]
    G --> L[切得太大]

    S --> S1[语义聚焦 检索精准]
    S --> S2[上下文缺失<br/>指代不明 结论没有前提]

    L --> L1[上下文完整]
    L --> L2[语义被稀释<br/>混入无关内容 检索不准]

这是一个无法被完全消除的矛盾,只能被缓解——第五章的方法都是围绕这组权衡展开的。

4.2.1 切得太小会发生什么

一个 100 字的片段可能长这样:

「该比例不得超过前款规定的上限。」

这段话单独存在时毫无检索价值:「该比例」是什么?「前款」是哪一款?向量化之后它既不像任何一个真实问题,命中了也无法支撑回答。

这就是语义碎片化

4.2.2 切得太大会发生什么

一个 5000 字的片段可能同时包含请假制度、报销制度和考勤制度。用户问报销时:

  • 这个片段的向量因为混了另外两个主题,与问题的相似度下降,可能根本召不回来
  • 就算召回了,也把两段无关内容塞进了 Prompt,按第二章 2.4.2 节的结论,这会主动损害生成质量

4.3 一个反直觉但重要的实证结论

常见做法是先上语义切分,认为「切分算法越聪明,效果越好」。

但系统性的对比实验给出了不同的结论:

chunk 的大小和重叠量,对最终效果的影响远大于切分算法的选择。

在多个数据集上的对比中,复杂的语义切分方法(先算句子向量、再找语义断点)相比简单的固定大小切分,增加了显著的计算成本,却没有带来稳定的效果提升

这个结论在工程上的含义很直接:

  1. 先把 chunk size 和 overlap 调好,这是投入产出比最高的动作;
  2. 不要默认先上语义切分,它的复杂度和收益不成正比;
  3. 如果要用更聪明的方法,优先考虑基于结构的切分(按标题层级),它几乎零成本且效果稳定。

这里说的语义切分,主要指「用 Embedding 相似度找语义断点」这一类方法。而基于 LLM 的命题化切分(把段落改写成一组独立自足的陈述句)是另一回事,它在实体密集的问答任务上有明确收益——但成本高得多(第五章展开)。

4.4 常见切分策略

flowchart TB
    C[切分策略] --> F[固定大小 + 重叠]
    C --> R[递归分隔符]
    C --> ST[结构化 按标题层级]
    C --> SE[语义切分]
    C --> SP[特殊内容专门处理]
策略 做法 优点 缺点
固定大小 + 重叠 按固定 Token 数切,相邻片段重叠一部分 简单、可预测、效果稳定 可能在句中截断
递归分隔符 依次按段落、句子、词尝试分隔,直到满足大小 尽量不破坏自然边界 对无明显分隔的文本退化为固定切分
结构化切分 按 Markdown 标题层级或文档章节切 保留文档天然语义边界,性价比最高 依赖前一步保留了结构信息
语义切分 计算相邻句子向量相似度,在低谷处切断 理论上贴合语义 成本高、收益不稳定
特殊内容处理 表格、代码、公式整体不切 避免破坏强结构内容 需要先识别出这些内容

工程上的推荐组合结构化切分为主(有标题层级时按章节切),固定大小 + 重叠兜底(章节过长时二次切分),特殊内容单独处理(表格和代码块整体保留)。

4.5 参数怎么定

4.5.1 chunk size

一个常用的起点500–1000 Token。但这只是起点,不是答案。单独给一个数字意义不大,关键是说明调整方向:

情况 调整方向 理由
事实型问答(FAQ、参数查询) 偏小(200–500) 答案集中在一两句话里,小片段更精准
需要推理和综合的问答 偏大(800–1500) 需要完整论证链,切碎后逻辑断裂
法律、合同类文档 按条款切 条款是天然的语义单元
技术文档、API 手册 按小节切 结构清晰,一节一主题
对话记录 按轮次或话题切 单轮太碎,整段太杂

另一个约束是 Embedding 模型本身:多数模型有最大输入长度限制(常见 512 Token),超出部分会被静默截断。如果 chunk 大小超过模型上限,超出的内容根本没有进入向量——这是一个不报错的严重 bug,务必检查。

4.5.2 overlap

重叠的作用是兜底:万一在关键位置切断了,重叠部分能让被切开的内容在相邻片段中至少完整出现一次。

常用值是 chunk size 的 10%–20%

  • 太小:起不到兜底作用;
  • 太大:存储和计算成本上升,且同一内容多次命中会挤占 Top-K 名额,降低召回结果的多样性

最后一点是重叠过大的隐性代价,容易被忽略。

4.5.3 怎么确定最终值

最终值要靠评测确定。流程是:

  1. 构造一个有标注答案的评测集(几十到几百条真实问题);
  2. 用不同的 chunk size / overlap 组合建库;
  3. 测检索层指标(Hit@K、MRR)和端到端答案质量;
  4. 选择效果与成本的平衡点。

关键提醒检索指标好不等于最终答案好。必须同时看端到端指标(详见第十八章)。

4.6 粒度与后续环节的联动

chunk 粒度不是孤立决策,它会影响下游多个环节:

影响的环节 影响方式
Top-K 取值 片段越小,需要的 K 越大才能覆盖同等信息量
Prompt 预算 K × chunk size 决定了送进模型的 Token 量
Rerank 成本 候选数越多,精排成本越高
引用溯源粒度 片段越小,引用定位越精确
更新成本 片段越小,文档变更时重建的片段越多

所以「chunk 调大一点」不是一个局部改动,它会连锁改变 Top-K、Prompt 预算和成本结构。调参时应该整体评估,而不是只看检索指标。

4.7 常见错误

4.7.1 死记一个数字

「500 Token」是起点不是答案。不说明调整依据,等于没回答。

4.7.2 一上来就上语义切分

有实证表明它成本高、收益不稳定。应该先把 size 和 overlap 调好。

4.7.3 chunk 超过 Embedding 模型输入上限

超出部分被静默截断,不报错,排查极其困难。

4.7.4 所有文档类型用同一套参数

合同、代码、对话记录的天然语义单元完全不同。

4.7.5 把表格和代码块按字符数硬切

强结构内容被切开后基本失去价值,应该整体保留或专门处理。

4.7.6 只看检索指标不看端到端效果

召回率提升但答案变差的情况是真实存在的(例如召回了更多但更杂的内容)。

4.7.7 忽略重叠过大的副作用

同一内容在 Top-K 里重复出现,会挤占其他有效片段的名额。

4.8 本章总结

  1. 切分的目的,是让每个向量表达一个聚焦的语义单元,而不只是为了装得下;
  2. 核心矛盾:切小了语义碎片化,切大了语义被稀释——只能缓解,无法消除;
  3. 实证结论:chunk size 和 overlap 的影响远大于切分算法;语义切分性价比不高
  4. 推荐组合:结构化切分为主 + 固定大小重叠兜底 + 特殊内容单独处理;
  5. 参数起点 500–1000 Token、重叠 10%–20%,但必须按文档类型和问题类型调整
  6. 硬性检查:chunk 不能超过 Embedding 模型的输入上限,否则被静默截断;
  7. 粒度是全局决策,会连锁影响 Top-K、Prompt 预算、Rerank 成本和更新成本;
  8. 必须用评测集实测,且检索指标和端到端指标都要看。

参考资料