Spanner 矢量搜索使用入门

1. 简介

Spanner 是一种可横向扩容的全球分布式全代管式数据库服务,非常适合关系型和非关系型运营工作负载。

随着精确 K 最近邻功能的发布,Spanner 现在也是一个扩缩能力极强的矢量数据库,使您能够在生成式 AI 应用中大规模执行相似度或语义搜索,并实现检索增强生成 (RAG)。事务提交后,Spanner 的矢量搜索查询就会立即返回最新的实时数据,就像对运营数据执行任何其他查询一样。

在本实验中,您将了解如何设置使用 Spanner 执行矢量搜索所需的基本功能,以及如何使用 SQL 从 Vertex AI 模型库访问嵌入和 LLM 模型。

架构将如下所示:

d179a760add7adc0.png

构建内容

在本实验中,您将:

  • 创建 Spanner 实例
  • 设置 Spanner 的数据库架构以与 Vertex AI 中的嵌入和 LLM 模型集成
  • 加载零售数据集
  • 针对数据集发出相似度搜索查询
  • 为 LLM 模型提供背景信息,以生成针对特定产品的建议。

学习内容

  • 如何设置 Spanner 实例
  • 如何与 VertexAI 集成
  • 如何使用 Spanner 执行矢量搜索,在零售数据集中查找类似项

所需条件

  • 与结算账号关联的 Google Cloud 项目。
  • 网络浏览器,例如 ChromeFirefox

2. 设置和要求

创建项目

如果您还没有 Google 账号(Gmail 或 Google Apps),则必须创建一个。登录 Google Cloud Platform 控制台 ( console.cloud.google.com) 并创建一个新项目。

如果您已经有一个项目,请点击控制台左上方的项目选择下拉菜单:

6c9406d9b014760.png

然后在出现的对话框中点击“新建项目”按钮以创建一个新项目:

949d83c8a4ee17d9

如果您还没有项目,则应该看到一个类似这样的对话框来创建您的第一个项目:

870a3cbd6541ee86.png

随后的项目创建对话框可让您输入新项目的详细信息:

6a92c57d3250a4b3.png

请记住项目 ID,它是所有 Google Cloud 项目中的唯一名称(很抱歉,上述名称已被占用,您无法使用!)。稍后,此 Codelab 将将其称为 PROJECT_ID。

接下来,您需要在 Developers Console 中启用结算功能(如果您尚未执行此操作),以便使用 Google Cloud 资源并启用 Spanner API

15d0ef27a8fbab27.png

在此 Codelab 中运行不会花费您超过几美元,但是如果您决定使用更多的资源或让它们运行(请参阅本文档末尾的“清理”部分),则可能会花费更多。如需了解 Google Cloud Spanner 价格,请参阅此处

Google Cloud Platform 的新用户均有资格获享 $300 赠金,免费试用此 Codelab。

Google Cloud Shell 设置

虽然 Google Cloud 和 Spanner 可以从笔记本电脑远程操作,但在此 Codelab 中,我们将使用 Google Cloud Shell,这是一个在云端运行的命令行环境。

基于 Debian 的这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证。这意味着在本 Codelab 中,您只需要一个浏览器(没错,它适用于 Chromebook)。

  1. 如需从 Cloud 控制台激活 Cloud Shell,只需点击“激活 Cloud Shell”图标 gcLMt5IuEcJJNnMId-Bcz3sxCd0rZn7IzT_r95C8UZeqML68Y1efBG_B0VRp7hc7qiZTLAF-TXD7SsOadxn8uadgHhaLeASnVS3ZHK39eOlKJOgj9SJua_oeGhMxRrbOg3qigddS2A 即可(预配和连接到环境应该只需要片刻时间)。

JjEuRXGg0AYYIY6QZ8d-66gx_Mtc-_jDE9ijmbXLJSAXFvJt-qUpNtsBsYjNpv2W6BQSrDc1D-ARINNQ-1EkwUhz-iUK-FUCZhJ-NtjvIEx9pIkE-246DomWuCfiGHK78DgoeWkHRw

Screen Shot 2017-06-14 at 10.13.43 PM.png

在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的 PROJECT_ID。

gcloud auth list

命令输出

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
gcloud config list project

命令输出

[core]
project = <PROJECT_ID>

如果出于某种原因未设置项目,只需发出以下命令即可:

gcloud config set project <PROJECT_ID>

