
面试官问“两句毫不相干的话embedding 相似度是 0 吗”简历“3 年 RAG 开发经验负责企业知识库检索系统熟悉主流 embedding 模型选型与向量数据库调优。”看到这份简历我问了个不需要任何准备的问题随便找两句毫不相干的话把它们的 embedding 算个余弦相似度你猜是多少候选人想了两秒说应该接近 0 吧不相关嘛。这个答案在 Qwen3-Embedding 上勉强算对在 BGE-M3 上偏了一倍在 multilingual-e5 上错得离谱。三个数字都不是我测的全写在这些模型自己的 HuggingFace 主页上就在示例代码下面第一行输出里。做向量检索的人不少认真看过自己那个模型分数长什么样的人不多。这场面试的五个问题全都绕着同一个数打转。Round 1不相干的两句话分数真是 0 吗面试官“余弦相似度的取值范围是 -1 到 1。两段完全没关系的文本你估计落在哪”候选人“应该在 0 附近吧高维空间里随机两个向量差不多是正交的。”正解随机向量确实接近正交但 embedding 模型吐出来的不是随机向量。三个主流模型对同一件事给出的答案分别是 0.68、0.35 和 0.08。全部出自官方 model card 的 Usage 示例作者自己跑出来贴上去的谁去跑都能复现。先看multilingual-e5-large-instruct它的 model card 用两个 query 和两个 passage 演示打印出的分数矩阵是[[91.93, 67.58], [70.38, 92.13]]乘了 100。对角线上匹配的那两对是 0.92非对角线上完全不匹配的两对是 0.68 和 0.70。换成BAAI/bge-m3dense 检索的示例矩阵是[[0.6265, 0.3477], [0.3499, 0.678]]匹配的 0.63不匹配的 0.35。再看Qwen3-Embedding-8B示例里匹配的两对是 0.75 和 0.63不匹配的两对是 0.08 和 0.09。三个模型同样是毫不相干一个说 0.68一个说 0.35一个说 0.08差了将近一个数量级。为什么不会归零主流 embedding 输出前都做了 L2 归一化所有向量落在单位球面上余弦相似度退化成两点的夹角。OpenAI 的文档写得很直白它家的 embedding 归一化到长度 1所以余弦相似度可以直接用点积算欧氏距离排出来的顺序也完全一样。关键在于这些向量在球面上不是均匀铺开的训练完之后它们挤在一个相对狭窄的锥形区域里。SimCSE 那篇论文arXiv 2104.08821就是冲这个去的核心贡献之一是用对比学习目标把预训练嵌入的各向异性空间正则化得更均匀。挤在一个锥里的两个点夹角天然小于 90 度余弦值天然大于 0。30 秒自己验证别信我也别信直觉from sentence_transformers import SentenceTransformerm SentenceTransformer(“BAAI/bge-m3”) # 换成你线上正在用的那个a m.encode([“今天下午三点开产品评审会”], normalize_embeddingsTrue)b m.encode([“这道菜的辣椒放多了”], normalize_embeddingsTrue)print(a b.T)嫌装库麻烦的话有个更快的办法打开你线上那个模型的 HuggingFace 页面往下翻到 Usage 那段示例代码作者已经把输出分数贴在注释里了。要点速记官方示例里的不相关分数e5-large-instruct 0.68BGE-M3 0.35Qwen3-Embedding 0.08主流 embedding 都做了 L2 归一化cosine 等价于点积欧氏距离排序结果一致分数不归零的直接原因是向量集中在球面的一个窄锥内随机两点夹角小于 90 度验证成本5 行代码或者翻一下 model card 的 Usage 段Round 2同样判定相关凭什么一个给 0.92 一个给 0.63面试官“e5 判定相关给 0.92BGE-M3 判定相关只给 0.63。哪个模型更有把握”候选人“那肯定是 e5 吧0.92 的置信度比 0.63 高多了。”正解这两个数没有可比性它们量的不是同一把尺子。分数分布的宽窄是训练时的温度参数直接压出来的和模型判得准不准是两件事。bi-encoder 的训练目标基本都是 InfoNCEL -log[ exp(s⁺/τ) / Σ exp(sᵢ/τ) ]其中s是 query 和 candidate 的余弦相似度s⁺是正样本那一对分母跑遍 batch 内所有负样本τ 是温度。E5 论文arXiv 2212.03533里明确写了默认 τ 取 0.01。把这个值代进去看会发生什么相似度差 0.01除以 τ 之后在 logit 层面就是 1.0 的差距。正负样本只要拉开 0.24 的余弦差距进 softmax 前的 logit 差就是 24指数化之后正样本概率无限逼近 1loss 趋近于 0梯度基本消失。训练到此为止。模型没有任何动力再把正负样本推得更开从 loss 的角度看它已经满分了。0.92 配 0.68 这个组合就是 τ0.01 训练收敛后的自然产物。E5 的 model card 自己也承认了这点说分数通常落在 0.7 到 1.0 之间这是低温度 InfoNCE 的预期行为。换个温度比如 τ 取 0.05同样 0.24 的余弦差距只能换来 4.8 的 logit 差softmax 之后正样本概率还没饱和梯度还在模型会继续把负样本往外推最后收敛出来的分布就宽得多。Qwen3-Embedding 那个 0.75 对 0.08 的分布宽度是 e5 的两倍多。温度是主要旋钮但不是唯一的。负样本的采样策略batch 内随机负样本还是挖过的 hard negative、有没有加 hard negative 的额外损失项、蒸馏时对齐的是分数还是排序都会改变最终分数落在哪个区间。共同点是这些全属于训练侧的工程选择没有一个跟这两句话在语义上有多像直接挂钩。BGE 的作者干脆把这件事写进了 model card 的 FAQ原文是a similarity score greater than 0.5 does not indicate that the two sentences are similarwhat matters is the relative order of the scores, not the absolute value分数超过 0.5 不代表这两句话像有意义的是分数之间的相对顺序不是绝对值。OpenAI 的 embedding 文档也一样通篇推荐用余弦相似度从头到尾没给过任何分数范围参考或者阈值建议。这不是文档写漏了。要点速记InfoNCE 的 τ 直接决定分数分布宽窄E5 论文默认 τ0.01分数被压在 0.7-1.0τ 越小同样的余弦差被放大越多饱和越早分布越窄影响分布的还有负样本采样、hard negative 损失项、蒸馏对齐目标BGE model card 原文分数 0.5 不代表相似有意义的是相对顺序OpenAI embedding 文档从未给出任何推荐阈值Round 3支持和不支持向量分得开吗面试官“知识库里有两段话一段说本产品支持离线部署一段说本产品不支持离线部署。用户问是否支持离线部署你的向量检索能把正确那段排前面吗”候选人“这两段相似度肯定都很高都在讲离线部署。不过 top-k 都召回了的话让大模型自己判断应该问题不大。”正解bi-encoder 在这类场景下的表现不是差一点是稳定地低于瞎猜。EACL 2024 的 NevIRarXiv 2305.07614专门测了这件事。构造方法很干净一对文档只在否定上有区别两个 query 分别对应其中一个要求模型两个方向都排对才算通过。随机排序的期望通过率是 25%。实测结果论文 Table 2模型类型代表模型pairwise accuracy随机基线—25%Cross-encoderMonoT5-3b50.6%Cross-encoderMonoT5-base34.9%Late-interactionColBERTv119.7%Late-interactionColBERTv213.0%Bi-encoder向量检索DPR6.8%Bi-encoder向量检索multi-qa-mpnet-base-dot-v111.1%该类最高SparseSPLADEv28.0% / 8.7%SparseTF-IDF2.0%论文的结论句是 nearly all models perform worse than randomly ranking几乎所有模型都比随机排序更差。低于随机这件事有结构性原因错误方向是固定的。bi-encoder 把整段文本压成一个定长向量池化那一步会把每个 token 的贡献摊平。一个否定词在几十上百个 token 里只占一份权重压缩之后基本被主题信息淹没了。而对比学习的训练语料里几乎不存在只差一个否定词的正负样本对模型从来没被要求过要把它们分开自然也没学会。排序稳定地错还有个更细的原因带否定的那条文档比不带的多了一个词主题重心被这个词轻微拉偏于是它和不含否定的 query 的距离反而近了一点。这个偏移在整个语料上方向一致所以错误是可复现的不是随机抖动。候选人说的兜底方案也不太成立。指望 top-k 全召回再让大模型判断前提是两条都进了 top-k。真实知识库里同一主题下有几十上百个 chunk两条只差一个否定词的文档排序上很可能被一堆同主题内容隔开真正拿到答案的只有排错的那条。更麻烦的是这类错误在评测里几乎查不出来。跑 faithfulness 指标大模型完全忠实于检索到的内容指标是满分跑 answer relevancy答案确实在回答用户的问题指标也漂亮。一个自信、流畅、和检索内容严格一致的错误答案整条评测链路上没有一个环节会报警。架构层面能救一部分。Cross-encoder 把 query 和 document 拼在一起过一遍完整的 attention否定词能和主题词直接交互MonoT5-3b 做到了 50.6%。这个数字比 bi-encoder 高了四五倍但也只是刚过及格线的一半加了 reranker 不等于这个问题解决了。要点速记NevIREACL 2024pairwise accuracy 随机基线 25%bi-encoder 全部落在 6.8%-11.1%ColBERTv2 13.0%SPLADEv2 8.0%TF-IDF 2.0%最好的 MonoT5-3b 也只有 50.6%根因池化把否定词权重摊平训练语料里没有只差否定词的 hard negative这类错误在 faithfulness / answer relevancy 评测里全是满分监控不到加 cross-encoder reranker 能提升四五倍仍然只到 50% 左右Round 4那阈值到底怎么定面试官“你们线上过滤低质量召回阈值设的多少”候选人“0.8低于 0.8 的直接丢掉避免噪声进 prompt。”面试官“这个 0.8 怎么来的换模型的时候动过吗”候选人“……应该是当时试出来的后面一直没改。”正解把 Round 1 那三组官方分数和 0.8 这个阈值放一起结果一目了然。模型官方示例·相关对官方示例·不相关对阈值 0.5阈值 0.8multilingual-e5-large-instruct0.92 / 0.920.68 / 0.70全放行等于没设工作正常BGE-M3dense0.63 / 0.680.35 / 0.35工作正常全拦截返回空Qwen3-Embedding-8B0.75 / 0.630.08 / 0.09工作正常全拦截返回空在 e5 上精心调出来的 0.8搬到 Qwen3-Embedding 上检索接口开始稳定返回空列表。Qwen3-Embedding-8B 在 MTEB 多语言榜上排第一截至 2025 年 6 月 5 日得分 70.58C-MTEB 73.84换过去是升级不是降级但阈值不动的话线上表现是知识库突然全空。反过来在 e5 上设 0.5等于什么都没过滤它连不相关的都给 0.68。能用的做法是分位数校准把阈值当成需要标定的量而不是常量import numpy as nprel / irr: 人工标注后相关对与不相关对各自的分数数组抽 200-500 条真实线上 query各标 top-10 就够thr np.percentile(irr, 95) # 让 95% 的不相关召回被挡住kept (rel thr).mean()print(f阈值 {thr:.3f}相关文档还能留下 {kept:.1%})标注量不用很大200 条 query 各标 top-10 是 2000 个判断两个人一天能干完。跑出来的阈值是这个模型 这批语料 这类 query 分布三者的联合产物三个里任何一个变了都得重新标。换 embedding 模型要重标知识库从产品文档扩到工单记录要重标产品从 to B 转 to C 导致提问方式变了也要重标。有个坑会让离线标好的阈值在线上直接失效非对称前缀。模型query 侧要求document 侧漏掉的代价multilingual-e5-large-instructInstruct: {task}\nQuery: {q}不加model card 原文会看到性能退化Qwen3-EmbeddingInstruct: {task}\nQuery: {q}不加官方说明掉 1%-5%bge-large-zh-v1.5可加为这个句子生成表示以用于检索相关文章不加v1.5 优化过不加只有轻微下降BGE-M3不需要不加—这几个模型对前缀的要求各不相同而且都只加在 query 一侧document 侧保持原文。真正出事的场景是这样离线批量灌库的脚本和线上查询的服务是两个人写的一边加了前缀一边没加模型照样跑得出向量检索照样返回结果没有任何报错。唯一的症状是整批分数集体偏移辛苦标定的阈值全部对不上号。另一个坑是归一化。OpenAI 的向量出厂就归一化到长度 1点积和余弦完全等价。自己训的模型、或者某些开源模型的原始输出没做归一化这时候用点积算相似度向量的模长会直接进结果。文本越长模长通常越大长 chunk 就天然拿高分。这类问题的典型症状是检索结果总是偏爱长文档而排查方向往往被引到分块策略上去。要点速记同一个 0.8e5 上工作正常BGE-M3 和 Qwen3-Embedding 上全部返回空阈值是 模型 × 语料 × query 分布 的联合产物任一变化都要重标校准成本200-500 条真实 query 标 top-10np.percentile(irr, 95)起步E5 / Qwen3 只在 query 侧加 Instruct 前缀document 侧不加两边不一致会整体偏移分数Qwen3-Embedding 官方数据不加 instruction 掉 1%-5%未归一化的向量用点积模长进结果长文档天然分数高Round 5怎么判断知识库里根本没有面试官“用户问了一个知识库里完全没有的问题你怎么让系统承认自己不知道而不是硬凑三条最像的”候选人“那就得提升召回质量比如上混合检索、加 reranker、优化分块……”正解问的是怎么识别没有答案答的是怎么把答案找得更准这两件事方向是反的。绝对阈值做不了这件事Round 4 已经说清楚了。三个可以落地的替代方案方案一看落差不看绝对值。记录 top1 与 top5 的分数差。库里确实有答案时top1 会明显甩开后面一截库里没有的时候top1 到 top10 是一条几乎水平的线一堆同样不相关的文档挤在一起谁排第一基本靠抖动。这个信号跨模型稳定因为它量的是相对量不受温度压出来的分布宽窄影响。落差阈值同样需要标定但它对换模型的鲁棒性远好于绝对阈值。方案二cross-encoder 二次判定。reranker 把 query 和候选拼在一起过完整 attention输出的相关性分数比 bi-encoder 更接近可解释。代价是延迟一次 rerank 通常在几十到几百毫秒量级取决于候选数和模型大小。Round 3 的数据提醒了这个方案的天花板在否定这类场景上最好的 cross-encoder 也就 50.6%。方案三把判断权交给大模型。在 prompt 里明确写清楚如果提供的资料里没有相关信息就直接回答不知道。大模型读的是文本能看懂否定、能看懂答非所问而这两件事恰恰是余弦相似度做不到的。成本是多进 prompt 的那几千 token比误答的代价便宜得多。四种做法放在一起对比方案判定信号换 embedding 模型后额外延迟主要局限绝对阈值top1 分数超过 T必须重新标定0跨模型直接失效见 Round 4分数落差top1 减 top5 超过 D建议复核一遍0库里有多条同样相关的文档时落差也小cross-encoderrerank 相关性分数建议复核一遍几十到几百毫秒否定场景上限 50.6%交给大模型模型自己回答不知道不用动一次生成的时间多进几千 token线上通常是后三种叠着用落差先做粗筛reranker 收一遍最后靠 prompt 兜底。绝对阈值那一列唯一的优点是实现起来只要一行 if。生产上还要加一条监控每天记录线上 query 的 top1 分数的 p50 和 p90画成时间序列。这两条线正常情况下是平的一旦整体平移说明三件事之一发生了embedding 模型版本变了、灌库脚本的前缀逻辑改了、或者用户的提问方式变了。分数分布漂移是这几类问题里最早出现也最容易被忽略的信号等到用户投诉搜不出东西的时候通常已经漂了好几天。要点速记绝对阈值判定不了无答案改用 top1 与 top5 的分数落差跨模型稳定cross-encoder 二次判定更可解释但否定场景上限只有 50.6%最可靠的是在 prompt 里写清楚资料里没有就回答不知道成本是几千 token监控 top1 分数的 p50/p90 时间序列整体平移意味着模型换了、前缀漏了或用户变了面试官点评这位候选人的问题不在于不懂向量检索混合检索、reranker、分块策略他都能说得头头是道。问题出在他把一个训练副产品当成了置信度在用而且用了三年没有怀疑过。余弦相似度是模型内部的一个刻度刻度间距由训练温度决定零点在哪没人定义过。拿它做绝对判断相当于拿一把没有起点的尺子量长度量出来的数字换一把尺子就全变了。三条建议打开你线上那个 embedding 模型的 model card翻到 Usage 段看一眼示例输出的分数是多少这是成本最低、信息量最大的一步花一天标 200 条真实 query把阈值从试出来的常量变成标定出来的分位数顺便你会第一次看清自己系统的分数分布长什么样检查灌库脚本和查询服务确认 query 前缀的处理逻辑一致。这个 bug 不报错、不崩溃只是悄悄让检索质量差一截做了几年向量检索天天看着日志里那一列 similarity 分数做判断却从来没打开过自己那个模型的 model card 看一眼作者写在 FAQ 里的第一句提醒。BGE 的作者把分数大于 0.5 不代表相似写进了文档OpenAI 的 embedding 指南一个阈值都不敢给。真正读到这两句话的人比用这两个模型的人少太多了。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】