做RAG系统的工程师有个共同的噩梦:用户问的是Python,系统却返回了Java的文档。检索结果里总混进不相干的内容,生成出来的答案也跟着跑偏。问题往往不出在向量模型上,而是更早的一步——数据切片(chunking)没做好。
切片是把原始文档切成小段的过程,发生在数据进入嵌入模型之前。嵌入模型把每个切片转成向量存入数据库,检索时再按向量相似度召回。切得好,召回精准;切得碎或切得乱,上下文就会掺杂噪音。
一个典型场景:某段落同时讲了Redis的持久化机制和集群部署。如果不拆分,整段变成一个向量,查询"Redis持久化"时,集群部署的内容也会被带出来。有效的切片能把不同主题拆开,让检索只拿该拿的部分。
最基础的方案是固定长度切片:按字符数或token数一刀切。简单直接,但有个明显缺陷——容易把句子拦腰截断。一个意思被劈成两半,嵌入模型读到的就是残缺的上下文,检索质量自然下降。改进做法是让切片在标点或空格处收尾,保证语义边界完整。
固定切片的另一个问题是语义漂移。相关的内容可能被切到两个相距很远的块里,大模型检索时容易漏掉。重叠切片(overlapping chunking)就是用来解决这个的:每个块开头包含上一块的结尾内容。这样嵌入模型会把相关块在向量空间里放得近一些,检索更容易成对召回。
但重叠也有副作用。假设段落A讲主题甲,段落B讲主题乙,重叠部分会让B块带上A的内容。查询主题乙时,甲的残留信息可能被一并捞出。这时候就需要更精细的策略——语义切片(semantic chunking),按内容主题而非机械长度来划分边界,把真正相关的内容归到一处,无关的自然分开。
没有放之四海而皆准的切片策略。数据类型不同、查询方式不同,最优解都不同。实际工程中往往需要反复试验,在召回率和精确率之间找到平衡点。切片这一步花的心思,会直接决定最终用户拿到的是精准答案还是一团浆糊。
热门跟贴