Leer en inglés

Compartir a través de

创建矢量索引

在 Azure AI 搜索中,可以将矢量存储在搜索索引中,并发送矢量查询以匹配语义相似性。 Azure AI 搜索中的矢量存储由同时具有向量和非矢量字段的索引架构定义。 该架构还具有用于指定用于创建和压缩嵌入空间的算法的矢量配置。

创建或更新索引 API 创建矢量存储。 按照以下步骤在 Azure AI 搜索中为矢量编制索引:

  • 从基本架构定义开始
  • 添加矢量算法和可选压缩
  • 添加矢量字段定义
  • 加载预矢量化的数据作为单独的步骤,或在索引期间使用集成矢量化进行数据分块和编码

本文介绍使用 REST API 进行演示的工作流。 了解基本工作流后,请继续阅读 azure-search-vector-samples 存储库中的 Azure SDK 代码示例,获取有关在测试和生产代码中使用矢量的指导。

Sugerencia

还可以使用 Azure 门户 创建矢量索引 ,并尝试集成的数据分块和向量化。

先决条件

  • 在任何区域内、任何层级上的 Azure 人工智能搜索。 如果计划使用 集成矢量化,Azure AI 搜索必须与 Azure OpenAI 或 Azure AI 视觉中托管的嵌入模型位于同一区域。

  • 源文档必须具有 向量嵌入 才能上传到索引。 或者,可以对此步骤使用 集成矢量化

  • 你应该知道用于创建嵌入的模型的维度限制,以便可以将该限制分配给矢量字段。 对于 text-embedding-ada-002,维度被固定为 1536。 对于 text-embedding-3-small 或 text-embedding-3-large,维度分别为 1 到 1536 和 1 到 3072。

  • 还应知道要使用的相似性指标。 对于 Azure OpenAI 上的嵌入模型,相似度是使用 cosine 计算的。

  • 你应该知道如何创建索引。 架构必须包含文档键的字段、要搜索或筛选的其他字段,以及索引编制和查询期间所需行为的其他配置。

局限性

对于在 2019 年 1 月之前创建的搜索服务,有一个小子集无法创建向量索引。 如果这适用于你,请创建新的服务以使用矢量。

准备文档用于索引

在编制索引之前,请组装包含向量和非向量数据字段的文档负载。 文档结构必须符合索引架构。

请确保源文档提供以下内容:

内容 DESCRIPTION
唯一标识符 唯一标识每个文档的字段或元数据属性。 所有搜索索引都需要文档键。 若要满足文档密钥要求,源文档必须在索引中具有一个字段或属性唯一标识它。 如果要为 blob 编制索引,则可能是唯一标识每个 blob 的metadata_storage_path。 如果要从数据库编制索引,它可能是主键。 此源字段必须映射到搜索索引中类型为 Edm.Stringkey=true 的索引字段。
非向量内容 提供包含可供人阅读的内容的其他字段。 人工可读内容对于查询响应以及包含同一请求中的全文搜索或语义排名的混合查询方案非常有用。 如果使用聊天完成模型,则大多数模型(如 ChatGPT)不接受原始矢量作为输入。
矢量内容 非矢量内容的矢量化版本。 矢量是嵌入模型生成的单精度浮点数数组。 每个向量字段都包含一个由嵌入模型生成的数组,每个字段对应一个嵌入,该字段为顶级字段(不是嵌套或复杂类型的一部分)。 为了简单集成,我们建议在 Azure OpenAI 中嵌入模型,例如 文本嵌入-3 模型,或者图像 检索 REST API 用于图像和多模式嵌入。

如果可以依赖索引器和技能集,请考虑在索引编制过程中使用集成矢量化对图像和文本内容进行编码。 字段定义用于矢量字段,但传入的源数据可以是文本或图像,它们会在索引编制过程中转换为矢量数组。

搜索索引应包含你想要支持的所有查询方案的字段和内容。 假设你想要搜索或筛选产品名称、版本、元数据或地址。 在这种情况下,矢量相似性搜索并不特别有用。 关键字搜索、地理搜索或筛选器是更好的选择。 包含矢量和非矢量字段综合集合的搜索索引为查询构造和响应组合提供了最大的灵活性。

本文的加载矢量数据部分提供了包含矢量和非矢量字段的文档有效负载的简短示例。

从基本索引开始

从最小模式开始,以便于在添加向量配置和向量字段之前有一个供您使用的定义。 简单的索引可能如以下示例所示。 可以在 “创建搜索索引”中了解有关索引架构的详细信息。

请注意,它具有必需的名称、必需的文档键("key": true)以及用纯文本表示的人类可读内容的字段。 通常,对要向量化的任何内容都有人可读版本。 例如,如果 PDF 文件中有一块文本,索引架构应具有与矢量化文本等效的纯文本。

