AlloyDB AI を使用して生成 AI アプリケーションを構築する

このセクションでは、pgvector 拡張機能を使用して予測を呼び出し、エンベディングをクエリしてインデックスに登録する方法について説明します。これらの ML を活用した AI 関数は、AlloyDB AI を介して利用できます。AlloyDB AI は、ML モデルのセマンティック機能と予測機能をデータに適用できる AlloyDB for PostgreSQL の機能スイートです。

AlloyDB AI の詳細については、https://cloud.google.com//alloydb/docs/ai をご覧ください。

予測を呼び出す

Vertex AI を AlloyDB Omni と統合し、Vertex AI に保存されたモデルで予測を実行する手順は次のとおりです。

始める前に

  1. GDC で Vertex AI オンライン予測を有効にします
  2. 次のコマンドを実行して、前の手順でダウンロードしたサービス アカウント キーに基づいて Kubernetes Secret を作成します。Kubernetes Secret は、DBCluster リソースと同じ Namespace に作成してください。

    kubectl create secret generic SECRET_NAME \
    --from-file=PATH_TO_SERVICE_ACCOUNT_KEY/private-key.json \
    -n NAMESPACE

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

    • SECRET_NAME: AlloyDB Omni が Distributed Cloud AI 機能にアクセスできるようにするために DBCluster マニフェストの作成時に使用される Secret の名前。例: vertex-ai-key-alloydb

    • PATH_TO_SERVICE_ACCOUNT_KEY: private-key.json サービス アカウント キーをダウンロードした場所のパス。

    • NAMESPACE: データベース クラスタの Namespace。

  3. データベース エンジンのタイプを選択してデータベース クラスタを作成するに記載されている手順に沿って、AlloyDB Omni Operator をインストールします。

  4. AlloyDB AI でデータベース クラスタを作成し、vertexAIKeyRef を、前の手順で DBCluster マニフェストの googleMLExtension フィールドに作成した Kubernetes Secret に設定します。

    apiVersion: v1
    kind: Secret
    metadata:
      name: db-pw-DBCLUSTER_NAME
      namespace: USER_PROJECT
    type: Opaque
    data:
      DBCLUSTER_NAME: "BASE64_PASSWORD"
    ---
    apiVersion: DBENGINE_NAME.dbadmin.gdc.goog/v1
    kind: DBCluster
    metadata:
      name: DBCLUSTER_NAME
      namespace: USER_PROJECT
    spec:
      primarySpec:
        adminUser:
          passwordRef:
            name: db-pw-DBCLUSTER_NAME
        features:
          googleMLExtension:
            config:
              vertexAIKeyRef: SECRET_NAME
        version: "DB_VERSION"
        resources:
          memory: DB_MEMORY
          cpu: DB_CPU
          disks:
          - name: DataDisk
            size: DB_DATA_DISK
    

    次の変数を置き換えます。

    • DBCLUSTER_NAME: データベース クラスタの名前。
    • USER_PROJECT: データベース クラスタが作成されるユーザー プロジェクトの名前。
    • BASE64_PASSWORD: データベースの管理者パスワード(base64 エンコード)。
    • DBENGINE_NAME: データベース エンジンの名前。alloydbomni に設定します。
    • DB_VERSION: データベース エンジンのバージョン。
    • DB_MEMORY: データベース クラスタに割り当てられるメモリ量。例: 5Gi
    • DB_CPU: データベース クラスタに割り当てられる CPU の量。例: 2
    • DB_DATA_DISK: データベース クラスタに割り当てられるスペースの量。例: 10 Gi

    マニフェストを適用します。

    kubectl apply -f DB_CLUSTER_YAML

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

    • DB_CLUSTER_YAML: このデータベース クラスタ マニフェスト ファイルの名前。例: alloydb-omni-db-cluster.yaml
  5. google_ml_integration 拡張機能をインストールします。

    CREATE EXTENSION google_ml_integration CASCADE;
    

予測を呼び出す

