语义理解与向量相似度

向量相似度高,为什么检索结果仍然答非所问?从 Embedding 的训练目标讲起,分析余弦相似度、点积与欧氏距离,说明 BM25、混合检索、Rerank 和评估指标各自解决的问题。

·19 minEmbeddingRAG向量检索

用户在知识库里输入:“iPhone 充满电为什么用不了半天?”

系统找到了“苹果手机续航异常排查”。这个结果很合理。用户没有使用“续航”这个词,检索仍然跨过了表达方式的差异,找到了相关资料。

但同一套系统也可能把“电池健康度低于某个数值时的更换建议”排在第一位,而用户的手机刚买一周,实际问题是某个应用持续在后台运行。返回的内容讨论电池,向量分数也很高,却没有对应用户的具体情况。

语义检索的价值和局限,都在这两个结果里。

Embedding 可以把不同表达中的关联转化为可计算的表示。检索系统据此寻找候选文档,但“有关联”到“能回答”,中间还隔着型号、时间、使用条件,以及文档是否提供了足够证据。

理解语义理解、Embedding 和向量相似度之间的关系,需要把这些层次分开。否则,“模型懂意思,所以距离越近答案越准”就会成为一个看似顺畅、实际经不起排查的解释。

一、相似度公式不负责理解文字

先从最容易混淆的地方开始:向量相似度是一种数学计算,可以作用于许多不同来源的向量。

假设有两个向量:

a = [1, 2, 3]
b = [2, 4, 6]

无论这些数字来自文本模型、图像模型,还是人工填写,计算程序都可以求出它们的余弦相似度。这两个向量方向相同,余弦相似度为 1。计算过程不需要知道“手机”是什么,也不需要知道“退款”和“退货”之间有什么区别。

数字具有什么含义,取决于向量的构造方式。

传统信息检索就会把文档表示成向量。例如,TF-IDF 用词项作为坐标,用词频和逆文档频率计算权重。这样的向量主要保留词项分布,也能用于有意义的检索。它并不需要先获得现代语言模型意义上的语义能力,更不是一组随机数字。《Introduction to Information Retrieval》对 TF-IDF 向量表示的说明

因此,“语义理解是向量相似度能够生效的前提”需要加上限定。

如果希望相似度反映文本的语义关系,就需要一套能够保留相关语义特征的表示。相似度函数只负责对这套表示进行计算,无法补回编码阶段已经丢失的信息。

在常见的稠密向量检索中,可以把职责分成三层:

层次 需要解决的问题 典型产物
任务定义 什么样的文档算相关? 查询与文档的相关性标准
表示学习 怎样让这种相关性体现在向量中? Embedding 模型与文本向量
打分和检索 怎样从向量中找出候选文档? 相似度分数与候选列表

第一层经常被忽略。团队还没有说清“相关”的含义,就开始比较模型维度、向量数据库和相似度阈值。后面的调优很容易围绕一个模糊目标展开。

二、“语义接近”至少包含几种不同关系

“苹果手机”和“iPhone”在许多语境下可以对应同一类产品;“电池续航差”和“充一次电用不了多久”也可以表达相近的抱怨。但这些例子不足以概括实际检索。

在售后系统里,“怎么退款”和“如何退货”就不能直接当成同一个意图。

退款讨论资金返还,退货讨论商品退回。未发货订单可能只需要退款;换货需要寄回商品,却未必涉及退款。如果系统因为两句话向量接近,就把它们归入完全相同的流程,用户可能拿到错误的操作指引。

需要区分的关系至少有下面几种:

关系 示例 对检索的意义
近义或复述 “续航很差”与“充一次电用不了多久” 有助于跨表达匹配
主题相关 “退款进度”与“退货运费” 同属售后,但未必回答同一问题
问答相关 “退款通过什么渠道退回?”与“审核通过后按原支付渠道退回” 表述不同,却可能形成问题与答案
事实一致 “支持离线使用”与“断网后仍可使用” 两段内容可能支持同一判断
事实冲突 “支持离线使用”与“不支持离线使用” 主题接近,结论相反

这里还有一个容易误判的地方:矛盾文本也可能是有价值的检索结果。

如果任务是检查两份规格书是否冲突,“支持离线使用”和“不支持离线使用”就应该同时被找到。若任务是回答产品能否离线使用,系统还必须判断两份资料各自对应的版本和发布时间。

文档是否相关,取决于任务。相似度本身无法替业务定义这个目标。

问答检索追求的是可回答性

