你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
本文指导你完成如何创建矢量数据、为数据编制索引,然后查询容器中的数据的过程。
在使用矢量索引和搜索之前,必须先在 Azure Cosmos DB for NoSQL 中启用矢量搜索。 设置用于矢量搜索的 Azure Cosmos DB 容器后,将创建矢量嵌入策略。 接下来,将向量索引添加到容器索引策略。 然后,创建包含矢量索引和矢量嵌入策略的容器。 最后,对存储的数据执行矢量搜索。
先决条件
- 一个现有的 Azure Cosmos DB for NoSQL 帐户。
- 如果没有 Azure 订阅, 可免费试用 Azure Cosmos DB for NoSQL。
- 如果你当前有 Azure 订阅,请创建新的 Azure Cosmos DB for NoSQL 帐户。
- Azure Cosmos DB .NET SDK 的最新版本(版本:3.45.0 或更高版本,预览版:3.46.0-preview.0 或更高版本)。
启用功能
若要为 Azure Cosmos DB for NoSQL 启用矢量搜索,请执行以下步骤:
- 转到 Azure Cosmos DB for NoSQL 资源页。
- 在左窗格中的 “设置”下,选择“ 功能”。
- 在 Azure Cosmos DB for NoSQL 中选择矢量搜索。
- 阅读该功能的说明以确认要启用该功能。
- 选择 “启用” 以在 Azure Cosmos DB for NoSQL 中启用矢量搜索。
提示
或者,使用 Azure CLI 更新帐户的功能,以支持 Azure Cosmos DB for NoSQL 矢量搜索。
az cosmosdb update \
--resource-group <resource-group-name> \
--name <account-name> \
--capabilities EnableNoSQLVectorSearch
注册请求已自动批准,但可能需要 15 分钟才能生效。
了解矢量搜索所涉及的步骤
以下步骤假定你知道如何 设置 Azure Cosmos DB for NoSQL 帐户并创建数据库。 现有容器当前不支持矢量搜索功能。 需要创建新的容器。 创建容器时,可以指定容器级矢量嵌入策略和矢量索引策略。
让我们以一个示例为例,了解如何为基于 Internet 的书店创建数据库。 你想要存储每本书的标题、作者、ISBN 和说明信息。 还需要定义以下两个属性来包含矢量嵌入:
- 该
contentVector
属性包含从书籍的文本内容生成的 文本嵌入 。 例如,在创建嵌入之前,您需要连接title
、author
、isbn
和description
属性。 - 该
coverImageVector
属性是从 书籍封面的图像生成的。
若要执行矢量搜索,请执行以下作:
- 为要执行矢量搜索的字段创建并存储矢量嵌入。
- 在矢量嵌入策略中指定矢量嵌入路径。
- 在容器的索引策略中包含所需的任何向量索引。
对于本文的后续部分,请考虑容器中存储的项的以下结构:
{
"title": "book-title",
"author": "book-author",
"isbn": "book-isbn",
"description": "book-description",
"contentVector": [2, -1, 4, 3, 5, -2, 5, -7, 3, 1],
"coverImageVector": [0.33, -0.52, 0.45, -0.67, 0.89, -0.34, 0.86, -0.78]
}
为容器创建矢量嵌入策略
现在需要定义容器向量策略。 此策略提供了用于通知 Azure Cosmos DB 查询引擎如何处理系统函数中的 VectorDistance
向量属性的信息。 如果选择指定一个,此策略还会向向量索引策略提供必要的信息。
容器向量策略中包括以下信息:
参数 | DESCRIPTION |
---|---|
path |
包含向量的属性路径。 |
datatype |
矢量的元素的类型。 (默认值为 Float32 。) |
dimensions |
路径中每个向量的长度。 (默认值为 1536 。) |
distanceFunction |
用于计算距离/相似度的指标。 (默认值为 Cosine 。) |
对于包含书籍详细信息的示例,矢量策略可能如以下示例所示:
Database db = await client.CreateDatabaseIfNotExistsAsync("vector-benchmarking");
List<Embedding> embeddings = new List<Embedding>()
{
new Embedding()
{
Path = "/coverImageVector",
DataType = VectorDataType.Float32,
DistanceFunction = DistanceFunction.Cosine,
Dimensions = 8,
},
new Embedding()
{
Path = "/contentVector",
DataType = VectorDataType.Float32,
DistanceFunction = DistanceFunction.Cosine,
Dimensions = 10,
}
};
在索引策略中创建矢量索引
确定矢量嵌入路径后,必须将向量索引添加到索引策略。 目前,Azure Cosmos DB for NoSQL 的矢量搜索功能仅在新容器上受支持。 创建容器时,应用向量策略。 以后无法修改策略。 索引策略类似于以下示例:
Collection<Embedding> collection = new Collection<Embedding>(embeddings);
ContainerProperties properties = new ContainerProperties(id: "vector-container", partitionKeyPath: "/id")
{
VectorEmbeddingPolicy = new(collection),
IndexingPolicy = new IndexingPolicy()
{
VectorIndexes = new()
{
new VectorIndexPath()
{
Path = "/vector",
Type = VectorIndexType.QuantizedFlat,
}
}
},
};
properties.IndexingPolicy.IncludedPaths.Add(new IncludedPath { Path = "/*" });
properties.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath { Path = "/vector/*" });
重要
将向量路径添加到索引策略的 excludedPaths
节,以确保插入性能的优化。 excludedPaths
不添加向量路径会增加矢量插入的请求单位费用和延迟时间。
运行矢量相似性搜索查询
使用所需的向量策略创建容器并将矢量数据插入容器后,请在查询中使用 VectorDistance 系统函数执行矢量搜索。
假设你想要通过查看描述来搜索有关食物食谱的书籍。 首先需要获取查询文本的嵌入。 在这种情况下,你可能希望为查询文本 food recipe
生成嵌入内容。 在为搜索查询生成嵌入后,您可以在矢量搜索查询的VectorDistance
函数中使用该嵌入,以获取与查询类似的所有项。
SELECT TOP 10 c.title, VectorDistance(c.contentVector, [1,2,3,4,5,6,7,8,9,10]) AS SimilarityScore
FROM c
ORDER BY VectorDistance(c.contentVector, [1,2,3,4,5,6,7,8,9,10])
此查询检索书名以及与你的查询相对应的相似度分数。 下面是一个使用 .NET 的示例:
float[] embedding = {1f,2f,3f,4f,5f,6f,7f,8f,9f,10f};
var queryDef = new QueryDefinition(
query: $"SELECT c.title, VectorDistance(c.contentVector,@embedding) AS SimilarityScore FROM c ORDER BY VectorDistance(c.contentVector,@embedding)"
).WithParameter("@embedding", embedding);
using FeedIterator<Object> feed = container.GetItemQueryIterator<Object>(
queryDefinition: queryDef
);
while (feed.HasMoreResults)
{
FeedResponse<Object> response = await feed.ReadNextAsync();
foreach ( Object item in response)
{
Console.WriteLine($"Found item:\t{item}");
}
}