大規模なテーブルの自動ベクトル エンベディングを生成および管理する

ドキュメントのバージョンを選択:

テーブル列全体のベクトル エンベディングを生成および管理できるため、大規模なベクトル エンベディングの作成に対応したスケーラブルなソリューションが実現します。このソリューションは、次のようなテキスト コンテンツに対するセマンティック検索と検索拡張生成(RAG)を容易にする場合に特に役立ちます。

  • 新しいテーブルの初期ベクトル エンベディングを作成する
  • 大規模なデータ インポート後にエンベディングを生成する
  • 大幅なデータ変更後にエンベディングを更新する
  • エンベディングを増分的にメンテナンスする

自動ベクトル エンベディングについて

AlloyDB Omni の自動ベクトル エンベディングは、データのベクトル エンベディングの生成とメンテナンスを自動化するスケーラブルな方法を提供します。自動ベクトル エンベディングを構成することで、新しいテキストや更新されたテキストごとにエンベディングを手動で生成する必要がなくなり、そのようなプロセスが自動化されます。これは、セマンティック検索、検索拡張生成(RAG)、その他の AI 搭載機能で最新のエンベディングを使用するアプリケーションで特に役立ちます。

自動ベクトル エンベディングを使用すると、次のことが可能になります。

  • テーブル全体のエンベディングを初期化する: 単一のコマンドで、テーブル列内の既存のすべてのデータのエンベディングを生成できます。
  • エンベディングの同期を維持する: ソースデータが変更されたときにエンベディングを自動的に更新し、AI アプリケーションが常に最新の情報を使用できるようにします。
  • エンベディングを大規模に生成する: 数百万行に及ぶ大規模なテーブルのエンベディングを効率的に作成できます。
  • 各エンベディング列の管理機能を呼び出して、同じテーブル内の複数の列のエンベディングを構成して管理できます。

この機能により、ベクトル エンベディングの作成とメンテナンスの複雑さが抽象化され、AI アプリケーションの開発とメンテナンスが簡素化されます。

始める前に

大規模なテーブルのベクトル エンベディングを生成して管理する前に、次の操作を行います。

  • Vertex AI の割り当てを確認して増やす: 最適なパフォーマンスを確保し、オペレーションの遅延、QPS の低下、複数の再試行を回避するには、Vertex AI の割り当てを確認し、必要に応じて増やします。

    割り当てを確認して増やす手順は次のとおりです。

    1. コンソールで、 [**割り当て**] ページに移動します。 Google Cloud
    2. モデルとリージョンに関連する次の指標でフィルタします。
      • 1 分あたりのリクエスト数(RPM)の場合: Regional online prediction requests per base model per minute per region per base_model
      • Gemini トークンの場合: Embed content input tokens per minute per region per base_model
    3. 現在の上限がテーブルサイズに対して不十分な場合は、更新する割り当て値を見つけて、割り当ての横にあるチェックボックスをオンにします。
    4. [編集] をクリックします。[割り当ての変更] ダイアログが表示されます。

      詳細については、割り当ての調整をリクエストするをご覧ください。

    Vertex AI エンベディング モデルの上限については、 Gemini エンベディング モデルのトークン上限をご覧ください。

    割り当ての完全なリストについては、 Vertex AI の割り当てと上限をご覧ください。

  • ユーザーとして postgres を使用してデータベースに接続します。psql

  • google_ml_integration 拡張機能がインストールされ、バージョンが 1.5.6 以降であることを確認します

  • google_ml_integration.enable_model_support フラグと google_ml_integration.enable_faster_embedding_generation フラグが on に設定されていることを確認します。

  • AlloyDB Omni データベースからエンベディングを生成する前に、Vertex AI と連携できるように AlloyDB Omni を構成する必要があります。詳細については、データベースを Vertex AI と統合するをご覧ください。

  • 自動エンベディング生成を管理およびモニタリングするために、ユーザーはデフォルトで google_ml.embed_gen_progress テーブルと google_ml.embed_gen_settings テーブルに対する Select アクセス権を持っています。

    ユーザーが自動エンベディング生成を管理できるようにするには、google_ml.embed_gen_progress テーブルと google_ml.embed_gen_settings テーブルに対する INSERTUPDATEDELETE の各権限を付与します。

    GRANT INSERT, UPDATE, DELETE ON google_ml.embed_gen_progress TO 'USER_NAME';
    

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

    • USER_NAME: 権限が付与されるユーザーの名前。
  • テキスト エンベディングを生成するで説明されている初期設定を完了します。

  • 使用する PostgreSQL クライアントで AUTOCOMMITON に設定されていることを確認します。