用户问“iPhone 电池能用多久”,可能在问单次充电续航,也可能在问电池几年后需要更换。这句话本身就有歧义。

下面几类文档都可能进入候选列表:

  • 某型号在规定测试条件下的续航记录;
  • 电池老化与循环次数的说明;
  • 后台耗电排查方法;
  • 电池更换服务介绍。

模型即使把这些材料都判断为相关,也没有解决用户究竟想问什么。系统可以根据会话上下文收窄问题;信息不足时,也可以让用户补充型号或明确关注单次续航还是使用寿命。

这类问题不能通过把余弦相似度换成点积来解决。查询中的信息缺失,需要在查询理解和交互中处理。

三、Embedding 如何学到“哪些文本应该接近”

“模型先理解文本,再把含义编码成向量”适合作为入门比喻,但容易让人误以为模型内部存在两个独立步骤:先生成一份完整的语义解释,再把解释压缩成数字。

常见的文本编码器直接把输入映射为表示:

文本 → 分词 → 神经网络计算 → 池化或投影 → 文本向量

模型参数来自训练。我们所说的“语义能力”,体现在它能否在不同措辞、上下文和任务中学到稳定的关系,不能仅凭它输出了一串数字就确认。

Sentence-BERT 的一个重要贡献,就是通过专门的训练方式得到适合句子比较的向量。语言模型拥有丰富的内部表示,并不意味着任意取一层输出、做一次平均,就能得到可靠的句子相似度。Sentence-BERT 论文

训练样本决定模型重视什么

以检索任务为例,训练数据可以包含一个查询、一篇相关文档和若干不相关文档。训练过程希望模型提高相关文档的得分,并降低其他候选的得分。

一种常见的对比学习目标可以写成:

L=loges(q,d+)/τes(q,d+)/τ+jes(q,dj)/τ\mathcal{L}=-\log\frac{e^{s(q,d^+)/\tau}} {e^{s(q,d^+)/\tau}+\sum_j e^{s(q,d_j^-)/\tau}}

其中,q 是查询,d⁺ 是相关文档,dⱼ⁻ 是负样本,s 是打分函数,τ 是温度参数。

公式表达的是一个相对排序目标:在这一组候选里,相关文档应该得到更高的分数。E5 等文本表示模型就使用了对比学习训练方法。E5 论文

负样本的选择会影响模型学到的区分能力。

对“退款什么时候到账”这个问题,用“如何更换手机壁纸”作为负样本,模型很容易完成区分。换成“退货包裹什么时候签收”,两段内容都涉及售后流程,模型就必须进一步关注用户要查的是资金到账还是物流签收。

后一类容易混淆的样本通常更有训练价值。但标注也更容易出错:一篇退货说明可能同时包含退款到账时间,不能只看标题就把它判成负样本。

“语义相近的文本在空间里靠近”因此应当被理解为训练希望实现的性质。它能实现到什么程度,取决于数据、训练目标和应用场景。

查询与文档可以采用不同的编码方式

查询通常很短,文档则可能包含背景、条件和答案。两者承担的角色不同。

双编码器检索可以分别计算:

u=fq(q),v=fd(d)u=f_q(q),\qquad v=f_d(d)

查询编码器与文档编码器可以共享参数,也可以分别训练;即使共享参数,也可能通过不同的前缀或指令区分输入角色。DPR 就采用了面向查询和段落的双编码器框架。DPR 论文

这也解释了一个实际问题:余弦公式虽然是对称的,整个检索任务仍然可以是不对称的。把查询与文档的角色交换后,输入处理和得到的表示可能发生变化。

部署时需要遵循模型的输入约定。例如,multilingual-e5-large 的模型卡要求在检索场景中分别使用 query:passage: 前缀。遗漏前缀会改变模型接收的输入形式,影响效果。Multilingual E5 模型说明

这属于模型接口的一部分,应当与模型版本、最大输入长度一起记录下来。

四、余弦相似度、点积和欧氏距离有什么区别

编码完成后,检索系统还需要选择打分函数。常见选择是余弦相似度、点积和欧氏距离。

对于两个非零向量,余弦相似度为:

cos(u,v)=uvuv\operatorname{cos}(u,v)=\frac{u^\top v}{\|u\|\|v\|}

这里的 u · v 表示点积,‖u‖ 表示向量 u 的欧氏范数,也就是向量长度。

余弦相似度衡量方向接近程度,理论范围是 [-1, 1]。值接近 1 表示方向接近,值接近 0 表示接近正交。负值表示方向夹角超过 90 度,不能直接解释为两段话在逻辑上互相否定。

