Skip to content

RAG 召回实测:bge-m3 和 nomic-embed-text,谁更适合中文知识库 ​

本文为中文原文。English version: RAG retrieval benchmark: bge-m3 vs nomic-embed-text(同一份数据)

搭 RAG 最容易踩的坑:向量模型随手装一个,结果问答一直答非所问。我用站内 27 篇文章做语料,把两个常见的本地向量模型各跑了一遍,看谁能把问题召回给正确的文章。

一、结论先说 ​

指标bge-m3nomic-embed-text
向量维度1024768
索引 156 块耗时39.9 秒(约 256ms/块)19.8 秒(约 127ms/块)
平均查询耗时50ms26ms
top1 命中(口语问法)8/104/10
top3 命中(口语问法)9/105/10

结论:中文知识库用 bge-m3。nomic 快一倍,但中文口语提问几乎一半召回不到正确文章。

二、怎么测的 ​

  • 语料:本站 docs 下 27 个 markdown 文件(含首页、栏目首页、关于等),按二级标题切块,得到 156 个分块
  • 问题:10 个自然口语问题,每个预先标注「应该命中哪篇文章」
  • 检索:余弦相似度,取 top3;先把分块结果去重到「文章级」,再看命中
  • 机器:i5-12400、32GB 内存、无独显,Ollama 0.40.13,模型 bge-m3:latest 与 nomic-embed-text:latest

两个向量模型的召回命中对比

三、三种条件下的完整结果 ​

条件bge-m3 top1 / top3nomic top1 / top3
分段索引 + 口语提问8 / 94 / 5
分段索引 + 关键词提问8 / 107 / 9
整篇索引 + 口语提问7 / 95 / 6

四、四个发现 ​

1. 中文口语提问,bge-m3 明显更稳 8/10 对 4/10,不是偶然差距。nomic 的中文语义抓得不准,问「魔方第一步先拼什么」,它给的答案是「常见问题」「计时与记录」,完全没碰《三阶入门》。

2. 换关键词问法能救 nomic,但救不回 bge 的上限 把口语问句换成关键词(「慢拧训练 越练越慢」),nomic 从 4/10 涨到 7/10,说明它更依赖字面重合。bge 的关键词版 top3 直接到 10/10,但也只是把原本就对的那题救得更稳。

3. 整篇索引用处不大 两个模型在「整篇索引」下都变差(bge 8→7,nomic 4→5)。整篇文章塞成一个向量,主题被平均掉了,反而不如按小节切。

4. 耗时和效果是反着的 nomic 索引快一倍、查询快一半,代价是命中率掉一半。个人知识库规模小(几百块),多花 20 秒建索引换 30% 命中率,很值。

五、失败案例(原文) ​

问题bge-m3 召回正确文章
为什么我魔方越练越慢,怎么改?常见问题 → 魔方选购指南 → 常见问题慢拧训练
本地大模型会不会泄露我的数据?数据与隐私 ✅—
RAG 检索不到内容是什么原因?RAG 与知识库 ✅—

bge 唯一实质失败的是「越练越慢」这种口语转述——文章里讲的是「慢拧训练」,字面差得远。这提醒:问题用词和文档用词差距大时,召回会掉,需要改写问题或者补充同义词。

六、怎么选 ​

场景建议
中文知识库、问答为主bge-m3(1024 维,召回优先)
英文资料、对延迟敏感nomic-embed-text,但要把问题写成关键词
中英混合bge-m3,省心
机器特别弱(内存 < 8GB)nomic 更轻,但要接受命中率下降

七、想自己复现 ​

ollama pull bge-m3
ollama pull nomic-embed-text

向量化接口:

curl http://127.0.0.1:11434/api/embed -d "{\"model\":\"bge-m3\",\"input\":\"要向量化的文本\"}"

本文的测试脚本存在 editor\_rag-eval.mjs 与 _rag-eval2.mjs,原始数据在 editor\logs\rag-eval2-*.json,每题召回了哪三篇都有记录,可以核对。

八、局限 ​

  • 10 个问题样本很小,只能看趋势,不能当基准分
  • 「正确答案」是我人工标注的,存在判断空间
  • 只测了召回,没测「召回对了之后模型能不能答对」
  • 单机、单次运行,换机器或换模型版本,数字会变