拡張機能のバージョンを確認する

google_ml_integration 拡張機能のバージョンを確認するには、次のコマンドを実行します。

SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';

拡張機能を更新する必要がある場合は、次のコマンドを実行します。

ALTER EXTENSION google_ml_integration UPDATE;

データベース フラグが on に設定されていることを確認する

データベース フラグが正しく設定されていることを確認するには、次のコマンドを実行します。

SHOW google_ml_integration.enable_model_support;
SHOW google_ml_integration.enable_faster_embedding_generation;

これらのフラグが off に設定されている場合は、インスタンスのデータベース フラグを構成するをご覧ください。これらのフラグについて詳しくは、サポートされているデータベース フラグをご覧ください。

テーブルを準備する

自動エンベディングを生成する前に、結果のベクトルを格納する列をテーブルに作成する必要があります。この列は通常 vector(DIMENSION) 型を使用し、DEFAULT NULL 値が必要です。

たとえば、768 次元のエンベディングの列を user_reviews という名前のテーブルに追加するには、次のようにします。

ALTER TABLE user_reviews ADD COLUMN IF NOT EXISTS content_embeddings vector(768) DEFAULT NULL;

テーブルのエンベディングを初期化する

自動ベクトル エンベディングを管理する関数は、ai スキーマと google_ml スキーマの両方で使用できます。ai スキーマは、AlloyDB Omni の最新の AI 機能のシンプルなインターフェースを提供します。

テーブルのコンテンツ列のエンベディングを生成するには、ai.initialize_embeddings() SQL 関数を使用します。これはブロッキング呼び出しです。つまり、データベース セッションはオペレーションが完了するまで待機してから結果を返し、そのセッションで新しいコマンドを発行できるようにします。ただし、データベースへの他の接続はブロックされず、引き続きテーブルを操作できます。

  • 関数が成功を返すと、ベクトル エンベディングの作成が完了します。
  • この関数は、モデルの割り当てエラーなどの一時的な問題から自動的に復元を試みます。復元を試みても失敗した場合にのみ、エラーが返されます。batch_size の構成ミスによってリクエストがサイズ上限を超えるような永続的な問題が発生した場合や、オペレーションが手動でキャンセルされた場合は、呼び出しを手動で再発行する必要があります。

この関数は、Google が提供するモデル(Vertex AI の text-embedding-005 など)と、登録済みのスタムモデルをサポートします。

バッチ生成を実行する

デフォルトでは、AlloyDB Omni はバッチ処理を使用し、複数のテキスト入力に対して 1 つのリクエストでエンベディングを生成することで、効率を向上させます。バッチサイズを明示的に指定しない場合、AlloyDB Omni は自動的に決定されたデフォルト値を適用します。

ヒントのバッチサイズ

ai.initialize_embeddingsbatch_size パラメータを使用すると、直接サポートされているモデルに対して推奨されるバッチサイズを提案することで、AlloyDB Omni のクエリ オプティマイザーを誘導できます。AlloyDB Omni は、モデルの上限または割り当てに基づいてこのサイズを動的に削減する場合がありますが、ヒントはクエリ実行プランに影響します。

CALL ai.initialize_embeddings(
    model_id => 'text-embedding-005',
    table_name => 'user_reviews',
    content_column => 'content',
    embedding_column => 'content_embeddings',
    batch_size => 50
);

バッチ処理をサポートするカスタム エンベディング モデルを使用する

