Appearance
3.1.1 什么是 Chunk?
先给结论:在 RAG 里,Chunk 不是“随便切出来的一段文字”,而是系统真正拿来做检索、过滤、排序和组织答案的知识单元。
理解这一点很重要。因为很多后续问题,看起来像是 embedding、检索器或模型的问题,实际上往往是 chunk 定义得不对。
先把最核心的概念说清楚
一篇原始文档通常太长、信息太杂、结构太复杂,系统很难直接拿它做稳定检索。
所以在进入索引前,文档通常会先被拆成一批更小的片段。每一个这样的片段,就是一个 chunk。
你可以把它先粗略理解成:
- 一段正文
- 一个小节
- 一组相关句子
- 一个带上下文边界的知识片段
但更准确一点说,chunk 不是按“看起来差不多长”定义的,而是按“系统后面要怎么用它”定义的。
为什么 Chunk 不是普通文本片段
如果只是从表面看,chunk 好像就是一小段字符串。
但在 RAG 系统里,它通常还会带着很多额外信息,比如:
- 它来自哪份文档
- 它在文档里的哪个位置
- 它属于哪个标题或章节
- 它的更新时间、版本、权限、租户是什么
也就是说,一个真正可用的 chunk,通常至少包括两层:
文本内容描述这个文本边界和来源的 metadata
少了后一层,它往往就只剩“可读”,但还谈不上“可被系统稳定使用”。
一个最小的 Chunk 示意
python
chunk = {
"text": "商品签收后 7 天内支持无理由退货,定制类商品除外。",
"metadata": {
"doc_id": "refund-policy-v3",
"title": "退款规则",
"section": "售后说明",
"source": "/help/refund",
"updated_at": "2026-04-01",
"chunk_index": 3
}
}这段示意代码里,真正重要的不是字段名字,而是它体现了一个事实:
系统后面检索到的,不应该只是“孤零零的一段话”,而应该是“带着上下文身份的一段话”。
Chunk 在 RAG 里到底承担什么角色
如果把 RAG 链路往后看,chunk 通常会同时承担几件事:
1. 作为检索的最小候选单位
系统不会每次都拿整篇文档去比较相关性,而是更常拿 chunk 去做召回。
2. 作为过滤和排序的基本单位
很多 metadata filter、版本优先级、权限判断,最后都是在 chunk 层真正生效。
3. 作为上下文构造的原材料
模型最后看到的回答依据,通常不是原始整篇文档,而是一组被挑出来的 chunk。
4. 作为引用和追溯的基础单元
如果后面要展示来源、章节、页码、标题,往往也要依赖 chunk 身上的来源信息。
所以 chunk 并不是“导入前顺手切一下”的中间产物,而是后面整条检索链路真正反复使用的对象。
一个更接近实际的理解方式
很多时候,读者容易把 chunk 理解成“分词的放大版”或者“把文档均匀切开的小块”。
更准确的理解方式其实是:
Chunk 是系统对知识粒度的第一次正式定义。
它回答的是下面这个问题:
系统以后准备按多大的知识单位去理解、匹配和组织答案?
如果这个单位太大,问题会是:
- 一块里混了太多主题
- 相关部分被无关内容稀释
- 检索到了也不代表真正命中了答案核心
如果这个单位太小,问题又会是:
- 语义断裂
- 前提丢失
- 模型看到的只是残片
所以 chunk 的本质,不是“切一刀”,而是在平衡:
- 语义完整性
- 检索定位能力
- 上下文成本
为什么这一层会直接影响后面所有模块
Chunk 定义得不合理,后面这些环节都会一起出问题:
- embedding 表示会失真
- 检索结果会偏大或偏碎
- rerank 很难准确判断
- Prompt 上下文会变得冗长或残缺
- 引用展示会难以解释
这也是为什么很多系统看起来像是“检索不准”,但往前追根因,最后会追到 chunk。
一个很常见的误区
很多人第一次做 RAG,会把 chunk 理解成:
- 只要按固定字符数切开就行
- 只要切得够碎,检索就会更准
- 只要文档能切成块,后面问题就解决了
这些理解都不够准确。
因为真正关键的不是“有没有切”,而是:
- 切出来的块是不是语义相对完整
- 它是不是保留了足够的来源和结构信息
- 它是不是符合后面的检索和生成目标
一句话总结
Chunk 在 RAG 里不是普通文本片段,而是系统真正拿来理解知识、做检索、做过滤和组织回答的基本单元。后面很多设计,本质上都是在围绕这个基本单元继续展开。