RAG 选型手册 · 实战篇

AI惊叹号 - Embedding 模型怎么选:榜单第一,往往不是你的第一

embeddinggemma-2 登顶 HF,MTEB 分数一路上涨,但换完模型召回率反而掉了。问题不在模型,在匹配度。从向量维度、量化损失、领域适配、自托管四个维度,给你一张能直接打分的选型表。

2026 年 10 月 20 日全文约 7,400 字读完约 17 分钟

Hugging Face 排第一,到你那为什么就不灵了

打开 Hugging Face 模型榜,Trending 第一名是 embeddinggemma-2。0.7B 参数、29.2k 下载、1.37k 点赞,标题里写着 state-of-the-art。你想,既然大家都在用,那我也换吧。

换完你发现了一件事:RAG 的召回率反而掉了 3 个百分点。客服知识库的检索,用户问「退款流程」,出来的是「退换货政策说明」——不是错的,但不是最准的。更奇怪的是,MTEB 榜单上 embeddinggemma-2 明明比你之前用的 bge-m3 高 2 分,怎么到了私有数据上就反过来了?

embeddinggemma-2 · 0.7B 29.2k 下载 1.37k 点赞

答案很简单:MTEB 测的是通用基准,你的数据有自己的分布。

MTEB(Massive Text Embedding Benchmark)有 58 个数据集、112 个任务,覆盖分类、聚类、检索、重排、STS 语义相似度。听起来很全面,但它的英语任务占了超过七成,中文任务只有少数几个,而且大多是公开的新闻、百科、小说文本。

你手里的数据呢?可能是几万条客服工单,里面全是「亲」「这边建议」「已催促」这种电商黑话;可能是几千份法律合同,满是「兹因」「 aforementioned」「违约责任」这种领域术语;也可能是代码仓库,变量名和函数调用占了一半字符。

这些数据,MTEB 里一条都没有。

核心认知

Embedding 模型的「好」是有条件的。它在 MTEB 上的分数,只代表它在 MTEB 那批数据上的表现。换一个数据分布,排名可能整个翻过来。选型的第一步,是放弃「看榜单选模型」的习惯。

那怎么判断一个模型适不适合你?有一个很朴素但有效的方法:拿你自己的 50—100 条真实 query,标注好标准答案,然后在同一个向量库里把候选模型都跑一遍,比召回率和 MRR。

这件事听起来麻烦,其实一个下午就能做完。而且它值回票价——因为 embedding 模型是 RAG 系统里最底层的组件,换一次的成本远高于换一个 reranker 或者换一个 prompt。你选对了,后面所有优化才有基础;选错了,上面叠再多层都补不回来。

向量维度越高越好吗:768、1536、3072 差多少召回

聊 embedding 必聊维度。OpenAI text-embedding-3-large 是 3072 维,Cohere Embed 5 是 1024 维,bge-m3 是 1024 维,embeddinggemma-2 有 768 和 1536 两个版本。

直觉上,维度越高,信息越丰富,召回应该越好。这个直觉对吗?

大致是对的,但收益递减得非常快。

768d
小模型主流
存储成本最低
1536d
性价比甜点
多数场景够用
3072d
旗舰级
边际收益递减

MTEB 上的规律大概是这样:从 256 维到 768 维,召回率能涨 5—8 个百分点,非常明显。从 768 到 1536,再涨 2—3 个点。从 1536 到 3072,可能再涨 1—2 个点,有时候甚至不涨。

但成本呢?维度翻倍,存储也翻倍。100 万条 768 维的 float32 向量,大约占 3 GB;1536 维就是 6 GB;3072 维就是 12 GB。这还只是裸向量,加上索引结构、元数据、冗余备份,实际占用还要多。

检索延迟也跟着涨。HNSW 索引的搜索复杂度和维度大致成正比,维度翻倍,单次查询的距离计算量也翻倍。在千万级向量库上,这个差距会从毫秒级变成几十毫秒级,用户是能感觉到的。

低维 · 768d
3 GB / 百万条
  • embeddinggemma-2 小版、bge-base
  • 适合千万级以内、对延迟敏感
  • 召回略低,但通常够用
  • 量化空间大,int8 后几乎无损
高维 · 3072d
12 GB / 百万条
  • OpenAI ada-002 后继、Cohere 旗舰
  • 适合百万级小库、追求极致召回
  • 存储和延迟都是 4 倍
  • 量化后损失相对更大

还有一件事很少有人提:维度越高,越容易过拟合基准数据集。

高维向量在 MTEB 这种多样化基准上确实占优,因为它能编码更多细微的语义差异。但换到你的私有数据上,如果你的 query 和文档的分布比较单一(比如全是客服问答),高维反而可能引入噪声——那些在通用语料上学到的细粒度差异,在你的场景里根本用不上,反而干扰了相似度计算。

