RAG文档切分最佳实践:chunk策略、粒度与召回评测

举报
数据库小学妹 发表于 2026/09/20 09:52:07 2026/09/20
【摘要】 线上RAG客服答非所问,换了模型调了向量库都没用,最后定位到文档切分。chunk是检索的最小单位,切太碎语义残缺、切太大向量被平均。这篇用同一份文档对比固定长度、递归、语义、结构化四种切分策略的召回效果,讲清chunk粒度与重叠怎么定,附避坑清单。

大家好,我是数据库小学妹👋 我踩过的坑,你别再踩。

上个月帮一个团队看线上RAG客服。用户问“退款几天到账”,它答的是退货流程。模型换了两个,向量库也重新调过,还是答不准。我让他们把检索命中的片段打出来看,问题一下就清楚了。命中的那段是半句话,前半句被切到了另一个chunk里。后来做信创项目的时候发现,切分只是RAG检索链路上的一环,底座选什么,同样影响最终效果。这个后面一起说。

一、答不准,先别急着换模型

遇到答非所问,多数人的第一反应是模型不行。这个判断常常是错的。RAG的回答质量,一大半由检索决定。检索回来的是垃圾,模型再强也只能基于垃圾答。

检索的最小单位,就是你切出来的那段文本,业内叫chunk。所以排查RAG答不准,正确的顺序是先看检索命中什么,再看切分合不合理,最后才轮到模型和向量库。

打日志看命中片段,这一步别省。它往往一眼就能看出问题:命中的是半句话,还是混着好几个话题的一整段。

二、chunk 是 RAG 的隐性天花板

把RAG链路摊开看。文档先切成chunk,每个chunk转成向量,存进向量库。用户提问时,把问题也转成向量,检索最相近的几个chunk,跟问题一起丢给模型生成答案。

chunk是整个链路的起点,它划定了语义最小的完整单位。切分这一步没做好,后面所有环节都在补救。

切太碎,是怎么坏的?一句话被拦腰截断,两个半句各自都不完整。检索命中的是哪半句都答不全。开头那个客服,就是把“退款到账需要X天”和“退款到账需满足某条件”切到了两块。

切太大,又是另一种坏。一个chunk塞进了三四个话题,向量把它平均成一个模糊的点。检索时它和哪个问题都不够近,精度直接掉。而且大chunk白占模型的上下文窗口,挤掉本可以放进去的其他信息。

三、几种切分策略,我拿同一份文档测了一遍

市面上常用的切分策略,我归成四类,用一份200页的产品手册实测了一遍。手册里既有FAQ、表格,也有代码示例。问题是50个真实用户提问。

固定长度切分最简单,按字符数或token数一刀切。递归切分按层级来,先按段落切,段落超长再按句子切,句子还长再按字符切。语义切分靠句子的向量相似度找断点,话题变了才切。结构化切分顺着文档本身的标题、表格、代码块走。

结果是这样:

切分策略 命中率 答案质量 主要问题
固定字符 500 61% 偏低 句子被切断,语义残缺
固定字符 500 + 100 重叠 74% 断裂缓解,仍会混话题
递归切分(段→句) 82% 较高 遇到长段落仍偏大
语义切分 88% 计算成本高
结构化切分 + 语义 91% 要求文档本身结构清晰

命中率是这次实测的数,换文档、换问题集会变,但趋势稳定:越尊重语义边界,检索越准。具体效果也取决于文档类型和embedding模型,不是绝对的。

差距很直观。固定字符切法最省事,也最粗糙,比结构化切法低了三十个点。省下来的那点开发时间,全在答不准里还回去了。

四、粒度和重叠怎么定

选完策略,还有两个参数要定,粒度多大、重叠多少。

粒度别按字符一刀切,尤其中文。中文一个字常常就是一个甚至几个token,按字符切,chunk大小忽大忽小,很不稳。按token切更靠谱,经验区间一段300到800 token。太短语义不够,太长混话题。不同embedding模型对token的切分方式不同,实际大小建议以token数为准,并在实测中验证。

重叠是防切断的保险。相邻chunk之间留一部分重复内容,正好被切在两块边界上的句子,两边都能捞到。实测里,重叠从0加到20%,召回提升很明显。再加下去收益就小了,成本反而涨。