点积为:

sdot(u,v)=uv=iuivis_{\mathrm{dot}}(u,v)=u^\top v=\sum_i u_i v_i

它同时受到方向和向量长度的影响。欧氏距离则计算两点之间的直线距离:

d(u,v)=i(uivi)2d(u,v)=\sqrt{\sum_i(u_i-v_i)^2}

相似度通常越大越靠前,距离通常越小越靠前。把两种排序方向混淆,足以让一个配置正确的模型返回完全错误的结果。

若查询和文档向量都做了单位长度归一化,则:

uv=cos(u,v)uv2=22cos(u,v)\begin{aligned} u^\top v&=\operatorname{cos}(u,v)\\ \|u-v\|^2&=2-2\operatorname{cos}(u,v) \end{aligned}

在这个条件下,精确计算时,点积、余弦相似度和欧氏距离会产生等价排序。Faiss 文档也说明了这一关系,并提醒其 L2 返回值是平方欧氏距离。Faiss 距离与度量文档

没有归一化时,这种等价关系不成立。一个依据点积目标训练的模型,也不应未经验证就改成归一化后的余弦检索,因为向量长度可能参与了原来的打分。

实际排查时,应先确认模型推荐的打分方式,再检查入库向量与查询向量是否采用相同的处理。数据库中的“分数”还可能经过转换,不能只凭字段名称判断其数学含义。

0.85 不是“85% 的概率相关”

余弦相似度是几何量,没有天然的概率解释。

同样是 0.85,在不同模型、语料和任务中可能对应不同的相关性水平。更换模型、输入前缀或分块方式后,原来的阈值也可能失效。

E5 模型卡专门解释过其相似度分数较集中的现象,并指出排序中的相对关系比绝对数值更值得关注。这是具体模型的行为,不能推广成所有 Embedding 模型都使用同一分数区间。Multilingual E5 模型说明

对于“是否返回答案”这样的决策,需要在真实标注数据上观察相关与不相关结果的分布,再评估阈值对应的漏检和误检。把别人的 0.8 阈值复制过来,没有可靠依据。

Top-K 检索也不会自动判断知识库有没有答案。只要候选数量足够,它就可以返回 K 条结果,即使这些结果都不满足问题要求。

五、高相似度为什么仍然会带来错误答案

相似度高而答案不合用,往往对应不同类型的故障。把它们都归为“模型不够聪明”,会掩盖真正应该修改的环节。

主题相同,关键条件不同

设想一组用于测试的设备说明:

A:X100 支持离线使用。
B:X100 不支持离线使用。
C:X100 Pro 支持离线使用。
D:X100 在升级到 2.3 版固件后支持离线使用。

这些是人为构造的测试句,不代表任何真实产品。

四句话的主题和措辞接近,但型号、否定词和版本条件决定了答案。对于“运行 2.1 版固件的 X100 能否离线使用”,只找到“支持离线使用”这几个词远远不够。

Embedding 模型可能识别这些差别,也可能没有把它们反映为足够明显的分数间隔。需要在测试集中单独检查,不能从一般语义相似度成绩推断。

能可靠提取的型号、地区、生效日期等字段,可以参与结构化过滤。模型负责处理自然语言关联,明确的业务条件则需要在检索或验证阶段落实。

分块把条件和结论拆开了

一份售后文档可能这样写:

本节适用于尚未发货的订单。

用户提交申请后,平台按以下流程处理退款……

如果分块只保留第二段,查询“已发货订单如何退款”时,这个片段可能得到不错的分数。模型接收到的文本已经缺少适用条件,再强的编码器也无法从中恢复确定的信息。

因此,分块需要保留必要的标题、条件和指代关系。可以让每个片段携带所属章节,也可以先检索较小片段,再读取相邻段落或父章节。

需要保留多少上下文,应由文档结构和问题类型决定。把所有材料都切成同一长度,并不能保证每块都有完整含义。

文档表达清楚,但内容已经过期

一篇旧版接口说明可能写得完整、术语匹配准确,因此容易排在前面。相似度不会自动把“当前有效”编码成稳定的业务约束。

这类问题需要文档版本、生效时间和替代关系。查询没有指定版本时,系统应有明确的默认规则;指定旧版本时,又不能把历史文档全部过滤掉。

在知识库问答中,来源正确、版本适用和语义相关必须同时满足。它们不能由一个相似度数字代替。

向量索引漏掉了本该进入候选的文档