所以维度选型的策略很明确:

先从 1024 或 1536 开始试。 这是当前性价比最高的区间,大多数场景够用。如果召回已经达标,就别往上加了——省下的存储和延迟都是真金白银。如果差一点点,先试试换个更好的模型,而不是升维度。

如果必须用高维,一定要配合量化。 int8 量化在大多数 embedding 模型上损失不到 1%,但存储直接砍半。Qdrant 做过一个测试,用 TurboQuant 把向量压缩 21 倍,召回率只掉了一点点——这不是魔法,是因为 embedding 向量里有大量冗余。

常见误区

「维度越高效果越好」只在一定范围内成立。超过 1536 维之后,每多一倍维度带来的召回提升,通常还不如换一个更好的模型、或者加一层 rerank 来得多。别在维度上死磕。

向量压到 21 倍还能召回吗:late-interaction 怎么回事

说到量化,就不得不提今年最火的一个方向:late-interaction,也叫 ColBERT 风格检索。

传统 embedding 是把一整段文本压缩成一个向量。一句话、一篇文章、一本书,都塞进同一个 1024 维的向量里。信息密度越高,损失越大——长文档的很多细节,在向量化的过程中被「平均」掉了。

late-interaction 的思路不一样:它不给整段文本生成一个向量,而是给每个 token 生成一个向量。查询的时候,query 的每个 token 向量去和文档的所有 token 向量做匹配,取最大相似度,然后加总。

听起来计算量很大对吧?是的。但它有一个巨大的好处:向量可以被极度压缩,因为不需要保留全局语义,只需要保留 token 级别的匹配信号。

压缩倍率 vs 召回保留率(示意)
float32 原始
100%
int8 量化
~97%
4bit 量化
~92%
late-interaction 21x
~90%

Qdrant 最近和 Perplexity 合作做了一个测试,用 late-interaction 模型配合 21 倍向量压缩,在检索质量上几乎和原始向量打平。这个结果之所以让人震惊,是因为传统单向量 embedding 如果压到 21 倍,召回率会掉得妈都不认。

为什么 late-interaction 这么能扛压缩?因为它的匹配逻辑是「找最像的 token 再相加」,而不是「两个整体向量比相似度」。每个 token 的向量就算被压得模糊一点,只要相对位置还在,最大相似度那一步就能把正确的 token 挑出来。就像你认一个人,哪怕照片糊了,只要眼睛鼻子嘴的相对位置没变,你还是能认出来。

这件事的影响很大。它意味着:

第一,向量数据库的存储成本可以再降一个数量级。 以前 1 亿条向量要几十 GB 内存,现在可能几 GB 就够了。Qdrant 有个案例,把德国 4,800 个地方议会的门户网站索引成 1.3 亿个点,用 hybrid search + TurboQuant,平均检索时间从 20 秒降到了 0.87 秒。20 秒到 0.87 秒,差了 23 倍。

第二,「先检索后重排」的两阶段流程可能被改写。 现在的标准做法是先用 embedding 召回 top-100,再用 reranker 精排到 top-10。如果 late-interaction 的检索质量已经接近 reranker,那中间这一步就省了。当然,目前还没到那个程度,但趋势是明的。

第三,embedding 模型的选型逻辑要加一条新的维度:支不支持 late-interaction。 如果你在建一个大规模知识库(千万级以上),late-interaction 的存储优势会非常明显。代价是查询更慢、索引更复杂,而且目前支持的向量数据库还不多——Qdrant 支持得比较早,Milvus、Weaviate 也在跟进。

「我们把 1.3 亿个点塞进一台机器,查询还不到 1 秒。放在两年前,这得要一个集群。」—— Qdrant 工程师在案例分享里说的原话

不过,late-interaction 不是银弹。它有两个很实际的限制:

一是索引构建慢。每个 token 一个向量,1 亿条文档如果平均每条 200 个 token,那就是 200 亿个向量。虽然每个向量维度不高,但总量摆在那里。

二是查询延迟。单向量检索是一次向量比较,late-interaction 是 N 次 token 级比较,计算量差一个数量级。对 QPS 要求很高的场景(比如搜索框实时联想),可能还是传统单向量 + rerank 更合适。

选型建议:如果你的库在百万级以内,老老实实单向量就行,别折腾。 如果是千万级甚至亿级,或者存储成本是你最大的痛点,再认真考虑 late-interaction。

中文法律、医疗术语,开源 embedding 真的懂吗

聊完了维度和压缩,回到一个更本质的问题:你的数据是什么语、什么领域的?

这个问题决定了大部分「国际大牌」embedding 模型在你手里的实际表现。

