Spanner Graph でベクトル検索を使用する

このページでは、Spanner Graph でベクトル検索を使用して、K 最近傍(KNN)と近似最近傍(ANN)を見つける方法について説明します。ベクトル距離関数を使用して、生成 AI アプリケーションの類似検索や検索拡張生成などのユースケースで KNN と ANN のベクトル検索を実行できます。

Spanner Graph は、KNN ベクトル類似性検索を実行するために次の距離関数をサポートしています。

  • COSINE_DISTANCE(): 2 つのベクトル間の最短距離を測定します。
  • EUCLIDEAN_DISTANCE(): 2 つのベクトル間の角度のコサインを測定します。
  • DOT_PRODUCT(): 角度のコサインに、対応するベクトルの大きさを掛けます。データセット内のすべてのベクトル エンベディングが正規化されていることがわかっている場合は、DOT_PRODUCT() を距離関数として使用できます。

詳細については、k 近傍法を探索して Spanner でベクトル類似性検索を行うをご覧ください。

Spanner Graph は、ANN ベクトル類似性検索を実行するための次の近似距離関数もサポートしています。

  • APPROX_COSINE_DISTANCE: 2 つのベクトル間の近似最短距離を測定します。
  • APPROX_EUCLIDEAN_DISTANCE: 2 つのベクトル間の角度の近似コサインを測定します。
  • APPROX_DOT_PRODUCT: 角度の近似コサインに、対応するベクトルの大きさを掛けます。データセット内のすべてのベクトル エンベディングが正規化されていることがわかっている場合は、DOT_PRODUCT() を距離関数として使用できます。

詳細については、近似最近傍を検索してベクトル インデックスを作成し、ベクトル エンベディングをクエリするをご覧ください。

始める前に

このドキュメントのサンプルを実行するには、まずSpanner Graph を設定してクエリを実行するの手順に沿って、次の操作を行います。

  1. インスタンスを作成する
  2. Spanner Graph スキーマを使用してデータベースを作成する
  3. 重要なグラフデータを挿入する

必要なグラフデータを挿入したら、データベースに次の更新を行います。

グラフ データベースに追加のベクトルデータを挿入する

グラフ データベースに必要な更新を行う手順は次のとおりです。

  1. Account 入力テーブルに新しい列 nick_name_embeddings を追加します。

    ALTER TABLE Account
    ADD COLUMN nick_name_embeddings ARRAY<FLOAT32>(vector_length=>4);
    
  2. 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;
    
  3. 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;
    
  4. AccountTransferAccount 入力テーブルに 2 つの新しい列(notesnotes_embeddings)を追加します。

    ALTER TABLE AccountTransferAccount
    ADD COLUMN notes STRING(MAX);
    ALTER TABLE AccountTransferAccount
    ADD COLUMN notes_embeddings ARRAY<FLOAT32>(vector_length=>4);
    
  5. 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;
    
  6. 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 が返されます。次の例では、レジャー旅行と休暇のアカウントのトップ 2 つの K 最近傍が結果に表示されます。これは、[0.2, 0.4, 0.9, 0.6] ベクトル エンベディングで表されます。

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 が返されます。次の例では、結果に 食費のトップ 2 つの K 最近傍が表示されます。これは、[0.2, 0.4, 0.9, 0.6] ベクトル エンベディングで表されます。

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 パラメータを COSINEDOT_PRODUCTEUCLIDEAN のいずれかに設定すると、ユースケースに最も適した距離指標を選択できます。詳細については、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 を返します。次の例では、レジャー旅行と休暇のアカウントの近似最近傍のトップ 2 が結果に表示されます。これは、[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 旅行のために貯金する

次のステップ