バッチ処理をサポートするカスタムモデルまたは外部でサポートされているモデルを使用する場合は、バッチ変換関数を定義し、モデルの作成時に model_batch_in_transform_fn および model_batch_out_transform_fn として指定します。また、initialize_embeddings 呼び出しで batch_size を指定することもできます。バッチ処理をサポートするモデルでは、パフォーマンスを向上させるために batch_size を 1 より大きい値にすることをおすすめします。

  1. カスタムモデルの入力関数、出力関数、バッチ変換関数を定義します。

    -- Scalar input transform functions
    CREATE OR REPLACE FUNCTION acme_text_input_transform(model_id TEXT, input TEXT) RETURNS JSON;
    CREATE OR REPLACE FUNCTION acme_text_output_transform(model_id TEXT, model_output JSON) RETURNS real[];
    CREATE OR REPLACE FUNCTION acme_generate_headers(model_id TEXT, input TEXT) RETURNS JSON;
    -- Batch input transform functions
    CREATE OR REPLACE FUNCTION acme_text_batch_input_transform(model_id TEXT, input TEXT[]) RETURNS JSON;
    CREATE OR REPLACE FUNCTION acme_text_batch_output_transform(model_id TEXT, model_output JSON) RETURNS real[][];
    
  2. モデルを作成するには、バッチ変換関数を指定します。

    CALL
      ai.create_model(
        model_id => 'custom-embedding-model',
        model_request_url => 'https://acme.com/models/text/embeddings/v1',
        model_type => 'text_embedding',
        model_in_transform_fn => 'acme_text_input_transform',
        model_out_transform_fn => 'acme_text_output_transform',
        generate_headers_fn => 'acme_generate_headers',
        model_batch_in_transform_fn => 'acme_text_batch_input_transform',
        model_batch_out_transform_fn => 'acme_text_batch_output_transform'
      );
    
  3. カスタムモデルを使用してベクトル エンベディングを生成します。

    CALL
      ai.initialize_embeddings(
        model_id => 'custom-embedding-model',
        table_name => 'user_reviews',
        content_column => 'content',
        embedding_column => 'content_embeddings',
        batch_size => 10
    );
    

バッチ処理をネイティブでサポートしていないカスタムモデルでも、自動エンベディング機能を使用できます。そのためには、バッチ変換関数 model_batch_in_transform_fnmodel_batch_out_transform_fn を定義する必要があります。バッチ処理をサポートしていないモデルの場合は、入力配列から一度に 1 つの入力を処理するように、これらの関数を定義します。このモデルに対して ai.initialize_embeddings を呼び出す場合は、batch_size1 に設定します。

バッチ処理をサポートするカスタム ディメンションを使用する

OUTPUT_DIMENSIONALITY パラメータでカスタム バッチ入力変換関数を使用するには、リクエスト パラメータで選択したディメンションを指定する関数を定義します。これは、可変出力サイズをサポートするモデルのエンベディング生成を最適化する場合に便利です。

たとえば、次の関数は、出力ディメンションが 768 のモデルのカスタム バッチ入力変換を定義します。

CREATE OR REPLACE FUNCTION google_ml.vertexai_text_embedding_batch_input_transform_with_768_dims(model_id VARCHAR(100), input_list TEXT[])
RETURNS JSON
LANGUAGE SQL
AS $$
  SELECT pg_catalog.json_build_object(
    'instances',
    pg_catalog.json_agg(pg_catalog.json_build_object('content', content)),
    'parameters',
    pg_catalog.json_build_object('outputDimensionality', 768)
  ) FROM unnest(input_list) AS content;
$$;

カスタムモデルで JSONB の最適化を使用する

カスタム出力変換関数で JSONB データ型を使用して、パフォーマンスを向上させることができます。バッチ処理をサポートするカスタムモデルを作成すると、google_ml_integration 拡張機能は変換関数の JSONB バリアントを自動的に検索して使用します。

この最適化により、自動エンベディング生成のパフォーマンスが大幅に向上します。これは、JSONB が PostgreSQL で JSON データを保存して処理するためのより効率的なバイナリ形式であるためです。

この機能を利用するには、JSON ではなく JSONB 引数を受け取る変換関数の別のバージョンを指定する必要があります。

たとえば、署名が次のバッチ出力変換関数があるとします。

CREATE OR REPLACE FUNCTION my_batch_output_transform(model_id TEXT, model_output JSON) RETURNS real[][];

次のように JSONB バリアントを作成できます。

