矢量搜索中的相关性

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

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

矢量搜索算法包括:

在索引中标记为searchable或在查询中标记为searchFields的矢量字段仅用于搜索和评分。

关于详尽的 KNN

穷举 KNN 计算所有数据点对之间的距离,并查找查询点的精确 k 最近的邻域。 由于算法不需要快速随机访问数据点,KNN 不使用 矢量索引大小 配额。 然而,它提供最近邻的全局集合。

详尽的 KNN 是计算密集型的,因此将其用于中小型数据集,或者当精度需求超过查询性能需求时。 另一个用例是生成数据集来评估 ANN 算法的召回率,因为穷尽的 KNN 可用于构建最近邻居的基准数据集。

关于 HNSW

HNSW 是一种 ANN 算法,针对具有未知或易失性数据分布的高召回率、低延迟应用程序进行优化。 在编制索引期间,HNSW 会创建额外的数据结构,用于将数据点组织到分层图中。 在查询执行期间,HNSW 会浏览此图以查找最相关的匹配项,从而实现最接近的邻居搜索。

HNSW 要求所有数据点驻留在内存中,以便进行快速随机访问,从而消耗 矢量索引大小 配额。 此设计平衡了搜索准确性与计算效率,并使 HNSW 适用于大多数方案,尤其是在搜索较大的数据集时。

HNSW 提供了多个无法调整的配置参数,以优化搜索应用程序的吞吐量、延迟和召回率。 例如,指定 HNSW 的字段还支持使用 查询请求 参数 "exhaustive": true进行完全的 KNN。 但是,为 exhaustiveKnn HNSW 查询编制索引的字段不支持 HNSW 查询,因为启用高效搜索的额外数据结构不存在。

关于 ANN

ANN 是一类算法,用于在矢量空间中查找匹配项。 此类算法使用不同的数据结构或数据分区方法来显著减少搜索空间并加速查询处理。

ANN 算法会牺牲一些准确性,但提供可缩放且更快的近邻检索,这使得它们非常适合在现代信息检索应用程序中平衡准确性和效率。 可以调整算法的参数,以微调搜索应用程序的召回率、延迟、内存和磁盘占用需求。

Azure AI 搜索将 HNSW 用于其 ANN 算法。

最近邻域搜索的工作原理

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

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

当矢量字段针对穷举 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-范数。

注意

如果并行运行两个或多个矢量查询,或者执行混合搜索,将矢量和文本查询合并在同一请求中,则使用倒数排名融合 (RRF) 对最终搜索结果进行评分。

矢量搜索结果中的评分

将计算分数并将其分配给每个匹配项,最高匹配项作为 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 结果,以将更多搜索结果输入聊天模型(如果使用)。

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

后续步骤