本页面介绍了如何在 Spanner Graph 中使用向量搜索来查找 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 Graph 中的步骤执行以下操作:
插入必要图表数据后,请对数据库进行以下更新。
在图表数据库中插入其他向量数据
如需对图表数据库进行必需的更新,请执行以下操作:
向
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]
向量嵌入表示的休闲旅游和度假账号的前 2 个 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]
向量嵌入表示的休闲旅游和度假账号的前 2 个近似最近邻。
图表提示会强制查询优化器在查询执行计划中使用指定的向量索引。
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 | 为旅行节省资金 |
后续步骤
- 在 Spanner 中通过查找 K 最近邻来执行向量相似度搜索。
- 查找近似最近邻、创建向量索引和查询向量嵌入。
- 获取 Vertex AI 文本嵌入
- 详细了解 Spanner Graph 查询。
- 了解对查询进行调优的最佳实践。