你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

基于 vCore 的 Azure Cosmos DB for MongoDB 中的矢量存储

适用对象: MongoDB vCore

使用 Azure Cosmos DB for MongoDB (vCore) 中的集成矢量数据库将基于 AI 的应用程序与 Azure Cosmos DB 中存储的数据无缝连接。 此集成可以包括使用 Azure OpenAI 嵌入生成的应用。 通过原生集成的矢量数据库,你可以高效地存储、查询直接存储在 Azure Cosmos DB for MongoDB vCore 中的高维矢量数据以及创建矢量数据时所基于的原始数据,并为其编制索引。 它使你无需将数据传输到其他矢量存储,也不会产生额外费用。

什么是矢量存储?

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

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

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

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

Azure Cosmos DB for MongoDB (vCore) 提供可靠的矢量搜索功能,允许跨复杂数据集执行高速相似性搜索。 若要在 Azure Cosmos DB for MongoDB 中执行矢量搜索,首先需要创建矢量索引。 Cosmos DB 目前支持三种类型的矢量索引:

  • DiskANN(推荐类型):非常适合大规模数据集,利用 SSD 实现高效的内存使用,同时在近似最近邻 (ANN) 搜索中保持高召回率。
  • HNSW:适用于需要高召回率的中等大小的数据集,具有可在准确性和资源效率之间实现平衡的基于图形的结构。
  • IVF:使用聚类分析优化在大型数据集中的搜索速度,从而将搜索集中在目标群集内以提高速度性能。

DiskANN 索引在 M40 层及更高层上可用。 若要创建 DiskANN 索引,请按照以下模板将 "kind" 参数设置为 "vector-diskann"

{ 
    "createIndexes": "<collection_name>",
    "indexes": [
        {
            "name": "<index_name>",
            "key": {
                "<path_to_property>": "cosmosSearch"
            },
            "cosmosSearchOptions": { 
                "kind": "vector-diskann", 
                "dimensions": <integer_value>,
                "similarity": <string_value>,
                "maxDegree" : <integer_value>, 
                "lBuild" : <integer_value>, 
            } 
        } 
    ] 
}
字段 类型​​ 说明
index_name string 索引的唯一名称。
path_to_property string 包含矢量的属性的路径。 此路径可以是顶级属性或属性的点表示法路径。 矢量必须是要编制索引并在矢量搜索结果中使用的 number[]。 使用另一种类型(如 double[]),可防止对文档编制索引。 不会在矢量搜索的结果中返回未编制索引的文档。
kind string 要创建的矢量索引的类型。 选项为 vector-ivfvector-hnswvector-diskann
dimensions integer 矢量相似度的维度数。 DiskANN 最多支持 2000 个维度,未来计划支持 40,000 个以上。
similarity string 用于索引的相似性指标。 可能的选项包括 COS(余弦距离)、L2(欧几里德距离)和 IP(内积)。
maxDegree integer 图形中每个节点的最大边缘数。 此参数的范围为 20 到 2048(默认值为 32)。 较高的 maxDegree 适用于具有高维性和/或高准确度要求的数据集。
lBuild integer 设置在 DiskANN 索引构造期间计算的候选近邻数。 此参数的范围为 10 到 500(默认值为 50),可在准确性与计算开销之间实现平衡:较高的值可提高索引质量和准确性,但也会增加生成时间

注意

在 Azure 订阅的“预览功能”选项卡中启用“基于 vCore 的 Azure Cosmos DB for MongoDB 的 DiskANN 矢量索引”功能。 在此处了解有关预览功能的详细信息。

使用 DiskANN 执行矢量搜索

若要执行矢量搜索,请使用 $search 聚合管道阶段,并使用 cosmosSearch 运算符进行查询。 DiskANN 允许使用可选的筛选条件(例如地理空间或基于文本的筛选器)跨大型数据集进行高性能搜索

{
  "$search": {
    "cosmosSearch": {
      "path": "<path_to_property>",
      "query": "<query_vector>",  
      "k": <num_results_to_return>,  
      "filter": {"$and": [
        { "<attribute_1>": { "$eq": <value> } },
        {"<location_attribute>": {"$geoWithin": {"$centerSphere":[[<longitude_integer_value>, <latitude_integer_value>], <radius>]}}}
      ]}
    }
  }
},
字段 类型​​ 说明
lSearch integer 指定用于搜索的动态候选列表的大小。 默认值为 40,可配置的范围为 101000。 增加该值可提高召回率,但可能会降低搜索速度。
k integer 定义要返回的搜索结果数。 k 值必须小于或等于 lSearch

