本文介绍如何创建矢量数据、为数据编制索引,然后查询容器中的数据。
在使用矢量索引和搜索之前,必须先在 Azure Cosmos DB for NoSQL 中启用矢量搜索。 设置用于矢量搜索的 Azure Cosmos DB 容器后,将创建矢量嵌入策略。 接下来,将向量索引添加到容器索引策略。 然后,创建包含矢量索引和矢量嵌入策略的容器。 最后,对存储的数据执行矢量搜索。
先决条件
- 一个现有的适用于 NoSQL 的 Azure Cosmos DB 帐户。
- 如果没有 Azure 订阅,可以 创建一个。
- 如果有现有的 Azure 订阅, 请创建新的 Azure Cosmos DB for NoSQL 帐户。
- 最新版本的 Azure Cosmos DB JavaScript SDK (4.1.0 或更高版本)。
启用功能
若要为 Azure Cosmos DB for NoSQL 启用矢量搜索,请执行以下步骤:
- 转到 Azure Cosmos DB for NoSQL 资源页。
- 在左窗格中的 “设置”下,选择“ 功能”。
- 选择矢量搜索以用于 NoSQL API。
- 阅读该功能的说明以确认要启用该功能。
- 选择 “启用” 以在 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。 |
对于包含书籍详细信息的示例,矢量策略可能如以下示例所示:
const vectorEmbeddingPolicy: VectorEmbeddingPolicy = {
vectorEmbeddings: [
{
path: "/coverImageVector",
dataType: VectorEmbeddingDataType.Float32,
dimensions: 8,
distanceFunction: VectorEmbeddingDistanceFunction.DotProduct,
},
{
path: "/contentVector",
dataType: VectorEmbeddingDataType.Float32,
dimensions: 10,
distanceFunction: VectorEmbeddingDistanceFunction.Cosine,
},
],
};
在索引策略中创建矢量索引
确定矢量嵌入路径后,必须将向量索引添加到索引策略。 创建容器时,应用向量策略。 以后无法修改策略。 索引策略类似于以下示例:
const indexingPolicy: IndexingPolicy = {
vectorIndexes: [
{ path: "/coverImageVector", type: VectorIndexType.QuantizedFlat },
{ path: "/contentVector", type: VectorIndexType.DiskANN },
],
includedPaths: [
{
path: "/*",
},
],
excludedPaths: [
{
path: "/coverImageVector/*",
},
{
path: "/contentVector/*",
},
]
};
现在,像往常一样创建容器。
const containerName = "vector embedding container";
// create container
const { resource: containerdef } = await database.containers.createIfNotExists({
id: containerName,
vectorEmbeddingPolicy: vectorEmbeddingPolicy,
indexingPolicy: indexingPolicy,
});
运行矢量相似性搜索查询
使用所需的向量策略创建容器并将矢量数据插入容器后,请在查询中使用 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])
此查询检索书名以及与你的查询相对应的相似度分数。 下面是一个 JavaScript 示例:
const { resources } = await container.items
.query({
query: "SELECT c.title, VectorDistance(c.contentVector, @embedding) AS SimilarityScore FROM c ORDER BY VectorDistance(c.contentVector, @embedding)"
parameters: [{ name: "@embedding", value: [1,2,3,4,5,6,7,8,9,10] }]
})
.fetchAll();
for (const item of resources) {
console.log(`${itme.title}, ${item.SimilarityScore} is a capitol `);
}