还有一种错误发生在编码之后。

大规模系统常使用近似最近邻搜索,以一定的召回损失换取速度和资源效率。此时,即便模型把正确文档放到了合适的位置,索引也可能没有把它返回。

可以在可控规模的数据集上,用同一批向量做一次穷举检索,再与近似索引比较。

如果穷举结果里也没有正确文档,优先检查表示、分块和查询;如果穷举可以找到、近似索引却漏掉,就应检查索引参数、量化和过滤执行方式。

这是两种不同的误差。混在一起调,可能为了补偿索引问题而更换模型,也可能为了模型排序问题不断扩大搜索范围。

六、关键词检索为什么仍然值得保留

把关键词检索描述成“只认字、不懂意思”,容易低估它在工程系统中的作用。

用户搜索错误码 PAYMENT_4097、函数名 createInvoice 或产品型号 X100-Pro 时,通常希望找到包含准确标识的资料。一个讨论相似问题、却对应另一个标识的文档,往往没有帮助。

BM25 也不只是统计重合了几个词。它结合词项的区分度、词频饱和与文档长度进行打分,因此能成为稳定的全文检索基线。《Introduction to Information Retrieval》对 BM25 的说明

不过,关键词检索同样需要配置。分词器可能拆坏错误码,中文分词可能影响短语匹配,大小写处理和字段类型也会改变结果。必须精确匹配的标识,适合使用专门字段,不宜完全依赖全文打分。

全文检索还可以加入同义词、词形处理和查询扩展。所以,“iPhone”和“苹果手机”无法通过关键词系统关联,也不是一个必然结论。能否匹配,取决于整个系统的分析和扩展机制。

稀疏表示与稠密表示同样不等于“没有语义”与“有语义”。学习型稀疏检索也能通过模型生成词项权重或扩展词项;稠密向量则可能保留大量主题信号,却忽略任务要求的细微条件。

BEIR 在跨领域检索评估中发现,BM25 是有竞争力的基线,稠密检索的收益具有任务差异。这项研究支持的工程判断是:需要用自己的数据比较方法,不能把“用了 Embedding”当成效果保证。BEIR 论文

七、混合检索与 Rerank 分别补什么

词项检索和稠密检索通常会漏掉不同的材料。

用户描述“钱一直没退回来”时,向量检索有机会找到“退款到账延迟”;用户输入明确错误码时,词项检索可以利用精确标识。混合检索把不同通道的候选合并,目的是提高覆盖率。

问题在于,两路原始分数通常不在同一个尺度上。直接计算“BM25 分数加余弦相似度”,很可能只是让数值范围较大的通道主导结果。

一种常用办法是 Reciprocal Rank Fusion,简称 RRF。它根据名次融合:

RRF(d)=i:dLi1c+ranki(d)\operatorname{RRF}(d)=\sum_{i:\,d\in L_i} \frac{1}{c+\operatorname{rank}_i(d)}

其中,Lᵢ 是第 i 路候选列表,rankᵢ(d) 是文档 d 在该列表中的名次,从 1 开始;c 是控制前排优势的常数。没有出现在某一路列表中的文档,不获得那一路贡献。这样可以避开原始分数不可直接比较的问题。Elasticsearch 的 RRF 文档

RRF 仍然受候选窗口和各通道质量影响。它能融合排名,却无法判断两个结果是否属于同一段重复内容,也不会自动发现文档已经失效。

重排让模型同时阅读问题与候选文档

初步召回需要处理大量文档,因此常把查询和文档分别编码。文档向量可以预先计算,这使检索具备较好的效率。

常见的 Cross-Encoder 重排器则把查询与一篇候选文档一起输入模型,让两段文本在计算中发生交互,再输出相关性分数。它适合对较小的候选集进一步排序。Sentence Transformers 检索与重排文档

但重排只能处理已经召回的内容。正确文档没有进入候选集,排序模型无从把它提升到前面。

重排也会遇到领域不匹配、长文截断和条件判断错误。某个重排器在公开问答数据上表现不错,不代表它能辨别内部产品编号或复杂业务规则。

它输出的分数也未必是概率。有的模型返回原始分数,有的经过 Sigmoid 映射到 0 到 1;数值落在这个区间,并不等于已经完成了概率校准。Sentence Transformers 重排模型说明

因此,加入 Rerank 后,应当比较前后排序质量及延迟。不能仅凭多了一层模型,就认定系统更准确。

八、用什么指标判断系统有没有进步

检索优化需要一批能够说明问题的标注样本。