使用带筛选功能的 DiskANN 索引的示例

将矢量添加到数据库

若要将矢量搜索与地理空间筛选器一起使用,请添加同时包含矢量嵌入和位置坐标的文档。 你可以使用自己的模型、Azure OpenAI 嵌入或其他 API(例如 Azure 上的 Hugging Face)创建嵌入

from pymongo import MongoClient

client = MongoClient("<your_connection_string>")
db = client["test"]
collection = db["testCollection"]

documents = [
    {"name": "Eugenia Lopez", "bio": "CEO of AdventureWorks", "is_open": 1, "location": [-118.9865, 34.0145], "contentVector": [0.52, 0.20, 0.23]},
    {"name": "Cameron Baker", "bio": "CFO of AdventureWorks", "is_open": 1, "location": [-0.1278, 51.5074], "contentVector": [0.55, 0.89, 0.44]},
    {"name": "Jessie Irwin", "bio": "Director of Our Planet initiative", "is_open": 0, "location": [-118.9865, 33.9855], "contentVector": [0.13, 0.92, 0.85]},
    {"name": "Rory Nguyen", "bio": "President of Our Planet initiative", "is_open": 1, "location": [-119.0000, 33.9855], "contentVector": [0.91, 0.76, 0.83]}
]

collection.insert_many(documents)

创建 DiskANN 矢量索引

以下示例演示如何设置带有筛选功能的 DiskANN 矢量索引。 这包括为相似性搜索创建矢量索引、添加具有矢量和地理空间属性的文档,以及用于其他筛选的索引字段。

db.command({
    "createIndexes": "testCollection",
    "indexes": [
        {
            "name": "DiskANNVectorIndex",
            "key": {
                "contentVector": "cosmosSearch"
            },
            "cosmosSearchOptions": {
                "kind": "vector-diskann",
                "dimensions": 3,
                "similarity": "COS",
                "maxDegree": 32,
                "lBuild": 64
            }
        },
        { 
            "name": "is_open",
            "key": { 
                "is_open": 1 
            }      
        },
        {
            "name": "locationIndex",
            "key": {
                "location": 1
            }
        }
    ]
})

此命令将针对 exampleCollection 中的 contentVector 字段创建 DiskANN 矢量索引,从而支持相似性搜索。 它还添加了:

  • 针对 is_open 字段的索引,使你可以根据商家是否营业来筛选结果。
  • 针对 location 字段的地理空间索引,将按地理邻近度进行筛选。

若要在特定地理半径内查找具有相似矢量的文档,请指定相似性搜索的 queryVector,并包括地理空间筛选器。

query_vector = [0.52, 0.28, 0.12]
pipeline = [
    {
        "$search": {
            "cosmosSearch": {
                "path": "contentVector",
                "vector": query_vector,
                "k": 5,
                "filter": {
                    "$and": [
                        {"is_open": {"$eq": 1}},
                        {"location": {"$geoWithin": {"$centerSphere": [[-119.7192861804, 34.4102485028], 100 / 3963.2]}}}
                    ]
                }
            }
        }
    }
]

results = list(collection.aggregate(pipeline))
for result in results:
    print(result)

在此示例中,矢量相似性搜索将根据指定的 COS 相似性指标返回最接近的 k 个矢量,同时筛选结果以仅包含 100 英里半径内的营业商家。

[
  {
    similarityScore: 0.9745354109084544,
    document: {
      _id: ObjectId("645acb54413be5502badff94"),
      name: 'Eugenia Lopez',
      bio: 'CEO of AdventureWorks',
      is_open: 1,
      location: [-118.9865, 34.0145],
      contentVector: [0.52, 0.20, 0.23]
    }
  },
  {
    similarityScore: 0.9006955671333992,
    document: {
      _id: ObjectId("645acb54413be5502badff97"),
      name: 'Rory Nguyen',
      bio: 'President of Our Planet initiative',
      is_open: 1,
      location: [-119.7302, 34.4005],
      contentVector: [0.91, 0.76, 0.83]
    }
  }
]