POST https://[servicename].search.azure.cn/indexes?api-version=[api-version] 
{
  "name": "example-index",
  "fields": [
    { "name": "documentId", "type": "Edm.String", "key": true, "retrievable": true, "searchable": true, "filterable": true },
    { "name": "myHumanReadableNameField", "type": "Edm.String", "retrievable": true, "searchable": true, "filterable": false, "sortable": true, "facetable": false },
    { "name": "myHumanReadableContentField", "type": "Edm.String", "retrievable": true, "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzer": "en.microsoft" },
  ],
  "suggesters": [ ],
  "scoringProfiles": [ ],
  "analyzers":(optional)[ ... ]
}

添加矢量搜索配置

接下来,向架构添加矢量搜索配置(配置文件)。 配置在字段定义之前进行,因为你需要在每个字段上指定一个配置文件,作为字段定义的一部分。 在架构中,矢量配置通常在字段集合之后,可能在"suggesters""scoringProfiles""analyzers"之后添加。

矢量配置指定在索引编制期间用于在向量节点中创建“最接近的邻居”信息的参数。 算法包括:

  • 分层可导航小世界 (HNSW)
  • 详尽的 k-最近的邻域 (KNN)

如果在某个字段中选择 HNSW,则可以在查询时选择使用详尽的 KNN。 但另一个方向不起作用:如果选择详尽索引,则以后无法请求 HNSW 搜索,因为启用近似搜索的额外数据结构不存在。

(可选)矢量配置还指定用于减小矢量大小的量化方法:

  • 标量
  • 二进制文件(仅在 2024-07-01 以及较新的 Azure SDK 包中提供)

2024-07-01 已全面推出。 它支持矢量配置,具有:

  • vectorSearch.algorithms 支持 HNSW 和详尽的 KNN。
  • vectorSearch.compressions 支持标量和二进制量化、过度采样以及使用原始矢量重新排名。
  • vectorSearch.profiles 用于指定算法和压缩配置的多个组合。

请务必制定矢量化内容的策略。 建议使用集成矢量化查询时间矢量化器进行内置编码。

  1. 使用创建或更新索引 API 创建索引。

  2. 在索引中添加 vectorSearch 节,以指定用于创建嵌入空间的搜索算法。

     "vectorSearch": {
         "compressions": [
             {
                 "name": "scalar-quantization",
                 "kind": "scalarQuantization",
                 "rerankWithOriginalVectors": true,
                 "defaultOversampling": 10.0,
                     "scalarQuantizationParameters": {
                         "quantizedDataType": "int8"
                     }
             },
             {
                 "name": "binary-quantization",
                 "kind": "binaryQuantization",
                 "rerankWithOriginalVectors": true,
                 "defaultOversampling": 10.0
             }
         ],
         "algorithms": [
             {
                 "name": "hnsw-1",
                 "kind": "hnsw",
                 "hnswParameters": {
                     "m": 4,
                     "efConstruction": 400,
                     "efSearch": 500,
                     "metric": "cosine"
                 }
             },
             {
                 "name": "hnsw-2",
                 "kind": "hnsw",
                 "hnswParameters": {
                     "m": 8,
                     "efConstruction": 800,
                     "efSearch": 800,
                     "metric": "hamming"
                 }
             },
             {
                 "name": "eknn",
                 "kind": "exhaustiveKnn",
                 "exhaustiveKnnParameters": {
                     "metric": "euclidean"
                 }
             }
    
         ],
         "profiles": [
           {
             "name": "vector-profile-hnsw-scalar",
             "compression": "scalar-quantization",
             "algorithm": "hnsw-1"
           }
         ]
     }
    

    要点

    • 压缩、算法和配置文件的每种配置的名称在索引中对于其类型必须具有唯一性。

    • vectorSearch.compressions 可以是 scalarQuantizationbinaryQuantization。 标量量化将浮点值压缩为更窄的数据类型。 二进制量化将浮点数转换为二进制 1 位值。

    • vectorSearch.compressions.rerankWithOriginalVectors 使用原始的未压缩向量来重新计算相似性,并对初始搜索查询返回的顶部结果进行重新排名。 即使 stored 为 false,未压缩的向量也存在于搜索索引中。 此属性是可选的。 默认值为 true。

    • vectorSearch.compressions.defaultOversampling 将考虑更广泛的潜在结果,以抵消量化导致的信息减少。 潜在结果的公式由查询中的 k 和过采样乘数组成。 例如,如果查询指定 k 为 5,并且过采样为 20,则查询实际上会请求 100 个文档用于重新排序,并为此使用原始未压缩向量。 仅返回前 k 个重新排名的结果。 此属性是可选的。 默认值为 4。

    • vectorSearch.compressions.scalarQuantizationParameters.quantizedDataType 必须设置为 int8。 这是目前唯一支持的基元数据类型。 此属性是可选的。 默认值为 int8

    • vectorSearch.algorithms"hnsw""exhaustiveKnn"。 它们是近似最近邻域 (ANN) 算法,用于在索引编制期间组织矢量内容。

    • vectorSearch.algorithms.m 是双向链接计数。 默认值为 4。 范围为 4 到 10。 较低的值应在结果中返回较少的干扰数据。

    • vectorSearch.algorithms.efConstruction 是索引编制期间使用的最近邻域数量。 默认值为 400。 范围为 100 到 1,000。

    • "vectorSearch.algorithms.efSearch 是搜索期间使用的最近邻域数量。 默认值为 500。 范围为 100 到 1,000。

    • 如果使用的是 Azure OpenAI,则 vectorSearch.algorithms.metric 应为“cosine”,否则请使用与你正在使用的嵌入模型关联的相似性指标。 支持的值为 cosinedotProducteuclideanhamming(用于对二进制数据编制索引)。

    • vectorSearch.profiles 添加一个抽象层以容纳更丰富的定义。 在 vectorSearch 中定义配置文件,然后在每个矢量字段中按名称进行引用。 它是压缩和算法配置的组合。 这是分配给矢量字段的属性,它可以确定字段的算法和压缩。