正在查找您的 PROJECT_ID?检查您在设置步骤中使用的 ID,或在 Cloud Console 信息中心查找该 ID:

158fNPfwSxsFqz9YbtJVZes8viTS3d1bV4CVhij3XPxuzVFOtTObnwsphlm6lYGmgdMFwBJtc-FaLrZU7XHAg_ZYoCrgombMRR3h-eolLPcvO351c5iBv506B3ZwghZoiRg6cz23Qw

默认情况下,Cloud Shell 还会设置一些环境变量,这对您日后运行命令可能会很有用。

echo $GOOGLE_CLOUD_PROJECT

命令输出

<PROJECT_ID>

启用 Spanner API

gcloud services enable spanner.googleapis.com

摘要

在此步骤中,您已设置项目(如果您还没有项目)、激活 Cloud Shell 并启用所需的 API。

后续步骤

接下来,您将设置 Spanner 实例和数据库。

3. 创建 Spanner 实例和数据库

创建 Spanner 实例

在此步骤中,我们将为 Codelab 设置 Spanner 实例。为此,请打开 Cloud Shell 并运行以下命令:

export SPANNER_INSTANCE_ID=retail-demo
gcloud spanner instances create $SPANNER_INSTANCE_ID \
--config=regional-us-central1 \
--description="spanner AI retail demo" \
--nodes=1

命令输出

$ gcloud spanner instances create $SPANNER_INSTANCE_ID \
--config=regional-us-central1 \
--description="spanner AI retail demo" \
--nodes=1
Creating instance...done.  

创建数据库

实例运行后,您就可以创建数据库了。Spanner 允许在单个实例上使用多个数据库。

数据库是您定义架构的地方。您还可以控制谁有权访问数据库、设置自定义加密、配置优化工具以及设置保留期限。

如需创建数据库,请再次使用 gcloud 命令行工具:

export SPANNER_DATABASE=cymbal-bikes
gcloud spanner databases create $SPANNER_DATABASE \
 --instance=$SPANNER_INSTANCE_ID

命令输出

$ gcloud spanner databases create $SPANNER_DATABASE \
 --instance=$SPANNER_INSTANCE_ID
Creating database...done.

摘要

在此步骤中,您已创建 Spanner 实例和数据库。

后续步骤

接下来,您将设置 Spanner 架构和数据。

4. 加载 Cymbal 架构和数据

创建 Cymbal 架构

如需设置架构,请转到 Spanner Studio:

3e1a0fed928b33cf.png

架构包含两个部分。首先,您需要添加 products 表。复制此语句并将其粘贴到空的标签页中。

对于架构,请复制此 DDL 并将其粘贴到框中:

CREATE TABLE products (
categoryId INT64 NOT NULL,
productId INT64 NOT NULL,
productName STRING(MAX) NOT NULL,
productDescription STRING(MAX) NOT NULL,
productDescriptionEmbedding ARRAY<FLOAT64>,
createTime TIMESTAMP NOT NULL OPTIONS (
allow_commit_timestamp = true
),
inventoryCount INT64 NOT NULL,
priceInCents INT64,
) PRIMARY KEY(categoryId, productId);

然后,点击 run 按钮并等待几秒钟,以便系统创建您的架构。

接下来,您将创建两个模型并将其配置为 Vertex AI 模型端点。

第一个模型是嵌入模型,用于根据文本生成嵌入,第二个模型是 LLM 模型,用于根据 Spanner 中的数据生成回答。

将以下架构粘贴到 Spanner Studio 中的新标签页中:

CREATE MODEL EmbeddingsModel INPUT(
content STRING(MAX),
) OUTPUT(
embeddings STRUCT<statistics STRUCT<truncated BOOL, token_count FLOAT64>, values ARRAY<FLOAT64>>,
) REMOTE OPTIONS (
endpoint = '//aiplatform.googleapis.com/projects/<PROJECT_ID>/locations/us-central1/publishers/google/models/textembedding-gecko@003'
);

CREATE MODEL LLMModel INPUT(
prompt STRING(MAX),
) OUTPUT(
content STRING(MAX),
) REMOTE OPTIONS (
endpoint = '//aiplatform.googleapis.com/projects/<PROJECT_ID>/locations/us-central1/publishers/google/models/text-bison@001',
default_batch_size = 1
);

然后,点击 run 按钮并等待几秒钟,直到模型创建完成。

在 Spanner Studio 的左侧窗格中,您应该会看到以下表和模型:

62455aa4b0e839d9

加载数据

现在,您需要将一些商品插入数据库中。在 Spanner Studio 中打开一个新标签页,然后复制并粘贴以下插入语句:

INSERT INTO products (categoryId, productId, productName, productDescription, createTime, inventoryCount, priceInCents)
VALUES (1, 1, "Cymbal Helios Helmet", "Safety meets style with the Cymbal children's bike helmet. Its lightweight design, superior ventilation, and adjustable fit ensure comfort and protection on every ride. Stay bright and keep your child safe under the sun with Cymbal Helios!", PENDING_COMMIT_TIMESTAMP(), 100, 10999),
(1, 2, "Cymbal Sprout", "Let their cycling journey begin with the Cymbal Sprout, the ideal balance bike for beginning riders ages 2-4 years. Its lightweight frame, low seat height, and puncture-proof tires promote stability and confidence as little ones learn to balance and steer. Watch them sprout into cycling enthusiasts with Cymbal Sprout!", PENDING_COMMIT_TIMESTAMP(), 10, 13999),
(1, 3, "Cymbal Spark Jr.", "Light, vibrant, and ready for adventure, the Spark Jr. is the perfect first bike for young riders (ages 5-8). Its sturdy frame, easy-to-use brakes, and puncture-resistant tires inspire confidence and endless playtime. Let the spark of cycling ignite with Cymbal!", PENDING_COMMIT_TIMESTAMP(), 34, 13900),
(1, 4, "Cymbal Summit", "Conquering trails is a breeze with the Summit mountain bike. Its lightweight aluminum frame, responsive suspension, and powerful disc brakes provide exceptional control and comfort for experienced bikers navigating rocky climbs or shredding downhill. Reach new heights with Cymbal Summit!", PENDING_COMMIT_TIMESTAMP(), 0, 79999),
(1, 5, "Cymbal Breeze", "Cruise in style and embrace effortless pedaling with the Breeze electric bike. Its whisper-quiet motor and long-lasting battery let you conquer hills and distances with ease. Enjoy scenic rides, commutes, or errands with a boost of confidence from Cymbal Breeze!", PENDING_COMMIT_TIMESTAMP(), 72, 129999),
(1, 6, "Cymbal Trailblazer Backpack", "Carry all your essentials in style with the Trailblazer backpack. Its water-resistant material, multiple compartments, and comfortable straps keep your gear organized and accessible, allowing you to focus on the adventure. Blaze new trails with Cymbal Trailblazer!", PENDING_COMMIT_TIMESTAMP(), 24, 7999),
(1, 7, "Cymbal Phoenix Lights", "See and be seen with the Phoenix bike lights. Powerful LEDs and multiple light modes ensure superior visibility, enhancing your safety and enjoyment during day or night rides. Light up your journey with Cymbal Phoenix!", PENDING_COMMIT_TIMESTAMP(), 87, 3999),
(1, 8, "Cymbal Windstar Pump", "Flat tires are no match for the Windstar pump. Its compact design, lightweight construction, and high-pressure capacity make inflating tires quick and effortless. Get back on the road in no time with Cymbal Windstar!", PENDING_COMMIT_TIMESTAMP(), 36, 24999),
(1, 9,"Cymbal Odyssey Multi-Tool","Be prepared for anything with the Odyssey multi-tool. This handy gadget features essential tools like screwdrivers, hex wrenches, and tire levers, keeping you ready for minor repairs and adjustments on the go. Conquer your journey with Cymbal Odyssey!", PENDING_COMMIT_TIMESTAMP(), 52, 999),
(1, 10,"Cymbal Nomad Water Bottle","Stay hydrated on every ride with the Nomad water bottle. Its sleek design, BPA-free construction, and secure lock lid make it the perfect companion for staying refreshed and motivated throughout your adventures. Hydrate and explore with Cymbal Nomad!", PENDING_COMMIT_TIMESTAMP(), 42, 1299);

点击 run 按钮插入数据。

摘要

在此步骤中,您创建了架构并将一些基本数据加载到 cymbal-bikes 数据库中。

后续步骤

接下来,您将与 Embedding 模型集成,以便为商品说明生成嵌入,并将文本搜索请求转换为嵌入以搜索相关商品。

5. 使用嵌入

为商品说明生成向量嵌入

为使相似度搜索适用于商品,您需要为商品说明生成嵌入。