此结果显示与 queryVector 最相似的文档,限制条件为 100 英里半径范围内且营业的商家。 每个结果都包括相似度分数和元数据,展示了 Cosmos DB for MongoDB 中的 DiskANN 如何支持合并的矢量和地理空间查询,以提供丰富的位置敏感型搜索体验。

获取矢量索引定义

要从集合中检索矢量索引定义,请使用 listIndexes 命令:

db.exampleCollection.getIndexes();

在此示例中,返回了 vectorIndex,其中包含用于创建索引的所有 cosmosSearch 参数:

[
  { v: 2, key: { _id: 1 }, name: '_id_', ns: 'test.exampleCollection' },
  {
    v: 2,
    key: { vectorContent: 'cosmosSearch' },
    name: 'vectorSearchIndex',
    cosmosSearch: {
      kind: <index_type>, // options are `vector-ivf`, `vector-hnsw`, and `vector-diskann`
      numLists: 3,
      similarity: 'COS',
      dimensions: 3
    },
    ns: 'test.exampleCollection'
  }
]

筛选的矢量搜索(预览版)

现在,可以使用任何受支持的查询筛选器(例如 $lt$lte$eq$neq$gte$gt$in$nin$regex)执行矢量搜索。 在 Azure 订阅的“预览功能”选项卡中启用“筛选矢量搜索”功能。 在此处了解有关预览功能的详细信息。

首先,除了矢量索引之外,还需要为筛选器定义索引。 例如,可以对属性定义筛选器索引

db.runCommand({ 
     "createIndexes": "<collection_name",
    "indexes": [ {
        "key": { 
            "<property_to_filter>": 1 
               }, 
        "name": "<name_of_filter_index>" 
    }
    ] 
});

接下来,可以将 "filter" 术语添加到矢量搜索,如下所示。 在此示例中,筛选器会查找 "title" 属性不在 ["not in this text", "or this text"] 列表中的文档。


db.exampleCollection.aggregate([
  {
      '$search': {
          "cosmosSearch": {
              "vector": "<query_vector>",
              "path": <path_to_vector>,
              "k": num_results,
              "filter": {<property_to_filter>: {"$nin": ["not in this text", "or this text"]}}
          },
          "returnStoredSource": True }},
      {'$project': { 'similarityScore': { '$meta': 'searchScore' }, 'document' : '$$ROOT' }
}
]);

重要

在预览版中,筛选的矢量搜索可能需要你调整矢量索引参数,以实现更高的准确度。 例如,在使用 HNSW 时增加 mefConstructionefSearch,或在使用 IVF 时增加 numListsnProbes 可能会带来更好的结果。 在使用之前,应先测试配置,以确保结果令人满意。

使用 LLM 业务流程工具

通过语义内核用作矢量数据库

使用语义内核协调对 Azure Cosmos DB for MongoDB vCore 和 LLM 的信息检索。 在此处了解更多信息。

https://github.com/microsoft/semantic-kernel/tree/main/python/semantic_kernel/connectors/memory/azure_cosmosdb

在 LangChain 中用作矢量数据库

使用 LangChain 协调对 Azure Cosmos DB for MongoDB vCore 和 LLM 的信息检索。 在此处了解更多信息。

通过 LangChain 用作语义缓存

使用 LangChain 和 Azure Cosmos DB for MongoDB (vCore) 来协调语义缓存,使用以前记录的 LLM 响应来节省 LLM API 成本并减少响应延迟。 在此处了解详细信息

功能和限制

  • 支持的距离指标:L2(欧几里德)、内积和余弦。
  • 支持的索引方法:IVFFLAT、HNSW 和 DiskANN(预览版)
  • 为最大大小为 2,000 个维度的矢量编制索引。
  • 索引仅适用于每个路径的一个矢量。
  • 每个矢量路径只能创建一个索引。

总结

本指南演示了如何创建矢量索引、添加包含矢量数据的文档、执行相似性搜索以及检索索引定义。 通过使用集成矢量数据库,可以直接在 Azure Cosmos DB for MongoDB vCore 中高效地存储和查询高维矢量数据并为其编制索引。 它支持通过矢量嵌入充分发挥数据的全部潜力,并生成更加准确、高效和强大的应用程序。

下一步