次の ml_predict_row() SQL 関数を実行して、Vertex AI モデル エンドポイントを使用してオンライン予測を呼び出します。

  SELECT ml_predict_row('PREDICTION_ENDPOINT/PROJECT_NAMESPACE/ORGANIZATION/ZONE/DNS/DNS_SUFFIX', '{ "instances": [ INSTANCES ], "parameters":
  PARAMETERS');

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

  • PREDICTION_ENDPOINT: Vertex AI エンドポイントの修飾名

  • PROJECT_NAMESPACE: Vertex AI エンドポイントがデプロイされている Namespace

  • ORGANIZATION: Vertex AI エンドポイントがデプロイされている組織の名前

  • ZONE: Vertex AI エンドポイントがデプロイされているゾーン

  • DNS: 組織の DNS

  • DNS_SUFFIX: DNS オブジェクトのサフィックス

  • INSTANCES: JSON 形式の予測呼び出しの入力

  • PARAMETERS: JSON 形式の予測呼び出しのパラメータ

pgvector を使用してエンベディングのクエリとインデックス作成を実行する

pgvector PostgreSQL 拡張機能を使用すると、データベースに対してテキスト エンベディングの保存、インデックス登録、クエリを行う際に、ベクトル固有の演算子と関数を使用できます。AlloyDB には、pgvector を処理するための最適化が用意されており、エンベディングを含む特定のクエリを高速化できるインデックスを作成できます。

AlloyDB を LLM として使用し、LLM に基づいてベクトル エンベディングを生成して保存する方法については、https://cloud.google.com/alloydb/docs/ai/work-with-embeddings#index をご覧ください。

ScaNN を使用してインデックスを作成し、ベクトルをクエリする

このセクションでは、保存されたエンベディングを使用してインデックスを生成し、エンベディングをクエリする方法について説明します。AlloyDB で ScaNN インデックスを作成できます。

始める前に

インデックスの作成を開始する前に、以下の前提条件を整える必要があります。

  • AlloyDB データベースのテーブルにエンベディング ベクトルが追加されている。

  • Google が AlloyDB 用に拡張した pgvector に基づく vector 拡張機能のバージョン 0.5.0 以降がインストールされている。

    CREATE EXTENSION IF NOT EXISTS vector;
    
  • ScaNN インデックスを作成するには、vector 拡張機能に加えて postgres_ann 拡張機能をインストールしてください。

    CREATE EXTENSION IF NOT EXISTS postgres_ann;
    

ScaNN インデックスを作成する

データベース内のテーブルに ScaNN インデックスを作成できます。

AlloyDB postgres_ann は、Google が開発した PostgreSQL 拡張機能であり、ScaNN アルゴリズムによる非常に効率的な最近傍インデックスを実装しています。

ScaNN インデックスは、近似最近傍検索用のツリーベースの量子化インデックスです。インデックスの構築時間が短く、メモリ使用量も小さくなります。また、ワークロードに応じて QPS が速くなります。

2 レベルツリー ScaNN インデックス

保存済みベクトル エンベディングを含む列に、ScaNN アルゴリズムを使用して 2 レベルのツリー インデックスを適用するには、次の DDL クエリを実行します。

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE);

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

  • INDEX_NAME: 作成するインデックスの名前(例: my-scann-index)。インデックス名はデータベース全体で共有されます。各インデックス名はデータベース内の各テーブルで一意となるようにしてください。

  • TABLE: インデックスを追加するテーブル。

  • EMBEDDING_COLUMN: vector データを格納する列。

  • DISTANCE_FUNCTION: このインデックスで使用する距離関数。次のいずれかを選択します。

    • L2 距離: l2

    • ドット積: dot_product

    • コサイン距離: cosine

  • NUM_LEAVES_VALUE: このインデックスに適用するパーティションの数。1 ~ 1048576 の任意の値に設定します。

3 レベルのツリー ScaNN インデックス

