Chunk 学习笔记

Chunk 学习笔记

1. 什么是 Chunk

在 embedding、检索和 RAG 场景里,chunk 指的是把原始文档切成一段一段可独立编码、可独立检索的小文本单元。

对应的过程通常叫:

  • chunking
  • 文本切块
  • 文档切分

可以先把 chunk 看成检索流程里的最小工作单元。它不是随便切一刀,而是既要保留语义完整性,也要方便后续编码和检索。


2. 为什么要做 Chunk

原始文档通常不适合整篇直接送去做 embedding 或检索,原因一般有三个:

  • 太长,超过模型输入限制
  • 粒度太粗,检索结果不精准
  • 一篇文档往往包含多个主题,整篇编码会让语义混在一起

切块的目的,是让每一块:

  • 尽量只表达一个相对完整的意思
  • 长度不要太长,避免语义被稀释
  • 长度也不要太短,避免上下文不足

3. Chunk 对检索效果为什么这么关键

检索效果不好时,很多人的第一反应是换 embedding 模型,但工程里更常见的问题其实出在 chunk 策略。

实际项目里,chunk 策略会直接影响:

  • 向量质量
  • 召回命中率
  • rerank 效果
  • 最终 LLM 回答质量

常见问题包括:

  • chunk 太大,相关信息被埋在长文本里,召回不准
  • chunk 太碎,单块语义不完整,召回上来后也不好用
  • 切断了标题和正文的关系,导致上下文丢失
  • overlap 设置不合理,重复太多或连续性不够

所以可以把它理解成:

embedding 决定“怎么表示”,chunking 决定“切得对不对”。


4. 一个好 Chunk 的目标

好的 chunk 通常要满足这几个条件:

  • 语义尽量完整
  • 长度尽量稳定
  • 有明确边界
  • 便于加标题、来源、页码等元数据
  • 便于后续召回、去重、引用和展示

如果一个 chunk 满足下面任意一种情况,通常都说明切得不够好:

  • 只有一句残缺的话
  • 标题和正文被拆开
  • 一个 chunk 同时塞了多个不相关主题
  • 文本大部分是模板、导航、页脚、噪声内容

5. 常见的 Chunk 策略

5.1 固定长度切块

例如每 300 字、每 500 tokens 切一块。

优点:

  • 简单
  • 稳定
  • 容易批量处理

缺点:

  • 可能把完整段落或完整论点切断

适合:

  • 初版 baseline
  • 结构不稳定的原始文本

5.2 按段落切块

按照自然段来切。

优点:

  • 语义边界自然
  • 可读性通常更好

缺点:

  • 长度不稳定
  • 某些段落可能过长或过短

适合:

  • 普通说明文档
  • 笔记
  • 博客文章

5.3 按标题和小节切块

按照文档层级来切,例如:

  • 一级标题
  • 二级标题
  • 小节内容

优点:

  • 结构清晰
  • 更适合知识库和技术文档

缺点:

  • 某些小节可能太长,还需要二次细分

适合:

  • API 文档
  • 产品文档
  • 教程型内容

5.4 混合切块

先按标题或段落切,再对过长部分按固定长度继续细分。

这是实际项目里很常见的一种方案,因为它兼顾了:

  • 语义完整性
  • 长度可控
  • 工程实现难度

6. 什么是 Overlap

overlap 是相邻 chunk 之间保留的一部分重复内容。

作用:

  • 避免关键信息刚好被切断
  • 提高上下文连续性
  • 减少边界句子丢信息的问题

例如:

  • chunk1: 第 1~300
  • chunk2: 第 260~560

这里就有 40 字重叠。

但 overlap 也不是越大越好。

如果 overlap 太大,会带来:

  • 存储冗余
  • 检索结果重复
  • top-k 被相似 chunk 挤占

因此,overlap 要处理的是下面这组平衡:

  • 上下文连续性
  • 检索去重成本

7. Chunk Size 怎么定

chunk 大小没有全场景通用的固定答案,应该结合下面几件事一起看:

  • 文档类型
  • 模型最大输入长度
  • 用户 query 的粒度
  • 是否有 rerank
  • LLM 最终要吃多少上下文

