很多人搭 RAG 时会把 embedding 模型和 BERT 混着说,结果选型会上吵半天:有人说 BERT 不就是做向量的吗,有人坚持 embedding 必须单独调。这篇不绕学术定义,只从工程分工讲——两者在链路里各占哪一段、接口形态差在哪、换掉其中一个会牵动什么。看完你能自己判断当前项目该用哪个,以及出了效果问题该先查哪一环。
搭 RAG 的时候,embedding 模型和 BERT 被混着说,是选型会上最常见的吵架来源。有人说 BERT 不就是做向量的吗,有人坚持 embedding 必须单独调。其实这两句话都没错,只是说的不是同一件事——一个在说结构,一个在说用途。
这篇不讲学术定义,只从工程分工切:两者在链路里各占哪一段、接口形态差在哪、换掉其中一个会牵动什么。看完你应该能自己判断当前项目该用哪个,以及出了效果问题先查哪一环。
先分清两者在链路里各站哪一段
embedding 模型在 RAG 里是索引端加查询端的编码器,负责把文档块和用户问题都压成同一空间的向量,交给向量库做近邻检索。它只输出向量,不生成任何文字,属于链路最前面那一段。
BERT 是一类预训练语言模型的结构范式。它既可以拿来做向量(取 CLS 或者做池化),也可以加个任务头做分类、抽取、相似度打分,本身不绑定检索这个用途。所以问区别之前,先分清你问的是哪种比法。
- 用法一
- 把 BERT 当 embedding 用——这时比的是同一段代码里的两种实现
- 用法二
- BERT 系模型与专门训练过的 embedding 模型——这时比的是训练目标和效果
- 共同点
- 两者都要把文本压成定长向量,都要处理长度截断和批处理
- 先去 /ai-dict/category/tech 把底层概念过一遍,确认自己嘴里的 embedding 指的是哪一层
- 再去 /stacks/vector-dbs 看向量库那边认的是哪种输入、维度上限多少
- 把团队里「BERT 出向量」和「embedding 出向量」两个说法写成同一句可验证的话,再开会
训练目标不同,直接决定谁更适合检索
通用 BERT 的预训练目标是完形填空式的语言建模,它擅长理解上下文,但没有被专门优化过「语义相近的句子向量距离要近」这件事。直接取句向量,走检索往往表现一般,这不是调参能救的。
面向检索的 embedding 模型通常是拿对比学习调过的:正样本对拉近、负样本对推远,目标就是让语义相似的内容在向量空间里聚在一起。这正是召回要的东西。所以同规模下,检索任务优先用检索向的 embedding。
| 对比项 | 检索向 embedding | BERT 系模型做向量 |
|---|---|---|
| 优化目标 | 对比学习,拉近正样本 | 语言建模,理解上下文 |
| 开箱即用度 | 做召回通常直接可用 | 上检索一般要再训一轮 |
| 调参关注点 | 维度、批大小、语料领域 | 池化方式、学习率、任务头 |
| 更合适的活 | 召回、聚类、去重 | 语义打分、分类、精排 |
接口形态和计算成本差在哪
embedding 模型接口一般是一次请求给一批文本、返回一批定长向量,调用方只关心维度和吞吐。它便宜、快,适合离线把整库刷成向量,服务端压力小。
用 BERT 类模型做向量,通常要自己起服务或者调托管推理,还要处理池化方式(取 CLS 还是平均)、最大长度截断、批大小这些细节,工程量明显更大,排查链路也更长。
- 维度要提前定:换 embedding 模型往往意味着整个向量库要重建索引,不能只换模型不换数据
- 换之前确认向量库支不支持在线重建或双写,避免停机刷库
- 算成本别只看单价,离线全量刷库的 token 量和重建耗时才是大头
- 两种口径可以到 /tools/model-cost-calculator 各算一遍,用同一批语料对
怎么选、怎么验:一份上手清单
选型分两步。先定任务:纯召回选检索向 embedding;要做语义打分或精排再看 BERT 系交叉编码器;两者并不互斥,常见组合就是 embedding 召回加交叉模型重排。
- 定任务先写清楚这一段是要召回还是要打分,召回和精排分开选,别一个模型干两件事
- 筛候选按语种、领域、维度到 /embeddings 里筛,中文、代码、法律医疗这类垂直语料优先找同类训过的
- 分层测先测召回命中率,看正确文档有没有进前 K;再测最终答案。召回不行就换 embedding,召回行但答案歪就是生成或提示词的问题
- 留基线固定一批问题,记录换模型前后的命中变化;榜单只能当参考,可以到 /benchmarks/registry 看看有哪些维度能对齐
评测这块最容易走偏的是只盯着最终答案。答案错有很多原因,直接怪 embedding 会浪费一轮迁移。把召回和生成拆开测,能省掉大半无效排查。
几个最容易踩的坑
- 拿通用 BERT 直接出向量上线,小样本看着还行,数据量一大会发现语义近的文档召不上来,这属于选型问题不是调参问题
- 查询端和索引端用了不同模型或不同版本,向量空间对不上,检索结果会莫名其妙地差,切换时两端务必一起换
- 长文档不分块就整篇塞进模型,被截断的部分等于没进库,分块策略和模型最大长度要一起定
- 只换模型不重建索引,老向量和新查询向量混着用,等于自建噪声源
先分清这段代码是在做召回还是在做打分,再决定叫它 embedding 还是 BERT,选型会快很多。
还有一类情况不必折腾:语料只有几百条、问题又高度依赖关键词时,传统全文检索可能更省事更快。先到 /stacks 看看有没有现成方案,不必硬上向量。
下一步把候选模型在同一批语料上跑一遍召回命中率,别只看榜单。到 /embeddings 按语种和维度筛一轮,再回 /tools/model-cost-calculator 估一次刷库成本,两项都过关再动手迁移。→常见问题
RAG 里能直接用 BERT 当向量模型吗?
能跑,但不建议直接上生产。通用 BERT 的预训练目标不是语义相似度,取出来的句向量在召回上通常弱于检索向的 embedding 模型。如果你的场景是短文本、关键词为主,先试全文检索;一定要用 BERT,就在自己的业务语料上做一轮对比学习再训,效果才稳。
换了 embedding 模型,向量库里的数据要重刷吗?
要。向量是模型算出来的,模型一换,同一句话的向量就变了,新旧混在一个索引里距离没有可比性。正确做法是双写或新建集合,把全量文档重新编码一次再切流量;同时确认查询端也换成同一个模型,两端必须一致。
BERT 和 embedding 模型,是不是后者全面更好?
不是,分工不同。召回要的是快和海量候选,embedding 更合适;精排要的是对「问题 + 文档」成对打分,BERT 系交叉编码器准确率往往更高但慢得多,只能对小候选集用。常见架构是前者召回、后者重排,不是二选一。