跳到主要内容

文档chunk切片

  • 切片大小配置 (chunk size)
  • 分块重叠字符配置 (chunk overlap)
    • 分块之间保留一小段的重复内容
    • 作用: 防止关键词被分割,相当于做一个边界兼容的处理,保证语义的完整性

为什么大分块会导致不准确​

  • 大分块chunk会导致噪音问题
  • 我以512为单位去查询,最终无论需要多少信息,都是回复512的⻓度,给到LLM

例子:

假设您设置的切片大小是 512 个 Token。

  1. 用戶查询: "保罗·格雷厄姆大学做了什么?" (答案只有一句话)

  2. 检索结果: 向量数据库返回了包含答案的那个 512 Token 的大块。

  3. 问题: 在这 512 个 Token 中,可能只有 20 个 Token 是答案,剩下的 492 个 Token 都是关于他童 年或创业的无关信息(即“噪音”)。

  4. LLM 困惑: LLM 接收到这堆“噪音”和查询,虽然它能找到答案,但这些噪音:

  • 稀释了上下文: 导致 LLM 在合成答案时引入不必要的细节或偏离焦点。
  • 增加了成本: 为这 492 个不必要的 Token 付费

业内一般使用多大的 chunk​

  • 业内没有一个绝对标准的切片大小,因为最佳大小取决于数据类型和使用场景
  • 行业项目一般不会对所有文档统一使用一个chunk来切一次
    • 而是按照文档类型选择不同策略

按照文档类型分块​

  • Unstructured库:支持自动识别类型并分块
文档类型实际分块方式
Markdown按 H1、H2、H3 标题切分
HTML按标题、Section、DOM 结构切分
PDF按页面布局、标题、段落、表格切分
Word按标题样式和段落切分
PPT通常一页或一个内容区域作为一个单元
Excel按工作表、表格区域、行组切分
代码按类、函数、方法切分
对话记录按连续轮次或会话主题切分
FAQ问答类型一组问题和答案作为一个 Chunk

Unstructured库识别文档类型拆分​

  • by_title 已经根据标题、段落等完整元素组合 Chunk。正常 Chunk 通常具有比较干净的语义边界, 因此可以设置overlap_all=False
配置作用简单理解
chunking_strategy="by_title"根据识别出的标题、章节结构进行分块遇到新标题时,尽量开启一个新的 Chunk
overlap_all=False不让所有相邻 Chunk 都产生重叠正常章节之间不重复内容,避免引入噪声
overlap=100超长内容被强制拆分时,前后保留 100 个字符的重复内容防止一句话或一个知识点在切片边界处断开
python
from unstructured.partition.auto import partition

chunks = partition(
filename="book.pdf",
chunking_strategy="by_title",

# 字符数,不是 token
max_characters=2000,
new_after_n_chars=1500,

# 合并过短的小章节
combine_text_under_n_chars=300,

# 只在超长元素被强制拆分时重叠
overlap=100,
overlap_all=False,
)

主流文档分块参考​

  • 问题类的使用 100~300,普通知识库使用 300~600,书籍和论文使用 500~1000 tokens;512 tokens 是最适合普通知识库的通用起点
场景建议分块范围建议重叠为什么这样选
FAQ、问答库100~300 tokens20~50每条问答通常只表达一个知识点。小切片可以减少无关内容,提高精确匹配能力
名词解释、百科词条150~350 tokens20~50用户问题通常很短,例如“什么是 HNSW”,小块更容易集中表达一个概念
普通企业知识库300~600 tokens50~100同时兼顾检索精度和上下文完整性,是最常见的通用范围
产品说明、帮助文档300~600 tokens50~100一个操作步骤或功能说明通常能在这个范围内完整表达
技术文档、API 文档300~700 tokens50~120需要保留参数、示例和上下文,但切片太长会混入多个接口或概念
教程、课程资料400~800 tokens80~150教程内容往往前后依赖,需要比 FAQ 保留更多解释过程
书籍、长篇文章500~1000 tokens100~200书籍段落上下文依赖较强,切片过小容易把论述、例子和结论拆开
规章制度、公司制度300~700 tokens50~120应优先保证一个条款完整,同时避免多个不同条款被放进同一个 chunk
法律合同400~800 tokens80~150条款中存在定义、条件和例外,切得太小容易改变条款含义
学术论文500~1000 tokens100~200需要保留论点、实验条件、结果和上下文,适合按章节或段落切分
新闻、短文章200~500 tokens30~80信息密度较高,一个 chunk 通常保留一个事件或一个主题即可
对话、客服记录200~500 tokens50~100应按连续对话轮次切分,避免把问题和对应回答拆开
代码按函数、类切分通常不固定代码必须保持语法和逻辑完整,不适合单纯按照 token 数硬切
表格按完整表格或行组切分重复表头表头和数据行必须一起保留,否则单独的数据值没有含义
Markdown、HTML按标题层级切分,再限制到 300~700 tokens50~100标题是天然的语义边界,应保留标题及其正文。LangChain 也提供按 Markdown 标题和 HTML 结构切分的方式。(Docs by LangChain)

最常见的三个档位​

分块大小特点适用场景
256 tokens检索精准,但上下文较少,chunk 数量多FAQ、名词解释、短问题
512 tokens精度与上下文比较均衡普通知识库、技术文档、产品文档
1024 tokens上下文完整,但容易混入多个知识点书籍、论文、复杂制度、长篇教程

子父分块​

子父分块就是“子块负责精准召回,父块负责完整回答”;它同时兼顾了小 Chunk 的检索精度和大 Chunk 的上下文完整性

用小块找到答案位置,用大块(父块)给模型完整上下文

  • 会把同一份文档切成两种粒度
text
父 Chunk:较大,保存完整上下文
子 Chunk:较小,用于精准检索
  • 核心流程是
    • 切成较大的父 Chunk
    • 每个父 Chunk 再切成多个较小的子 Chunk
text
文档
↓
切成较大的父 Chunk
↓
每个父 Chunk 再切成多个较小的子 Chunk
↓
对子 Chunk 生成向量
↓
用户查询时检索子 Chunk
↓
根据子 Chunk 找到对应父 Chunk
↓
把父 Chunk 交给大模型回答

为什么子 Chunk 用于检索​

  • 子 Chunk 内容集中,语义更纯
  • 小 Chunk 和用户问题的语义更接近,因此检索更精准

为什么父 Chunk 用于生成​

  • 父 Chunk 保留了更多上下文

相关问题​

  • 我假设512为单位切片,但实际上我问的问题很短,对应书里的内容也很短,会不会回复不精准呢?
    • 不一定,短问题可以正常匹配 512-token Chunk;影响精准度的不是问题短,而是 Chunk 是否包含答案、以及检索和 Rerank 是否合理
      • 检索和 Rerank 方案
        • 检索阶段有没有把真正包含答案的 Chunk 找出来
        • Rerank 阶段有没有把最相关的 Chunk 排到前面并保留下来

  • 假如我以512切片,最终查询给到LLM的数据大小是512吗
    • chunk_size = 512 表示:单个文档切片最多约 512 tokens。
    • 它不代表最终只给 LLM 512 tokens。
    • 最终给 LLM 的知识库内容,取决于保留了多少个 chunk文档(top-k)
text
chunk_size = 512
检索 top_k = 10
Rerank 后保留 3 个
  • 最终发送给 LLM 的知识库内容大约是
    • 512 × 3 ≈ 1536 tokens