在架构中创建 EmbeddingsModel 后,这是一个简单的 UPDATE DML 语句。

UPDATE products p1
SET productDescriptionEmbedding =
(SELECT embeddings.values from ML.PREDICT(MODEL EmbeddingsModel,
(SELECT productDescription as content FROM products p2 where p2.productId=p1.productId)))
WHERE categoryId=1;

点击 run 按钮以更新商品说明。

在此示例中,您将通过 SQL 查询提供自然语言搜索请求。此查询会将搜索请求转换为嵌入,然后根据在上一步生成的商品说明的存储嵌入来搜索类似结果。

-- Use Spanner's vector search, and integration with embedding and LLM models to
-- return items that are semantically relevant and available in inventory based on
-- real-time data.


SELECT productName, productDescription, inventoryCount, COSINE_DISTANCE(
productDescriptionEmbedding,
(   SELECT embeddings.values
FROM ML.PREDICT(
MODEL EmbeddingsModel,
(SELECT "I'd like to buy a starter bike for my 3 year old child" as content)
)
)
) as distance
FROM products
WHERE inventoryCount > 0
ORDER BY distance
LIMIT 5;

点击 run 按钮可查找类似商品。结果应如下所示:

672e111753077fcf.png

请注意,查询中还使用了其他过滤条件,例如只对有货产品 (inventoryCount > 0) 感兴趣。

摘要

在此步骤中,您利用了 Spanner 与 Vertex AI 中的模型的集成,使用 SQL 创建了商品说明嵌入和搜索请求嵌入。您还执行了矢量搜索,以查找与搜索请求匹配的类似商品。

后续步骤

接下来,我们将搜索结果馈送到 LLM,以便为每种产品生成自定义响应。

6. 与 LLM 合作

Spanner 可让您轻松与 Vertex AI 提供的 LLM 模型集成。这使开发者能够使用 SQL 与 LLM 直接交互,而无需应用执行相应逻辑。

例如,我们获得了来自用户 "I'd like to buy a starter bike for my 3 year old child". 的上一个 SQL 查询的结果

对于每条结果,开发者希望使用以下提示回答商品是否适合用户:

"Answer with ‘Yes' or ‘No' and explain why: Is this a good fit for me? I'd like to buy a starter bike for my 3 year old child"

您可以使用如下查询:

-- Use an LLM to analyze this list and provide a recommendation on whether each
-- product is a good fit for the user. We use the vector search and real time
-- inventory data to first filter the products to reduce the size of the prompt to
-- the LLM.
SELECT productName, productDescription, inventoryCount, content AS LLMResponse
FROM ML.PREDICT(
MODEL LLMModel,
(   SELECT
inventoryCount,
productName,
productDescription,
CONCAT(
"Answer with ‘Yes' or ‘No' and explain why: Is this a good fit for me?",
"I'd like to buy a starter bike for my 3 year old child \n",
"Product Name: ", productName, "\n",
"Product Description:", productDescription) AS prompt,
FROM products
WHERE inventoryCount > 0
ORDER by COSINE_DISTANCE(
productDescriptionEmbedding,
(   SELECT embeddings.values
FROM ML.PREDICT(
MODEL EmbeddingsModel,
( SELECT "I'd like to buy a starter bike for my 3 year old child" as content)
)
)
) LIMIT 5
),
STRUCT(256 AS maxOutputTokens)
);

点击 run 按钮以发出查询。结果应如下所示:

35878cd0f88f1470

根据商品说明中的年龄段(2-4 岁),第一件商品适合 3 岁儿童。其他产品则不适合。

摘要

后续步骤

接下来该清理了!

7. 清理(可选)

如需进行清理,只需进入 Cloud 控制台的 Cloud Spanner 部分,然后删除我们在此 Codelab 中创建的“retail-demo”实例即可。

41cbc1a84b3588d5.png

8. 恭喜!

恭喜,您已成功使用 Spanner 的内置矢量搜索执行相似度搜索。此外,您还看到,使用嵌入和 LLM 模型来直接使用 SQL 提供生成式 AI 功能是多么容易。

后续操作

如需详细了解 Spanner 的最近邻(KNN 向量搜索)功能,请访问:https://cloud.google.com/spanner/docs/find-k-nearest-neighbors

您还可以访问以下网址,详细了解如何使用 Spanner 的 VertexAI 集成功能通过 SQL 执行在线预测:https://cloud.google.com/spanner/docs/ml