RAG 切块策略实战:chunk 大小、重叠与结构感知

切块为什么是第一道生死关

上一篇给出 RAG 最小流水线时,「切块」还只是个一行循环。真到生产里,切块质量往往决定整个系统的上限:检索的匹配发生在「问题向量」与「块向量」之间,块的形状直接决定匹配质量。

两个方向的失败都很典型:

  • 块太大:一段里混进多个主题,每个主题的语义都被稀释。问题问 A,这块里 A 只占两成篇幅,块向量被另外八成内容拉偏,相似度算不高;就算侥幸命中,塞进提示词也白白挤占上下文预算,还带来噪音。
  • 块太小:语义聚焦了,但上下文残缺。「因此它的性能提升了三倍」——「它」是谁?块里没有答案。小块检索容易命中,模型拿到手却答不出,等于白命中。

由此得出切块的总目标:**每一块自包含、可独立理解,且只讲一个主题。**下面从最朴素到最讲究,过一遍常用策略。

固定长度切块:size 与 overlap

最朴素的办法是按固定长度切:每块取固定数量 token(词元,模型处理文本的最小单位;常见分词器下一个汉字大约占一到两个 token),相邻块之间保留一段重叠(overlap),避免关键句子恰好被切在缝里、两块各拿一半。

经验量级上:块大小从几百 token 起步试起,重叠取块大小的 10%–20% 是常见起点。没有放之四海皆准的数字——技术手册与问答对的合适块大小可以差出一倍以上,只能拿自己的数据验证(文末给验收方法)。固定切块实现最简单,但它对「句子被拦腰斩断」无能为力,于是有了下一层。

递归与分隔符切块

聪明一点的做法:优先按语义边界切。维护一个分隔符优先级列表——先试段落分隔(空行),切出来还太大就降级到句子边界(句号、问号、换行),最后才轮到字符级硬切。主流工具里常见的 recursive chunker 用的正是这个思路:自上而下尝试分隔符,尽量让每块落在自然边界上。成本几乎为零,收益立竿见影,是多数场景的合理默认。

结构感知切块:按文档骨架切

对结构化文档,最强的信号是结构本身:

  • Markdown:按标题层级切,每个 H2/H3 小节自成一块,并把标题路径(如「部署 › 回滚」)记进元数据。
  • 代码:按函数、类为界切,一个函数就是一个自包含单元;按行数切会得到大量「半截函数」,向量既不像文档也不像代码。
  • 表格:整表保留为一块。表格按行切开,每行的「列名—值」对应关系就丢了,几乎必然不可用;太大的表宁可做行级展开(每行拼上表头再成块),也不要裸切。

父子块:检索用小块,生成用父块

一个实用技巧是两层索引:先把文档切成较大的父块(量级上千 token),再把每个父块细分成较小的子块。检索时用子块匹配——小块语义聚焦,容易精准命中;命中后把它所属的父块交给模型——上下文完整,指代不缺。

相当于「用小块找位置,用父块给上下文」。索引多存一层,工程上只是多一个「子块 → 父块」的映射,检索质量却常有肉眼可见的改善。它和结构感知切块天然兼容:按标题切的节就是父块,节内再按句子细分出子块。

元数据随块走

每一块都应携带元数据:来源文件、标题路径、更新时间、文档类型、权限标签。它的价值在检索之后才显现:

  • 过滤:按时间取「最新版」,按部门做权限隔离,按文档类型收窄范围,都靠检索后的元数据过滤完成。
  • 引用:答案附上「出自哪份文档哪一节」。可溯源是 RAG 相对微调的核心优势,而出处信息从切块那一刻起就要跟着块走,事后补非常痛苦。

怎么验收切块质量

不需要复杂指标体系,最小方法如下:抽 20 个真实用户问题,逐个人工检查检索命中的块——

  1. 这个块自包含吗?不看原文也能读懂?
  2. 只凭这个块(或它的父块)能回答问题吗?

命中块大多答不上来,就回头调块大小、加重叠或改用结构感知切法,改完再抽一轮。顺带一提,这 20 道题正是系列评测篇最好的种子评测集——验收时你已经在人工看命中块了,顺手把「答案在哪一块」记下来就是标注。

要点小结:块太大稀释相似度,太小丢上下文;起点用几百 token 加 10%–20% 重叠;能按结构切就别按字符切;检索用子块、生成用父块;元数据从切块起随块走。切块之外,检索本身还有另一类病:该命中的没命中、命中的排得靠后——下一篇讲混合检索与重排序。

← 返回资讯列表

读者留言

COMMENTS 暂无
仅本站原创文章开放留言 · 请勿留下手机号、邮箱等个人信息

还没有留言,来说第一句?