ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

RAG嵌入模型选型指南:从向量化原理到实战评测

RAG嵌入模型选型指南:从向量化原理到实战评测 1. 嵌入模型在RAG里的真实分量——选错比不选更麻烦先说一个让我印象很深的案例。之前有个做企业知识库的项目第一批上线用的是某个通用大模型自带的 embedding 接口向量化之后丢进向量数据库整体跑通了。但等评测数据出来问题问得稍微绕一点召回的第一屏内容就跟问题对不上逼得做 RAG 的同事天天在 prompt 里加各种限制词效果还是时好时坏。后来我们把嵌入模型换成了针对中文优化过的开源模型其他环节一点没动同样的测试集召回准确率直接提了差不多 20%。这个项目经历让我彻底意识到RAG 这条链路里真正决定天花板的往往是嵌入模型。很多人一上来就盯着大模型怎么选、向量数据库用哪个、chunk 怎么切反而把最基础的这个环节放在最后才考虑。实际上检索质量的上限在你把文本转成向量的那一刻就已经被定死了后面所有 rerank、prompt 优化都是在有限的空间里找补。这篇文章我就把主流嵌入模型放在一起按我的实测经验和踩坑记录做一个尽量贴近实战的比对。先说清楚这篇文章的场景边界。我聊的嵌入模型特指用于 RAG 检索阶段的文本向量化模型也就是把 query 和知识库文档切片映射到同一个向量空间、再用相似度计算做召回的那类模型。至于多路召回里常见的 BM25 稀疏检索、graph rag 里的图结构编码以及 agentic rag 里动态规划检索路径的问题这次不展开后面系列文章单聊。嵌入模型在一条典型的 RAG 链路里的位置其实比很多人以为的要靠前得多。一条完整流程通常是文档解析、清洗、chunk 切分然后进嵌入模型做向量化写入向量数据库查询时再把 query 向量化做相似度检索拿到候选切片后往往接一个 rerank 模型精排最后喂给大模型生成答案。这张链路图里的每一步都会影响最终效果但最容易被低估的就是文本向量化这步——因为它看起来太简单了一行代码就能调很多人也就懒得深究。但简单只是表面。嵌入模型本身承担了语义压缩的职责它必须把一段话的核心含义压缩成几百上千个浮点数而且要在压缩过程中保留足够多的语义细节让相似的问题能落到相近的区域。模型在这件事上做得好不好直接决定了你后面的检索是大海捞针还是按图索骥。这也是为什么选错比不选更麻烦——选错模型会让整套系统所有下游组件都以为自己在正确工作但每次检索都在一个失真的语义空间里打转。关于嵌入模型还有一个经常被忽略的底层事实现在的嵌入模型大多基于 Transformer 架构但训练目标和生成式大模型正好相反。生成模型学的是下一个 token 是什么嵌入模型学的是什么文本和什么文本在语义上是靠近的。这让它在数学上天然倾向于压缩语义主干、忽略细节噪声也会让它对 chunk 长度、文本风格、领域术语比很多人预期的更敏感。用大白话说embedding 模型不关心这段话读起来怎么样它只关心这段话和哪段话像是同一件事。接下来我会把当前市面上主流的嵌入模型分成几类逐个讲清楚它们的参数、真实表现和适用边界再给出我自己的选型框架和一套不需要花太多成本的评测方法。全文基于我自己的实测和公开评测数据个别结论如果跟你在 MTEB 榜上看到的不完全一致不奇怪因为榜单分数和你自己的业务数据之间往往隔着一整个领域的差距。2. 主流嵌入模型横向扫描参数、维度、上下文与适用边界先把大家提到烂熟的那几个模型按我的理解重新梳理一遍。每个模型我都尽量说清楚三件事官方声称的优势、我在实际项目中的感受、它真正适合什么样的场景。2.1 OpenAI 系text-embedding-3-small / largeOpenAI 现在主推的是 text-embedding-3 系列上一代的 ada-002 已经慢慢退出推荐名单了。3-small 默认输出 1536 维3-large 默认输出 3072 维而且这两个模型官方都支持通过 dimensions 参数把向量降到更低维度比如 512 维甚至 256 维代价是检索精度会有一定程度的线性下降。实测下来text-embedding-3 系列的优势有三点API 极稳基本不存在网络抽风的问题文档完善生态完善任何语言都能轻松接入。它对英文和代码类文本的语义理解在通用场景里相当能打中文也过得去但谈不上最优。最大的问题主要有两个一个是文本长度上限卡在 8191 token处理长文档切片时需要格外小心截断另一个是 API 调用毕竟是按 token 计费的知识库到了千万级切片的量级做全量向量化的成本不是一笔小数目。另一个容易踩的坑是维度和存储。text-embedding-3-large 默认 3072 维如果你之前用的是 ada-002 的 1536 维库换模型后不只是索引要重建向量检索的内存占用和检索耗时也会明显上升。我在一个百万级切片的项目里做过粗略估算3072 维用 float32 存光向量本身差不多要 12GB 内存再加上索引和原始文本的映射部署规格直接上了一个台阶。2.2 开源主流bge 系列、e5 系列、gte 系列开源模型这块智源研究院的 bge 系列是中文场景绕不开的名字。bge-m3 是支持多语言的综合模型亮点是一次性支持 dense稠密向量、sparse稀疏向量、multi-vector多向量三种检索方式输出维度 1024上下文窗口做到了 8192。你在做多路召回的时候一个模型就能同时产出两种检索路径的输入很省事。bge-large-zh-v1.5 则是纯中文特化1024 维在中文语义相似度和检索任务上的表现非常稳定是不少国内知识库项目的默认选择。bge 系列在使用上有一个很关键的细节官方发布的模型默认是给 query 侧和 passage 侧分别加指令前缀的。query 侧要加为这个句子生成表示以用于检索相关文章passage 侧加为这个句子生成表示。很多人从 HuggingFace 拉下来就直接丢进去用前缀不加效果打折了 10% 都不知道为什么。这个细节我在第四节会展开讲。e5 系列是微软出的早期版本在 MTEB 霸榜过一段时间。e5-large-v2 和后来基于 Mistral 7B 的 e5-mistral-7b 都是 strong baseline特别是 e5-mistral-7b语义理解深度很足但 4096 维、7B 参数量在实际部署中对显存和推理时延的压力不小适合实验室环境或离线批量向量化不适合做线上实时 query 编码。gte 系列来自阿里通义实验室gte-large 在英文和代码上都很强但中文相对弱一点不过它的许可是 Apache 2.0商用友好。2.3 商用 API 与垂类优化jina、cohere、voyage如果你不想自己扛开源模型的部署和运维直接买商用 API 是省心的选择。Jina Embeddings v3 是最近两年我高频使用的一个它的特点是支持 8192 的上下文长度并且通过 task 参数来切换 query 和 document 两种编码模式还内置了 Matryoshka Representation LearningMRL可以输出 32 到 1024 维之间任意长度的向量。这个设计对灵活性和成本控制都很有价值——比如同一个模型在不需要太强召回精度的场景里可以直接用 256 维输出省一半存储。Cohere 的 Embed v3 在英文和多语言场景的工业应用里也很成熟支持 1024 维、多语言检索官方还提供 int8 和 binary 两种量化压缩选项可以把向量体积压缩到原来的八分之一到三十二分之一副作用是检索精度会有一定比例的折损。Voyage AI 的 voyage-3 是为 RAG 专门做过优化的商用模型上下文窗口拉到 32000 token对长文档切片尤其友好英文检索能力相当强但中文支持和本地部署这两点目前还是短板。2.4 一张表看明白模型参数与选型轮廓我把上面提到的模型和几个我实际接触过的变体整理成了下面这张表。注意表中的价格和推理性能是 2025 年初我实测的参考值并非官方承诺值。维度会直接决定存储成本和检索速度上下文长度则决定了 chunk 切分策略的设计空间这两列我觉得是选型时最先要看的。模型参数规模默认向量维度上下文长度支持语言许可/收费模式适用定位text-embedding-3-smallAPI1536可降至5128191 token多语言按 token 计费通用英文/多语言快速接入text-embedding-3-largeAPI3072可降至10248191 token多语言按 token 计费对精度要求高、云上预算充足的场景bge-m3~570M10248192 token中英等100语言Apache 2.0中文多语言、多路召回、私有化部署bge-large-zh-v1.5~326M1024512 token中文/英文MIT中文知识库主力选择bge-small-zh-v1.5~24M512512 token中文/英文MIT资源受限的轻量服务e5-mistral-7b7B40964096 token多语言MIT离线高精度向量化、研究场景jina-embeddings-v3~570M1024可低至328192 token多语言开源商业API长文档、灵活降维、内存敏感场景cohere embed-v3API10244096 token多语言按 token 计费多语言量化压缩存储voyage-3API102432000 token多语言按 token 计费英文长文档、RAG 专门优化这里额外提醒一句维度这个指标在开源生态里容易被拿来营销但实际意义要结合实际来解读。维度越高表达能力通常越强但存储成本和计算成本也同步上升dimension 低到一定程度比如 32 维就只适合做粗粒度聚类不适合做精细检索。所以看到一个模型支持 32 维到 1024 维可调别觉得小维度更好部署就盲目选小要看你的业务对召回精度的真实需求。3. 按业务场景选模型我的决策框架和具体建议参数表看完还是得落到选择上。我自己在实际项目中通常按四个维度来做决策业务语言的单一性、数据的领域特殊性、是否允许私有化部署、以及成本预算是按年付的硬件费用还是按量计费的 API 费用。把每个项目套进这四个维度基本一两轮就能锁定候选列表。3.1 中文知识库场景怎么选如果你的知识库是纯中文或中英混合且数据有一定领域属性比如法律、医疗、财务、制造我首推 bge-large-zh-v1.5 作为底线选择理由是它对中文短文本的语义区分度足够细而且 MIT 许可商用无风险。chunk 长度如果经常超过 300 字就升级到 bge-m3后者上下文窗口大对长段落的理解几乎没有压力。若是对检索精度要求很高、同时又有 GPU 资源做离线批量向量化还可以拿 bge-m3 的 multi-vector 模式配合 rerank 模型做精排。但这里有一个重要经验别拿开源模型的零样本能力硬扛强领域数据。中文法律条文里的应当可以这种词通用嵌入模型很可能把它们当成修饰词忽略掉而领域语义恰恰藏在里面。我有一次测医疗知识库发现低剂量螺旋 CT 筛查肺癌的适用人群这个 query召回出来的第一屏全是讲CT 检查注意事项的切片问题就出在模型对筛查适用人群这类结构化的领域表达不敏感。解决方案不是换一个更大的模型而是做一个针对性的领域微调或者至少做一次领域词典增强后再向量化。3.2 多语言和出海场景怎么选多语言场景的核心矛盾是单语言的强模型切换语言时效果衰落明显而多语言模型在特定语言上的表现往往不如单语言特化模型。我的实践结论是如果业务中需要检索多语言内容优先选 bge-m3 或者 jina-embeddings-v3它们是多语言检索方向上的第一梯队。bge-m3 在中文、英文以及不少欧洲语言上的平衡性不错jina 的 task 指令机制可以根据 query 和 document 的不同角色做区分编码实际检索效果会更稳定。如果是纯英文且文本偏长voyage-3 值得认真考虑。32000 token 的上下文意味着你几乎不需要为适应模型而强行切 chunk可以先把整个章节丢进去做向量化这在一部分需要段落级语义的场景下很有价值。需要注意的是商用 API 在跨境调用时可能存在网络延迟和合规问题你在设计整体架构时得把这些因素提前考虑进去不然最后被迫换框架成本不低。3.3 私有化部署与成本约束下怎么选对于大多数 To B 和政务、金融类项目数据不能出域是硬要求这时候只能用开源模型做私有化部署。我的经验是小型项目优先 bge-small-zh-v1.5因为 512 维、24M 参数量对 CPU 机器都能友好运行查询量不大的情况下甚至不需要 GPU 就能扛住日常检索中型项目用 bge-large-zh-v1.5 或 bge-m3如果真的到了千万级文档、追求极致精度的层面再考虑 e5-mistral-7b 这种大模型离线做段落向量化然后接一个轻量模型做在线 query 编码。成本计算方面有一个容易被忽略的点嵌入模型的部署成本大头在内存和显存不在显存因为 embedding 模型做的是单次前向推理batch 通常不会太大显存占用反而不高但向量库的内存占用是持续的。假设一个项目有 300 万条切片用 1024 维 float32 向量存储公式大概是切片数 × 维度 × 4 字节也就是 300 万 × 1024 × 4 ÷ 1024³ ≈ 11.4GB算上索引膨胀和原始文档存储一台 32GB 内存的服务器会很紧张。这也是为什么 jina 的 MRL 降维和 cohere 的量化方案会吸引人——有时一个维度选项就能帮你省掉一半的服务器采购费用。3.4 多路召回时机什么时候需要同时上多个嵌入模型多路召回不是标配它是在单一嵌入模型明显不能满足召回完整性需求时才引入的。比较容易判断的两个信号一是长尾 query 在小规模评测里频繁出现召回为空或者第一屏完全无关二是业务数据高度多元化比如知识库里既有技术文档又有销售话术一个模型很难同时对齐两套语义体系。这时可以采用双路召回一个主嵌入模型负责通用语义一个领域模型或 BM25 负责兜底最后用 rerank 统一精排。需要注意的是多路召回不是简单地多加一个模型如果两组向量没有统一的精排逻辑后面的融合阶段很容易出现分数打架的问题。4. 自己动手做评测MTEB 榜单之外的参考方法聊到评测多数人的第一反应是打开 MTEB 榜单哪个分高选哪个。这个思路不能说错但对 RAG 项目来说它有明显的局限性。MTEB 涵盖大量任务类型包括分类、聚类、 STS 等而你在 RAG 里真正关心的是检索任务retrieval这一个子项。更关键的是MTEB 的评测集大多来自公开通用数据和你自己知识库里的领域数据、query 口语习惯往往差距巨大。我自己的做法是用小样本自建评测集来做选型判断成本不高但结果非常有参考价值。下面这套流程我建议每个正在选嵌入模型的人都可以试一遍。4.1 自建评测集的构建方法评测集不用大100 到 200 条即可但要有代表性。我的做法是从知识库里挑出 20 到 30 个有代表性的业务域每个域里人工构造 5 到 8 条 query然后由熟悉业务的人标注每一条 query 对应的 golden passage正确答案所在的原始切片。这步工作看着繁琐但其实半天时间就能完成换来的是选型阶段拥有一个可信的标尺。标注的时候有一个细节golden passage 不能只看原文里是否存在答案而是要关注一条合格的 RAG 系统应该能把这个 chunk 召回上来。有些答案分布在多个切片里你需要把逻辑上关联的那几个都标成 golden而不是只标一个。这一步直接决定了评测分数有没有意义否则一个模型召回了一个包含关键词但语义不对的切片也会被算成正确。4.2 核心指标召回率、MRR、以及第一屏命中率评测时我重点看三个数字Recall5前 5 个结果里至少命中了 1 条 golden 的比例。这个指标衡量的是系统有没有能力把该找到的东西找回来。Recall10前 10 个结果里的命中率一般会明显高于 Recall5。如果两者差距太大说明排序能力不足需要加 rerank。MRRMean Reciprocal Rank衡量 golden passage 在排名中位次的平均值。MRR 高说明不仅召回了排序也合理这会极大降低 rerank 的压力。很多项目只关注了有没有召回到却忘了看排序。实际上在大模型生成环节排在第十位的正确答案大概率不会进入上下文窗口所以第一屏前 5的命中率比总召回率更能预测 RAG 体验。我见过不少模型 Recall10 能到 0.85但 Recall5 只有 0.55这种场景下如果你没有加 rerank用户感知就是经常答非所问。4.3 跑分过程中的两个隐藏变量第一个是 query 的构造方式。在真实系统里用户输入的 query 往往是口语化的比如那个备案要啥材料而知识库里的原文则是规范的书面语备案申请所需材料清单如下。嵌入模型对两种文本分布的适配能力差异很大专业术语叫对称搜索 vs 非对称搜索。有些模型如 bge 系列发布了 query 指令和 passage 指令就是为了缓解这种分布差异。评测的时候记得把 query 和 passage 分开编码按官方建议加指令不要图省事用同一个函数处理两侧。第二个是向量维度和损失精度的问题。如果你的向量库里只有 1000 条数据试不出维度的真实影响但数据量上到百万级后高维向量带来的内存压力和近邻检索的维度灾难会逐步显现。我建议在评测阶段把这些因素都存在一个可比较的基线里比如固定用 bge-m3 的 1024 维作为参考再测你要对比的模型最后所有结论都围绕与 baseline 的相对差异来说话。4.4 一个真实的评测小实操拿我服务过的一个制造业客服项目举例。知识库包含 8000 份产品手册和售后问答业务query 多是口语化描述故障现象。我先随机抽了 150 个 query由售后主管标好 golden passage然后跑了一轮对比结果如下数字做了脱敏处理保留相对关系模型Recall5MRR5备注text-embedding-3-small0.620.43召回不稳定故障描述越长越差bge-large-zh-v1.50.760.57整体表现稳定bge-m30.790.61对长文本切片明显更友好jina-embeddings-v3 (512维)0.740.55降维后精度略降但存储省一半这个结果反映出的规律是在这个中文领域场景里OpenAI 的通用模型并不占优势反而是开源中文优化模型取得了明显更好的结果。更关键的是这个评测只花了一个人半天时间相比上来就买最高配模型性价比高出太多。我特别建议所有做 RAG 项目的朋友选型阶段一定留出半天到一天做这件事绝对比直接看榜单决定要靠谱得多。5. 接入 RAG 全流程时最容易踩的坑与解决思路选好模型只是第一步。真等你把嵌入模型接进 RAG 链路还有几个坑会接连冒出来。我按出现频率从高到低理一遍。5.1 query 和 chunk 的双编码不对称问题这是最常见、也最容易被忽视的问题。很多开源模型对 query 和 passage 的定义是区分的比如 bge 系列需要加不同的 instructionjina v3 用 task 参数区分 retrieval.query 和 retrieval.passage。如果两侧都用同一个纯编码函数embedding 空间的两端就拉伸不到同一个语义维度上表现出来就是你在离线评估上做得挺好一上线就感觉检索结果有点偏。解决方法是把编码过程封装成两个函数并且严格按照模型文档来处理。BGE 系列在 sentence-transformers 里加载时通常会自动处理 instruction但如果你用 bare transformers API就得自己写前缀。这个细节测试集上就看出来我在一次对比里不加前缀的 bge-m3 在中英混合数据集上的 Recall5 掉了 6 个百分点对于已经上线的系统来说这是个巨大的回退。5.2 向量维度对齐与数据库迁移的成本问题嵌入模型一旦换原来的向量数据库索引基本就得重建。比如从 1536 维降到 1024 维表面上看存储空间省了但 HNSW 这类索引结构、efConstruction 参数、聚类中心数量都需要重新调优。还有更隐蔽的问题如果向量库里已经写了几百万条旧向量线上线下版本不一致就会出现部分查询走新模型、部分数据还是旧向量的混乱状态相似度分数彻底不可比。我踩过一次这种坑当时的处理办法是把新旧两套向量分别存两个 collection查询时都查一遍再合并结果虽然损失了一点性能但至少保证了数据一致性。5.3 chunk 切分策略与上下文上限的配合很多人会忽略模型上下文长度和 chunk 切分的关系。假设你用的是 bge-large-zh-v1.5上下文 512 token却把文档切成 800 token 的大块超过部分会被截断等于是让模型只看前半段就做语义压缩。反过来如果你用 jina v38192 上下文却把 chunk 切成 128 token 的小碎片语义完整性又会受影响尤其是技术文档里经常出现前后文交织的情况。我目前的实践做法是先根据嵌入模型的上下文长度确定单块 token 上限一般取模型的 70% 到 80%再按语义边界做递归切分保证每个 chunk 在主题上完整、长度上不超标。在 bge-m3 上一般用 800 到 1200 token 的块在 bge-large-zh-v1.5 上就卡在 350 到 450 token。不要一层不变的照搬别人的参数模型变了切分策略必须跟着变。5.4 嵌入模型和 rerank 的配合顺序和字段选择引入 rerank 模型后嵌入模型的角色会从精排退到粗排这其实是好事。粗排阶段不需要保证 Top1 绝对正确只需要保证 Top20 或 Top50 里包含正确答案精排交给 rerank 模型去处理。这时嵌入模型的主要压力就变成了召回完整性而不是排序准确性选型时可以更激进一点甚至可以尝试降维来换成本。有一个配合上的细节值得注意传入 rerank 的候选片段是否保留了你原本 chunk 的上下文。我在项目里遇到的情况是嵌入模型召回的是 400 token 的 chunk但 rerank 阶段如果直接拿这个 chunk 去算相关性往往会因为切片不够完整而漏判。后来我改成把命中 chunk 的前后各 200 token 一并传给 rerank相关性判断准确度明显提升。如果你已经把原始文档做了段落级拼接这一层就没那么必要但多数人做的还是小块召回这个操作带来的收益非常直接。5.5 归一化、相似度阈值和不必要的分数迷信做向量检索时别只看分数绝对值。不同模型产出的向量在归一化方式上差异很大bge 系列明确建议用 cosine 相似度有些模型则默认使用 dot product。把一种模型的相似度阈值用到另一个模型上是最常见的调参错误。我自己的做法是在每个模型上线前用评测集跑一遍分数分布看 golden 命中的最低分是多少再按这个分布去定业务阈值而不是拍脑袋定一个 0.7 或者 0.8。最后还想吐槽一个现象很多文章爱强调相似度分数低就没救实际并不完全是。分数低有两种可能一是真的语义无关二是 query 太短、信息量不足导致向量落点发散。后者可以通过 query 改写比如结合历史会话做扩展来改善而不是直接提高阈值。我在客服系统里就试过对用户的一条简短的发票怎么开做 query 扩展成发票开具流程需要提供哪些材料召回质量好了非常多。嵌入模型选型很重要但同样重要的还有 query 侧怎么喂给模型这个往往被忽略了。嵌入模型的选型没有一劳永逸的答案不同数据分布下的最优解会变化。我的建议是每个季度拿小评测集跑一次新模型对照胜出者再上灰度而不是一步到位绑定某一家厂商。毕竟 RAG 这条链路里嵌入模型是离数据最近的组件它的每一次升级都可能是最省事的性能提升方案。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进