在 Fabric 中的 Cosmos DB 中为矢量数据编制索引

Fabric 中的 Cosmos DB 现在提供高效的矢量索引和搜索。 此功能旨在处理多模式、高维向量,从而在任何规模上实现高效准确的矢量搜索。 现在可以直接将矢量与数据一起存储在文档中。 数据库中的每个文档不仅可以包含传统的无架构数据,还可以包含多模式高维向量作为文档的其他属性。 这种数据和矢量的并置可以实现高效的索引和搜索,因为矢量与它们所代表的数据存储在同一个逻辑单元中。 将矢量和数据放在一起简化了数据管理、AI 应用程序体系结构以及基于矢量的操作效率。

Fabric 中的 Cosmos DB 提供选择矢量索引方法的灵活性:

  • 对于较小、集中的矢量搜索,“扁平”或 k 最近邻精确搜索(有时也称为暴力搜索)可以提供 100% 的检索召回率。 尤其是与查询筛选器和分区键结合使用时。

  • 一种量化扁平索引,使用基于 DiskANN 的量化方法压缩矢量,以提高 kNN 搜索的效率。

  • DiskANN 是一套由 Microsoft Research 开发的最先进的矢量索引算法,可在任何规模上实现高效、高精度的多模式矢量搜索。

Cosmos DB 中的矢量搜索可与所有其他支持的 NoSQL 查询筛选器和索引结合使用,并使用 WHERE 子句。 这种组合使矢量搜索成为应用程序最相关的数据。

此功能增强了 Cosmos DB 的核心功能,使其更适用于处理 AI 应用程序中的矢量数据和搜索要求。

什么是矢量存储?

矢量存储或向量数据库是一个旨在存储和管理矢量嵌入的数据库,它是高维空间中数据的数学表示形式。 在此空间中,每个维度对应于数据的一个特征,数万个维度可用于表示复杂的数据。 矢量在此空间中的位置表示其特征。 字词、短语或整个文档、图像、音频和其他类型的数据都可以矢量化。

矢量存储的工作原理是什么?

在矢量存储中,矢量搜索算法用于查询嵌入项以及为其编制索引。 一些已知的矢量搜索算法包括分层导航小型世界 (HNSW)、倒置文件(IVF)、DiskANN 等。借助矢量搜索,可根据数据特征而不是属性字段上的精确匹配项来查找相似的项。 这种方法在搜索相似文本、查找相关图像、提出建议甚至是检测异常等应用中很有用。 它用于通过嵌入 API 查询你使用机器学习模型创建的数据的向量嵌入。 嵌入 API 的示例包括 Azure OpenAI EmbeddingsAzure 上的 Hugging Face。 矢量搜索测量数据矢量与查询矢量之间的距离。 与查询矢量最接近的数据矢量是在语义上发现最相似的。

在 Fabric 中的 Cosmos DB 的集成向量数据库中,可以存储嵌入向量,并与原始数据一起编制索引和查询。 此方法避免了在单独的纯矢量数据库中复制数据产生的额外成本。 此外,此体系结构可将矢量嵌入和原始数据保存在一起,从而更好地促进多模式数据操作,并且可以实现更高的数据一致性、缩放和性能。

容器向量策略

在 Fabric 中使用 Cosmos DB 执行矢量搜索需要为容器定义向量策略。 此策略为数据库引擎提供重要信息,用于对容器文档中找到的矢量进行高效的相似性搜索。 如果选择此选项,此配置还会通知向量索引策略所需的信息。 包含的矢量策略中包含以下信息:

  • path:包含向量(必需)的属性。

  • datatype:矢量属性的数据类型。 支持的类型为 float32 (默认值), int8uint8

  • dimensions:路径中每个向量的维度或长度。 路径中的所有矢量应具有相同的维度数。 (默认值 1536)。

  • distanceFunction:用于计算距离/相似性的指标。 支持的指标包括:

    • cosine,其值从 $-1$ (最低相似) 到 $+1$ (最相似)。

    • dot product,其值从 $-\infty$ (最不相似) 到 $+\infty$ (最相似)。

    • euclidean,其值从 $0$ (最相似) 到 $+\infty$ (最不相似)。

注释

每个唯一路径最多可以有一个策略。 但是,如果多个策略都以不同的路径为目标,则可以指定这些策略。

容器矢量策略可描述为 JSON 对象。 下面是有效容器矢量策略的两个示例:

具有单个矢量路径的策略

{
  "vectorEmbeddings": [
    {
      "path": "/vector1",
      "dataType": "float32",
      "distanceFunction": "cosine",
      "dimensions": 1536
    }
  ]
}

具有两个矢量路径的策略

