这道题其实问的是,在[[RAG]]系统里,怎么把文档切成合适的小块,既让检索能精准命中,又不把语义切碎。说白了,就是信息密度和语义完整性之间的取舍。
先说几种常见的[[分块]]策略,以及它们各自该在什么场景用。固定长度分块,就是按token数硬切,比如512个token一段。好处是简单,向量索引对齐也方便,但问题很明显,可能一句话被拦腰切断,检索时上下文就丢了。[[滑动窗口]]分块会让相邻块保留一部分重叠,可能减少边界信息丢失,但代价是存储、计算与去重成本上升。窗口大小仍应作为候选变量,用同一评测集比较后再定。真正落地的话,这两种其实更适合英文或者短文本场景,中文用它们很容易出问题。
语义分块是我更推荐的,就是按句子或段落边界切,保持语义完整。中文场景里,用标点符号切分比按字符切分靠谱得多,因为中文不像英文天然有空格。举个例子,客服退款场景里,用户问“我的退款为什么还没到”,如果切块把“退款”和“还没到”分到两段,检索召回就偏了。用语义分块就能保证整句在一起,匹配更准。
结构化分块适合有层次结构的文档,比如PDF或Markdown,按标题、章节、段落来切,保持层级信息。这样检索时可以先定位章节,再找细节,效率高。
这里有个关键权衡:分块粒度。小块比如100-300 token,检索精准但容易碎片化,适合问答;大块比如1000+ token,语义完整但噪声多,适合摘要或分析。具体用多大,得看下游任务和[[Embedding]]模型的最大长度。比如text-embedding-ada-002虽然支持8191 token,但有效信息往往在前512,切太大反而浪费。
实际工程里,我通常不会只用一种策略。比如处理企业SOP文档,我会先用结构化分块按章节切,再对每个章节用语义分块按段落切,这样既保留了文档结构,又保证了段落语义完整。检索时粗排用大块保召回,精排用小块保精准,配合[[Rerank]]效果更好。
落地风险也很明显。前提是分块策略要和检索方式匹配。如果只做向量检索,语义分块比固定长度好;但如果混合了[[BM25]]关键词检索,固定长度分块反而可能因为词频统计更均匀而表现更好。常见失败场景是,分块切得太碎,导致检索时上下文丢失,生成结果出现[[Hallucination]]。上线我会特别关注分块数对[[向量库]]规模和推理延迟的影响,分块数太多,检索延迟会飙升。
另外,我现在比较关注动态分块,就是根据内容类型自适应调整。比如代码块保留完整,正文按段落切,甚至用模型判断语义边界。这个方向如果能做好,能进一步减少人工调参的工作量。
所以整体上,我更倾向从固定长度加滑动窗口快速验证,再逐步引入语义分块优化,最后根据业务场景做定制。