每条样本至少应包括查询、相关文档及相关程度;业务问题还需要适用版本或其他必要条件。数据集里也要包含知识库没有答案的查询,否则系统只会接受“总能找出一个答案”的考验。

样本应覆盖不同难度:同义改写、精确标识,以及否定、数字和条件变化。前面的 X100 示例就可以扩展成一组最小差异测试,逐项检查系统是否因为只差一个词或一个版本号而返回错误结果。

评估时需要把不同阶段分开。

阶段 可以观察的指标 回答的问题
初步召回 Recall@K 标注相关文档有多少进入候选集?
首条有效结果 MRR@K 第一条相关结果排得够不够靠前?
整体排序 nDCG@K 更有用的文档是否排在更前面?
近似索引 相对精确检索的近邻召回率 索引额外漏掉了多少向量近邻?
问答结果 证据覆盖、回答正确性、无答案时的行为 最终回答是否有足够依据?

这里的“近邻召回率”和业务相关文档的 Recall@K 不应混用。

一个近似索引可能准确找到了向量空间里的近邻,但这些近邻并不是业务上相关的文档。反过来,模型表示有效,近似搜索却可能漏掉重要候选。两种指标分别衡量不同环节。

评估重排时也要保留真实的召回结果。为了方便测试而把正确文档手动加入候选集,可以考察重排器自身的能力,却无法代表线上系统的端到端效果。

先建立能够复现的基线

一套便于比较的实验可以从三个版本开始:

  1. BM25;
  2. 稠密向量检索;
  3. 两者混合,再根据需要加入重排。

比较时固定文档版本、标注集和分块方式,把候选数量与计算预算记录下来。如果一个方案召回了更多候选,也消耗了更多延迟,质量提升需要连同成本一起看。

调参使用验证集,最后再用独立测试集检查结果。反复查看同一批错误并逐条修补,可能让系统记住测试集,却没有改善新查询。

平均分之外,还要查看不同查询类别。整体 nDCG 提高,可能掩盖产品型号查询的退步;自然语言问答变好,也可能伴随错误码检索变差。对业务影响大的查询,应单独设定验收标准。

九、检索结果必须回到原文验证

在检索增强生成系统中,候选文档还要交给生成模型组织答案。到了这一步,相似度的作用已经完成了大半:它帮助系统缩小阅读范围。

接下来需要检查的是证据。

继续看“运行 2.1 版固件的 X100 能否离线使用”这个问题。即使系统召回了四篇都在讨论离线功能的文档,也不能让生成模型挑一句最顺口的回答。

它需要读出文档对应的型号与版本,确认“升级后支持”是否适用于用户当前环境,并检查是否存在更新的说明。证据不足时,回答应该说明缺少哪项信息;资料互相冲突时,需要保留冲突及来源,不能把两段话拼成一个没有出处的结论。

对于需要多份证据的问题,单篇文档相关还不够。回答“升级后有哪些兼容性变化”,可能同时需要版本说明、迁移指南和已知问题列表。候选集里即使有一篇高度相关的发布公告,也可能缺少完成回答所需的其余材料。

文档去重和结果多样性因此也会影响质量。如果前十条只是同一段内容的重复副本,模型能读到的有效信息仍然有限。

十、把一次失败拆成可以验证的问题

当系统再次返回一个高分但无用的结果,可以沿着下面的顺序排查:

先打开实际入库的文本,确认答案确实存在,且没有在解析、截断或分块时丢失条件。随后核对查询与文档使用的模型版本、输入格式和归一化方式。

再用精确向量检索与线上索引比较,区分表示问题和近似搜索损失。正确文档进入候选集后,检查融合与重排是否把它压到了后面;排名没有问题,就继续检查生成模型是否忽略了原文中的限制。

这条排查路径对应的是一组可以观察的结果:

  • 文档中有没有答案;
  • 模型有没有把它排进合理范围;
  • 索引有没有把它取回来;
  • 排序有没有保留它;
  • 最终回答有没有忠实使用它。

每一步都能留下证据,也对应不同的修改位置。

回到最初那句“iPhone 充满电为什么用不了半天”,一个合格系统应当先利用 Embedding 找到续航与耗电相关的材料,再识别用户尚未提供的型号、设备状态和使用条件。等这些信息足够,系统才能从通用电池知识收窄到适用的排查步骤。

验收时,应当观察它是否找到适用文档、是否保留关键条件、是否给出有出处的判断。分数负责排序,答案仍需要原文和任务要求共同检验。