将矢量字段添加到字段集合

获得向量配置后,可以将向量字段添加到字段集合。 记住,字段集合必须包含一个字段用于文档键、矢量字段,以及在RAG工作负载中混合搜索方案或聊天模型完成所需的任何其他非矢量字段。

矢量字段的特点是 其数据类型、基于用于生成矢量的嵌入模型的属性,以及你在上一步中创建的矢量描述文件。

{
    "name": "contentVector",
    "type": "Collection(Edm.Single)",
    "searchable": true,
    "retrievable": false,
    "stored": false,
    "dimensions": 1536,
    "vectorSearchProfile": "vector-profile-1"
}

2024-07-01 已全面推出。

  1. 使用创建或更新索引创建索引。

  2. 使用以下属性定义矢量字段。 可为每个字段存储一个生成的嵌入。 对于每个矢量字段:

    • type 必须是矢量数据类型Collection(Edm.Single) 是嵌入模型最常见的属性。
    • dimensions 是嵌入模型生成的维度数。 对于 text-embedding-ada-002,此值固定为 1536。 对于 text-embedding-3 模型系列,可以使用一系列值。 如果你使用集成矢量化和嵌入技能来生成向量,请确保将此属性设置为嵌入技能使用的同一维度值
    • vectorSearchProfile 是在索引中的其他位置定义的配置文件的名称。
    • searchable 必须为真。
    • retrievable 可以为 true 或 false。 True 以纯文本形式返回原始向量(其中 1,536 个),并占用存储空间。 如果你要将矢量结果传递给下游应用,请设置为 true。
    • stored 可以为 true 或 false。 它确定是否存储额外的矢量副本以供检索。 有关详细信息,请参阅减小矢量大小
    • filterablefacetablesortable 必须为 false。
  3. 如果您想在向量查询中调用预筛选或后期筛选,请向集合中添加可筛选的非向量字段,例如“title”,并将filterable设置为 true。

  4. 添加其他字段用于定义你要编制索引的文本内容的主旨和结构。 至少需要一个文档密钥。

    还应该添加在查询或其响应中有用的字段。 以下示例显示了标题和内容(等效于矢量)的矢量字段(“titleVector”、“contentVector”)。 它还提供了等效文本内容的字段(“title”、“content”),可用于在搜索结果中进行排序、筛选和读取。

    以下示例显示了字段集合:

    PUT https://my-search-service.search.azure.cn/indexes/my-index?api-version=2024-07-01&allowIndexDowntime=true
    Content-Type: application/json
    api-key: {{admin-api-key}}
    {
        "name": "{{index-name}}",
        "fields": [
            {
                "name": "id",
                "type": "Edm.String",
                "key": true,
                "filterable": true
            },
            {
                "name": "title",
                "type": "Edm.String",
                "searchable": true,
                "filterable": true,
                "sortable": true,
                "retrievable": true
            },
            {
                "name": "titleVector",
                "type": "Collection(Edm.Single)",
                "searchable": true,
                "retrievable": true,
                "stored": true,
                "dimensions": 1536,
                "vectorSearchProfile": "vector-profile-1"
            },
            {
                "name": "content",
                "type": "Edm.String",
                "searchable": true,
                "retrievable": true
            },
            {
                "name": "contentVector",
                "type": "Collection(Edm.Single)",
                "searchable": true,
                "retrievable": false,
                "stored": false,
                "dimensions": 1536,
                "vectorSearchProfile": "vector-profile-1"
            }
        ],
        "vectorSearch": {
            "algorithms": [
                {
                    "name": "hnsw-1",
                    "kind": "hnsw",
                    "hnswParameters": {
                        "m": 4,
                        "efConstruction": 400,
                        "efSearch": 500,
                        "metric": "cosine"
                    }
                }
            ],
            "profiles": [
                {
                    "name": "vector-profile-1",
                    "algorithm": "hnsw-1"
                }
            ]
        }
    }
    