7.1 中文场景一个常见起点

如果是中文知识库、普通笔记或教程类文本,可以先从下面这个 baseline 开始:

  • 每块 300~500
  • overlap 取 10%~20%
  • 优先按标题和段落切,超长再二次切分

这不是固定标准,但很适合作为第一版默认策略。

7.2 用 token 还是字数

更严格的工程实现通常按 token 控制,因为模型真正受限的是 token 数。

但在中文笔记场景里:

  • 用字数做初版规则更直观
  • 用 token 做最终线上控制更稳妥

8. 不同文档类型怎么切

8.1 FAQ

优先按一问一答切。

原因:

  • 每条 FAQ 本身就是天然语义单元
  • 非常适合检索

8.2 API 文档

优先按接口、参数、返回值、错误码分块。

原因:

  • 用户检索时往往是精确问题
  • 结构化切分更利于命中

8.3 教程和博客

优先按标题和段落切,再对过长部分二次细分。

原因:

  • 这类文档有明显章节结构
  • 语义常围绕小节展开

8.4 法规、合同、制度文档

优先按条款、章节切,再保留章节编号。

原因:

  • 编号本身很重要
  • 后续引用和回溯都依赖这些元数据

9. Chunk 不只是文本,还要带元数据

实际工程里,向量库里存的往往不只是 chunk 文本本身,还包括一组元数据。

常见字段:

  • chunk_id
  • doc_id
  • title
  • section
  • source
  • page
  • url
  • create_time

这些元数据很重要,因为它们会影响:

  • 过滤
  • 去重
  • 排序
  • 页面展示
  • 来源追踪

一句话说:

没有元数据的 chunk,很难在真实系统里长期维护。


10. Chunk 怎么评估好不好

chunk 没有一个单独的万能评分,通常要放到检索链路里一起评估。

最常见的评估方式有:

  • 看 Recall@K 是否提升
  • 看 badcase 是否减少
  • 看召回结果是否更少重复
  • 看 LLM 最终回答是否更稳定

排查时,通常先看这几个问题:

  1. 召回不到,是不是 chunk 太大
  2. 召回到了但答不好,是不是 chunk 太碎
  3. top-k 很重复,是不是 overlap 太大
  4. 标题命中了但正文没进来,是不是标题和内容被拆开了

11. 常见坑

11.1 只按固定长度切,不看语义边界

这样最容易把一句完整的话切断。

11.2 标题和正文分离

很多技术文档里,标题本身就是关键检索信号,和正文拆开后效果通常会明显变差。

11.3 chunk 太碎

如果一个 chunk 只剩一句短句,虽然向量容易算,但语义往往不完整。

11.4 chunk 太大

如果一块里塞进多个主题,检索时很容易语义发散。

11.5 overlap 太大

会导致召回结果里出现很多几乎一样的片段,影响 top-k 质量。

11.6 没做清洗就直接切

页眉、页脚、导航栏、版权信息、空白符噪声,都会污染 chunk 质量。


12. 一个实用的默认方案

如果你是第一次给中文知识库做 chunk,可以先这样做:

  1. 先清洗无关噪声
  2. 按标题和段落切
  3. 过长段落按 300~500 字继续切
  4. overlap 先取 10%~15%
  5. 保留 doc_idtitlesectionsource
  6. 离线抽样检查 top-k 检索效果
  7. 根据 badcase 再回调 chunk size 和 overlap

这套方案不是最优,但通常足够当第一版生产 baseline。


13. Chunk、Embedding、RAG 的关系

可以把三者简单理解成:

  • chunking 决定“怎么切”
  • embedding 决定“怎么表示”
  • retrieval / rerank 决定“怎么找”
  • LLM 决定“怎么答”

如果 chunk 切得不对,后面的 embedding、rerank、LLM 往往都只能被动补救。


14. 一句话总结

Chunk 的核心不是“把文档切小”,而是:

把文档切成既适合向量表示、又适合检索召回、还能支撑最终回答的语义单元。