切分:RAG 成败的第一步
建知识库时,切分是最先做、最没技术含量、也最容易被随便糊弄过去的一步。但它决定了检索的最小单位——切错了,后面所有环节都在补救。
- 它答对了主条款,却漏掉了紧跟着的例外情况
- 召回的片段读起来像半句话,前后文都不知道在说什么
- 一段材料里塞了五个主题,模型抓错了重点
为什么这步最关键
因为切出来的片段,就是检索能返回的最小单位。库里没有一段能完整回答问题的内容,检索再准也拿不出来。
看图上的三种切法。
切得太碎:「七日内可无理由退货,但生鲜类除外」被切成了四段。用户问能不能退,检索命中「七日内可无理由」那段,「生鲜除外」留在了另一段没被召回。模型于是答「可以退」——答案错了,但每一步看起来都没毛病。
这类错误特别危险,因为它是自信的、有出处的、而且只在特定情况下出现。测试时很难覆盖到。
切得太大:一整章塞进一段。一段文字压成一个坐标,等于把里面所有主题平均了一下——退货、换货、发票、客诉全混在一个坐标里,哪个主题都不突出,结果是什么问题都能召回一点,什么问题都不够准。而且这一大段塞进上下文,中间部分很可能被忽略。
按结构切:一段说完一件事,条件和它的例外在同一段里。这才是要的。
怎么切
按可靠性从高到低,三种做法。
一、按文档自身的结构切(首选)。按标题层级、按条款编号、按 Markdown 的小节。文档作者已经替你把「一个完整意思」的边界标出来了,直接用就是。
这条能覆盖大部分结构化文档:产品手册、政策条款、API 文档、帮助中心。如果你的文档有清晰的小标题,几乎不用考虑别的方案。
二、按语义边界切。文档没有明确结构时(比如会议记录、长邮件),按段落和话题转折切。可以用模型辅助判断话题在哪换的。
三、按固定长度切(下策)。每 500 字切一刀。实现最简单,也最容易把一句完整的话拦腰砍断。
如果不得不用固定长度,一定要加重叠——相邻两段共享一部分内容(比如重叠 10% 到 20%)。这样即使切在了关键句中间,至少有一段是完整的。重叠是固定长度切分的必备补丁,代价只是多一点存储。
关于长度,给个起点:多数场景下每段 200 到 500 个 Token 比较合适。但这真的要看内容——法律条款可以短,技术教程往往需要更长才说得完整。别信任何一个「标准值」,拿你自己的文档试。
带上标题再入库
这一招几乎零成本,但效果明显,很多团队不知道。
做法:每一段入库前,在开头拼上它的来源路径。比如「售后政策 > 第三章 退货 > 3.2 不适用情形」,然后才是正文。
为什么有用?因为切出来的片段常常是「无主」的——正文里写着「本条不适用于以下情形」,但「本条」是哪条,信息在标题里,而标题被切走了。算向量时,这段孤零零的文字既不知道在讲什么主题,检索时自然也匹配不上。
拼上路径之后,这段文字自带了主题信息,向量位置立刻准确多了。而且模型拿到材料时也能看出它出自哪,标注出处更方便。
同理,还应该给每段存上元数据:来源文档、章节、生效日期、版本、可见范围。这些在检索时能用来过滤——比如只查当前有效的版本,或者只查这个用户有权限看的内容。过期版本被召回这个坑,就靠它来堵。
几类特殊内容
几种常见的、按普通方式切一定出问题的内容。
表格。按行切会丢表头,整表入库又可能太大。可行做法是把每行转成一句自然语言(「产品 A 的保修期是 12 个月」),或者至少保证每段都带着表头。直接把表格当普通文本切,基本等于废掉。
问答对。如果你的资料本来就是 FAQ,那太好了——一问一答就是天然的切分单位,而且问题本身和用户提问的向量天然接近。这是效果最好的一类语料,值得优先整理。
长流程和步骤。「第五步」单独被召回是没意义的。要么整个流程作为一段,要么每段都带上流程名和总步数。
代码和配置。按语法边界切(一个函数、一个配置块),别按行数。
最后一条务实建议:切完之后,随机抽二十段出来自己读一遍。问自己:单看这一段,能明白它在说什么吗?信息完整吗?——这个五分钟的检查,比调任何参数都有价值。
