Embedding 模型选型:从 ada-002 到 Qwen3-Embedding
2026 年 4 月,三地市场的分层架构刚定完(那是第 11 篇的事),我回头补一个一直将就的环节:embedding 模型。库最早是用 ada-002 建的——2023 年那阵子它就是约定俗成的默认选项,能跑就没动过。我打开 MTEB 榜单和几篇选型帖,两小时后人更糊涂了:每篇帖子推荐的“最佳模型“都不一样。
后来想明白了,问题不在帖子,在我——别人测的不是我的数据。这篇就讲一件事:我怎么把候选圈从“全网都在讨论的模型“,收敛到“我这台机器、这个库能用的模型“。
一、先划候选圈:三个硬指标
选型帖最大的误导,是让你以为目标是选出“最好“的模型。我的顺序相反:先用硬约束把候选圈砍小,剩下的再谈好坏。筛子有三个,按使用顺序排。
第一个是语言矩阵。你的文档和 query 是什么语言组合——纯中文、中英混合、还是多语言?不在这个矩阵里的模型直接排除,不用看分数。它排第一是因为最省事:一个主打英文的模型,榜单名次再高,对中文财报也没有意义。
第二个是最大序列长度。先数一遍自己 chunk 的实际长度分布,再对照模型上限。多数模型的上限是 512 token;chunk 普遍更长(财报段落很容易超),就得挑支持长序列的,bge-m3、jina-embeddings-v3 这类能到 8192 token。这个指标不决定好坏,只决定能不能用——chunk 被截断,编出来的向量天生缺一块。
第三个才是检索精度。放最后不是不重要,而是它最贵:前两个翻文档就能查,精度只能实测。这里我给自己立了条规矩:MTEB 是通用 benchmark,跟领域表现可能不一致,所以只配做初筛,不配做判决。这条规矩的用处在第三节。
二、当前候选盘点:按场景分组,不按榜单排队
先交代口径:这份盘点写于 2026 年 5 月,里面的型号和版本我当时逐一核对过。embedding 这行的名单半年就换一轮,你读到的时候请按当月情况复核。
组织方式我没按榜单名次往下抄,而是按自己的场景——中文财报为主、中英混合、本地优先——分组:
| 模型 | 维度 | 最大长度 | 在我场景里的定位 | 代价 |
|---|---|---|---|---|
| multilingual-e5-large-instruct | 1024 | 512 token | 中英混合文档的默认项;instruct 版支持任务指令 | 512 上限,长 chunk 受限 |
| Qwen3-Embedding | — | 32K | 中文为主、chunk 偏长时的重点评估对象 | 参数量大,本地跑要挑尺寸(见第四节) |
| bge-m3 | 1024 | 8192 token | 一个模型同时出 dense + sparse 权重 | sparse 通道用不上,就不必为它付部署成本 |
| Cohere Embed v4 / text-embedding-3-large | — | — | 不想管基础设施时的省事项 | 调用费 + 数据过第三方 |
| all-MiniLM-L6-v2 | 384 | — | 原型期先验证管道 | 精度有限,验证完要换强模型 |
multilingual-e5-large-instruct 是 2024 年初发的 instruct 版本,支持给检索和聚类下不同的任务指令,query 改写场景比基础版好;512 token 的上限对长 chunk 偏紧。Qwen3-Embedding 是 2025 年 6 月发布的,0.6B / 4B / 8B 三个尺寸,8B 以 70.58 分登上 MTEB 多语言榜第一,中文表现是它的主打——我的文档以中文为主、chunk 偏长(它支持 32K 序列),所以它是我的重点评估对象。bge-m3 的卖点是一个模型同时出 dense 向量和 sparse 权重,不想分别维护 embedding 模型和 BM25 索引时,这是个省事选项。
商业 API 那行单独说代价:每百万输入 token,text-embedding-3-large 约 $0.13、3-small 约 $0.02、Cohere Embed v4 约 $0.12、gemini-embedding-001 约 $0.15(2026 年中的公开定价,这类价格变得快,用前再查一次)。精度接近开源 top 模型,但文档内容要经过第三方 API——财报这种数据,这一条的权重自己掂量。
最后补一句笔记里的判断:老的 bge-large-zh 不建议作为新项目首选;要用 BGE 的中文模型,至少是 bge-large-zh-v1.5。
三、分水岭:在自有财报数据上评估
回应一下开场。榜单越看越糊涂,解法不是再看一份榜单,而是花两小时跑一轮自己的评估。我的流程四步:
- 从自己的文档库里挑 30–50 个典型 query,人工标注每个 query 的“正确 chunk“。30–50 是我工作流里够用的量,不是标准。GPT 可以辅助标注,但必须人工复核——标注错了,后面所有结论都是反的。
- 每个候选模型把全部 chunk 编码一遍,对每个 query 检索 top-10。
- 算两个指标:Recall@5 和 MRR。白话说,Recall@5 看“正确答案有没有进前 5“,MRR 看“正确答案平均排第几“。
- 重点比较各模型在“困难 query“上的差异。
第四步是整轮评估的关键,单独说透。简单 query——“腾讯 2025 年营收多少“这种——几乎所有模型都能召回正确 chunk,分数漂亮,但拉不开差距。真正拉开差距的是这几类:“为什么腾讯游戏毛利下降了”(问原因,不是问数字)、“跟去年同期比较”(带相对时间关系)、“Non-GAAP 口径下”(带专业口径约束)。模型之间的真实差距、值得你为之付费的差距,都藏在这种 query 里。评估集如果全是简单 query,等于白测:大家都是 90 分,闭着眼选都对。
说句诚实的话:这套流程我有,但到写这篇为止,还没攒下一整轮能拿出来的自有财报库实测数字——素材里没有 Recall@5/MRR 的结果,我不编。方法在前,数字后补【待补:自有财报库上的实测 Recall@5/MRR 数字;发布前若能补一轮小规模实测,本节可升级为方法 + 结果】。
四、本地约束再砍一刀:M1 Pro 32GB 的现实
评估解决“哪个好“,部署约束解决“哪个能用“。我把它们并列成分水岭的两半,是因为在我这儿,部署约束不是选定之后的优化项——它直接决定候选集。
我的机器是 M1 Pro、32GB 统一内存。注意“统一内存“四个字:这 32GB 不是全给模型的,macOS 本身、浏览器、IDE、向量库、脚本进程都在里面分。所以判断标准从来不是“能不能加载“,而是“能不能舒服地长期用“。按这个标准,Qwen3-Embedding 系列在我机器上分三档:
- 4B 是本地主力。 走 MLX + 4-bit 量化,模型直接用
mlx-community/Qwen3-Embedding-4B-4bit-DWQ。MLX 对 Apple Silicon 更原生,比 transformers + MPS 那条路省心,资源占用也可控,日常常驻没问题。 - 0.6B 是轻量稳妥的起步项。 先把管线跑通、验证流程时用它。
- 8B 只配当实验对照。 量化后也能跑,但长文本前向慢、批量建库重、跟其他程序抢内存。想看理论上限就小规模跑一轮,不常驻。
强调一遍:这是“我这台机器“的分档,不是普遍排名。换台 64GB 的机器结论就会变;不在 Apple Silicon 上的读者,MLX 这条路本身就不成立。
落地还有三个最容易错的细节。
一是 query 和 document 分开处理。Qwen3-Embedding 是 instruction-aware 的:query 侧加任务指令,document 侧直接编码原文。我用的财报指令长这样:
Instruct: Given a financial-report question, retrieve relevant passages from Chinese annual or quarterly reports.
Query: 宁德时代2024年经营活动现金流怎么样?
二是取向量的方式。Qwen3-Embedding 的官方做法是 last-token pooling——取序列最后一个 token 的 hidden state 当向量——再做 L2 normalize,检索时算 cosine similarity(归一化后等价于点积)。decoder-only 架构的 embedding 模型不都是这一种取法,mean pooling 也常见,换模型时以官方模型卡为准,别把 A 模型的取法套到 B 模型上。pooling 搞错不会报错,只会让向量悄悄变差,这类坑最难排查。
三是别被 32K 上限诱惑。那是理论上限,不是本地稳定高效工作的默认输入长度。文本越长,前向越慢、峰值内存越高。我的口径:单段输入先控制在 2K–4K tokens,切块每块 600–1000 中文字、overlap 100–150,Dense 检索 top_k 取 10–20。这是我工作流里定的参数,不是通用推荐。
最后提醒一句:embedding 不是检索链路上唯一的变量。财报这种数字、指标名、年份密集的场景,BM25 + Dense + reranker 的组合,通常比把 4B 换成 8B 更划算。两路怎么分工是第 9 篇的事,reranker 怎么排是第 10 篇的事,本篇不展开。
五、选定之后:换模型的成本账
选定不代表结束。换 embedding 模型意味着所有 chunk 重新编码、向量索引整个重建——一次性操作,但成本不低,库越大越疼。所以选型时我就多问两句:这个模型一年后还有人维护吗?下次再换,重建成本我接不接受?
第二个问题有架构上的预留手段:把向量库和“chunk 原始文本 + metadata“分开存储。重编码时拿原始文本重新过一遍模型就行,不用重走整个 ingestion 管线。这跟第 5 篇讲的 metadata 设计是配套的——原始文本和 metadata 本来就是该留下的资产,顺手多了一层保险。
六、收尾
本篇所有推荐都带一个前提:我的场景是中文财报、M1 Pro 32GB、本地优先。换场景,请重跑第三节那套评估流程,别抄我的结论。
结论会过期,方法不会。第二节的名单半年后就是旧闻,第三节那套两小时的评估流程可以一直用——这才是本篇真正想留下的东西。
模型选定,系统还可能烂在一堆没人动过的默认参数上。第四节里的 chunk 600–1000 字、overlap 100–150、top_k 10–20,是我在自己场景里定的值,不是默认值。下一篇——第 13 篇《RAG 的七个“默认参数陷阱“》——就讲 chunk_size、top_k 这些默认值为什么都只是别人 demo 的终点。