本页介绍了如何在 Spanner 图中使用向量搜索查找 K 最近邻 (KNN) 和近似最近邻 (ANN)。您可以使用向量距离函数执行 KNN 和 ANN 向量搜索,以便在生成式 AI 应用中实现相似度搜索或检索增强生成等用例。
Spanner Graph 支持以下距离函数来执行 KNN 向量相似度搜索:
COSINE_DISTANCE()
:衡量两个向量之间的最短距离。EUCLIDEAN_DISTANCE()
:测量两个向量之间的余弦角度。DOT_PRODUCT()
:计算角度余弦乘以相应矢量大小的乘积。如果您知道数据集中的所有向量嵌入均已归一化,则可以使用DOT_PRODUCT()
作为距离函数。
如需了解详情,请参阅通过查找 K 个最近邻在 Spanner 中执行向量相似度搜索。
Spanner Graph 还支持以下近似距离函数,以执行 ANN 向量相似度搜索:
APPROX_COSINE_DISTANCE
:衡量两个向量之间的近似最短距离。APPROX_EUCLIDEAN_DISTANCE
:测量两个向量之间的夹角的近似余弦值。APPROX_DOT_PRODUCT
:计算角度的近似余弦乘以相应矢量大小的乘积。如果您知道数据集中的所有向量嵌入都已归一化,则可以将DOT_PRODUCT()
用作距离函数。
如需了解详情,请参阅查找近似最近邻、创建矢量索引和查询矢量嵌入。
准备工作
如需运行本文档中的示例,您必须先按照设置和查询 Spanner 图中的步骤执行以下操作:
插入基本图表数据后,请对数据库进行以下更新。
在图数据库中插入其他矢量数据
如需对图表数据库进行必要的更新,请执行以下操作:
向
Account
输入表添加新列nick_name_embeddings
。ALTER TABLE Account ADD COLUMN nick_name_embeddings ARRAY<FLOAT32>(vector_length=>4);
向
nick_name
列添加数据。UPDATE Account SET nick_name = "Fund for a refreshing tropical vacation" WHERE id = 7; UPDATE Account SET nick_name = "Fund for a rainy day!" WHERE id = 16; UPDATE Account SET nick_name = "Saving up for travel" WHERE id = 20;
为
nick_name
列中的文本创建嵌入,并将其填充到新的nick_name_embeddings
列中。如需为 Spanner Graph 中的运营数据生成 Vertex AI 嵌入,请参阅获取 Vertex AI 文本嵌入。
为了说明问题,我们的示例使用了人工的低维向量值。
UPDATE Account SET nick_name_embeddings = ARRAY<FLOAT32>[0.3, 0.5, 0.8, 0.7] WHERE id = 7; UPDATE Account SET nick_name_embeddings = ARRAY<FLOAT32>[0.4, 0.9, 0.7, 0.1] WHERE id = 16; UPDATE Account SET nick_name_embeddings = ARRAY<FLOAT32>[0.2, 0.5, 0.6, 0.6] WHERE id = 20;
向
AccountTransferAccount
输入表格添加两个新列:notes
和notes_embeddings
。ALTER TABLE AccountTransferAccount ADD COLUMN notes STRING(MAX); ALTER TABLE AccountTransferAccount ADD COLUMN notes_embeddings ARRAY<FLOAT32>(vector_length=>4);
为
notes
列中的文本创建嵌入,并将其填充到notes_embeddings
列中。如需为 Spanner Graph 中的运营数据生成 Vertex AI 嵌入,请参阅获取 Vertex AI 文本嵌入。
为了说明问题,我们的示例使用了人工的低维向量值。
UPDATE AccountTransferAccount SET notes = "for shared cost of dinner", notes_embeddings = ARRAY<FLOAT32>[0.3, 0.5, 0.8, 0.7] WHERE id = 16 AND to_id = 20; UPDATE AccountTransferAccount SET notes = "fees for tuition", notes_embeddings = ARRAY<FLOAT32>[0.1, 0.9, 0.1, 0.7] WHERE id = 20 AND to_id = 7; UPDATE AccountTransferAccount SET notes = 'loved the lunch', notes_embeddings = ARRAY<FLOAT32>[0.4, 0.5, 0.7, 0.9] WHERE id = 20 AND to_id = 16;
向
Account
和AccountTransferAccount
输入表添加新列后,使用以下语句更新属性图定义。如需了解详情,请参阅更新现有节点或边定义。CREATE OR REPLACE PROPERTY GRAPH FinGraph NODE TABLES (Account, Person) EDGE TABLES ( PersonOwnAccount SOURCE KEY (id) REFERENCES Person (id) DESTINATION KEY (account_id) REFERENCES Account (id) LABEL Owns, AccountTransferAccount SOURCE KEY (id) REFERENCES Account (id) DESTINATION KEY (to_id) REFERENCES Account (id) LABEL Transfers );
查找 K 个最近邻
在以下示例中,使用 EUCLIDEAN_DISTANCE()
函数对图数据库中的节点和边执行 KNN 向量搜索。
对图节点执行 KNN 向量搜索
您可以对 Account
节点的 nick_name_embeddings
属性执行 KNN 向量搜索。此 KNN 向量搜索会返回账号所有者的 name
和账号的 nick_name
。在以下示例中,结果显示了休闲旅行和度假的账号(由 [0.2, 0.4, 0.9, 0.6]
向量嵌入表示)的前两个 K 个最近邻。
GRAPH FinGraph
MATCH (p:Person)-[:Owns]->(a:Account)
RETURN p.name, a.nick_name
ORDER BY EUCLIDEAN_DISTANCE(a.nick_name_embeddings,
-- An illustrative embedding for 'accounts for leisure travel and vacation'
ARRAY<FLOAT32>[0.2, 0.4, 0.9, 0.6])
LIMIT 2;
结果
name | nick_name |
---|---|
Alex | 为热带度假储备资金 |
Dana | 存钱准备旅行 |
对图边执行 KNN 向量搜索
您可以对 Owns
边的 notes_embeddings
属性执行 KNN 向量搜索。此 KNN 向量搜索会返回账号所有者的 name
和转移的 notes
。在以下示例中,结果显示了餐费(由 [0.2, 0.4, 0.9, 0.6]
向量嵌入表示)的前两个 K 个最近邻。
GRAPH FinGraph
MATCH (p:Person)-[:Owns]->(:Account)-[t:Transfers]->(:Account)
WHERE t.notes_embeddings IS NOT NULL
RETURN p.name, t.notes
ORDER BY EUCLIDEAN_DISTANCE(t.notes_embeddings,
-- An illustrative vector embedding for 'food expenses'
ARRAY<FLOAT32>[0.2, 0.4, 0.9, 0.6])
LIMIT 2;
结果
name | 注释 |
---|---|
Lee | 用于分摊晚餐费用 |
Dana | 非常喜欢午餐 |
创建向量索引并查找近似最近邻
如需执行 ANN 搜索,您必须创建一个专用矢量索引,供 Spanner Graph 用于加速矢量搜索。向量索引必须使用特定的距离衡量标准。您可以将 distance_type
参数设置为 COSINE
、DOT_PRODUCT
或 EUCLIDEAN
之一,从而选择最适合您的用例的距离衡量标准。如需了解详情,请参阅 VECTOR INDEX 语句。
在以下示例中,您将使用欧几里得距离类型在 Account
输入表的 nick_name_embedding
列上创建向量索引:
CREATE VECTOR INDEX NickNameEmbeddingIndex
ON Account(nick_name_embeddings)
WHERE nick_name_embeddings IS NOT NULL
OPTIONS (distance_type = 'EUCLIDEAN', tree_depth = 2, num_leaves = 1000);
对图节点执行 ANN 向量搜索
创建向量索引后,您可以对 Account
节点的 nick_name
属性执行 ANN 向量搜索。ANN 矢量搜索会返回账号所有者的 name
和账号的 nick_name
。在以下示例中,结果显示了休闲旅行和度假的账号(由 [0.2, 0.4, 0.9, 0.6]
向量嵌入表示)的前两个近似最近邻。
图表提示会强制查询优化器在查询执行计划中使用指定的矢量索引。
GRAPH FinGraph
MATCH (@{FORCE_INDEX=NickNameEmbeddingIndex} a:Account)
WHERE a.nick_name_embeddings IS NOT NULL
RETURN a, APPROX_EUCLIDEAN_DISTANCE(a.nick_name_embeddings,
-- An illustrative embedding for 'accounts for leisure travel and vacation'
ARRAY<FLOAT32>[0.2, 0.4, 0.9, 0.6],
options => JSON '{"num_leaves_to_search": 10}') AS distance
ORDER BY distance
LIMIT 2
NEXT
MATCH (p:Person)-[:Owns]->(a)
RETURN p.name, a.nick_name;
结果
name | nick_name |
---|---|
Alex | 为热带度假储备资金 |
Dana | 存钱准备旅行 |
后续步骤
- 通过查找 k 个最近邻在 Spanner 中执行向量相似度搜索。
- 查找近似最近邻、创建向量索引和查询向量嵌入。
- 获取 Vertex AI 文本嵌入
- 详细了解 Spanner 图查询。
- 了解优化查询的最佳实践。