保存されたベクトル エンベディングを含む列に ScaNN アルゴリズムを使用して 3 レベルのツリー インデックスを作成するには、次の DDL クエリを実行します。

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE, max_num_levels = MAX_NUM_LEVELS);

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

  • MAX_NUM_LEVELS: K 平均法クラスタリング ツリーのレベルの最大数。2 レベルのツリーベースの量子化の場合は 1(デフォルト)、3 レベルのツリーベースの量子化の場合は 2 に設定します。

インデックスを作成すると、指定されたテキストで類似クエリを作成する手順に沿って、インデックスを使用する最近傍探索クエリを実行できます。

インデックス パラメータは、QPS とリコールのバランスを適切にとるように設定する必要があります。

このインデックスを、vector ではなく real[] データ型を使用するエンベディング列に作成するには、列を vector データ型にキャストします。

CREATE INDEX INDEX_NAME ON TABLE
  USING scann (CAST(EMBEDDING_COLUMN AS vector(DIMENSIONS)) DISTANCE_FUNCTION)
  WITH (num_leaves=NUM_LEAVES_VALUE, max_num_levels = MAX_NUM_LEVELS);

DIMENSIONS は、エンベディング列のディメンション幅に置き換えます。

インデックス作成の進行状況を確認するには、pg_stat_progress_create_index ビューを使用します。

SELECT * FROM pg_stat_progress_create_index;

phase 列には、インデックス作成の現在のステータスが示されます。インデックスが作成されると、building index: tree training フェーズが消えます。

クエリの実行

エンベディングをデータベースに保存してインデックスを作成した後は、pgvector クエリ機能を使用してクエリを開始できます。postgres_ann 拡張機能を使用して一括検索クエリを実行することはできません。

エンベディング ベクトルの最も近いセマンティック ネイバーを見つけるには、次のサンプルクエリを実行します。ここでは、インデックスの作成時に使用した距離関数を設定します。

  SELECT * FROM TABLE
    ORDER BY EMBEDDING_COLUMN DISTANCE_FUNCTION_QUERY ['EMBEDDING']
    LIMIT ROW_COUNT

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

  • TABLE: テキストを比較するエンベディングを含むテーブル。

  • INDEX_NAME: 使用するインデックスの名前。例: my-scann-index

  • EMBEDDING_COLUMN: 保存されたエンベディングを含む列。

  • DISTANCE_FUNCTION_QUERY: このクエリで使用する距離関数。インデックスの作成時に使用した距離関数に基づいて、次のいずれかを選択します。

    • L2 距離: <->

    • 内積: <#>

    • コサイン距離: <=>

  • EMBEDDING: 保存されているセマンティック ネイバーの中で最も近いものを見つけるエンベディング ベクトル。

  • ROW_COUNT: 返される行数。

    最も適合するものが 1 つだけ必要な場合は、1 を指定します。

embedding() 関数を使用してテキストをベクトルに変換することもできます。ベクトルを pgvector 最近傍演算子(L2 距離の場合は <->)のいずれかに適用して、意味的に最も類似したエンベディングを含むデータベース行を見つけます。この関数を使用するには、まずテキスト エンベディング Gecko モデルを登録する必要があります。

embedding()real 配列を返すため、これらの値を pgvector 演算子で使用するには、embedding() 呼び出しを vector に明示的にキャストする必要があります。

  CREATE EXTENSION google_ml_integration;
  CREATE EXTENSION IF NOT EXISTS vector;

  SELECT * FROM TABLE
    ORDER BY EMBEDDING_COLUMN::vector
    <-> embedding('MODEL_IDVERSION_TAG', 'TEXT')
    LIMIT ROW_COUNT

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

  • MODEL_ID: クエリするモデルの ID。

    Vertex AI Model Garden を使用している場合は、モデル ID として textembedding-gecko@003 を指定します。これらは、Distributed Cloud がテキスト エンベディングに使用できるクラウドベースのモデルです。

  • 省略可: VERSION_TAG: クエリするモデルのバージョンタグ。タグの前に @ を付けます。

    Vertex AI で textembedding-gecko 英語モデルのいずれかを使用している場合は、バージョンタグのいずれか(例: textembedding-gecko@003)を指定します。

    バージョンタグは常に指定することを強くおすすめします。バージョンタグを指定しない場合、AlloyDB は常に最新のモデル バージョンを使用します。これにより、予期しない結果が生じる可能性があります。

  • TEXT: ベクトル エンベディングに変換するテキスト。

