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

Azure DocumentDB 中的集成矢量存储

使用 Azure DocumentDB 中的集成矢量数据库将基于 AI 的应用程序与存储在 Azure DocumentDB 中的数据无缝连接。 此集成可以包括使用 Azure OpenAI 嵌入生成的应用。 通过本机集成的向量数据库,可以有效地存储、索引和查询直接存储在 Azure DocumentDB 中的高维向量数据,以及创建矢量数据的原始数据。 它无需将数据传输到备用矢量存储并产生额外费用。

什么是矢量存储?

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

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

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

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

矢量数据库用例

矢量数据库用于 AI 和数据分析的许多领域。 它们有助于完成理解自然语言、识别图像和视频、构建建议系统和支持搜索功能等任务。 可以在分析 AI 和生成 AI 应用程序中找到它们。

例如,可以使用矢量数据库来执行以下操作:

  • 根据内容、主题、情绪和样式识别类似的图像、文档和歌曲。
  • 根据特征、功能和用户组识别相似产品。
  • 根据个人的偏好推荐内容、产品或服务。
  • 根据用户组的相似性推荐内容、产品或服务。
  • 从大型选择池中确定最适合的潜在选项,以满足复杂的要求。
  • 识别与主要模式或正常模式不同的数据异常或欺诈活动。
  • 为 AI 代理实现持久性内存。
  • 启用检索增强生成(RAG)。

集成向量数据库与纯向量数据库

存在两种常见的矢量数据库实现类型:NoSQL 或关系数据库中的纯向量数据库和集成向量数据库。

纯矢量数据库可有效地存储和管理矢量嵌入以及少量元数据。 它与从中派生嵌入项的数据源是分开的。

集成到高性能 NoSQL 或关系数据库中的矢量数据库提供额外的功能。 NoSQL 或关系数据库中的集成矢量数据库可以存储、索引和查询嵌入以及相应的原始数据。 此方法避免了在单独的纯矢量数据库中复制数据产生的额外成本。 此外,将矢量嵌入和原始数据放在一起可以更好地促进多模式数据作,并实现更高的数据一致性、缩放和性能。

开源矢量数据库

当开发人员选择矢量数据库时,开放源选项可提供许多优势。 开源 意味着软件的源代码可供自由使用,使用户能够根据其特定需求自定义数据库。 这种灵活性有利于那些需要满足数据独特监管要求的组织,例如金融服务行业的公司。

开源矢量数据库的另一个优势是享有强大的社区支持。 活跃的用户社区通常有助于开发这些数据库、提供支持和共享最佳做法,从而促进创新。

一些个人选择开放源代码矢量数据库,因为它们是“免费”的,这意味着无需获取或使用该软件。 另一种方法是使用托管矢量数据库服务提供的免费层。 这些托管服务不仅提供免费的访问权限(有特定的使用量限制),还通过处理维护、更新和可伸缩性来简化运营负担。 因此,通过使用托管向量数据库服务的免费层,可以节省成本,同时降低管理开销。 此方法使你能够更专注于核心活动,而不是数据库管理。

选择最佳开源矢量数据库

选择最佳开源矢量数据库需要考虑多种因素。 数据库的性能和可伸缩性至关重要,因为它们会影响数据库是否可以处理特定的工作负荷要求。 具有高效索引和查询功能的数据库通常会提供最佳性能。 另一个因素是可获取的社区支持和数据库相关的文档。 强大的社区和充足的文档可以提供有价值的帮助。 例如, DocumentDB 是一种常用的开源矢量数据库:

最常用的选项可能不是最适合你的选项。 因此,应根据功能、支持的数据类型以及与使用的现有工具和框架的兼容性来比较不同的选项。 还应记住开源矢量数据库的挑战。

开源矢量数据库的挑战

大多数开源矢量数据库(包括前面列出的数据库)都是纯矢量数据库。 换句话说,它们旨在仅存储和管理矢量嵌入,以及少量的元数据。 由于它们与原始数据分开工作,因此需要在不同的服务之间移动数据。 这种复杂性增加了额外的成本,使事情更加复杂,并可能会降低生产系统的速度。

它们也带来了开源数据库的典型挑战:

  • 设置:您需要深入了解如何安装、配置和操作数据库,尤其是在处理复杂部署时。 在纵向扩展操作时优化资源和配置需要密切监视和调整。
  • 维护:必须管理自己的更新、修补程序和维护。 机器学习专业知识不够;还必须在数据库管理方面拥有丰富的经验。
  • 支持:与托管服务相比,官方支持可能有限,更多地需要依靠社区协助。

因此,虽然最初是免费的,但开放源代码矢量数据库在纵向扩展时会产生巨大的成本。 扩大运营需要更多的硬件、熟练的 IT 人员和先进的基础结构管理,这会导致硬件、人员和运营成本增加。 尽管缺少许可费用,但缩放开源矢量数据库在财务上可能要求很高。

解决开源矢量数据库的挑战