先说中文。MTEB 中文任务的分数,和英文任务的分数,经常差 5—10 个百分点。不是模型不行,是训练数据里中文占比本来就低。embeddinggemma-2 主要训练语料是英语,虽然也有一部分多语言,但中文的比例和质量,跟专门训练的 bge-m3、gte、bce 这些国产模型比,差得远。

有一个很经典的测试:拿「苹果」这个词,分别和「水果」「手机」做相似度计算。英语模型大概率会把「苹果」和「水果」排得更近,因为它的训练数据里苹果作为水果出现的频率远高于作为公司。但中文场景下,如果用户搜的是数码产品,这个结果就是错的。

通用多语言模型
embeddinggemma-2
  • 英语表现强,中文中等
  • 泛化能力好,什么都能做一点
  • 对专业术语理解浅
  • 适合:跨语言、通用搜索
中文专用模型
bge-m3 / gte / bce
  • 中文 MTEB 分数普遍高 5-8 分
  • 对中文歧义、成语、网络用语理解深
  • 支持多粒度(词、短语、句子)
  • 适合:中文知识库、客服、文档

然后是领域。法律、医疗、金融、代码——每个垂直领域都有自己的术语体系,这些术语在通用语料里出现的频率很低,模型学不到足够好的表示。

举个例子。法律文本里「善意第三人」不是说一个善良的人,而是一个特定的法律概念。通用 embedding 模型可能把它和「好人好事」排得很近,因为它只理解字面意思。但在法律检索场景里,它应该和「无权处分」「物权变动」这些概念更接近。

医疗领域更夸张。ICD 编码、药名、手术术式,每一样都是黑话。通用模型在这上面的表现,往往还不如一个简单的关键词匹配。

那怎么办?有三条路,成本从低到高:

第一条:换切分策略。 很多时候不是模型不行,是你把文本切得不对。法律条文适合按条款切,医疗病历适合按章节切,代码适合按函数切。切对了,召回率能涨好几个点,一分钱不花。

第二条:用领域预训练好的模型。 现在已经有不少垂直领域的 embedding 模型了——法律的、医疗的、金融的、代码的。它们在各自领域的表现通常比通用模型好一截,而且开箱即用,不需要你自己训练。

第三条:自己微调。 如果你的数据足够独特(比如某家公司内部的技术文档),而且标注了一批 query-文档对,那微调一个 embedding 模型是回报率最高的做法。用对比学习(contrastive learning),几千对标注数据就能看到明显提升。

实操建议

顺序别搞反:先优化切分,再换领域模型,最后才考虑微调。大多数情况下,前两步就能把召回从 70 分拉到 85 分。微调是最后那 10 分的事,成本最高,也最吃数据质量。

还有一个容易被忽略的点:query 和 document 的分布差异。

用户的 query 通常很短——「怎么退款」「XX 怎么用」「报错 500」——可能就几个词。而你的文档可能是几百字、几千字的长文。一短一长,向量空间里的分布本来就不一样。通用 embedding 模型训练的时候,正样本通常是成对的相似文本,长度差不多。到了真实的检索场景,短 query 配长文档,效果会打折扣。

解决这个问题,一个简单有效的办法是:给文档生成一个「摘要式标题」,用标题来做检索,而不是用全文。标题短,和 query 的长度更接近,向量空间更对齐。很多人试了之后发现,就这一招,召回率能涨 3—5 个点。

为什么能不能自托管,正在变成选型第一条件

前两年聊 embedding 选型,大家最关心的是 MTEB 分数、向量维度、支持多少种语言。

今年变了。越来越多团队把「能不能自托管」放在了第一位。

原因有三个:成本、合规、可控性。

先算成本账。OpenAI text-embedding-3-large 定价是 0.13 美元/百万 token。看起来不贵——100 万字的文本,向量化一次才 1 美元出头。但如果你的知识库有 1000 万篇文档,每篇平均 500 字,那就是 50 亿字,向量化一次要 650 美元。而且每次更新都要重新算。

自托管呢?一张 H100 或者国产的昇腾卡,每秒能处理几千到几万条文本。1000 万篇文档,几个小时就跑完了,边际成本几乎为零。量大到一定程度,自托管怎么都划算。

0.13$
API 调用
每百万 token
~0$
自托管
边际成本
vLLM
部署框架
开箱即用

然后是合规。这个不用多说——金融、医疗、政务、法律,哪个行业的数据能随便往外发?就算是普通企业,内部文档、客户信息、代码仓库,也没有人愿意传到第三方 API 里去做向量化。数据不出域,是很多行业的硬要求。

Cohere 最近发布的 Embed 5,专门强调了支持用 vLLM 私有化部署。这不是巧合。企业客户在问,而且问得越来越多——你们的模型能不能跑在我自己的机器上?

