这道题问的是文本[[分块]],但本质其实是在问怎么在信息密度和检索精度之间做平衡。块切太大,语义是完整了,但检索时容易命中一堆无关内容;块切太小,精度上去了,但上下文碎片化,大模型反而看不懂。所以没有一个万能策略,得根据文档类型和业务场景来选。
先说三种核心策略,各有各的适用边界。固定长度分块最简单,按token数或者字符数一刀切,具体长度作为候选变量。优点是实现快、[[Embedding]]均匀、批量处理效率高。但缺点是它不管语义边界,可能一句话被拦腰切断,关键信息就丢了。所以它适合那种内容结构统一、长度一致的文档,比如日志或者固定格式的报告。递归分块就聪明一些,它先按段落切,段落太长再按句子切,句子还长才用固定长度兜底。这样尽量保住语义单元完整,但代价是块大小不均匀,短块信息密度低。语义分块更高级,用 Embedding 算句子相似度,把主题一致的句子聚成一个块。块内主题纯度高,检索精度好,但计算成本高,而且块大小不好控制,可能有的块特别大。
真正落地的时候,我很少只用一种策略。更常见的做法是混合。比如处理客服退款文档,我会先按文档固有结构分,像标题、章节、表格这些,结构化强的部分直接用结构化分块;对里面的大段说明文字,再用递归分块,保证句子完整;如果某个段落跨越多个主题,比如既有退款规则又有操作流程,那我会考虑用语义分块把它拆开。这样既利用了结构信息,又兼顾了语义连贯性。
具体参数上,有几个坑要注意。块大小要结合Embedding模型的实际输入限制、文档结构和LLM上下文预算提出候选。重叠也要比较零重叠、短窗口与较长窗口,用同一评测集验证是否补回边界证据。边界对齐很重要,一定要在句号、换行处切,别在句子中间截断。还有元数据要保留,比如来源位置、标题,这对后续[[重排序]]和答案溯源很有帮助。
最后说落地风险。一个常见失败场景是,块大小和LLM上下文窗口不匹配。比如LLM支持8K上下文,你把块切成2K,然后检索时一次塞4个块,结果超出窗口长度,模型直接截断。所以上线前一定要验证检索召回率和端到端问答效果,不能只看分块本身。
我其实更倾向把分块看成整个[[RAG]]系统的一部分,跟检索、重排一起调优。比如分块粒度细了,检索精度会高,但可能漏掉全局信息,这时候可以用 [[Parent Document]] 机制,先召回子块,再关联到父块喂给大模型。
所以我的总结是,没有最优策略,只有场景最优。我会先根据文档类型选基础策略,然后通过实验调块大小和重叠,最后结合检索效果做取舍。