好,这道题问的是 [[Chunk]] 划分策略,我觉得它本质上是在考一个取舍:你如何在检索精度和上下文完整性之间做平衡。因为 [[RAG]] 的召回质量,很大程度上取决于你切出来的块是不是既独立又完整。
先说最直接的固定长度分块,按多少 token 或者字符数硬切。这个方案好处是简单、快,[[Embedding]] 批量处理效率高,而且能精确控制上下文长度。但它有个硬伤,就是边界可能把一句话或者一个逻辑单元从中间切断。举个例子,如果一篇文档在讲「深度学习的优化方法」,其中一句刚好被拦腰截断,那检索时返回的片段可能就变成了「深度学习的优化」,意思就偏了。所以它只适合文档结构松散、对语义完整性要求不高的通用场景,比如新闻聚合或者日志检索。如果你要快速上线一个 MVP,用这个没问题,但追求高精度问答就不行。
再一个就是语义边界分割,按句子、段落或者主题来切。这个能最大程度保留语义完整,检索回来的片段读起来通顺、可理解。但代价是块大小不均匀,有的块可能特别长,超出模型窗口;有的又特别短,信息密度低。而且像按主题切分,用 BERTopic 之类的模型,计算开销不小。它适合法律合同、学术论文这种结构清晰的文档,因为这些文档天然有段落和章节,切出来不会太离谱。
还有个常见的策略是[[滑动窗口]],也叫重叠分块。它通过设定块大小和滑动步长,让相邻块有重叠。这么做的好处是彻底避免了边界信息丢失,比如一个关键概念跨了两块,重叠能保证至少有一块完整包含它。但代价也很明显,存储冗余,数据量可能翻倍,而且检索时可能返回多个高度相似的结果,需要额外去重。所以它适合对话历史、代码这类强上下文依赖的场景,比如你查一段代码,如果切断了函数定义和调用,那检索回来的就没法用。
真正落地的时候,我基本不会只用一种策略。通常是组合使用:先用语义边界粗分,保证核心块完整,然后对长度超过窗口的块,再用滑动窗口细分。举个例子,在企业 SOP 和合规文档检索里,文档结构很清晰,按章节切分后,有的章节特别长,比如「退款流程」可能包含好几页,这时候我就用滑动窗口把这一章切成几个 512 token 的块,步长设 256,这样既保证了语义边界,又控制了块大小。
这里有个坑一定要提:滑动窗口的冗余不是随便设的。步长太短,冗余太多,检索结果里全是重复信息;步长太长,重叠不够,又回到边界问题。我一般会先根据文档的平均句子长度来调,上线后监控 [[RAGAS]] 指标里的上下文精度,如果重复率太高就加大步长。另外,块大小不能超过 LLM 的上下文窗口,但也不能太小,否则信息密度低,[[Rerank]] 也救不回来。
还有一个方向我最近在关注,就是智能分块,比如用 LLM 自己判断断点,或者对 Markdown、JSON 按语法树切分。这个在代码或表格场景里效果很好,但代价是延迟和成本。如果面试官感兴趣,我可以展开讲讲结构化分块怎么跟元数据标注结合,来提升检索精度。
所以总结一下,我不会把 chunk 策略看成孤立的选择,我更倾向把它当成一个系统工程,结合文档结构、业务场景和上线指标来动态调整。没有银弹,关键是理解每种策略的代价,然后做取舍。