RAG 固定大小分块有什么问题?
一则或许对你有用的小广告
欢迎加入小哈的星球,你将获得:专属的实战项目(4个项目都能学) / 1v1 提问 / 简历修改 / Java 学习路线 / 社群讨论 / 学习打卡 / 每月赠书
《Spring AI 项目实战(问答机器人、RAG 智能客服、联网搜索)》已完结,基于
Spring AI + Spring Boot 3.x + JDK 21...,查看介绍《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...,查看介绍;演示链接:http://116.62.199.48:7070/《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接:http://116.62.199.48/
新开坑项目:《从零手撸:秒杀系统高并发优化实战》 正在更新中...,查看介绍
截止目前,星球内专栏累计输出 150w+ 字,讲解图 5110+ 张,还在持续爆肝中.. 后续还会上新更多项目,已有 4700+ 小伙伴加入学习,欢迎点击围观
面试考察点
- 分块策略的理解深度:面试官不仅仅是想知道固定大小分块的缺点,更想知道你是否理解分块策略对整个 RAG 检索效果的连锁影响——从 Embedding 质量到召回精度再到最终生成质量。
- 实践经验:你有没有实际调过 Chunk 大小?有没有遇到过因为切分不当导致检索不命中或答案不完整的情况?
- 方案选型能力:知道固定大小分块的问题后,你能给出什么更好的替代方案?各自的适用场景是什么?
核心答案
固定大小分块(Fixed-size Chunking)是 RAG 中最简单粗暴的分块方式——不管三七二十一,按固定的字符数或 Token 数把文本切成等长的片段。但它有几个致命问题:
| 问题 | 说明 |
|---|---|
| 语义被腰斩 | 一句话、一个段落、甚至一个逻辑论证可能被从中间截断,检索到的 Chunk 只包含部分信息 |
| 主题被打散 | 同一个主题的内容可能被分散到多个 Chunk 中,检索时只能命中一部分 |
| 信息冗余或缺失 | 不同 Chunk 之间要么重叠太多浪费存储,要么重叠太少丢失关键上下文 |
| 缺乏文档结构感知 | 无视标题、段落、列表等文档结构,所有内容一刀切 |
| 检索噪声大 | Chunk 内可能混合多个不相关的话题,导致检索时匹配到不相关的内容 |
一句话总结:固定大小分块最大的问题是 "只看长度不看意义",它完全忽略了文本的语义边界。
深度解析
一、语义断裂——最致命的问题
上图展示了固定大小分块的核心问题——语义断裂。具体来说:
- 固定大小分块在字符计数到达阈值时就 "咔嚓" 一刀切下去,完全不考虑当前是否在一句话的中间、一个段落的中间,甚至一个词的中间
- 检索时,用户可能搜到了包含 "结合外部知识库" 的 Chunk,但这个 Chunk 缺少前半句 "RAG 的核心优势",导致模型拿到的上下文不完整
- 更糟糕的是,如果你的 Chunk 大小恰好把一个完整的因果论证(比如某个技术方案的优缺点分析)切成两半,检索只命中一半,模型就会给出 "只见树木不见森林" 的回答
这个坑我之前做 RAG 项目的时候就踩过——一个技术文档里关于 "为什么选择 Milvus 而不是 Pinecone" 的对比分析被固定分块切成三段,检索只命中了其中一段,结果模型回答得牛头不对马嘴。
二、Overlap 是个 "补丁",不是 "解药"
固定大小分块通常配合 Overlap(重叠)来缓解语义断裂问题:
// LangChain4j 中的固定大小分块示例
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.data.document.DocumentSplitters;
// 创建固定大小分块器
// chunkSize: 每个 Chunk 的最大 Token 数
// overlapSize: 相邻 Chunk 之间的重叠 Token 数
DocumentSplitter splitter = DocumentSplitters.recursive(
500, // chunkSize: 每个 Chunk 最多 500 Token
100 // overlapSize: 相邻 Chunk 重叠 100 Token
// 注意:recursive 分块器会先按段落、换行符等分隔符尝试切分
// 如果某段超过 chunkSize,才会按字符强制切分
// 这比纯固定大小分块要好一些,但仍然不是语义级别的切分
);
// 对文档进行分块
Document document = Document.from(documentText);
List<TextSegment> segments = splitter.split(document);
但 Overlap 本身也带来新问题:
- 存储膨胀:如果 Overlap 设为 20%,相当于向量库存储量增加了 20%,Embedding 计算量也同步增加
- 检索冗余:同一个内容可能出现在多个 Chunk 中,检索时返回重复信息,浪费 LLM 的上下文窗口
- 治标不治本:Overlap 只能缓解 "句子被截断" 的问题,对 "主题被打散" 基本无能为力
所以 Overlap 就像是给一个设计缺陷打补丁——有用,但远远不够。
三、更好的替代方案
| 分块策略 | 原理 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 固定大小分块 | 按固定字符/Token 数切分 | 实现简单、性能高、大小可控 | 语义断裂、主题打散 | 快速原型、结构化文本 |
| 递归字符分块 | 按分隔符优先级递归切分(段落 → 句子 → 字符) | 兼顾语义和大小控制 | 仍然依赖分隔符,不够智能 | 通用场景(LangChain 默认) |
| 语义分块 | 根据 Embedding 相似度变化点切分 | 语义完整性最好 | 计算成本高,需要 Embedding 模型 | 高质量问答、法律文档 |
| 文档结构分块 | 按标题/章节/段落等文档结构切分 | 保留文档逻辑结构 | 依赖文档格式规范 | 结构化文档(Markdown、HTML) |
| Agentic 分块 | 用 LLM 判断语义边界 | 最智能,适合复杂文档 | 成本极高、速度慢 | 前沿研究,特定场景 |
四、生产环境的分块实践建议
结合实战经验,给几个实际可操作的建议:
- 不要纯固定大小分块:至少用递归字符分块(Recursive Character Splitting),LangChain4j 和 Spring AI 都支持
- 利用文档结构:如果源文档是 Markdown 或 HTML,优先按标题层级切分,这样每个 Chunk 都有明确的主题
- 加元数据:给每个 Chunk 附上来源文档名、章节标题、页码等元数据,检索时可以利用元数据过滤
- Chunk 大小根据场景调:问答场景 200-500 Token,摘要场景可以更大。经验值:先从 300 Token、50 Overlap 开始试,再根据效果调优
- 多粒度分块:同时维护粗粒度和细粒度的 Chunk,粗粒度用于上下文补充,细粒度用于精准匹配
// Spring AI 中的文档处理示例
import org.springframework.ai.document.Document;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import java.util.List;
// 使用 TokenTextSplitter 进行分块
TokenTextSplitter splitter = new TokenTextSplitter(
500, // defaultChunkSize: 每个 Chunk 的目标 Token 数
100, // minChunkSizeChars: 最小 Chunk 字符数
50, // minChunkLengthToEmbed: 最小可嵌入长度
100, // maxNumChunks: 最大 Chunk 数量
true // keepSeparator: 是否保留分隔符
);
// 分块处理
List<Document> chunks = splitter.apply(originalDocuments);
// 为每个 Chunk 添加元数据(生产环境强烈建议)
chunks.forEach(chunk -> {
chunk.getMetadata().put("source", "技术文档.pdf");
chunk.getMetadata().put("section", "第三章-架构设计");
chunk.getMetadata().put("page", 42);
});
五、2025-2026 年的前沿进展
这个领域发展很快,几个值得关注的方向:
- Late Chunking(Jina AI 提出):先对整个文档做 Embedding,再进行分块。这样每个 Chunk 的向量表示会包含全局上下文信息,大幅减少语义断裂问题
- Max-Min 语义分块(2025 年论文):利用语义相似度 + Max-Min 算法自动识别语义边界,比传统固定分块效果提升显著
- 上下文感知分块:在 Chunk 中自动补充前后文的摘要信息,让每个 Chunk 自带 "上下文包装",检索效果更好
- 多模态分块:针对包含图表、代码、公式的文档,按模态类型分别处理,不再用统一的文本分块策略
面试高频追问
-
追问一:你项目中用的是什么分块策略?效果怎么样?
建议结合实际项目回答。比如说:"我们用的是递归字符分块 + 按文档标题层级辅助切分,Chunk 大小 300 Token、Overlap 50 Token。后续发现某些长文档的跨章节问题检索效果不好,又引入了父文档索引(Parent-Child Indexing)来补充上下文。"
-
追问二:Chunk 大小怎么确定?越大越好还是越小越好?
不是越大越好也不是越小越好。Chunk 太小,语义不完整;Chunk 太大,检索噪声高,而且浪费 LLM 的上下文窗口。需要根据场景实验调优,通常问答场景 200-500 Token 是比较好的起点。
-
追问三:如何评估分块策略的好坏?
最直接的方法:准备一批测试问题和标准答案,对比不同分块策略下的检索召回率和答案准确率。可以用 RAGAS 框架做自动化评估,重点关注 Context Precision(检索到的 Chunk 中相关内容的比例)和 Context Recall(回答问题所需的 Chunk 是否都被检索到了)。
常见面试变体
- "RAG 中的文本分块策略有哪些?各有什么优缺点?"
- "为什么不能直接把整篇文档作为检索单位?"
- "如何优化 RAG 的 Chunk 策略来提升检索效果?"
- "说一下你了解的语义分块和固定大小分块的区别?"
记忆口诀
固定分块 "三宗罪":语义断裂、主题打散、结构无感。记住一句话就行——"只看长度不看意义的分块,就是在给 RAG 系统埋雷"。
总结
固定大小分块最大的问题是完全忽略语义边界,导致检索时拿到的 Chunk 信息不完整或不相关。生产环境中建议至少使用递归字符分块,配合 Overlap 和元数据管理,有条件的场景可以上语义分块。面试时重点讲清楚 "为什么固定分块不好" 和 "你用了什么更好的方案",基本就能过关。
