RAG 知识库效果不好,八成人的第一反应是换 embedding 模型。但更多时候,问题出在更上游:分块(chunking)策略。这个问题社区吵了很久——按文档结构切还是按语义切,我的实践结论:这不是二选一,是分流问题。
按结构切:适合「有骨架」的文档
技术手册、API 文档、产品白皮书——这类文档天然有标题层级,结构就是最好的分块依据。按 H2/H3 切块,每块自带「它是谁的一部分」的上下文。检索命中时,块标题本身就是最好的元数据(用户问「部署配置」,命中的块标题就是「部署配置」,答案可信度天然高)。
按语义切:适合「一锅粥」的文档
会议记录、客服对话、邮件往来——没有结构,硬按字数切会把一个完整话题切成两半。语义切块(按主题变化检测切分点)能保住话题完整性,代价是计算成本高、切分点不稳定(同一文档两次切分结果可能不同,调试噩梦)。
实践中的分流规则
我们最终落地的规则很简单:
- 有标题层级 → 结构切,块间保留父标题前缀
- 无结构纯文本 → 语义切,设置最小/最大块长兜底
- 问答对、FAQ → 按条目切,绝不拆散一对
- 表格 → 整表一块(超过长度做行列摘要而非切分)
一个容易被忽略的细节:块 overlap
相邻块保留 10~20% 的重叠(overlap)是通行做法,但很多实现把 overlap 做成了「固定字数回退」——这对结构切分是错的。结构切分的 overlap 应该是层级式的:子块共享父标题,这本身就是一种语义重叠,比机械回退有效得多。
结语
分块策略没有银弹,但有正确的思考顺序:先看文档有没有结构,再决定切法;检索效果差时,先检查分块是不是把完整语义切碎了,再考虑换模型。上游一分钱不花就能修好的问题,别急着在下游烧钱。