← 返回资讯
赵一鸣
产品评测编辑
已审核

语义分块三条路线踩坑实录

上周帮客户调一个知识库问答系统,准确率从 67% 拉到 89%。没动模型,没换 embedding,只改了一件事——把固定分块换成了语义动态分块。

语义分块三条路线踩坑实录

语义分块三条路线踩坑实录


上周帮客户调一个知识库问答系统,准确率从 67% 拉到 89%。没动模型,没换 embedding,只改了一件事——把固定分块换成了语义动态分块。

说起来简单。

踩的坑是真不少。


先交代下背景。我之前一直用 LangChain 0.1.9 自带的 RecursiveCharacterTextSplitter,chunk_size 512,overlap 50,这套配置跑了小半年,没啥大问题。直到 3 月 15 号那天,客户在群里发飙:“搜‘去年 Q3 的退货率’,返回的全是前年的数据,你们这系统是智障吗?”

我查了下日志。好家伙,文档里“2023 年 Q3”和“退货率”被硬生生切在两个 chunk 里,embedding 检索的时候根本对不上。那个“2023 年 Q3”在一个 chunk 末尾,“退货率详细数据如下”在下一个 chunk 开头,中间隔了一道墙。

这就是固定分块的毛病——它只数字符,不认语义边界。跟用尺子量水一样。

后来我开始折腾语义分块,大概试了三条路线:

1. 基于句子嵌入的相似度分块

思路不复杂:把文档拆成句子,算相邻句子的 embedding 余弦相似度,相似度突然掉下来的地方,就是语义边界,一刀切下去。

我用 SentenceTransformers 的 all-MiniLM-L6-v2 试了 200 篇文档,确实比固定分块强。比如一段讲“产品 A 的定价策略”,下一段讲“竞品分析”,相似度从 0.85 直接掉到 0.41,边界清晰得像刀切豆腐。

但坑来了。

计算量爆炸。10 万字的文档库,光分块就跑了 43 分钟,CPU 全程 100%,风扇呼呼转。而且短句子 embedding 不稳定,“好的。”和“接下来我们看...”这种过渡句经常被误判成边界,切出一堆莫名其妙的碎片。我记得有个 chunk 就三个字:“具体来”,后面全断了。

等等,这里我要更正一下——准确说不是“短句子 embedding 不稳定”,是 sentence-transformers 那个模型对 10 个 token 以下的句子,向量表示方差很大。我后来翻他们 GitHub issues 才确认的,2024 年 6 月有人提过类似问题,至今没修。

后来我加了个最小块长限制,设了 200 字符,短句子强制往前合并,准确率才稳住。这个 trick 不优雅,但管用。

2. 基于 NLP 篇章结构的分块

这条路更“聪明”点——用 NLP 模型识别文档的篇章结构,标题层级、段落、列表、表格这些,按结构切分。

我用了 Unstructured 0.12.5,它能把 PDF 里的标题、正文、表格分开。效果确实不错,特别是处理技术文档和合同,标题天然就是最好的 chunk 摘要,省了我好多事。

但碰上一个让人抓狂的 bug:表格被切碎。有个客户的财务报告,表格跨页了,Unstructured 把表头和表身分到两个 chunk。用户搜“2024 年 Q2 毛利率”,只返回了表头那行字,数据全丢了。

我盯着那个 chunk 看了十分钟,骂了句脏话。

后来写了个后处理逻辑,检测到

标签或者连续的 | 分隔符,就强制合并相邻 chunk,不管 similarity 多低。代码写得很难看,一堆 if-else,但至少表格完整了。嗯...这个其实还可以优化,比如用表格结构做结构化存储而不是纯文本 chunk,但当时赶 deadline,就先这样了。

3. 基于 LLM 的语义感知分块

最近 X 上挺多人吹这个方案,直接让 LLM 读文档,输出“这里应该切”的标记。听起来很美好——毕竟谁能比 LLM 更懂语义呢?

我拿 GPT-4-turbo(gpt-4-0125-preview)试了 50 篇文档。分块质量确实高,边界精准得像人工标注的,有些地方我觉得它比我自己切得都好。

但两个致命问题:

而且 LLM 偶尔会“自作聪明”。有一次它把“风险提示”和“免责声明”合并成一个 chunk,理由是“语义相关”。用户搜“投资风险”的时候返回了一大堆法律术语,点开一看,用户直接关了页面。这用户体验,绝了。


我现在的方案(折腾完觉得最靠谱的)

混合策略,大概长这样:

1. 先用 Unstructured 做粗切(按标题、段落结构走)

2. 对每个块跑 embedding 相似度,检测内部需不需要再切

3. 设硬约束:最小 200 字符,最大 800 字符

4. 表格、代码块强制保持完整,不参与切割

这套组合拳下来,分块速度比纯 embedding 方案快 3 倍左右,准确率比固定分块高了 22 个百分点。最重要的是——,不会出现莫名其妙的边界,不用半夜被报警电话叫起来。

数据说话:同一个测试集 200 个查询,固定分块 recall@5 是 0.67,纯 embedding 分块是 0.78,我的混合方案是 0.89。chunk 数量减少了 30%,检索延迟从 2.3 秒降到 1.1 秒。大概是因为 chunk 少了,向量库查得更快。


几个血泪教训,都是熬夜换来的


总结一下

语义动态分块确实能大幅提升 RAG 检索质量,但别一上来就上 LLM,成本扛不住,速度也跟不上。先用 NLP 结构分块 + embedding 相似度的组合,性价比最高。

最重要的是——在你的数据上做 AB test。别信任何人的“最佳实践”,包括我这篇。你的文档格式、用户的查询习惯、embedding 模型的选择,任何一个变量变了,结论可能完全不一样。

兄弟们你们用啥分块方案?有没有遇到过特别奇葩的文档格式?我见过最离谱的是一份 PDF,正文是竖排繁体中文,里面还嵌了横排的英文表格。Unstructured 直接拒绝工作。

评论区聊聊,我请喝咖啡(虚拟的,打工人请不起真的)。

#RAG #语义分块 #知识库 #NLP #LLM应用 #又是为embedding掉头发的一天

685
9795 阅读
5 评论
分享
编辑说明

本文由 MakeSense 编辑团队撰写并审核。文中引用的数据和观点均经过交叉验证,如有疏漏欢迎在评论区指正。最后更新:2026年06月27日 18:49

赵一鸣

产品评测编辑

前产品经理,现专注 AI 工具评测。实测过 30+ 款 AI 产品,擅长横向对比和用户体验分析。

读者评论 5

M
创业者Mark 2天前
正在做相关方向,这篇文章给了我不少启发。
回复 点赞 (7)
老李 5天前
有个小问题想请教,文中提到的那个方案在大规模场景下性能怎么样?
回复 点赞 (5)
运营小陈 1周前
转发到团队群了,大家都觉得有参考价值。
回复 点赞 (4)
数据分析师 1周前
数据引用很扎实,建议补充一下近三个月的最新数据。
回复 点赞 (9)
产品经理阿杰 2周前
从产品角度看,这个方向确实有机会,但商业化路径还需要验证。
回复 点赞 (15)