Spanner ベクトル検索のスタートガイド

1. はじめに

Spanner は、水平スケーリングが可能なフルマネージドのグローバル分散データベース サービスで、リレーショナルと非リレーショナルの両方の運用ワークロードに最適です。

厳密な K 最近傍機能のリリースにより、Spanner はスケーラビリティの高いベクトル データベースとしてもなり、類似検索またはセマンティック検索を実行し、生成 AI アプリケーションに検索拡張生成(RAG)を大規模に実装できるようになりました。Spanner のベクトル検索クエリは、運用データに対する他のクエリと同様に、トランザクションが commit されるとすぐに最新のリアルタイム データを返します。

このラボでは、Spanner を活用してベクトル検索を実行し、SQL を使用して VertexAI の Model Garden からエンベディング モデルと LLM モデルにアクセスするために必要な基本機能の設定について説明します。

アーキテクチャは次のようになります。

d179a760add7adc0.png

作成するアプリの概要

このラボでは、次の作業を行います。

  • Spanner インスタンスの作成
  • Spanner のデータベース スキーマを設定して、VertexAI のエンベディング モデルと LLM モデルと統合する
  • 小売データセットを読み込む
  • データセットに対して類似性検索クエリを発行する
  • LLM モデルにコンテキストを提供して、プロダクト固有のレコメンデーションを生成します。

学習内容

  • Spanner インスタンスの設定方法
  • VertexAI と統合する方法
  • Spanner を使用してベクトル検索を行い、小売データセット内の類似商品を見つける方法

必要なもの

  • 請求先アカウントに接続されている Google Cloud プロジェクト。
  • ウェブブラウザ(ChromeFirefox など)

2. 設定と要件

プロジェクトを作成する

Google アカウント(Gmail または Google Apps)をお持ちでない場合は、1 つ作成する必要があります。Google Cloud Platform コンソール(console.cloud.google.com)にログインし、新しいプロジェクトを作成します。

すでにプロジェクトが存在する場合は、コンソールの左上にあるプロジェクト選択プルダウン メニューをクリックします。

6c9406d9b014760.png

表示されるダイアログで [新しいプロジェクト] ボタンをクリックして新しいプロジェクトを作成します。

949d83c8a4ee17d9.png

まだプロジェクトが存在しない場合は、次のような最初のプロジェクトを作成するためのダイアログが表示されます。

870a3cbd6541ee86.png

続いて表示されるプロジェクト作成ダイアログでは、新しいプロジェクトの詳細を入力できます。

6a92c57d3250a4b3.png

プロジェクト ID を忘れないようにしてください。プロジェクト ID は、すべての Google Cloud プロジェクトを通じて一意の名前にする必要があります(上記の名前はすでに使用されているため使用できません)。以降、この Codelab では PROJECT_ID と呼びます。

次に、Google Cloud リソースを使用して Spanner API を有効にするために、Cloud Console で課金を有効化します(まだ行っていない場合)。

15d0ef27a8fbab27.png

この Codelab をすべて実行しても費用はかかりませんが、より多くのリソースを使用する場合や実行したままにする場合は、コストが高くなる可能性があります(このドキュメントの最後にある「クリーンアップ」セクションをご覧ください)。Google Cloud Spanner の料金については、こちらをご覧ください。

Google Cloud Platform の新規ユーザーの皆さんには、$300 の無料トライアルをご利用いただけます。その場合は、この Codelab を完全に無料でご利用いただけます。

Google Cloud Shell の設定

Google Cloud と Spanner はノートパソコンからリモートで操作でき、この Codelab では、Google Cloud Shell(Cloud 上で動作するコマンドライン環境)を使用します。

この Debian ベースの仮想マシンには、必要な開発ツールがすべて揃っています。永続的なホーム ディレクトリが 5 GB 用意されており、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 コンソール ダッシュボードで確認します。

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 では、1 つのインスタンスで複数のデータベースを使用できます。

データベースはスキーマを定義する場所です。また、データベースにアクセスできるユーザーの制御、カスタム暗号化の設定、オプティマイザーの構成、保持期間の設定を行うこともできます。

データベースを作成するには、ここでも 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

スキーマは 2 つの部分からなりますまず、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] ボタンをクリックし、スキーマが作成されるまで数秒待ちます。

次に、2 つのモデルを作成し、VertexAI モデルのエンドポイントに構成します。

1 つ目のモデルはテキストからエンベディングを生成するために使用されるエンベディング モデルで、2 つ目のモデルは Spanner のデータに基づいてレスポンスを生成するために使用される LLM モデルです。

次のスキーマを 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.png

データを読み込む

ここで、いくつかの商品をデータベースに挿入する必要があります。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 データベースに読み込みました。

次回

次に、エンベディング モデルと統合して商品説明のエンベディングを生成するとともに、テキスト検索リクエストをエンベディングに変換して関連する商品を検索します。

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 と VertexAI のモデルとのインテグレーションを活用して、SQL を使用して商品説明のエンベディングと検索リクエストのエンベディングを作成しました。また、ベクトル検索を実行して、検索リクエストに一致する類似商品を見つけました。

次のステップ

次に、検索結果を使用して LLM にフィードし、商品ごとにカスタム レスポンスを生成しましょう。

6. LLM を操作する

Spanner を使用すると、VertexAI から提供される 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.png

最初の製品は、商品説明に記載されている年齢層から 3 歳(2 ~ 4 歳)向けです。他の製品は適していません。

まとめ

次のステップ

次はクリーンアップです。

7. クリーンアップ(省略可)

クリーンアップするには、Cloud コンソールの Cloud Spanner セクションに移動し、Codelab で作成した retail-demo インスタンスを削除します。

41cbc1a84b3588d5.png

8. 完了

これで、Spanner の組み込みベクトル検索を使用した類似検索の実行が完了しました。さらに、SQL を使用して直接生成 AI 機能を提供するために、エンベディング モデルと LLM モデルを扱うのがいかに簡単であるかを確認しました。

次のステップ

Spanner の厳密最近傍(KNN ベクトル検索)機能の詳細については、https://cloud.google.com/spanner/docs/find-k-nearest-neighbors をご覧ください。

Spanner の VertexAI インテグレーションを使用して SQL でオンライン予測を実行する方法の詳細については、https://cloud.google.com/spanner/docs/ml をご覧ください。