第三是可控性。API 模式下,模型什么时候更新、会不会偷偷改行为、会不会涨价,你都控制不了。OpenAI 曾经把 embedding 模型从 ada-002 升级到 text-embedding-3,效果确实好了,但向量维度变了,所有老用户的向量库都得重建。这要是在生产环境里,就是一次计划外的大工程。

自托管就没这个问题。你用哪个版本、什么时候升级,全自己说了算。模型文件就在你本地磁盘上,哪天服务商涨价了、倒闭了、被收购了,跟你没关系。

那自托管难不难?两年前可能还挺折腾的,现在已经简单很多了。

vLLM 一条命令就能起一个 OpenAI 兼容的 embedding 服务,性能还比原生实现快好几倍。Ollama 更简单,桌面点点鼠标就能跑几个模型玩玩。LM Studio 也在做类似的事。对个人开发者和小团队来说,自托管的门槛已经低到了「会用命令行就行」的程度。

自托管 vs API 对比
初始成本
API 胜
大规模成本
自托管胜
数据合规
自托管胜
运维复杂度
API 胜
模型选择自由度
自托管胜

当然,自托管也不是没有代价。你得管服务器、管 GPU、管模型更新、管监控。如果你的团队很小、数据量也不大(比如几万篇文档),用 API 可能更省心。

但趋势是明确的:embedding 正在从「API 服务」变回「基础组件」。 就像当年的数据库、缓存、消息队列一样——一开始大家都用云服务,规模上去了、合规要求严了,最后还是得自己管。

选型的时候,把「是否支持自托管」从加分项变成及格线,大概率不会错。

一张打分表:embedding 模型怎么选

讲了这么多,最后收束成一张可以直接用的选型表。

四个维度,每个维度 0—25 分,总分 100 分。你拿着候选模型一个一个打分,分数最高的那个,大概率就是最适合你的。

四维选型评分表(每项 25 分,总分 100)
召回质量
25
存储/延迟
18
领域适配
15
自托管能力
20

怎么打分

第一维:召回质量(25 分)。 拿你自己的 50—100 条真实 query,标注好 top-5 标准答案,跑一下候选模型。top-1 命中率每 10 个百分点给 5 分,top-5 命中率每 10 个百分点给 2.5 分。注意:一定用你自己的数据测,别光看 MTEB 分数。

第二维:存储与延迟(25 分)。 维度越低分越高——768 维 25 分、1024 维 20 分、1536 维 15 分、3072 维 8 分。再加上延迟测试:在你的目标量级下,P95 查询时间低于 50ms 加 5 分,50—200ms 加 3 分,超过 500ms 扣 5 分。

第三维:领域适配(25 分)。 通用模型 10 分起,中文专用模型 15 分起,有领域预训练版本 20 分起。如果你的数据里行业术语很多,而模型在该领域有公开的 benchmark 成绩不错,再加 3—5 分。

第四维:自托管能力(25 分)。 完全开源、vLLM 直接支持 25 分。开源但需要自己改部署脚本 20 分。只有 API 不能自托管 10 分。有私有化部署方案但不开源 15 分。

三问快速决策法

如果你不想打分,就问自己三个问题,答案基本上就出来了:

1
数据能不能出域?
不能 → 直接排除所有纯 API 模型,只看能自托管的。能 → 继续往下看。
2
数据是什么语言和领域的?
纯中文 → 优先 bge-m3、gte、bce 等国产模型。英文为主 → 可以考虑 embeddinggemma-2、Cohere。垂直领域 → 找领域专用模型。
3
量级有多大?
百万级以内 → 1024/1536 维足够,选召回最好的。千万级以上 → 关注存储和量化,考虑 late-interaction。
最后一个提醒

别追榜。Hugging Face Trending 第一名、MTEB 最新 SOTA,这些都是给研究者看的,不是给工程师看的。工程师要做的是拿自己的数据测,选一个够用的、稳定的、好维护的,然后把精力放在更重要的事情上——比如数据质量、prompt 工程、reranker 调优。

总结:选型的核心不是追榜,是匹配

embedding 模型选型,说穿了就是四件事:召回够不够用、存不存得起、懂不懂你的领域、能不能跑在你自己的机器上。

这四件事里,没有一件是看榜单能看出来的。榜单第一的模型,到了你手里可能还不如一个三年前的老模型。不是模型不行,是不匹配。

最好的选型方法,永远是拿自己的数据测一次。一个下午,50 条 query,一张表,结论就有了。比看十篇评测文章都管用。

如果实在不想测,记住这个保守策略:中文场景先用 bge-m3,英文场景先用 embeddinggemma-2 或 gte-large,有合规需求就自托管,量级大了再看 late-interaction。

够用,就好。