CREATE OR REPLACE FUNCTION my_batch_output_transform(model_id TEXT, model_output JSONB) RETURNS real[][];

この拡張機能は、関数の JSONB バージョンが存在することを自動的に検出し、バッチ処理に使用します。JSON 変換関数を使用するモデル登録をすでに作成している場合は、ai.create_model 呼び出しを更新する必要はありません。新しい JSONB 関数が既存の JSON 関数とまったく同じ名前を使用している限り、拡張機能は JSONB バリアントを透過的に検出してバッチ処理に使用します。

エンベディングを増分更新する

エンベディングを更新すると、入力コンテンツ列の最新の値に基づいて再生成されます。

整合性とパフォーマンスを制御できるように、AlloyDB Omni は増分のエンベディング更新について、複数のモードをサポートしています。モードは、ai.initialize_embeddings()incremental_refresh_mode 列挙型引数を使用して選択できます。使用できるモードは次のとおりです。

  • transactional: コンテンツ列を更新するトランザクションの一環として、エンベディングが更新されます。このプロセスでは、多くの場合、コンテンツ列の更新時にデータベース トリガーに似たメカニズムを使用してエンベディングを自動的に生成しますが、このプロセスではオーバーヘッドが発生するため、更新オペレーションに時間がかかる可能性があります。このオーバーヘッドは、トランザクション セマンティクスを維持し、エンベディングとコンテンツの同期を確保するためのトレードオフです。このモードはモデルのスカラー変換関数に依存するため、モデルの作成時に model_in_transform_fnmodel_out_transform_fn を定義する必要があります。transactional モードを使用するには、テーブルに対するオーナー ロール が必要です。

    CALL
      ai.initialize_embeddings(
        model_id => 'text-embedding-005',
        table_name => 'user_reviews',
        content_column => 'content',
        embedding_column => 'content_embeddings',
        batch_size => 10,
        incremental_refresh_mode => 'transactional'
    );
    

    transactional モードでは、トリガーを使用してエンベディングが自動的に同期されるため、ai.refresh_embeddings() 関数は無効になります。テーブル全体のエンベディングを再生成する場合や、このモードで中断された ai.initialize_embeddings() 呼び出しから復元する場合は、まず ai.drop_embedding_config() 関数を使用して構成を削除してから、ai.initialize_embeddings() 呼び出しを再発行する必要があります。

    この自動モードは、デモ、小規模なデータセット、または初期読み込みと比較して挿入と更新の量が少ないテーブル(100 万行のテーブルで 1 日に数百件の更新など)に便利です。更新オペレーションで発生する追加のレイテンシよりも、データの即時整合性を維持することが重要な場合に適しています。

  • manual: これがデフォルト モードです。このモードでは、古いエンベディングをトラッキングするために、新しいブール値のトラッキング列がテーブルに追加されます。ai.refresh_embeddings() 関数を呼び出すと、新しい行または更新された行のエンベディングのみを生成することで、定期的な増分更新が実行されます。このモードは、特に初期読み込み後に多数の挿入または更新を処理する場合に、パフォーマンスをより細かく制御する必要があるユーザーにおすすめします。書き込みレイテンシを最小限に抑えることが優先され、ai.refresh_embeddings を使用して定期的な増分更新がトリガーされるまで、一時的に古いエンベディングまたは null エンベディングを使用できるシナリオで役立ちます。古い行または新しい行を更新するには、ai.refresh_embeddings() 関数を テーブルのすべてのエンベディングを更新する セクションで説明されているように使用します。

更新モードを選択する

次の表は、2 つの増分更新モードを比較したものです。アプリケーションに最適なアプローチを選択する際に役立ちます。

モード 説明 整合性とパフォーマンス 最適な用途
transactional エンベディングは、トリガーに似たメカニズムを使用して、データベース トランザクションの一部として更新されます。このモードでは ai.refresh_embeddings() は無効になります。 即時整合性。INSERT または UPDATE ごとにエンベディング生成がトリガーされるため、書き込みレイテンシのオーバーヘッドが高くなります。 デモ、小規模なデータセット、またはデータの整合性が重要なテーブル。
manual(デフォルト) ブール値のトラッキング列を使用して、古い行または新しい行をモニタリングします。ai.refresh_embeddings() を呼び出して、定期的な増分更新をトリガーする必要があります。 結果整合性。エンベディングは選択したタイミングで一括生成されるため、書き込みレイテンシは最小限に抑えられます。 大規模なデータセット、書き込み頻度の高い本番環境、パフォーマンスが重要なアプリケーション。

