矢量搜索中的相关性

在执行矢量查询期间,搜索引擎会查找相似的矢量,以找到要在搜索结果中返回的最佳候选项。 根据矢量内容的索引编制方式,搜索相关匹配项的过程要么是穷举式的,要么仅限于附近邻居以加快处理速度。 找到候选项后,将使用相似性指标根据匹配的强度对每个结果评分。

本文介绍用于查找相关匹配项和用于评分的相似性指标的算法。 本文还介绍了搜索结果不符合预期时关于提高相关性的提示。

矢量搜索算法包括穷举 k 最近的邻域 (KNN) 和分层可导航小世界 (HNSW)。

只有索引中标记为 searchable 或查询中标记为 searchFields 的向量字段才用于搜索和评分。

何时使用穷举 KNN

穷举 KNN 计算所有数据点对之间的距离,并查找查询点的精确 k 最近的邻域。 它适用于高召回率至关重要,并且用户愿意接受查询延迟弊端的场景。 由于它是一种计算密集型算法,因此对于中小型数据集,或者当精度要求超过查询性能考量时,请使用穷举 KNN。

另一个用例是生成数据集来评估近似最近的邻域算法召回率。 穷举 KNN 可用于生成最近邻域的事实数据集。

何时使用 HNSW

在编制索引期间,HNSW 会创建额外的数据结构以加快搜索速度,将数据点组织到分层图形结构中。 HNSW 有多个配置参数,可以优化这些参数来实现搜索应用程序的吞吐量、延迟和召回率目标。 例如,在查询时,可以指定穷举搜索选项,即使矢量字段针对 HNSW 编制了索引。

在查询执行期间,HNSW 通过浏览图形来启用快速邻域查询。 此方法在搜索准确性和计算效率之间取得平衡。 由于 HNSW 在搜索较大数据集时的效率较高,建议将其用于大多数方案。

最近邻域搜索的工作原理

矢量查询针对由同一嵌入模型生成的矢量组成的嵌入空间执行。 通常,查询请求中的输入值将馈送到在矢量索引中生成了嵌入的同一机器学习模型。 输出是同一嵌入空间中的矢量。 由于相似的矢量紧密地聚类到一起,因此查找匹配项相当于查找最接近查询矢量的矢量,并将相关文档作为搜索结果返回。

例如,如果查询请求与酒店有关,则模型会将查询映射到表示有关酒店的文档的矢量聚类中某个位置处存在的矢量。 根据相似性指标识别哪些矢量与查询最相似可以确定哪些文档最相关。

当矢量字段针对穷举 KNN 编制了索引时,查询将针对“所有邻居”执行。 对于针对 HNSW 编制了索引的字段,搜索引擎将使用 HNSW 图形来搜索矢量索引中的一部分节点。

创建 HNSW 图形

在索引编制期间,搜索服务将构造 HNSW 图。 在 HNSW 图形中为新矢量编制索引的目标是,以一种可以实现高效最近邻域搜索的方式将此矢量添加到图形结构中。 以下步骤概述了这一过程:

  1. 初始化:从一个空的 HNSW 图形开始,如果索引不是新索引,则从现有的 HNSW 图形开始。

  2. 入口点:这是分层图形的最高级别,充当索引编制的起点。

  3. 添加到图形:不同的分层级别代表图形的不同粒度,级别越高,全局性越大,级别越低,粒度越小。 图形中的每个节点代表一个矢量点。

    • 每个节点最多连接到附近的 m 个邻居。 这是 m 参数。

    • 视为候选连接的数据点的数量由 efConstruction 参数控制。 此动态列表形成了现有图形中的最近点集,供算法考虑。 efConstruction 值越大,要考虑的节点就越多,这通常会导致每个矢量出现更密集的局部邻域。

    • 这些连接使用配置的相似性 metric 来确定距离。 某些连接是跨不同分层级别进行连接的“远距离”连接,在图形中会创建快捷方式来增强搜索效率。

  4. 图形修剪和优化:这可以在为所有矢量编制索引之后发生,并可以提高 HNSW 图形的可导航性和效率。

