一个检索团队针对其产品目录发布了一个开箱即用的嵌入模型 (embedding model)。评估集——从上个月搜索日志中抓取的几百个查询——回传的 recall@10 达到了 0.91。他们将其推向生产环境。三周后,支持部门开始转发工单:一位用户搜索了某个零件的具体 SKU,结果得到了五个看起来很有道理但错误的零件。另一位用户搜索了一个功能的内部代号,结果得到了一个无关功能的营销名称。评估集从未捕捉到这一点,因为评估集是从系统已经处理过的查询中提取的——即关于常用术语的查询。作为业务核心的长尾术语 (jargon) 从未被采样。
模型并没有失败。模型完全按照其训练要求执行了任务,只是针对的是一个不包含团队提供语料库的词汇分布。团队将嵌入视为一种领域中性的原语 (domain-neutral primitive)——一个从文本到向量的函数——而实际上,它是一份关于它可以解析哪些词汇的契约,是与别人的训练语料库签署的。
双峰覆盖问题
嵌入模型是在互联网规模的语料库(Common Crawl、维基百科、书籍、代码)上训练的。它们内化的词汇分布反映了公开互联网最常讨论的内容。领域特定术语——药物名称、内部产品代号、合同条款、零件编号、科学记数法、仅存在于某一行业内部的术语——很少出现或根本不出现。
结果是一种双峰覆盖模式。常用标记 (common tokens)(动词、介词、流行产品名称、众所周知的概念)在嵌入空间中密集表示;模型在许多语境中见过它们,并学会了区分它们的语义邻域。稀有标记——领域词汇所在的长尾部分——则坐落在稀疏、区分度差的区域。多个截然不同的稀有术语坍缩到同一个邻域,因为模型从未有足够的信号来推开它们。
2025 年记录这种失败模式的研究对此直言不讳:稠密检索器 (dense retrievers) 在长尾实体上失败,因为模型内部的标记分布“忘记”了这些实体的某些标记。一个稀有药物名称的嵌入并不是该药物的真实嵌入——它是分词器 (tokenizer) 将其拆分成的子词片段 (subword pieces) 的嵌入,这些片段被平均成一个向量,指向那些恰好共享这些片段的常用词。两个具有重叠子词的不同药物名称最终在嵌入空间中成为邻居,不是因为它们语义相似,而是因为它们的分词结果相似。检索系统会很自然地将一个作为另一个的结果返回。
这就是开头段落中团队遇到的失败模式。产品目录包含嵌入模型从未作为完整标记见过的零件编号和 SKU。模型将每一个都嵌入为对其子词组件的模糊覆盖。检索就变成了针对分词器产物的某种模糊匹配,而不是针对意义。
为什么评估套件没有捕捉到它
评估套件没有捕捉到它,是因为评估套件是从错误的分布中提取的。团队根据生产系统已经处理过的查询构建了评估集。由于选择偏差,系统已经处理过的查询正是系统所擅长的——常用术语、释义、导航式查找。长尾的术语密集型查询要么不在日志中(因为用户已经放弃并直接使用了 SKU 列),要么数量非常少,以至于被总体的召回率数字淹没了。
即使是知道要平衡评估集的团队,也往往平衡错了方向。他们根据查询长度、用户细分、类别进行分层抽样。他们没有根据查询的词汇分布相对于嵌入模型训练语料库的词汇分布进行分层。这种分层才是真正重要的,而且几乎没有人去计算。
MTEB 和 BEIR 基准测试在大规模上也存在同样的问题。它们聚合了许多任务并产生一个单一的数字,让你能够对模型进行排名,但排名榜首的模型在词汇分布与基准测试不同的特定领域中,表现仍然可能不佳。将排行榜得分视为领域质量信号,与将查询日志评估视为覆盖率信号是同一类范畴错误——两者都是针对模型已经训练或评估过的文本进行衡量,而不是针对你自己的语料库实际包含的文本。
该团队需要的纪律是一个领域词汇评估,将稀有术语固定下来,并专门针对它们衡量检索效果。根据语料库词汇的长尾部分构建评估集,而不是根据查询日志的头部。这两个分布完全不同,在一个分布上表现良好的模型在另一个分布上可能会悄无声息地失效。
实践中“糟糕”的表现是什么样的
当这种情况失败时,它不会产生明显的报错。用户输入一个 SKU,返回的却是五个与查询共享三个子词片段但指向无关产品的 SKU。用户输入一个内部代号,返回的却是关于另一个分词方式类似的代号的文档。用户输入一个精确的合同条款名称,返回的却是来自另一份协议的段落,而那段话恰好包含了嵌入模型无法区分的词汇。
每一次单独的失败看起来都足够合理,以至于你甚至可能意识不到结果是错误的。医生搜索某种特定的药物,却得到了一个听起来类似的药物,这种类型的失败是嵌入模型根本无法检测到的,因为在模型的表示中,这两种药物几乎是相同的向量。法律团队搜索一个特定的定义术语,却得到了一个包含重叠词法结构的、关于另一个定义术语的段落,在快速阅读时可能无法发现这种替换。
这是最糟糕的一种检索失败:结果表面上的合理性掩盖了底层的错误。如果未命中且没有返回任何内容,会提示你去优化查询。而如果未命中却返回了看起来很有把握的垃圾信息,则会诱导你去信任它。
修复它的三种模式
有三种模式可以解决底层的覆盖缺口。它们都不能孤立存在;对于大多数团队来说,正确的答案是根据你的词汇分布相对于嵌入模型的具体情况进行某种组合调整。
锁定罕见术语的领域词汇评估(Domain-vocab eval)。 挑选出定义你业务的长尾词汇——SKU、药物名称、代号、定义术语、缩写、科学计数法。构建包含这些术语的查询,以及每个查询对应的已知正确的文档。将这组数据的召回率与普通查询流量的召回率分开衡量。将领域词汇评估中的回归视为独立于核心指标的发布阻碍项。如果没有这种约束,任何其他干预措施都无法验证——你无法修复你无法衡量的覆盖缺口。
在域内配对数据上训练的微调嵌入头(Fine-tuned embedding head)。 开箱即用的嵌入是通用的;你可以通过对来自你所在领域的 (查询, 相关文档, 不相关文档) 三元组进行对比训练,教一个小型嵌入头将其投影到具备领域感知能力的坐标空间中。最近的研究表明,即使只有几千个领域特定的配对,也足以实质性地提高术语密集型查询的召回率。代价是你必须维护一套训练流水线,依赖于你的域内配对数据保持更新,并且在词汇发生偏移时要有重新训练的纪律。
以 BM25 作为兜底的词法混合检索(Lexical-hybrid retrieval)。 当嵌入模型不确定时——当前 K 个嵌入距离普遍较高,表明语料库中没有确定的语义匹配时——回退到 BM25 或其他优先考虑精确标记匹配的稀疏方法。BM25 在稠密嵌入表现最差的查询上出奇地有效:精确标识符、罕见专业术语、命名实体、代码,以及任何用户因为想要特定内容而输入特定术语的情况。混合检索作为生产环境的解决方案已经存在了一段时间;2025–2026 年的前沿是针对每个查询的动态权重分配,它可以检测查询是偏向关键词还是偏向语义,并据此进行路由。
Most teams 发现正确的做法是三管齐下:用领域词汇评估来衡量,用微调嵌入头来提升域内语义匹配的下限,用词法混合检索来捕捉嵌入模型根本无法表示的失败情况。
架构上的认知
更深层次的认知是,嵌入模型并不是一个中性的原语。它是一份关于它能解析哪些词汇的契约,是基于它所训练的语料库编写的。采用该模型就意味着接受了那份契约。契约的条款——哪些词在头部,哪些在尾部,哪些被分词为内聚单元,哪些被拆分为子词——通常是不成文的,但它们具有约束力。
那些交付了可用检索系统的团队将其视为一个采购问题。在采用嵌入模型之前,请根据你实际想要检索的语料库词汇分布对其进行审计。在部署前运行领域词汇评估,而不是在收到第一个错误的支持工单后才开始。了解哪些术语它可以解析,哪些不可以,以及哪些术语它会静默地塌陷到错误的邻域中。
那些交付了破碎检索系统的团队将嵌入视为一个通用的商品层——选择排行榜顶部的模型,直接丢进去,然后在系统处理的任何查询上衡量总体的召回率。总体数字看起来不错,但长尾部分却在悄无声息地失效。只有当用户将检索到的文本发回给人类,而人类说“我们不再那样说了”,或者更糟,“我们从未那样说过”时,Bug 才会浮出水面。
一个检索系统的优劣,取决于其嵌入模型与语料库签署的覆盖契约。没有阅读这份契约的团队使用的是针对别人的词汇校准的工具,而别人的词汇与你的词汇之间的差距,就是你的检索系统只要没有人去衡量,就会一直静默且“自信”地失败的地方。
会员专享
余下内容仅对会员开放。
会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
- —完整文章,包含未公开存档的部分
- —可落地的工作框架,附带权衡与决策依据
- —新文章抢先看,先于公开发布
随时取消 · 一次订阅,畅读全部