生成 AI アプリケーションでの Spanner の使用を開始する

このチュートリアルでは、Spanner と Vertex AI を使用して生成 AI アプリケーションを構築する方法について説明します。

このアプリケーションでは、セマンティック類似度検索を実行して、自然言語クエリに一致する商品を見つけることができます。これは、単語の意味とコンテキストを捉えたテキストの数値表現であるエンベディングを使用することで実現されます。Vertex AI モデルを使用してこれらのエンベディングを生成し、Spanner にエンベディングを保存して検索します。このアプローチは、ユーザーが特定のキーワードではなく自然言語で欲しいものを説明する商品検索などのユースケースで特に役立ちます。

次のトピックでは、以下の方法について説明します。

  1. Google Cloud プロジェクトを作成する
  2. Spanner インスタンスを作成する
  3. データベースを作成する
  4. エンベディング モデルを作成する
  5. データを Spanner に読み込む
  6. データのエンベディングを生成する
  7. KNN ベクトル類似性検索を実行する
  8. ベクトル インデックスを使用してベクトル検索をスケーリングする
  9. リソースをクリーンアップする

Spanner の料金の詳細については、Spanner の料金をご覧ください。

Codelab を試すには、Spanner ベクトル検索を使ってみるをご覧ください。

始める前に

請求先アカウントに接続された Google Cloud プロジェクトを作成する必要があります。

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

  6. 通常、Spanner API は自動的に有効になります。それ以外の場合は、手動で有効にします。

    Spanner API を有効にする
  7. 通常、Vertex AI API は自動的に有効になります。それ以外の場合は、手動で有効にします。

    Vertex AI API を有効にする
    1. インスタンスとデータベースを作成するために必要な権限を取得するには、プロジェクトに対する Cloud Spanner 管理者 roles/spanner.admin)IAM ロールを付与するよう管理者に依頼してください。

    1. Cloud Spanner 管理者ロールが付与されていない場合、Spanner グラフに対してクエリを実行するために必要な権限を取得するには、プロジェクトに対する Cloud Spanner データベース リーダー roles/spanner.databaseReader)IAM ロールを付与するよう管理者に依頼してください。

    インスタンスの作成

    Spanner を初めて使用する際は、インスタンスを作成する必要があります。インスタンスとは、Spanner データベースによって使用されるリソースの割り当てのことです。このセクションでは、 Google Cloud コンソールを使用してインスタンスを作成する方法について説明します。

    1. Google Cloud コンソールで、[Spanner] ページに移動します。

      [Spanner] に移動

    2. Google Cloud プロジェクトを選択するか、まだ作成していない場合は新しく作成します。

    3. 次のいずれかを行います。

      1. まだ Spanner インスタンスを作成していない場合は、[Spanner へようこそ] ページで [プロビジョニングされたインスタンスを作成] をクリックします。
      2. Spanner インスタンスを作成している場合は、[インスタンス] ページで [インスタンスを作成] をクリックします。
    4. [エディションを選択] ページで、[Enterprise Plus] または [Enterprise] を選択します。

      Spanner ベクトル検索は、Enterprise エディションまたは Enterprise Plus エディションでのみ使用できます。異なるエディションを比較するには、[エディションを比較] をクリックします。詳細については、Spanner エディションの概要をご覧ください。

    5. [続行] をクリックします。

    6. [インスタンス名] にインスタンス名(test-instance など)を入力します。

    7. [インスタンス ID] で、インスタンス ID をそのままにしておくか、変更します。デフォルトでインスタンス名がインスタンス ID になりますが、変更できます。インスタンス名とインスタンス ID は同じものでも異なるものでもかまいません。

    8. [続行] をクリックします。

    9. [構成を選択] で、次の操作を行います。

      1. [リージョン] を選択したままにします。
      2. [構成を選択] でリージョンを選択します。選択したリージョンにインスタンスが保存され、複製されます。
      3. [続行] をクリックします。
    10. [コンピューティング容量を構成する] で、次の操作を行います。

      1. [ユニットを選択] で、[処理ユニット(PU)] を選択します。
      2. [スケーリング モードを選択] で [手動で割り当てる] を選択し、[数量] は 1,000 処理ユニットのままにします。
    11. [作成] をクリックします。 Google Cloud コンソールに、作成したインスタンスの [概要] ページが表示されます。

    データベースの作成

    インスタンスの実行が開始されたら、データベースを作成できます。スキーマはデータベースで定義します。

    1. Google Cloud コンソールで、[Spanner インスタンス] ページに移動します。

      [Spanner インスタンス] に移動

    2. 作成したインスタンスをクリックします(例: test-instance)。

    3. [概要] で、インスタンスの名前の下にある [データベースを作成] をクリックします。

    4. [データベース名] にデータベース名を入力します。例: example-db

    5. [データベース言語の選択] で、Google 標準 SQL を選択します。

      PostgreSQL 言語では Spanner ベクトル検索を使用できません。

    6. 次のスキーマを [DDL テンプレート] エディタタブにコピーして貼り付けます。スキーマは Products テーブルを定義します。

        CREATE TABLE products (
          categoryId INT64 NOT NULL,
          productId INT64 NOT NULL,
          productName STRING(MAX) NOT NULL,
          productDescription STRING(MAX) NOT NULL,
          productDescriptionEmbedding ARRAY<FLOAT32>,
          createTime TIMESTAMP NOT NULL OPTIONS (
          allow_commit_timestamp = true
          ), inventoryCount INT64 NOT NULL,
          priceInCents INT64,
        ) PRIMARY KEY(categoryId, productId);
      
    7. [暗号化オプションを表示する] で変更は行わないでください。

    8. [作成] をクリックします。 Google Cloud コンソールに、作成したデータベースの [概要] ページが表示されます。

    エンベディング モデルを作成する

    Spanner で CREATE MODEL DDL ステートメントを使用すると、データベースから Vertex AI モデルのエンドポイントへの参照が登録されます。モデルを登録したら、ML.PREDICT 関数を使用して、クエリでモデルにアクセスできます。

    次の例では、Vertex AI のテキスト エンベディング モデルを登録する方法を示します。このモデルは、類似性検索を実行して、データベース内の類似商品を検索するために使用されます。

    1. データベースの [概要] ページで、[Spanner Studio] をクリックします。
    2. [Spanner Studio] ページで、[ 新しいタブ] をクリックするか、空のエディタタブを使用します。
    3. 次のように入力します。

      CREATE MODEL EmbeddingsModel INPUT(
      content STRING(MAX),
      ) OUTPUT(
      embeddings STRUCT<values ARRAY<FLOAT32>>,
      ) REMOTE OPTIONS (
      endpoint = '//aiplatform.googleapis.com/projects/PROJECT_ID/locations/us-central1/publishers/google/models/TEXT_EMBEDDING_MODEL'
      );
      

      次のように置き換えます。

      • PROJECT_ID:Google Cloud プロジェクトで一意の永続的な識別子。
      • TEXT_EMBEDDING_MODEL: テキスト エンベディング モデルの名前。Vertex AI テキスト エンベディング モデルの一覧については、サポートされているモデルをご覧ください。
    4. [実行] をクリックしてモデルを作成します。

      モデルが正常に追加されると、[エクスプローラ] ペインに表示されます。

    データの読み込み

    Cymbal サンプルデータを products テーブルに読み込むには、次の操作を行います。

    1. 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);
      
    2. [実行] をクリックしてデータを挿入します。

    ベクトル エンベディングを生成する

    モデルを登録して Spanner にデータを読み込んだら、データの商品説明を使用してベクトル エンベディングを生成できます。ベクトル エンベディングは、単語の意味とコンテキストを捉える数値にテキストデータを変換します。この変換は、セマンティック検索を実行するうえで不可欠です。

    このステップでは、ML.PREDICT を使用して productDescription 列からエンベディングを生成し、productDescriptionEmbedding 列にデータを入力します。これにより、次のステップでベクトル類似性検索を実行できます。

    1. Spanner Studio の新しいタブで、次の更新ステートメントをコピーして貼り付けます。

      UPDATE products p1
      SET productDescriptionEmbedding =
        (SELECT embeddings.values
          FROM ML.PREDICT(MODEL EmbeddingsModel,
            (SELECT p1.productDescription as content)
          )
        )
      WHERE categoryId=1;
      
    2. [実行] をクリックして、エンベディングを生成します。

    次の例では、SQL クエリを使用して自然言語検索リクエストを指定します。SQL クエリは、以前に生成したベクトル エンベディングを使用してベクトル類似度検索を実行します。クエリは、次の処理を行って検索を実行します。

    • ML.PREDICT を使用して、指定された検索クエリ(「3 歳の子ども用の自転車を購入したい」)のエンベディングを生成します。
    • このクエリ エンベディングと商品テーブルの各商品の productDescriptionEmbedding の間の COSINE_DISTANCE を計算して、Cymbal ストアで類似する結果を見つけます。
    • 結果をフィルタして、inventoryCount が 0 より大きい商品のみを含めます。
    • 計算された距離で結果を並べ替え、最も近い上位 5 つの一致と productNameproductDescriptioninventoryCount を返します。
    1. Spanner Studio の新しいタブで、次のクエリをコピーして貼り付けます。

      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;
      
    2. [実行] をクリックすると、検索テキストに最も一致する商品が返されます。

      出力例:

      /*-----------------+--------------------+----------------+--------------------*
      | productName      | productDescription | inventoryCount | distance           |
      +------------------+--------------------+----------------+--------------------+
      | Cymbal Sprout    | Let their cycling  | 10             | 0.3094387191860244 |
      |                  | journey begin with |                |                    |
      |                  | the Cymbal Sprout, |                |                    |
      |                  | the ideal balance  |                |                    |
      |                  | bike for beginning |                |                    |
      |                  | riders ages 2-4    |                |                    |
      |                  | years...           |                |                    |
      | Cymbal Spark Jr  | Light, vibrant,    | 34             | 0.3412342902117166 |
      |                  | and ready for      |                |                    |
      |                  | adventure, the     |                |                    |
      |                  | Spark Jr. is the   |                |                    |
      |                  | perfect first bike |                |                    |
      |                  | for young riders   |                |                    |
      |                  | (ages 5-8)...      |                |                    |
      | Cymbal Helios    | Safety meets style | 100            | 0.4197863319656684 |
      | Helmet           | with the Cymbal    |                |                    |
      |                  | children's bike    |                |                    |
      |                  | helmet...          |                |                    |
      | Cymbal Breeze    | Cruise in style and| 72             | 0.485231776523978  |
      |                  | embrace effortless |                |                    |
      |                  | pedaling with the  |                |                    |
      |                  | Breeze electric    |                |                    |
      |                  | bike...            |                |                    |
      | Cymbal Phoenix   | See and be seen    | 87             | 0.525101413779242  |
      | Lights           | with the Phoenix   |                |                    |
      |                  | bike lights...     |                |                    |
      *------------------+--------------------+----------------+--------------------*/
      

    前のベクトル検索の例では、正確な k 近傍法(KNN)ベクトル検索を使用しています。KNN ベクトル距離関数(コサイン距離、ユークリッド距離、ドット積)は、Spanner データの特定のサブセットをクエリできる場合に役立ちます。KNN 検索では、クエリベクトルとデータベース内のすべてのベクトルの間の正確な距離が計算されるため、データをパーティショニングできる場合に効率的です。クエリで特定のフィルタなしでクエリベクトルとデータベース内のすべてのベクトルを比較する必要があり、クエリを独立したサブクエリに分割できない場合は、KNN を使用するとパフォーマンスのボトルネックが発生する可能性があります。このような状況では、近似最近傍(ANN)ベクトル検索が役立ちます。詳細については、近似最近傍を検索するをご覧ください。

    ワークロードをパーティショニングできず、大量のデータがある場合は、ANN ベクトル検索を使用して、大規模なデータセットのクエリ パフォーマンスを向上させることができます。

    Spanner で ANN ベクトル検索をスケーリングして使用する手順は次のとおりです。

    ベクトル インデックスを作成する

    Spanner は、Google Research の Scalable Nearest Neighbor(ScaNN)を活用する専用のベクトル インデックスを使用して、ANN ベクトル検索を高速化します。

    データセットにベクトル インデックスを作成するには、productDescriptionEmbeddings 列を変更して vector_length アノテーションを定義する必要があります。vector_length アノテーションは、各ベクトルのディメンションを示します。次の DDL ステートメントは、productDescriptionEmbedding 列を削除し、vector_length を使用して再作成します。ベクトルの最大長(ディメンション)は、選択したエンベディング モデルによって異なります。

    1. Spanner Studio の新しいタブで、次の DDL ステートメントをコピーして貼り付け、productDescriptionEmbedding 列を再作成します。

      ALTER TABLE products DROP COLUMN productDescriptionEmbedding;
      ALTER TABLE products
        ADD COLUMN productDescriptionEmbedding ARRAY<FLOAT32>(vector_length=>VECTOR_LENGTH_VALUE);
      

      VECTOR_LENGTH_VALUE は、選択したエンベディング モデルの最大出力ディメンションに置き換えます。

    2. [実行] をクリックします。

    3. 次の挿入ステートメントをコピーして貼り付け、ベクトル エンベディングを再生成します。

      UPDATE products p1
      SET productDescriptionEmbedding =
      (SELECT embeddings.values from ML.PREDICT(MODEL EmbeddingsModel,
      (SELECT p1.productDescription as content)))
      WHERE categoryId=1;
      
    4. [実行] をクリックします。

    5. 次の DDL ステートメントをコピーして貼り付け、ベクトル インデックスを作成します。

      CREATE VECTOR INDEX ProductDescriptionEmbeddingIndex
          ON products(productDescriptionEmbedding)
          WHERE productDescriptionEmbedding IS NOT NULL
      OPTIONS (
      distance_type = 'COSINE'
      );
      
    6. [実行] をクリックします。

    ANN ベクトル距離関数を使用する

    Spanner で ANN ベクトル検索を使用するには、SQL クエリで次の点を変更します。

    • SQL クエリ内ではなく、プロンプト エンベディングを個別に生成します。
    • エンベディングの結果をクエリにコピーします。
    • FORCE_INDEX ヒントを使用して、新しいベクトル インデックスを参照します。@{force_index=ProductDescriptionEmbeddingIndex}
    • COSINE_DISTANCE ではなく、APPROX_COSINE_DISTANCE ベクトル距離関数を使用します。JSON '{"num_leaves_to_search": num_leaves}' オプションは必須です。
    1. Spanner Studio の新しいタブで、次のクエリをコピーして貼り付け、プロンプト エンベディングを生成します。

      -- Generate the prompt embedding
      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)
        );
      
    2. [実行] をクリックします。

    3. embeddings.values の結果をコピーします。

    4. 次のクエリの embedding を、前の手順でコピーしたエンベディング結果に置き換えます。

      -- Update embedding query using the vector index
      SELECT productName, productDescription, inventoryCount,
        (APPROX_COSINE_DISTANCE(productDescriptionEmbedding,
        array<float32>[embedding],
        options => JSON '{\"num_leaves_to_search\": 10}')) as distance
      FROM products @{force_index=ProductDescriptionEmbeddingIndex}
      WHERE productDescriptionEmbedding IS NOT NULL AND inventoryCount > 0
      ORDER BY distance
      LIMIT 5;
      

      新しい SQL クエリは次のようになります。

      SELECT productName, productDescription, count,
        (APPROX_COSINE_DISTANCE(productDescriptionEmbedding,
          array<float32>[-0.00457216799,-0.0771846101,-0.0319350846,0.0352052487,-0.0457422845,0.0183265656...],
          options => JSON '{\"num_leaves_to_search\": 10}')) as distance
      FROM products @{force_index=ProductDescriptionEmbeddingIndex}
      WHERE productDescriptionEmbedding IS NOT NULL AND inventoryCount > 0
      ORDER BY distance
      LIMIT 5;
      

      出力例:

      /*-----------------+--------------------+----------------+--------------------*
      | productName      | productDescription | inventoryCount | distance           |
      +------------------+--------------------+----------------+--------------------+
      | Cymbal Sprout    | Let their cycling  | 10             | 0.30935457151661594|
      |                  | journey begin with |                |                    |
      |                  | the Cymbal Sprout, |                |                    |
      |                  | the ideal balance  |                |                    |
      |                  | bike for beginning |                |                    |
      |                  | riders ages 2-4    |                |                    |
      |                  | years...           |                |                    |
      | Cymbal Spark Jr  | Light, vibrant,    | 34             | 0.34116496551593656|
      |                  | and ready for      |                |                    |
      |                  | adventure, the     |                |                    |
      |                  | Spark Jr. is the   |                |                    |
      |                  | perfect first bike |                |                    |
      |                  | for young riders   |                |                    |
      |                  | (ages 5-8)...      |                |                    |
      | Cymbal Helios    | Safety meets style | 100            | 0.4198014303921187 |
      | Helmet           | with the Cymbal    |                |                    |
      |                  | children's bike    |                |                    |
      |                  | helmet...          |                |                    |
      | Cymbal Breeze    | Cruise in style and| 72             | 0.4850674854267337 |
      |                  | embrace effortless |                |                    |
      |                  | pedaling with the  |                |                    |
      |                  | Breeze electric    |                |                    |
      |                  | bike...            |                |                    |
      | Cymbal Phoenix   | See and be seen    | 87             | 0.525101413779242  |
      | Lights           | with the Phoenix   |                |                    |
      |                  | bike lights...     |                |                    |
      *------------------+--------------------+----------------+--------------------*/
      

      Cymbal Sprout の APPROX_COSINE_DISTANCE は 0.30935457151661594 で、元のクエリとの類似度が最も高くなっています。

      ベクトル関数と類似性の関係の解釈の詳細については、ベクトル距離関数から選択してベクトル エンベディングの類似性を測定するをご覧ください。

    クリーンアップ

    このセクションでは、 Google Cloud コンソールを使用してリソースをクリーンアップする方法について説明します。Cloud 請求先アカウントに追加料金が課されないように、設定時に作成したデータベースとインスタンスを削除します。インスタンスを削除すると、そのインスタンス内に作成されたすべてのデータベースが削除されます。

    データベースの削除

    1. Google Cloud コンソールで、[Spanner インスタンス] ページに移動します。

      [Spanner インスタンス] に移動

    2. test-instance」など、削除するデータベースがあるインスタンスの名前をクリックします。

    3. example-db など、削除するデータベースの名前をクリックします。

    4. [データベースの概要] ページで、[データベースを削除] をクリックします。

    5. データベース名を入力して [削除] をクリックし、データベースの削除を確定します。

    インスタンスを削除する

    1. Google Cloud コンソールで、[Spanner インスタンス] ページに移動します。

      [Spanner インスタンス] に移動

    2. test-instance」など、削除するインスタンスの名前をクリックします。

    3. [インスタンスの削除] をクリックします。

    4. インスタンス名を入力し [削除] をクリックして、インスタンスの削除を確定します。

    次のステップ