{
  "vectorEmbeddings": [
    {
      "path": "/vector1",
      "dataType": "float32",
      "distanceFunction": "cosine",
      "dimensions": 1536
    },
    {
      "path": "/vector2",
      "dataType": "int8",
      "distanceFunction": "dotproduct",
      "dimensions": 100
    }
  ]
}

有关容器向量策略设置的详细信息和示例,请参阅 矢量索引策略示例

矢量索引策略

矢量索引可在使用 系统函数执行矢量搜索时提高效率VectorDistance。 使用矢量索引时,矢量搜索的延迟降低、吞吐量变高、RU 消耗量降低。 可以指定以下类型的矢量索引策略:

DESCRIPTION 最大维度
flat 将向量存储在与其他已索引属性相同的索引上。 505
quantizedFlat 在索引上存储之前,量化(压缩)矢量。 此策略可以通过略微降低准确性来提高延迟和吞吐量。 4096
diskANN 基于 DiskANN 创建索引,实现快速高效的近似搜索。 4096

注释

quantizedFlatdiskANN索引要求插入至少 1,000 个向量。 此最小值是确保量化过程的准确性。 如果矢量少于 1,000 个,则会改为执行完全扫描,并导致矢量搜索查询的 RU 费用较高。

请注意以下几点:

  • flatquantizedFlat 类型的索引使用 Cosmos DB 的索引在矢量搜索期间存储和读取每个向量。 使用flat索引的矢量搜索是暴力搜索法,其准确性或召回率为100%。 也就是说,可以保证在数据集中找到最相似的向量。 但是,平面索引上的向量存在 505 维度限制。

  • quantizedFlat 索引在该索引上存储量化(压缩)矢量。 使用 quantizedFlat 索引的矢量搜索也是暴力搜索,但由于矢量在添加到索引之前进行了量化,因此其准确度可能略低于 100%。 但相较于 quantized flat 索引上的矢量搜索,使用 flat 的矢量搜索应会具有更低的延迟、更高的吞吐量和更低的 RU 成本。 对于较小的方案,或使用查询筛选器将矢量搜索缩小到相对较小的矢量集的方案,此索引是一个不错的选择。 当每个物理分区中要编制索引的矢量数约为 50,000 或更少时,建议使用 quantizedFlat。 但是,此建议只是一般准则,应测试实际性能,因为每个方案可能有所不同。

  • diskANN 索引是专门为利用 DiskANN 的矢量定义的单独索引,DiskANN 是 Microsoft Research 开发的高性能矢量索引算法套件。 DiskANN 索引可提供一些延迟最低、吞吐量最高且 RU 成本最低的查询,同时仍保持较高的准确度。 通常,如果每个物理分区的矢量数超过 50,000 个,DiskANN 通常是所有索引类型中性能最佳的选择。

下面是有效矢量索引策略的示例:

{
  "indexingMode": "consistent",
  "automatic": true,
  "includedPaths": [
    {
      "path": "/*"
    }
  ],
  "excludedPaths": [
    {
      "path": "/_etag/?"
    },
    {
      "path": "/vector1/*"
    }
  ],
  "vectorIndexes": [
    {
      "path": "/vector1",
      "type": "diskANN"
    }
  ]
}
{
  "indexingMode": "consistent",
  "automatic": true,
  "includedPaths": [
    {
      "path": "/*"
    }
  ],
  "excludedPaths": [
    {
      "path": "/_etag/?"
    },
    {
      "path": "/vector1/*",
    },
    {
      "path": "/vector2/*",
    }
  ],
  "vectorIndexes": [
    {
      "path": "/vector1",
      "type": "quantizedFlat"
    },
    {
      "path": "/vector2",
      "type": "diskANN"
    }
  ]
}

重要

在索引策略的 excludedPaths 部分中添加了向量路径,以确保插入操作的性能优化。 未添加向量路径到 excludedPaths 会导致矢量插入的请求单位费用和延迟增加。

重要

矢量策略或向量索引目前不支持通配符(*[])。

使用查询执行矢量搜索 VECTORDISTANCE

创建具有所需向量策略的容器,并将矢量数据插入到容器中后,可以使用查询中的 内置 VECTORDISTANCE 函数 执行矢量搜索。 下面是一个 NoSQL 查询的示例,该查询将相似度分数投影为别名 score,并按照从最相似到最不相似的顺序进行排序:

SELECT TOP 10
  c.title,
  VECTORDISTANCE(c.contentVector, [1,2,3]) AS score 
FROM
  container c
ORDER BY
  VECTORDISTANCE(c.contentVector, [1,2,3])   

重要

始终在查询的 TOP N 语句中使用 SELECT 子句。 否则,矢量搜索会尝试返回更多结果,导致查询花费的请求单位数(RU)多,延迟比必要时间高。