在 Azure AI 搜索中,可以将矢量存储在搜索索引中,并根据语义相似性发送矢量查询进行匹配。 矢量索引由具有向量字段、非矢量字段和矢量配置部分的索引架构定义。
创建或更新索引 REST API 创建向量索引。 若要在 Azure AI 搜索中为矢量编制索引,请执行以下步骤:
本文使用 REST 进行说明。 了解基本工作流后,请继续学习 azure-search-vector-samples 存储库中的 Azure SDK 代码示例,该存储库提供有关在测试和生产代码中使用矢量的指导。
提示
还可以使用 Azure 门户 创建矢量索引 ,并尝试集成的数据分块和向量化。
先决条件
在任何区域和任意层级中提供的 Azure AI 搜索服务。 如果计划将 集成矢量化 与 Azure AI 技能和矢量化配合使用,Azure AI 搜索必须与 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.String 和 key=true 的索引字段。 |
非向量内容 | 提供包含可供人阅读的内容的其他字段。 人工可读内容对于查询响应和 混合查询 非常有用,这些查询包含同一请求中的全文搜索或语义排名。 如果使用的是聊天完成模型,则大多数模型(如 ChatGPT)需要人工可读的文本,并且不接受原始矢量作为输入。 |
矢量内容 | 非函数内容的矢量化表示形式,以便在查询时使用。 矢量是嵌入模型生成的单精度浮点数数组。 每个向量字段都包含一个模型生成的数组。 每个字段都有一个嵌入,其中字段是顶级字段(不是嵌套或复杂类型的一部分)。 为了简单集成,我们建议在 Azure OpenAI 中嵌入模型,例如 文本嵌入-3 (适用于文本文档)或图像 检索 REST API (用于图像和多模式嵌入)。 如果可以使用索引器和技能集,请考虑 集成矢量化,在编制索引期间对图像和文本进行编码。 字段定义用于矢量字段,但传入的源数据可以是文本或图像,它们会在索引编制过程中转换为矢量数组。 |
搜索索引应包含你想要支持的所有查询方案的字段和内容。 假设你想要搜索或筛选产品名称、版本、元数据或地址。 在这种情况下,矢量相似性搜索并不特别有用。 关键字搜索、地理搜索或循环访问逐字内容的筛选器将是更好的选择。 包含矢量字段和非矢量字段的搜索索引为查询构造和响应组合提供了最大的灵活性。
有关包含向量和非矢量字段的文档有效负载的简短示例,请参阅本文的 加载向量数据 部分。
从基本索引开始
从最小模式开始,以便于在添加向量配置和向量字段之前有一个供您使用的定义。 简单的索引可能如以下示例所示。 有关索引架构的详细信息,请参阅 创建搜索索引。
请注意,索引具有必需的名称、必需的文档键("key": true
),以及用于存放可读内容的纯文本字段。 通常,对要向量化的任何内容都有人可读版本。 例如,如果 PDF 文件中有一个文本区块,索引架构应具有纯文本区块的字段,以及矢量化区块的第二个字段。
下面是一个基本索引,包括"name"
、"fields"
集合和其他一些进行额外配置的构造:
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" },
],
"analyzers": [ ],
"scoringProfiles": [ ],
"suggesters": [ ],
"vectorSearch": [ ]
}
添加矢量搜索配置
接下来,将 "vectorSearch"
配置添加到架构。 在字段定义之前指定配置非常有用,因为在此定义的配置将成为矢量字段定义的一部分。 在架构中,矢量配置通常插入到字段集合之后,可能在"analyzers"
、"scoringProfiles"
、和"suggesters"
之后。 然而,顺序并不重要。
矢量配置包括:
-
vectorSearch.algorithms
在索引过程中用于在向量节点之间创建“最接近的邻居”信息。 -
vectorSearch.compressions
用于标量或二进制量化、过度采样和使用原始向量重新进行重新排序。 -
vectorSearch.profiles
用于指定算法和压缩配置的多个组合。
2024-07-01 已全面推出。 它支持具有以下功能的向量配置:
- 分层可导航小型世界 (HNSW) 算法。
- 详尽的 K-近邻 (KNN) 算法。
- 标量压缩。
- 二进制压缩(仅在 2024-07-01 和较新的 Azure SDK 包中提供)。
- 过度采样。
- 使用原始向量重新排序。
如果在某个字段中选择 HNSW,则可在查询时选择使用详尽的 KNN。 但是,相反不起作用。 如果选择详尽的索引编制,则以后无法请求 HNSW 搜索,因为启用近似搜索的额外数据结构不存在。
请务必制定矢量化内容的策略。 建议使用集成矢量化和查询时间矢量化器进行内置编码。
使用 创建或更新索引 REST API 创建索引。
在索引中添加
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
可以是scalarQuantization
或binaryQuantization
。 标量量化将浮点值压缩为更窄的数据类型。 二进制量化将浮点转换为二进制 1 位值。vectorSearch.compressions.rerankWithOriginalVectors
使用原始的未压缩向量来重新计算相似性,并对初始搜索查询返回的顶部结果进行重新排名。 即使stored
为 false,未压缩的向量也存在于搜索索引中。 此属性是可选的。 默认值为 true。vectorSearch.compressions.defaultOversampling
将考虑更广泛的潜在结果,以抵消量化导致的信息减少。 潜在结果的公式由查询中的k
和过采样乘数组成。 例如,如果查询指定了 5 个k
,并且过度采样为 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。vectorSearch.algorithms.metric
应该是cosine
,如果您使用的是 Azure OpenAI;否则,请使用与您所使用的嵌入模型相关的相似性指标。 支持的值是cosine
、dotProduct
和euclidean
hamming
(用于为二进制数据编制索引)。vectorSearch.profiles
添加一个抽象层以容纳更丰富的定义。 在vectorSearch
中定义配置文件,并在每个矢量字段中按名称进行引用。 它是压缩和算法配置的组合。 将此属性分配给向量字段,并确定字段的算法和压缩。
将矢量字段添加到字段集合
获得向量配置后,可以将向量字段添加到字段集合。 请注意,字段集合必须包含文档键、矢量字段,以及在混合搜索方案或RAG 工作负载中聊天模型完成所需的任何其他非矢量字段。
矢量字段的特点是 其数据类型、基于用于生成矢量的嵌入模型的属性,以及你在上一步中创建的矢量描述文件。
2024-07-01 已全面推出。
使用 创建或更新索引 REST API 创建索引并将向量字段添加到字段集合。
{ "name": "example-index", "fields": [ { "name": "contentVector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": false, "stored": false, "dimensions": 1536, "vectorSearchProfile": "vector-profile-1" } ] }
使用以下属性指定向量字段。 可为每个字段存储一个生成的嵌入。 对于每个矢量字段:
-
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。 它确定是否存储额外的矢量副本以供检索。 有关详细信息,请参阅减小矢量大小。 -
filterable
,facetable
且sortable
必须为 false。
-
添加其他字段用于定义你要编制索引的文本内容的主旨和结构。 至少需要一个文档密钥。
还应该添加在查询或其响应中有用的字段。 以下示例显示了与矢量等效的标题和内容(
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 中的 CreateOrUpdateIndex、Azure SDK for Python 中的create_or_update_index,以及其他 Azure SDK 中的类似方法。
有关更新索引的标准指南,请参阅 更新或重新生成索引。
要点包括:
对现有字段的更新和删除通常需要进行删除和完整索引重建。
可以进行以下修改,无需重新生成:
- 向字段集合添加新字段。
- 添加新的向量配置,分配给新字段,而不是已经向量化的现有字段。
- 更改现有字段上的值
retrievable
(值为 true 或 false)。 矢量字段必须是可搜索和可检索的,但如果希望在无法删除和重新生成的情况下禁用对矢量字段的访问,则可以将“可检索”设置为 false。
后续步骤
下一步建议 创建向量查询。
azure-search-vector-samples 存储库中的代码示例演示了包括架构定义、矢量化、索引编制和查询在内的端到端工作流。
有可参阅的 Python、C# 和 JavaScript 的演示代码。