テーブルのすべてのエンベディングを更新する

manual 増分更新モードを使用してテーブルに対して ai.initialize_embeddings() を正常に実行したら、エンベディングの定期的な増分更新を実行できます。これは ai.refresh_embeddings を使用してトリガーされます。更新オペレーションを使用すると、最初の initialize_embeddings 呼び出し時に同時に変更された行のエンベディングを更新したり、定期的な増分更新を実行したりできます。

手動モードでエンベディング作成プロセスが中断された場合(pg_cancel など)、ai.refresh_embeddings() 関数を呼び出して、残りの行の生成を完了します。

refresh 関数は最初の呼び出しの設定を再利用するため、テーブルとエンベディング列のみを指定する必要があります。オプションで batch_size を指定して、デフォルト値をオーバーライドすることもできます。

CALL ai.refresh_embeddings(
    table_name => 'user_reviews',
    embedding_column => 'content_embeddings',
    batch_size => 50  -- Optional override
);

ベクトル エンベディングの作成時にテーブルデータを操作する

ai.initialize_embeddings() は、実行されているセッションに対してはブロッキング呼び出しとなりますが、他の接続は引き続きテーブルを操作できます。自動ベクトル エンベディング プロセスでは、標準の行レベルのロックが使用され、行がバッチで更新されます。つまり、他の接続からの同時実行データ操作言語(DML)オペレーション(UPDATEDELETE など)は、アクティブなエンベディング タスクのターゲットと同じ行を変更しようとした場合にのみ、短時間ブロックされます。変更しない SELECT クエリはブロックされません。

自動ベクトル エンベディングの設定を削除する

特定のテーブルとエンベディング列の組み合わせの自動ベクトル エンベディング構成を削除する必要がある場合は、ai.drop_embedding_config() 関数を使用します。この関数は、クリーンアップや、列のエンベディング管理を再構成する場合に便利です。

CALL
  ai.drop_embedding_config(
    table_name => 'user_reviews',
    embedding_column => 'content_embeddings');

パーティション分割テーブルを操作する

自動ベクトル エンベディング機能は、パーティション分割テーブルをサポートしています。これにより、大規模なパーティション分割データセットのエンベディングを効率的に管理できます。パーティション分割テーブルを操作する一般的なユースケースは次のとおりです。

パーティション分割テーブルでエンベディングを初期化する

エンベディングを初期化できるのは、テーブルのルート パーティションのみです。これは、パーティション分割テーブル全体に対して 1 回限りのオペレーションです。

CALL ai.initialize_embeddings(
    model_id => 'text-embeddings-005',
    table_name => 'documents', -- This is the root partitioned table
    content_column => 'content',
    embedding_column => 'content_embeddings'
);

パーティション分割テーブルでエンベディングを更新する

初期化後、ルート パーティション、サブパーティション、個々のリーフ パーティションなど、任意のパーティションでエンベディングを更新できます。大規模なデータセットの場合は、異なるデータベース接続から個別のパーティションのエンベディングを並行して更新することで、パフォーマンスを向上させることができます。

  • テーブル全体を更新するには、次を実行します。
CALL ai.refresh_embeddings(
    table_name => 'documents', -- This is the root partitioned table
    embedding_column => 'content_embeddings'
);
  • 単一のパーティションを更新するには、次を実行します。
CALL ai.refresh_embeddings(
    table_name => 'documents_eu',
    embedding_column => 'content_embeddings'
);

新しく追加または接続されたパーティションのエンベディングを更新する

自動エンベディング機能は、初期設定後にメインテーブルに組み込まれたパーティションのエンベディングの生成をサポートしています。具体的な手順は、完全に新しいパーティションを追加するか、既存のテーブルを接続するかによって異なります。

  • 新しく追加されたパーティション: 新しいパーティションをテーブルに追加する場合は、新しいパーティションで ai.refresh_embeddings を呼び出してエンベディングを生成できます。
