很多人在做 RAG 时,会把精力放在:
- 模型选型
- Prompt 优化
- Rerank
但在真实工程中,一个更底层、但经常被忽略的问题是:
你是怎么“切数据”的?
也就是:
Chunk(分块)策略
一、为什么一定要分块?
因为大模型有一个硬限制:
上下文窗口(Context Window)是有限的
你不可能把整本知识库直接喂进去。
本质问题是:
如何把“大文档”
拆成
“既能被检索命中,又能被模型理解”的最小单位?
二、Chunk 本质:信息的“最小可检索单元”
很多人把 Chunk 理解成:
“按字数切一下”
但更准确的定义应该是:
Chunk = 检索系统中的最小语义单元
它必须同时满足两件事:
- 能被检索命中(Recall)
- 被模型理解时是完整的(Coherence)
而问题在于:
这两个目标是天然冲突的
三、Chunk 太小 vs Chunk 太大(核心矛盾)
1. Chunk 太小(例如:50 tokens)
优点
- 更容易命中关键词
- Recall 更高
缺点
- 语义不完整
- 模型理解困难
- 上下文断裂
- 更容易产生幻觉
2. Chunk 太大(例如:1000 tokens)
优点
- 语义完整
- 上下文充分
缺点
- 不容易命中
- 噪声变多
- Token 浪费严重
本质冲突:
小 chunk → 检索友好,但理解差
大 chunk → 理解好,但检索差
四、最常见的错误:按字符硬切
很多系统是这样做的:
chunk_size = 500
overlap = 50
然后直接切文本
问题在于:
- 破坏语义结构
- 句子被截断
- 标题和内容分离
举个真实错误:
Chunk1: 报销流程包括提交申请...
Chunk2: ...审批通过后进入财务打款
模型看到的是:
- 两段“半截话”
- 无法建立完整逻辑
五、正确思路:基于“语义结构”分块
不要按长度切,要按结构切
推荐优先级:
1. 文档结构切分(最优)
- 标题(H1 / H2 / H3)
- 段落
- 列表
2. 语义边界切分
- 句号
- 换行
- 语义停顿
3. 长度兜底
- 超长再切
示例
【报销流程】
1. 提交申请
2. 部门审批
3. 财务打款
应该作为一个 chunk,而不是拆开
六、Overlap(重叠)到底有没有用?
很多教程会写:
overlap = 50 / 100
但很少讲清楚:
为什么需要 Overlap?
本质作用:
防止信息被“切断”
举个例子:
Chunk A: 提交申请 → 审批
Chunk B: 审批 → 打款
如果没有 overlap:
“审批”这个关键连接点可能丢失
但注意:
- overlap ≠ 越大越好
- 过大会导致:
- 冗余
- 检索污染
工程建议:
chunk_size: 300~500
overlap: 10%~20%
七、不同业务的最优 Chunk 策略(重点)
不同数据类型,本质上需要不同的 Chunk 结构。
1. 企业知识库
特点:
- 结构化文档多
- 流程类信息多
推荐:
- 按“段落 / 流程”切
- 保证每个 chunk 是一个完整步骤
2. 技术文档
特点:
- 上下文依赖强
- 逻辑连续
推荐:
- 较大 chunk(400~800)
- 保留上下文连续性
- 避免代码 / 配置被拆散
3. FAQ / 问答库
特点:
- 每条独立
推荐:
- 一个 QA = 一个 chunk
- 不需要 overlap
4. 结构化数据(表格 / JSON)
不要乱切:
- 一行 / 一条记录 = 一个 chunk
八、一个你必须知道的高级优化
多粒度 Chunk(Multi-Granularity)
思路:
同一份数据,切两套:
小 Chunk → 提高 Recall
大 Chunk → 提高语义完整性
检索时:
- 先用小 chunk 找
- 再映射回大 chunk
这可以同时解决:
- “找不到”
- “看不懂”
九、Chunk = RAG 的“地基”
很多人会优先优化:
- 模型
- Prompt
但忽略:
数据是怎么被组织的
更本质地理解:
Embeddin 决定表达能力
Chunk 决定信息结构
检索决定信息范围
Prompt 决定输入质量
十、一个重要事实
Chunk 不是“切文本”,而是在设计知识的最小表达单位。
收尾
如果你发现:
- RAG 经常“答非所问”
- 或者“明明有数据但就是答不出来”
那很可能不是模型问题,而是:
你的数据,从一开始就被切错了。
下一篇预告
下一篇我们继续往下拆:
Embedding 深入:为什么“相似”不等于“相关”?
包括:
- 向量空间是怎么“失真”的
- 为什么中文效果更难
- 如何做模型选型与评估