我的经验是重叠给到10%到20%。手册那类边界多的文档给20%,规整的文档10%就够。

# 一个可用的切分参数起点
chunk_size: 500        # 按 token,不是字符
chunk_overlap: 100     # 约 20% 重叠
splitter: recursive    # 递归:段落 -> 句子 -> 字符
separators: ["\n\n", "。", "!", "?", "\n", " "]

分隔符那行多提一句。中文文档的分隔符别只写英文句点,要把中文的句号、问号、感叹号都列上,不然句子判断全靠换行,切得乱七八糟。

五、切分之外,检索架构也得看一眼

前面讲的都是怎么切。但切完之后,chunk存在哪、怎么检索,同样影响最终效果。

传统RAG架构通常是“MySQL存原文+独立向量库存向量”,两套系统通过ETL同步。这个架构有个隐患:切分策略再好,如果检索时需要按业务线、按租户过滤,向量库的元数据过滤能力弱,只能应用层先查MySQL拿ID,再去向量库搜,性能会卡在ID列表的规模上。

那次信创项目里,我还试过另一种思路。金仓KES Vector把向量直接做成了数据库的原生类型,原文和向量待在同一个引擎里。检索时一条SQL就能完成向量相似度、标量过滤、全文检索的混合查询,要按业务线、按权限、按时效过滤,不用先查原文库拿一批ID,再去向量库挨个搜。我跑过这套,最直观的感受是少维护一套系统,两库之间那份同步延迟的账,也一并省了。

切分管的是原料质量,检索架构管的是原料用不用得上。这两件事在RAG上线前想清楚,比事后换模型省事得多。

六、别把表格和代码切坏

有一类错误特别隐蔽,就是把结构切坏了。

表格按字符数一切,某一行的前半截在上一块、后半截在下一块。检索回来一行残缺的表,模型读得云里雾里。表格要么整块保留,要么老老实实按行切。

代码块更别切。一段能跑的逻辑,被从中间切断,两个半块都失去了意义。代码块要当整体处理,宁可让它超长。

还有标题。有清晰结构的文档,顺着标题层级切效果最好。切的时候,把标题文本拼进每个chunk的开头,检索时能蹭到标题里的关键词,命中率会更好。

七、怎么验证切分好不好

调切分最忌讳凭感觉。改完一版,随机问几个问题看着还行,就上线了。等问题暴露,往往是上线之后。

稳妥的做法是搭一个小评测集。挑30到50个真实问题,每个问题标注“应该命中的原文片段”。每次调整切分,跑一遍这个评测集,看命中率有没有涨。

这个评测集不用多复杂,一个表格就够:

问题ID 用户问题 应命中片段 命中的chunk ID 是否命中
Q001 退款几天到账 “退款将在7个工作日内到账…” chunk_042

它是你调切分的标尺。没有标尺,你改的是好是坏,全靠猜。命中率上不去的RAG,模型换得再勤也白搭。先把切分这关过了,再谈别的。

避坑清单

别用固定字符数硬切中文。中文一个字可能是好几个 token,按字符切,块大小忽大忽小,句子还容易断在中间。先换成按 token、按层级递归,效果立刻不一样。

别省掉重叠。零重叠的切法,跨边界的句子必然残缺。加到 10% 到 20%,是性价比最高的一档。多花的存储和检索成本,远小于答不准的代价。

排查答不准,顺序别搞反。先打日志看检索命中的片段,再回头看切分,最后才怀疑模型和向量库。跳过前两步直接换模型,钱花了,问题还在。

调切分要有评测集。没有一组"问题对片段"的标尺,你永远不知道这一版比上一版好还是坏。凭感觉调,等于闭眼开车。

我的判断

RAG 这套东西,模型那一层大家在卷,切分这一层却常被忽略。可恰恰是切分,决定了检索能捞回什么。捞回来的原料不对,后面的模型再贵也是白费。

我一直觉得,切分这活儿更像一个数据层的设计决策。chunk 怎么切,决定了它怎么被存、怎么被检索,跟建表时定字段、建索引是同一类思考。做数据库的人看 RAG,别只盯着向量库,切分这层和它后面的存储、检索架构,得放在一起看。

你做过 RAG 吗?有没有遇到过答非所问,最后发现是切分的问题?

我是数据库小学妹,帮你少走弯路少踩坑,咱们下篇见👋

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。