矢量查询导航分层图形结构以扫描匹配项。 下面总结了该过程的步骤:

  1. 初始化:算法在分层图形的最高级别启动搜索。 此入口点包含用作搜索起点的矢量集。

  2. 遍历:接下来,此算法从高到低逐级别遍历图形,并根据配置的距离指标(例如余弦相似性)选择与查询矢量较接近的候选节点。

  3. 修剪:为了提高效率,此算法通过仅考虑可能包含最近邻域的节点来修剪搜索空间。 这是通过维护潜在候选项的优先级队列并随着搜索的进展不断更新该队列来实现的。 该队列的长度由参数 efSearch 配置。

  4. 细化:随着算法转向更低、更精细的级别,HNSW 将考虑查询附近的其他邻居,这使得候选矢量集得以细化,从而提高了准确度。

  5. 完成:当识别到所需数量的最近邻域或满足其他停止条件时,搜索即告完成。 所需的最近邻域数量由查询时参数 k 控制。

用于度量接近度的相似性指标

该算法将查找候选矢量来评估相似性。 为了执行此任务,相似性指标计算会将候选矢量与查询矢量进行比较,并度量相似性。 该算法会跟踪其找到的最相似矢量的有序集,当算法完成时,该集将形成排名结果集。

指标 说明
cosine 此指标度量两个矢量之间的角度,并且不受不同矢量长度的影响。 从数学上讲,它会计算两个矢量之间的角度。 余弦是 Azure OpenAI 嵌入模型使用的相似性指标,因此,如果你使用的是 Azure OpenAI,请在矢量配置中指定 cosine
dotProduct 此指标度量每一对(两个矢量)的长度及其之间的角度。 从数学上讲,它会计算矢量的大小及其之间的角度的乘积。 对于规范化矢量,这与 cosine 相似性相同,但性能稍高一些。
euclidean (也称为 l2 norm)此指标度量两个矢量之间的矢量差长度。 从数学上讲,它会计算两个矢量之间的欧几里得距离,即两个矢量之差的 l2-范数。

矢量搜索结果中的评分

将计算分数并将其分配给每个匹配项,最高匹配项作为 k 结果返回。 @search.score 属性包含分数。 下表显示了分数的范围。

搜索方法 参数 评分指标 范围
矢量搜索 @search.score 余弦 0.333 - 1.00

对于 cosine 指标,请务必注意,计算 @search.score 不是查询向量和文档向量之间的余弦值。 Azure AI 搜索将应用转换,使评分函数单调递减,这意味着,随着相似性变差,评分值始终会减小。 这种转换确保搜索分数可用于排名目的。

相似性评分存在一些细微差别:

  • 余弦相似性定义为两个矢量之间角度的余弦。
  • 余弦距离定义为 1 - cosine_similarity

若要创建单调递减函数,需将 @search.score 定义为 1 / (1 + cosine_distance)

需要余弦值而不是合成值的开发人员可以使用公式将搜索评分转换回余弦距离:

double ScoreToSimilarity(double score)
{
    double cosineDistance = (1 - score) / score;
    return  -cosineDistance + 1;
}

使用原始余弦值对于设置阈值来剪裁低质量结果的自定义解决方案非常有用。

相关性优化提示

如果未获得相关结果,请尝试更改查询配置。 对于矢量查询,没有特定的优化功能,例如计分概要文件或字段或术语提升:

  • 请尝试区块大小和重叠。 尝试增加区块大小并确保有足够的重叠来保留区块之间的上下文或连续性。

  • 对于 HNSW,请尝试不同级别的 efConstruction 来更改邻近图形的内部组合。 默认值为 400。 范围为 100 到 1,000。

  • 增加 k 结果,以将更多搜索结果输入聊天模型(如果使用)。

  • 尝试使用语义排名进行混合查询。 在基准测试中,这种组合始终生成了最相关的结果。

后续步骤