在高性能 NoSQL 或关系数据库中集成的完全托管矢量数据库可避免开源向量数据库的额外费用和复杂性。 这种数据库将嵌入向量与相应的原始数据一起存储、建立索引并进行查询。 此方法避免了在单独的纯矢量数据库中复制数据产生的额外成本。 此外,将矢量嵌入和原始数据放在一起可以更好地促进多模式数据作,并实现更高的数据一致性、缩放和性能。 同时,完全托管的服务帮助开发人员避免了设置、维护开源矢量数据库以及需要依赖社区援助所带来的麻烦。 此外,某些托管向量数据库服务提供终身免费套餐。

例如 Azure DocumentDB 中的集成向量数据库。 此设置允许开发人员像使用开源矢量数据库一样节省资金。 但与开源选项不同,服务提供商负责为您进行维护、更新和扩展。 升级快捷且容易,并可在需要扩大运营时保持较低的总拥有成本(TCO)。 还可以使用此服务方便地缩放已在生产中的 MongoDB 应用程序。

Azure DocumentDB 提供可靠的矢量搜索功能,允许跨复杂数据集执行高速相似性搜索。 若要在 Azure DocumentDB 中执行矢量搜索,首先需要创建矢量索引。 虽然 Azure DocumentDB 提供了多个选项,但下面是一些一般准则,可帮助你根据数据集的大小开始:

IVF HNSW DiskANN (建议)
说明 IVFFlat 索引将矢量划分为列表,然后搜索离查询向量最近的子集。 HNSW 索引创建多层图。 DiskANN 是一种近似近邻搜索算法,旨在在任何规模上高效矢量搜索。
关键权衡 优点: 更快的生成时间,降低内存使用量。
缺点: 查询性能较低(在速度与召回率折衷方面)。
优点:可以在空表上产生更好的查询性能(就速度-召回率权衡而言)。
缺点: 生成时间变慢,内存使用率越高。
优点: 在任何规模上高效、高召回率、高吞吐量、低延迟。
矢量计数 低于 10,000 最多 50,000 多达 50 万以上
建议的群集层 M10 或 M20 M30 及更高版本 M30 及更高版本

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

使用 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>]}}}
      ]}
    }
  }
},
字段 类型 Description
lSearch 整数 指定用于搜索的动态候选列表的大小。 默认值为 40,可配置范围为 10 到 1000。 增加该值可增强召回率,但可能会降低搜索速度。
k 整数 定义要返回的搜索结果数。 k 值必须小于或等于 lSearch

使用 DiskANN 索引进行筛选的示例

将矢量添加到数据库

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

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
            }
        }
    ]
})

此命令将针对 contentVector 中的 exampleCollection 字段创建 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)

在此示例中,矢量相似性搜索将根据指定的 k 相似性指标返回最接近的 COS 个矢量,同时筛选结果以仅包含 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 英里半径范围内且营业的商家。 每个结果包括相似性分数和元数据,演示 Azure DocumentDB 中的 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)执行矢量搜索。

若要使用预筛选,首先需要在要筛选的属性上定义标准索引,以及矢量索引。 下面是创建筛选器索引的示例:

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

设置筛选器索引后,可以直接将 "filter" 子句添加到矢量搜索查询中。 此示例演示如何筛选结果,其中 "title" 属性的值不在提供的列表中:

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' }
}
]);

重要

若要优化预筛选矢量搜索的性能和准确性,请考虑调整矢量索引参数。 对于 DiskANN 索引,增加 maxDegreelBuild 可能产生更好的结果。 对于 HNSW 索引,尝试为 mefConstructionefSearch 设定更高的值,可以提高性能。 同样,对于 试管婴儿 索引,优化 numListsnProbes 可能导致更令人满意的结果。 使用您自己的数据非常重要,以测试您的特定配置,确保结果满足您的要求。 这些参数会影响索引结构和搜索行为,最佳值可能因数据特征和查询模式而异。

使用大型语言模型(LLM)编排工具

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

使用语义内核协调从 Azure DocumentDB 和 LLM 检索的信息。 有关详细信息,请参阅 GitHub 存储库

在 LangChain 中用作矢量数据库

使用 LangChain 协调对 Azure DocumentDB 和 LLM 的信息检索。 有关详细信息,请参阅 Azure DocumentDB 的 LangChain 集成

通过 LangChain 用作语义缓存

使用 LangChain 和 Azure DocumentDB 协调语义缓存,使用以前录制的 LLM 响应,可以节省 LLM API 成本并减少响应的延迟。 有关详细信息,请参阅 LangChain 与 Azure DocumentDB 的集成

功能和限制

  • 支持的距离指标:L2(欧几里德)、内积和余弦。
  • 支持的索引方法:IVFFLAT、HNSW 和 DiskANN。
  • 使用 DiskANN 和 产品量化,可以为最多 16,000 个维度的向量编制索引。
  • 使用具有 半精度 的 HNSW 或 IVF,可对最多 4,000 个维度的向量编制索引。
  • 没有任何压缩,索引的默认最大矢量维度为 2,000。
  • 索引仅适用于每个路径的一个矢量。
  • 每个向量路径只能创建一个索引。

概要

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

后续步骤