选 embedding 模型的时候,我干了一件挺典型的事:去翻榜单。
几个中文检索榜拉下来,前三名分数差不到两个点,看着都行,于是挑了个下载量最大的准备用。同事问了一句"咱自己的问题测过吗",我说没有,榜单差不多就行了。
后来真测了,才发现榜单和我们的场景中间隔着挺远一段路。
三十条问法
我从客服日志里摘了三十条真实提问,又给每条配了一句标准问法,凑成一组"同一个意思、两种说法"的对照。然后拿三个候选模型分别算向量,看标准问法在候选库里排第几。
不比整体分数,只看几个具体翻车的地方:
第一类是近义但不同义。「解析失败」和「下载失败」,字面上就差两个字,向量挨得极近,三个模型里有两个把它们当成一回事。可在我们站上这是两条完全不同的排查路径:前者是拿不到地址,后者是地址拿到了但传输出问题。模型 A 把这两句排进了彼此的 top 2,模型 C 勉强拉开了距离。
第二类是否定句。「会员能用的平台有哪些」和「不用会员能下吗」,意思有重叠但答案不一样。三个模型在这组上都一般,其中有一个给这两句打了 0.89 的相似度,我盯着这个数看了半天。
第三类是专有名词和年份。「2021 版标准」和「2024 版标准」,纯数字差异,语义上几乎一样,向量距离近得离谱。这个不能全怪模型——它的任务本来就是判断"意思像不像",而这两句意思确实像。但它意味着光靠向量检索,年份这种关键信息永远筛不准,得靠关键词那一路补。
| 模型 | 近义区分 | 否定句 | 短文本 | 维度 | 单条耗时 |
|---|---|---|---|---|---|
| A(多语言大尺寸) | 差 | 一般 | 好 | 1024 | 慢 |
| B(中文中等) | 一般 | 一般 | 好 | 768 | 中 |
| C(中文小尺寸) | 较好 | 较好 | 一般 | 512 | 快 |
表里这些"好/一般"全是我在那三十条上肉眼judge出来的,不是什么严谨评测。样本小得可笑,换个领域结论可能就反了。但对我们够用——至少知道不能照着榜单第一名直接选。
最后选了 C,不是因为它最好,是因为它最快、维度最低,而且在我们最在意的那两组上没掉链子。
维度不是越大越好
一开始我下意识觉得 1024 维比 512 维"表达能力强",后来算了下账才改主意。
站里那份文档库切完大约两万块。512 维 float32 一块要 2 KB,两万块是 40 MB;1024 维翻一倍,80 MB。内存里放着都不算什么,但每次检索要跟两万条逐一算相似度,维度翻倍就是计算量翻倍,再叠上并发,延迟是能看出来的。
而且我们后面还打算把索引持久化,向量文件进备份、进部署包,这块体积会一直跟着。
真正让我换思路的是另一件事:那三十条测试里,1024 维的模型并没有比 512 维的强。表达能力的上限高,不等于在我们这种短句、领域窄的场景里用得上。多出来的维度更像是留给了别的语言和别的任务。
换模型最疼的地方
这条是踩了才知道:embedding 模型不是一个能随时换的插件。
向量库里存的全是旧模型算出来的坐标。新模型有自己的一套坐标系,同样的句子会落到一个完全不同的位置上。新旧向量混在同一个库里做相似度比较,结果没有任何意义——不是"稍微不准",是乱的。
所以要换,就得把两万块原文全部重新过一遍新模型,重建整个索引。我们那次重建跑了一个多小时,期间检索服务只能停掉用旧的顶着。后来学乖了,把原文和切块结果单独存了一份,重建时不用再解析一遍 PDF,省了大半时间。
还有个容易漏的:查询侧也得用同一个模型。有同事调接口的时候顺手用了默认配置,查询向量是新模型算的、库里是旧的,返回的相似度全在 0.9 以上,看着特别"准",其实全是错的。这个现象比直接报错吓人,因为它看起来像变好了。
我现在会在索引元数据里记一条 embedding_model 和 dim,查询前对一下,不一致就直接拒掉,宁可报错也别返回一堆漂亮的错误答案。
那三个模型我后来想起还有一件事没测:长文本。三十条全是短问句,最长的不到二十字,而实际库里存的是切好的几百字文本块。短句上表现好的模型,换成一整段带表格的文字未必还是那个排序。这个漏洞我知道,一直没补,因为要重新标一批长查询,得拉客服一起过。
还有个挺现实的问题:选型是我一个人拍的。当时拿那张表给同事看,对方问的第一句是"这些好和一般谁判的",我只能说是我在三十条上肉眼看出来的。换个人标,结论可能就不一样。后来我们把判定依据也写进表格,每条为什么算好、为什么算差,留一句话,至少下次争论时有据可查。
模型版本也是个坑。同一个名字的模型隔几个月会更新权重,我们库里的向量还是旧的,新版本算出来的坐标对不上。这跟换模型是同一类问题,只是更容易被忽略——名字没变,谁也不会想到要重建一遍。
发在 VidDown 技术博客,站上的中文内容也算被这些模型折腾过。
那三十条对照我还留在一个表格里,文件名叫 embedding_bad_cases.xlsx,最后一次修改是上个月。本来想扩到一百条,一直没排上。