ベクトル インデックス指標

このセクションでは、AlloyDB で生成するベクトル インデックスに関連する指標の一覧を示します。これらの指標は、postgres_ann 拡張機能をインストールすると利用できる pg_stat_ann_indexes ビューを使用して表示できます。

ユーザビリティ指標

ユーザビリティ指標には、インデックス構成やインデックス スキャン数など、インデックス使用率の状態を把握する際に役立つ指標が含まれています。

指標名 データ型 説明
relid OID ベクトル インデックスを含むテーブルの固有識別子。
indexrelid OID ベクトル インデックスの一意の識別子。
schemaname NAME インデックスが属するスキーマの名前。
relname NAME インデックスを含むテーブルの名前。
indexrelname NAME インデックスの名前。
indextype NAME インデックスの種類。この値は常に postgres_ann に設定されます。
indexconfig TEXT[] インデックスの作成時に定義された、リーフ数や量子化などの構成。
indexsize TEXT インデックスのサイズ。
indexscan BIGINT インデックスで開始されたインデックス スキャンの数。

チューニング指標

チューニング指標を使用すると、現在のインデックスの最適化に関する分析情報を取得し、推奨事項を適用してクエリのパフォーマンスを向上させることができます。

指標名 データ型 説明
insertcount BIGINT インデックスに対する挿入オペレーションの数。この指標には、インデックスの作成前に存在していた行数も含まれます。
updatecount BIGINT インデックスに対する更新オペレーションの数。この指標には HOT アップデートは含まれません。
deletecount BIGINT インデックスに対する削除オペレーションの数。
distribution JSONB インデックスのすべてのパーティションにわたるベクトル分布。

次のフィールドに分布が表示されます。
  • maximum (INT8): すべてのパーティションにわたるベクトルの最大数。
  • minimum (INT8): すべてのパーティションにわたるベクトルの最小数。
  • average (FLOAT) : すべてのパーティションの平均ベクトル数。
  • outliers (INT8[]): すべてのパーティションの上位外れ値。この値は、上位 20 個の外れ値を示します。

注: K 平均法クラスタリング アルゴリズムの固有の特性により、インデックスの初期作成時であっても、パーティション間でベクトルの分布に常に一定のばらつきが生じます。

指標に基づくチューニングの推奨事項

ミューテーション
insertcountupdatecountdeletecount の指標を組み合わせると、インデックスのベクトルの変更またはミューテーションを確認できます。
インデックスは、特定の数のベクトルとパーティションを使用して作成されます。ベクトル インデックスに対して挿入、更新、削除などのオペレーションが実行されると、ベクトルが存在する最初のパーティション セットにのみ影響します。そのため、各パーティション内のベクトル数は時間とともに変動し、再現率、QPS、またはその両方に影響する可能性があります。
ANN 検索クエリで、時間の経過とともに QPS の低下や低い再現率などの速度や精度の問題が発生した場合は、これらの指標を確認することを検討してください。ベクトルの合計数に対してミューテーションの数が多い場合は、インデックスの再作成が必要になる可能性があります。
分布
distribution 指標は、すべてのパーティションにわたるベクトル分布を示します。
インデックスを作成すると、特定の数のベクトルと固定パーティションを使用して作成されます。パーティショニング プロセスとその後の分布は、この考慮事項に基づいて行われます。ベクトルが追加されると、既存のパーティションにパーティショニングされるため、インデックスの作成時とは異なる分布になります。最終的な分布ではすべてのベクトルが同時に考慮されないため、再現率、QPS、またはその両方に影響する可能性があります。
応答時間が長くなる、結果の精度が低下する(QPS または再現率で測定)など、ANN 検索クエリのパフォーマンスが徐々に低下している場合は、この指標を確認してインデックスを再作成することを検討してください。