-- Add a new partition
CREATE TABLE documents_africa PARTITION OF documents
    FOR VALUES IN ('africa');

-- Refresh embeddings for the new partition
CALL ai.refresh_embeddings(
    table_name => 'documents_africa',
    embedding_column => 'content_embeddings'
);
  • 新しく接続されたパーティション: 既存のテーブルをパーティションとして接続するには、まず ai.embedding_prepare_partition プロシージャを使用して、スキーマがパーティション分割テーブルと互換性があることを確認します。自動エンベディング機能は、階層型パーティション設定の任意のレベルでパーティションを追加または接続することをサポートしています。ai.embedding_prepare_partition プロシージャにより、スキーマが階層内の任意の親テーブルと互換性があることが保証されます。

既存のテーブルをパーティションとして接続するには、まず ai.embedding_prepare_partition プロシージャを使用して、スキーマがパーティション分割テーブルと互換性があることを確認します。

-- Prepare the table to be attached
CALL ai.embedding_prepare_partition(
    parent_table => 'documents',
    child_table => 'documents_misc'
);

-- Attach the partition
ALTER TABLE documents ATTACH partition documents_misc DEFAULT;

-- Refresh embeddings for the newly attached partition
CALL ai.refresh_embeddings(
    table_name => 'documents_misc',
    embedding_column => 'content_embeddings'
);

自動エンベディング機能は、階層型パーティション設定の任意のレベルでパーティションを追加または接続することをサポートしています。ai.embedding_prepare_partition プロシージャにより、スキーマが階層内の任意の親テーブルと互換性があることが保証されます。

-- Prepare a sub-partition for a non-root parent table
CALL ai.embedding_prepare_partition(
    parent_table => 'documents_eu', -- An existing partition
    child_table => 'documents_eu_germany'
);

-- Attach the new sub-partition
ALTER TABLE documents_eu ATTACH PARTITION documents_eu_germany
    FOR VALUES IN ('germany');

-- Refresh embeddings for the new sub-partition
CALL ai.refresh_embeddings(
    table_name => 'documents_eu_germany',
    embedding_column => 'content_embeddings'
);

エンベディング生成の進行状況をモニタリングする

ai.embedding_progress_view にクエリを実行すると、アクティブな initialize_embeddings 呼び出しと refresh_embeddings 呼び出しのリアルタイム ステータスをモニタリングできます。このビューには、完了率、経過時間、推定残り時間など、オペレーションの進行状況の詳細が表示されます。

進行状況を確認するには、次のクエリを実行します。

SELECT
  table_name,
  content_column,
  embedding_column,
  model_id,
  percent_progress,
  status,
  elapsed_time,
  rows_processed,
  partition_root
FROM
  ai.embedding_progress_view;

このビューには次の情報が表示されます。

説明
table_name 処理中のテーブルまたはパーティションの名前。
content_column エンベディングのソース コンテンツを含む列。
embedding_column エンベディングが保存される列。
model_id 生成に使用されるモデル。
percent_progress 完了したオペレーションの割合。
status オペレーションの現在のステータス(実行中、成功など)。
elapsed_time オペレーションの開始からの経過時間。
rows_processed これまでに処理された行数。
partition_root ルート パーティション分割テーブルの名前。

自動でエンベディングを生成する例

このセクションでは、登録済みのモデル エンドポイントを使用して自動でエンベディングを生成する例を示します。

OpenAI のエンベディング モデル

OpenAI が提供する登録済みの text-embedding-3-small モデル エンドポイントを使用してエンベディングを生成するには、次のステートメントを実行します。

CALL ai.initialize_embeddings(
    model_id => 'text-embedding-3-small',
    table_name => 'user_reviews',
    content_column => 'content',
    embedding_column => 'content_embeddings'
);

カスタムのエンベディング モデル

独自モデルまたは外部でサポートされているモデルの場合は、入出力変換関数を定義して ai.create_model に登録する必要があります。自動エンベディング機能を使用する場合は、スカラー変換関数(acme_text_input_transformacme_text_output_transform など)とバッチ変換関数(acme_text_batch_input_transformacme_text_batch_output_transform など)の両方を指定する必要があります。

次のステップ