加载要编制索引的矢量数据

你提供的要编制索引的内容必须符合索引架构,并包含文档键的唯一字符串值。 预矢量化数据将加载到一个或多个矢量字段中,这些矢量字段可与包含非矢量内容的其他字段共存。

可以使用推送或拉取方法进行数据引入。

使用文档 - 索引将矢量和非矢量数据加载到索引中。 用于索引的推送 API 在所有稳定版本和预览版本中都是相同的。 使用以下任意 API 加载文档:

POST https://{{search-service-name}}.search.azure.cn/indexes/{{index-name}}/docs/index?api-version=2024-07-01

{
    "value": [
        {
            "id": "1",
            "title": "Azure App Service",
            "content": "Azure App Service is a fully managed platform for building, deploying, and scaling web apps. You can host web apps, mobile app backends, and RESTful APIs. It supports a variety of programming languages and frameworks, such as .NET, Java, Node.js, Python, and PHP. The service offers built-in auto-scaling and load balancing capabilities. It also provides integration with other Azure services, such as Azure DevOps, GitHub, and Bitbucket.",
            "category": "Web",
            "titleVector": [
                -0.02250031754374504,
                 . . . 
                        ],
            "contentVector": [
                -0.024740582332015038,
                 . . .
            ],
            "@search.action": "upload"
        },
        {
            "id": "2",
            "title": "Azure Functions",
            "content": "Azure Functions is a serverless compute service that enables you to run code on-demand without having to manage infrastructure. It allows you to build and deploy event-driven applications that automatically scale with your workload. Functions support various languages, including C#, F#, Node.js, Python, and Java. It offers a variety of triggers and bindings to integrate with other Azure services and external services. You only pay for the compute time you consume.",
            "category": "Compute",
            "titleVector": [
                -0.020159931853413582,
                . . .
            ],
            "contentVector": [
                -0.02780858241021633,
                 . . .
            ],
            "@search.action": "upload"
        }
        . . .
    ]
}

查询索引以获取矢量内容

要进行验证,可以使用 Azure 门户中的搜索资源管理器或 REST API 调用来查询索引。 由于 Azure AI 搜索无法将矢量转换为人类可读的文本,因此请尝试从同一文档中返回提供匹配证据的字段。 例如,如果矢量查询针对“titleVector”字段,则你可以为搜索结果选择“title”。

必须将字段的属性设置为“retrievable”才能将其包含在结果中。

  • 查看“搜索管理”>“索引”中的索引,以查看总体索引大小和矢量索引大小。 正向的矢量索引大小表明矢量存在。

  • 使用搜索资源管理器来查询索引。 搜索资源管理器有两个视图:查询视图(默认)和 JSON 视图。

    • 设置“查询选项”>“隐藏搜索结果中的矢量值”以获取更多可读结果。

    • 将 JSON 视图用于矢量查询。 你可以粘贴要执行的矢量查询的 JSON 定义,或者如果索引具有矢量器赋值,则使用内置的文本到矢量或图像到矢量转换。

    • 使用默认查询视图可以快速确认索引是否包含矢量。 查询视图用于全文搜索。 尽管无法将其用于矢量查询,但可以发送空搜索 (search=*) 来检查内容。 所有字段(包括矢量字段)的内容均以纯文本形式返回。

有关详细信息,请参阅 创建矢量查询

更新矢量数据库

若要更新矢量存储,请修改架构并重新加载文档以填充新字段。 用于架构更新的 API 包括创建或更新索引 (REST)Azure SDK for .NET 中的 CreateOrUpdateIndexAzure SDK for Python 中的create_or_update_index,以及其他 Azure SDK 中的类似方法。

有关更新索引的标准指南,请参阅更新或重新生成索引

要点包括:

  • 对现有字段的更新和删除通常需要进行删除和完整索引重建。

  • 无需重新生成即可进行一些修改:

    • 向字段集合添加新字段。
    • 添加新的向量配置,分配给新字段,而不是已经向量化的现有字段。
    • 更改现有字段上的“可检索”(值为 true 或 false)。 矢量字段必须是可搜索和可检索的,但如果希望在无法删除和重新生成的情况下禁用对矢量字段的访问,则可以将“可检索”设置为 false。

后续步骤

接下来,我们建议在搜索索引中查询矢量数据

azure-search-vector 存储库中的代码示例演示了包括架构定义、矢量化、索引和查询的端到端工作流。

有可参阅的 PythonC#JavaScript 的演示代码。