如果在 Azure AI 搜索中有 矢量索引 ,本文将介绍如何:
本文使用 REST 进行说明。 了解基本工作流后,请继续学习 azure-search-vector-samples 存储库中的 Azure SDK 代码示例,该存储库提供包含矢量查询的端到端解决方案。
也可以在 Azure 门户中使用搜索资源管理器。
先决条件
在任何区域和任意层级中提供的 Azure AI 搜索服务。
矢量索引。 若要确认矢量索引,请检查你的索引中是否有
vectorSearch
部分。(可选)向索引中添加矢量器,以便在查询期间进行内置文本到矢量转换或图像到矢量转换。
如果要自行运行这些示例,使用 Visual Studio Code 以及 REST 客户端和示例数据。 若要开始使用 REST 客户端,请参阅 快速入门:使用 REST 进行全文搜索。
将查询字符串输入转换为矢量
若要查询矢量字段,查询本身必须是矢量。
将用户的文本查询字符串转换为矢量表示的一种方法是在应用程序代码中调用嵌入库或 API。 最佳做法是始终使用与在源文档中生成嵌入时相同的嵌入模型。 可以在 azure-search-vector-samples 存储库中找到展示如何生成嵌入的代码示例。
第二种方法是 使用现已正式提供的集成矢量化,让 Azure AI 搜索处理查询向量化输入和输出。
下面是提交到 Azure OpenAI 嵌入模型部署的查询字符串的 REST API 示例:
POST https://{{openai-service-name}}.openai.azure.com/openai/deployments/{{openai-deployment-name}}/embeddings?api-version={{openai-api-version}}
Content-Type: application/json
api-key: {{admin-api-key}}
{
"input": "what azure services support generative AI'"
}
如果成功调用了部署的模型,则预期的响应为 202。
embedding
响应正文中的字段是查询字符串input
的向量表示形式。 出于测试目的,你将使用后续几个部分中所示的 embedding
语法将数组的值复制到 vectorQueries.vector
查询请求中。
对已部署模型的 POST 调用的实际响应包括 1,536 个嵌入内容。 为了提高可读性,此示例仅显示前几个向量。
{
"object": "list",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [
-0.009171937,
0.018715322,
...
-0.0016804502
]
}
],
"model": "ada",
"usage": {
"prompt_tokens": 7,
"total_tokens": 7
}
}
在此方法中,应用程序代码负责连接到模型、生成嵌入和处理响应。
矢量查询请求
本部分介绍矢量查询的基本结构。 可以使用 Azure 门户、REST API 或 Azure SDK 来构建矢量查询。
如果要从 2023-07-01-Preview 迁移,则存在中断性变更。 有关详细信息,请参阅 升级到最新的 REST API。
2024-07-01 是 搜索 POST 的稳定 REST API 版本。 此版本支持:
-
vectorQueries
是矢量搜索的构造。 -
vectorQueries.kind
设置为vector
,如果输入是矢量数组,或者如果输入是字符串并且您有text
,则设置为 。 -
vectorQueries.vector
是查询(文本或图像的矢量表示形式)。 -
vectorQueries.exhaustive
(可选)在查询时调用穷举 KNN,即使字段已根据 HNSW 编制了索引。 -
vectorQueries.fields
(可选)针对查询执行的特定字段(每个查询最多可选 10 个)。 -
vectorQueries.weight
(可选)指定搜索作中包含的每个向量查询的相对权重。 有关详细信息,请参阅 矢量权重。 -
vectorQueries.k
是要返回的匹配项数。
在以下示例中,矢量是此字符串的表示形式: "what Azure services support full text search"
查询面向 contentVector
字段并返回 k
结果。 实际向量有 1,536 个嵌入项,在此示例中进行了剪裁,以便进行可读性。
POST https://{{search-service-name}}.search.azure.cn/indexes/{{index-name}}/docs/search?api-version=2024-07-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
"count": true,
"select": "title, content, category",
"vectorQueries": [
{
"kind": "vector",
"vector": [
-0.009154141,
0.018708462,
. . .
-0.02178128,
-0.00086512347
],
"exhaustive": true,
"fields": "contentVector",
"weight": 0.5,
"k": 5
}
]
}
矢量查询响应
在 Azure AI 搜索中,查询响应默认包含所有 retrievable
字段。 但是,通常通过将搜索结果列在 retrievable
语句中,将搜索结果限制为 select
字段的子集。
在矢量查询中,请仔细考虑是否需要在响应中使用矢量字段。 矢量字段不可读,因此,如果要将响应推送到网页,则应选择表示结果的非函数字段。 例如,如果查询针对 contentVector
执行,则可以改为返回 content
。
如果想要结果中的向量字段,下面是响应结构的示例。
contentVector
是嵌入的字符串数组,在此示例中剪裁为可读性。 搜索分数指示相关性。 其他非矢量字段也包括在内,以提供上下文。
{
"@odata.count": 3,
"value": [
{
"@search.score": 0.80025613,
"title": "Azure Search",
"category": "AI + Machine Learning",
"contentVector": [
-0.0018343845,
0.017952163,
0.0025753193,
...
]
},
{
"@search.score": 0.78856903,
"title": "Azure Application Insights",
"category": "Management + Governance",
"contentVector": [
-0.016821077,
0.0037742127,
0.016136652,
...
]
},
{
"@search.score": 0.78650564,
"title": "Azure Media Services",
"category": "Media",
"contentVector": [
-0.025449317,
0.0038463024,
-0.02488436,
...
]
}
]
}
要点:
k
决定返回的最近的邻域结果数,在本例中为 3。 矢量查询始终返回k
结果,假设至少k
存在文档,即使某些文档的相似性差。 这是因为算法会查找查询向量最近的k
领域结果数。矢量搜索算法确定
@search.score
。搜索结果中的字段要么是所有
retrievable
字段,要么是在select
子句中的字段。 在矢量查询执行期间,仅对矢量数据进行匹配。 但是,响应可以包含索引中的任何retrievable
字段。 由于没有用于解码向量字段结果的设施,因此包含非矢量文本字段有助于其人类可读的值。
多个矢量字段
可以将属性 vectorQueries.fields
设置为多个向量字段。 矢量查询针对你在 fields
列表中提供的每个矢量字段执行。 最多可以指定 10 个字段。
查询多个矢量字段时,请确保每个字段都包含同一嵌入模型中的嵌入内容。 还应从同一嵌入模型生成查询。
POST https://{{search-service-name}}.search.azure.cn/indexes/{{index-name}}/docs/search?api-version=2024-07-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
"count": true,
"select": "title, content, category",
"vectorQueries": [
{
"kind": "vector",
"vector": [
-0.009154141,
0.018708462,
. . .
-0.02178128,
-0.00086512347
],
"exhaustive": true,
"fields": "contentVector, titleVector",
"k": 5
}
]
}
多个矢量查询
多查询矢量搜索跨搜索索引中的多个矢量字段发送多个查询。 这种类型的查询通常用于多模态搜索,例如使用 CLIP 等模型,其中同一模型可以将文本和图像转化为向量。
以下查询示例在 myImageVector
和 myTextVector
两者中查找相似性,并分别发送两个查询嵌入,每个嵌入都是并行执行的。 此查询的结果是使用 对等排名融合 (RRF)评分的。
-
vectorQueries
提供矢量查询的数组。 -
vector
包含搜索索引中的图像矢量和文本矢量。 每个实例都是单独的查询。 -
fields
指定要针对的矢量字段。 -
k
是要包含在结果中的最近邻域匹配项的数量。
{
"count": true,
"select": "title, content, category",
"vectorQueries": [
{
"kind": "vector",
"vector": [
-0.009154141,
0.018708462,
. . .
-0.02178128,
-0.00086512347
],
"fields": "myimagevector",
"k": 5
},
{
"kind": "vector"
"vector": [
-0.002222222,
0.018708462,
-0.013770515,
. . .
],
"fields": "mytextvector",
"k": 5
}
]
}
搜索索引无法存储图像。 假设索引包含图像文件的字段,搜索结果将包括文本和图像的组合。
使用集成矢量化进行查询
本部分显示一个矢量查询,该查询调用 集成向量 以将文本转换为向量。 对于此功能,建议使用稳定的 2024-07-01 REST API、搜索资源管理器或较新的 Azure SDK 包。
先决条件是提供一个已配置矢量化器并分配到矢量字段的搜索索引。 矢量化器为查询时使用的嵌入模型提供连接信息。
搜索资源管理器支持在查询时进行集成矢量化。 如果索引包含矢量字段且有矢量器,则可以使用内置文本到矢量转换。
矢量查询响应中的排名结果数
矢量查询指定 k
参数,该参数确定在结果中返回多少个匹配项。 搜索引擎始终返回 k
个匹配项。 如果 k
文档数大于索引中的文档数,则文档数决定了可以返回的项的上限。
如果熟悉全文搜索,则如果索引不包含字词或短语,则知道预期结果为零。 但是,在矢量搜索中,搜索操作会识别最近的邻居,即使这些最近的邻居不是那么相似,也始终返回 k
结果。 可以获取非敏感或非主题查询的结果,尤其是在未使用提示设置边界时。 相关性较低的结果的相似性评分较差,但如果没有更接近的矢量,它们仍然是“最接近的”矢量。 因此,没有有意义的结果的响应仍可返回 k
结果,但每个结果的相似性分数将较低。
包含全文搜索的 混合方法 可以缓解此问题。 另一种解决方案是在搜索分数上设置最小阈值,但前提是查询是纯单向量查询。 混合查询不利于最小阈值,因为 RRF 范围要小得多,而且波动性更大。
影响结果计数的查询参数包括:
-
仅矢量查询的
"k": n
结果 -
包含
"top": n
参数的混合查询的search
结果。
k
和 top
都是可选的。 如果未指定,则响应中的默认结果数为 50。 可以设置 top
和 skip
以逐页浏览更多结果或更改默认值。
矢量查询中使用的排名算法
结果排名由以下任一计算:
- 相似性指标。
- 如果有多个搜索结果集,请使用 RRF。
相似性指标
在仅矢量查询的索引 vectorSearch
节中指定的相似性指标。 有效值为:cosine
、euclidean
和 dotProduct
。
Azure OpenAI 嵌入模型使用余弦相似性,因此如果你使用 Azure OpenAI 嵌入模型,则 cosine
是建议的指标。 其他支持的排名指标包括 euclidean
和 dotProduct
。
RRF
如果查询面向多个向量字段、并行运行多个矢量查询,或者是矢量和全文搜索的混合,并且不带 语义排名,则会创建多个集。
在查询执行期间,矢量查询只能针对一个内部矢量索引。 对于 多个向量字段 和 多个矢量查询,搜索引擎将生成多个查询,这些查询面向每个字段的相应向量索引。 输出是每个查询的一组排名结果,这些结果使用 RRF 融合。 有关详细信息,请参阅使用倒数排序融合进行相关性评分。
矢量权重
添加 weight
查询参数来指定搜索操作中包含的每个矢量查询的相对权重。 当合并由同一请求中的两个或多个矢量查询生成的多个排名列表的结果,或者合并来自混合查询矢量部分的结果时,将使用此值。
默认值为 1.0,该值必须是大于零的正数。
计算每个文档的 RRF 分数 时,使用权重。 计算结果是 weight
值与文档在其各自结果集中的排名分数的乘积。
以下示例是一个混合查询,其中包含两个矢量查询字符串和一个文本字符串。 权重分配给矢量查询。 第一个查询是 0.5 或一半的权重,其在请求中的重要性有所减少。 第二个矢量查询的重要性达到两倍。
POST https://[service-name].search.azure.cn/indexes/[index-name]/docs/search?api-version=2024-07-01
{
"vectorQueries": [
{
"kind": "vector",
"vector": [1.0, 2.0, 3.0],
"fields": "my_first_vector_field",
"k": 10,
"weight": 0.5
},
{
"kind": "vector",
"vector": [4.0, 5.0, 6.0],
"fields": "my_second_vector_field",
"k": 10,
"weight": 2.0
}
],
"search": "hello world"
}
矢量权重仅适用于矢量。 此示例 "hello world"
中的文本查询的隐式中性权重为 1.0。 但是,在混合查询中,可以通过设置 maxTextRecallSize 来增加或减少文本字段的重要性。
设置阈值以排除低分结果(预览版)
由于最近邻搜索始终返回所请求的 k
邻域,因此,为了满足搜索结果的 k
数量要求,可能会有多个低分匹配项。 若要排除低评分搜索结果,可以添加一个 threshold
查询参数,该参数基于最低分数筛选出结果。 筛选后将从不同的调用集中融合结果。
此参数仍以预览版提供。 建议使用 2024-05-01-preview REST API 版本。
在此示例中,所有分数低于 0.8 的匹配项均从矢量搜索结果中排除,即使结果数低于 k
。
POST https://[service-name].search.azure.cn/indexes/[index-name]/docs/search?api-version=2024-05-01-preview
Content-Type: application/json
api-key: [admin key]
{
"vectorQueries": [
{
"kind": "vector",
"vector": [1.0, 2.0, 3.0],
"fields": "my-cosine-field",
"threshold": {
"kind": "vectorSimilarity",
"value": 0.8
}
}
]
}
后续步骤
接下来,请查看 Python、C# 或 JavaScript 语言的矢量查询代码示例。