跳到主要内容

K2.1 为什么要切块,又怎么切坏

为什么不能整篇塞进去​

你有一份 50 页的员工手册,要放进知识库。最偷懒的想法是:整篇存进去、整篇检索。为什么不行?两个硬约束把这条路堵死了。

约束一:检索要精准。 用户问「年假有几天」,你该给模型的是「年假」那一小段,而不是把整本手册甩过去。为什么?因为把 50 页全塞进模型的上下文,既贵(上篇 8.2 节算过,长上下文又慢又费钱),又蠢——年假那一句被埋在几万字里,重点被大量无关内容稀释,模型反而容易「看走眼」。给它精准的一段,它才答得准。

约束二:向量装不下整篇。 回想 K1:语义检索靠的是「把资料变成一个向量」。可一篇 50 页的长文,压成一个向量会怎样?细节全糊了。上篇 1.4 节讲过,一个向量的表达能力是有限的——它能概括「这篇大致讲人事制度」,却记不住「年假 5 天、病假需医院证明、婚假 3 天」这些具体事实。用一个模糊的向量去检索,什么都对得上一点,什么都不精准。

所以,长文档必须先切块:切成一段段小的文档块,每块单独编码成向量、单独入库。检索时,匹配到哪块就取哪块。

两个极端,两种坑​

切块的核心矛盾,藏在「块该多大」这个问题里。往两个极端走,各有各的死法:

  • 切太大:一块里塞了太多不同的事。检索时就算命中了,捞回来的也不干净——你要的那句话,混在一堆无关内容里;而且一块内容太杂,它的向量会被「平均」得谁都不像,相似度反而拉低。
  • 切太小:一个完整的事实,被块的边界拦腰截断。比如「会员 15 天无理由退货」在一句、「但生鲜、定制不能退」在另一句——切开之后,检索可能只捞回前半句,模型就会自信地告诉你「都能退」,把关键的例外漏得干干净净。

光说太抽象。下面这个实验,把同一篇「会员退货说明」用三种切法切开,你亲眼看每种切法在同一个问题上的命运:

🎮 动手实验
切块对比器:切在哪,决定查得准不准
下面这篇「会员退货说明」要入库,先得切成块。三种切法各有各的命。选一个查询,点「开始检索」,看每种切法捞回哪一块、答得完不完整。(检索结果为教学示意)
📄 待入库文档:
【会员退货说明】本店黑卡会员享有专属退货政策,普通商品支持 15 天无理由退货,比非会员多 8 天。但需注意:定制类商品、生鲜食品和已拆封的数码配件,不在无理由退货范围内。退货运费方面,会员退货免运费由本店承担,非会员需自付 10 元退货运费。如需退货,请在「我的订单」中选择对应订单,点击「申请退货」并上传凭证。
🧑‍💻 会员退货,有什么东西是不能退的?
🎯 需要「15 天无理由」+「例外清单」两句一起,才算完整
① 整篇一大块不切,整个文档当一个块
【会员退货说明】本店黑卡会员享有专属退货政策,普通商品支持…
② 每句一小块按句号一刀切,每句一个块
【会员退货说明】本店黑卡会员享有专属退货政策,普通商品支持 15 天无理由…但需注意:定制类商品、生鲜食品和已拆封的数码配件,不在无理…退货运费方面,会员退货免运费由本店承担,非会员需自付 10…如需退货,请在「我的订单」中选择对应订单,点击「申请退货」…
③ 按语义切(刚好)把「讲同一件事」的句子并到一块
【会员退货说明】本店黑卡会员享有专属退货政策,普通商品支持 15 天无理由…退货运费方面,会员退货免运费由本店承担,非会员需自付 10…如需退货,请在「我的订单」中选择对应订单,点击「申请退货」…
💡 要点:切块是 RAG 里最不起眼、却最容易翻车的一步。切太大——一块里塞太多事,重点被稀释、相似度被拉平;切太小——一个完整的事实被边界拦腰截断,检索只捞回半个答案(比如漏掉「例外」)。好的切块让「每一块 = 一个完整的意思」。这也是「语义切块」「滑窗」「late chunking」这些技术想解决的同一个问题。

从实验里读出三条教训​

先玩第一个查询「会员退货,有什么东西是不能退的?」,点「开始检索」,三种切法三种结局:

  • ① 整篇一大块:捞回了整篇——答案确实在里面,但混着运费、退货操作等一堆无关内容(🌀 噪声多)。文档一大,重点就被稀释、相似度被拉平。
  • ② 每句一小块:💥 只命中了「15 天无理由」那句(它和「会员退货」字面最像),却把关键的「例外清单」那句漏在了另一个块里。结果模型会告诉你「会员都能退」——把生鲜、定制不能退这个要命的例外,漏得一干二净。这就是切太碎,切断了完整语义。
  • ③ 按语义切:把「时长 + 例外」这两句放进了同一块,所以答案完整:会员 15 天无理由,但生鲜、定制、拆封数码除外(✅)。

再玩第二个查询「退货要自己付运费吗?」,你会发现一个反转:这次「② 每句一小块」也答对了!因为「运费」这个事实,本来就完整地待在一句话里,没有跨越块的边界。

这个反转很重要,它揭示了切块真正的原则:

好切块的唯一标准

让每一块 = 一个完整的意思。 既不掺太多别的事(否则重点被稀释),也不把一件事切散(否则只捞回半个答案)。「切太碎」本身不是错——只有当它把一个完整的事实切断时,才致命。

切块的两个基本旋钮​

实践中,最常见的切块方式就是「按固定长度切」,它有两个要调的旋钮:

  • 块大小(chunk size):一块多长,通常按 token 数算(比如 256512 token)。这是最关键的超参数。顺带记个换算:中文里 1 个汉字大致对应 12 个 token(取决于分词器),所以 512 token 差不多是 300~500 个汉字——你可以拿自己文档的字数除一下,估出大概能切多少块。
  • 重叠(overlap):相邻两块之间留一段重叠内容(比如后一块的开头,重复前一块的结尾 50 个字)。这样即使某个句子正好压在边界上,它至少在某一块里是完整的——像给切口打了个「补丁」。
切块没有「万能最优解」

不要指望有一个「切块大小 = 400」的标准答案。最优切法高度依赖你的文档类型(手册按小节切、对话按轮次切、代码按函数切、财报按表格切)和查询类型(问细节要小块,问概括要大块)。chunk size 是一个必须拿真实查询去测、去调的超参数,不是拍脑袋定的——这也是为什么业界常把切块称作 RAG 里最需要「手艺」和耐心的一步。垃圾的切块,会让后面所有环节都白费力气。

小结​

本节要点
  • 长文档必须切块:整篇检索既稀释重点、又浪费上下文,且一个向量装不下整篇的细节。
  • 切太大→命中也不干净、相似度被拉平;切太小→完整的事实被边界切断、只捞回半个答案。
  • 好切块的唯一标准:每一块是一个完整的意思。切太碎不是永远错,只有切断完整事实时才致命。
  • chunk size 和 overlap 是要拿真实查询调的超参数;切块没有万能最优解,高度依赖文档和查询类型。
📝 动手自测0/3
1. 为什么不能把一份 50 页的长文档「整篇」存进知识库、整篇检索?
2. 实验里,查询「会员退货有什么不能退的」时,「每句一小块」为什么给出了不完整的答案?
3. 同样是「每句一小块」,为什么在查询「退货要付运费吗」时反而答对了?这说明什么?

延伸阅读​