自然言語の質問を使用して SQL クエリを生成する

このページでは、AlloyDB AI の自然言語を使用して、SQL ステートメントを設定、構成、生成する方法について説明します。自然言語を使用すると、自然言語を使用してデータベースをクエリするユーザー向けの生成 AI アプリケーションを作成できます。

AlloyDB for PostgreSQL の自然言語サポート API である alloydb_ai_nl 拡張機能を有効にするには、大きく分けて次の手順を実施します。

  1. alloydb_ai_nl 拡張機能をインストールします。
  2. アプリケーションの自然言語構成を定義します。
  3. スキーマを登録します。
  4. コンテキストを追加します。
  5. クエリ テンプレートを追加します。
  6. コンセプト タイプを定義し、値インデックスを作成します。
  7. 自然言語インターフェースを使用して SQL ステートメントを生成します。

始める前に

  • AlloyDB AI 自然言語へのアクセスをリクエストし、有効化の確認が届くまで待ってから、このページの手順に沿って操作します。
  • AlloyDB データベースに接続して PostgreSQL コマンドを実行する方法を把握します。さらに詳しい内容については、接続の概要をご覧ください。
  • エンドユーザーがアクセスするデータとスキーマをデータベースに入力します。

クラスタを作成して Vertex AI の統合を有効にする

  1. AlloyDB クラスタとインスタンスを作成します。AlloyDB インスタンスを使用して、アプリケーション データベースとスキーマを作成してください。
  2. Vertex AI の統合を有効にします。詳細については、Vertex AI と統合するをご覧ください。

必要なロール

alloydb_ai_nl 拡張機能をインストールして他のユーザーにアクセス権を付与するには、使用している Google Cloud プロジェクトで次の Identity and Access Management(IAM)ロールが必要です。

詳細については、標準認証で PostgreSQL ユーザーを管理するをご覧ください。

環境を準備する

自然言語クエリを生成する準備を行うには、必要な拡張機能をインストールして、構成を作成し、スキーマを登録する必要があります。

alloydb_nl_ai 拡張機能をインストールする

alloydb_ai_nl 拡張機能は google_ml_integration 拡張機能を使用して、Vertex AI の Gemini モデルなどの大規模言語モデル(LLM)とやり取りします。

alloydb_ai_nl 拡張機能をインストールするには、データベースに接続し、次のコマンドを実行します。これにより、google_ml_integration 拡張機能と alloydb_ai_nl 拡張機能が有効になります。

CREATE EXTENSION google_ml_integration;
CREATE EXTENSION alloydb_ai_nl cascade;

自然言語構成を作成してスキーマを登録する

AlloyDB AI の自然言語は、nl_config を使用して、特定のスキーマ、クエリ テンプレート、モデル エンドポイントにアプリケーションを関連付けます。nl_config は、アプリケーションをスキーマ、テンプレート、その他のコンテキストに関連付ける構成です。大規模なアプリケーションでは、アプリケーションの各部分に異なる構成を使用することもできます。ただし、アプリケーションのその部分から質問が送信されるときに、適切な構成を指定する必要があります。スキーマ全体を登録することも、テーブル、ビュー、列などの特定のスキーマ オブジェクトを登録することもできます。

  1. 自然言語構成を作成するために、次の例を使用します。

    SELECT
      alloydb_ai_nl.g_create_configuration(
        'my_app_config'        -- configuration_id
      );
    

    「gemini-2.0-flash:generateContent」はモデル エンドポイントです。

  2. 次の例を使用して、指定した構成のスキーマを登録します。

    SELECT
      alloydb_ai_nl.g_manage_configuration(
        operation => 'register_schema',
        configuration_id_in => 'my_app_config',
        schema_names_in => '{my_schema}'
      );
    

コンテキストを追加する

コンテキストには、エンドユーザーの質問に回答するために使用できるあらゆる種類の情報が含まれます。たとえば、スキーマの構造と関係、列の概要と説明、列の値とそのセマンティクス、アプリケーションまたはドメインに固有のビジネス ロジックのルールやステートメントなどがあります。

アプリケーション固有のルールに一般的なコンテキストを追加する

一般的なコンテキスト項目には、アプリケーション固有のルール、ビジネス ロジック ステートメント、特定のスキーマ オブジェクトにリンクされていないアプリケーション固有およびドメイン固有の用語が含まれます。

アプリケーション固有のルールとアプリケーションやドメイン固有の用語の一般的なコンテキストを追加する手順は次のとおりです。

  1. 指定した構成の一般的なコンテキスト項目を追加するには、次の例を使用します。

    SELECT
      alloydb_ai_nl.g_manage_configuration(
        'add_general_context',
        'my_app_config',
        general_context_in => '{"If the user asks for a good seat, assume that means a window or aisle seat."}'
      );
    

    上記のステートメントは、AlloyDB AI 自然言語がユーザーの自然言語による質問に質の高い回答を提供できるようにします。

  2. 指定した構成の一般的なコンテキストを表示するには、次のステートメントを実行します。

    SELECT alloydb_ai_nl.list_general_context(nl_config TEXT);
    

スキーマ コンテキストを生成して確認する

スキーマ コンテキストは、テーブル、ビュー、マテリアライズド ビュー、列などのスキーマ オブジェクトを表します。このコンテキストは、各スキーマ オブジェクトの COMMENT として保存されます。

  1. スキーマ オブジェクトのコンテキストを生成するには、次の API を呼び出します。最良の結果を得るには、データベース テーブルに代表的なデータが含まれるようにしてください。

    -- For all schema objects (tables, views, materialized views and columns)
    -- within the scope of a provided nl_config.
    SELECT
      alloydb_ai_nl.generate_schema_context(
        'my_app_config' -- nl_config
      );
    
  2. 次のステートメントを実行して、生成されたスキーマ コンテキストを確認します。

    SELECT schema_object, object_context
    FROM alloydb_ai_nl.generated_schema_context_view;
    

    生成されたスキーマ コンテキストは、前のビューに保存されます。

  3. 省略可: 生成されたスキーマ コンテキストを更新します。

    SELECT
      alloydb_ai_nl.update_generated_relation_context(
        'my_schema.my_table',
        'This table contains archival records, if you need latest records use records_new table.'
      );
    
    SELECT
      alloydb_ai_nl.update_generated_column_context(
        'my_schema.my_table.column1',
        'The seat_class column takes single letters like "E" for economy, "P" for premium economy, "B" for business and "F" for First.'
      );
    
  4. コンテキストを適用します。コンテキストを適用すると、すぐに有効になり、generated_schema_context_view から削除されます。

    -- For all schema objects (tables, views, materialized views and columns) 
    -- within the scope of nl_config.
    SELECT 
      alloydb_ai_nl.apply_generated_schema_context(
        'my_app_config' --nl_config
      );
    
  5. 省略可: 生成されたコンテキストを確認します。次の API を使用すると、SQL ステートメントの生成時に使用されるスキーマ コンテキストを確認できます。

    -- For table, view or materialized view.
    SELECT
      alloydb_ai_nl.get_relation_context(
        'my_schema.my_table'
      );
    
    -- For column.
    SELECT
      alloydb_ai_nl.get_column_context(
        'my_schema.my_table.column1'
      );
    
  6. 省略可: スキーマ コンテキストを手動で設定します。

    -- For table, view or materialized view.
    SELECT 
      alloydb_ai_nl.set_relation_context(
        'my_schema.my_table',
        'One-to-many mapping from product to categories'
      );
    
    -- For column.
    SELECT 
      alloydb_ai_nl.set_column_context(
        'my_schema.my_table.column1',
        'This column provides additional tagged info for the product in  Json format, e.g., additional color or size information of the product - tags: { "color": "red", "size": "XL"}'
      );
    

クエリ テンプレートを作成する

LLM で構築された生成 AI アプリケーションの品質を高めるには、テンプレートを追加します。クエリ テンプレートは、代表的な自然言語の質問や一般的な質問のセットと、対応する SQL クエリ、および自然言語から SQL(NL2SQL)への変換の宣言的な根拠を示す説明をまとめたものです。テンプレートは主にアプリケーションで指定することを目的としていますが、よく使用される SQL クエリに基づいて alloydb_ai_nl 拡張機能によってテンプレートが自動生成されることもあります。各テンプレートは nl_config に関連付ける必要があります。

alloydb_ai_nl 拡張機能は、template_store を使用して、ユーザーの質問に回答する SQL ステートメントを生成するプロセスで、関連する SQL テンプレートを動的に組み込みます。template_store は、自然言語で尋ねられた質問と意図が類似するテンプレートを識別し、対応するパラメータ化された SQL ステートメントを識別します。また、自然言語の質問の値でパラメータをインスタンス化して SQL ステートメントを合成します。ただし、ユーザーが尋ねた質問と同じインテントを持つテンプレートがない場合、alloydb_ai_nl は関連するすべてのテンプレートとコンテキストを使用して SQL ステートメントを作成します。

テンプレートを追加するには、質問(intent という名前のパラメータを使用)と SQL クエリを指定します。

テンプレートをテンプレート ストアに追加するには、次のステートメントを実行します。

SELECT
  alloydb_ai_nl.add_template(
    nl_config => 'my_app_config',
    intent => 'How many accounts associated with loans are located in the Prague region?',
    sql => 'SELECT COUNT(T1.account_id)
            FROM bird_dev_financial.account AS T1
            INNER JOIN bird_dev_financial.loan AS T2
              ON T1.account_id = T2.account_id
            INNER JOIN bird_dev_financial.district AS T3
              ON T1.district_id = T3.district_id
            WHERE T3."A3" = ''Prague''',
    check_intent => TRUE
  );

check_intentTRUE の場合、alloydb_ai_nl はセマンティック チェックを実行して、指定されたインテントのみが渡された SQL ステートメントと一致することを確認します。インテントが SQL ステートメントと一致しない場合、テンプレートは追加されません。

テンプレートを自動生成する

テーブルに代表的なデータセットを作成したら、エンドユーザーがよく行う一般的な質問に対応する SQL クエリを実行することをおすすめします。クエリに適切なクエリプランがあり、適切に機能することを確認することが重要です。

クエリを実行すると、AlloyDB AI 自然言語はクエリ履歴に基づいてテンプレートを自動的に生成できます。テンプレートは、次の API を呼び出して生成できます。生成されたテンプレートは、使用する前に確認して適用する必要があります。

テンプレートの自動生成は、クエリログ(google_db_advisor_workload_statements)で最もよく使用されるクエリに基づいて行われます。クエリは次の条件に基づいてフィルタされます。

  • SELECT 件のステートメント
  • 実行可能数: EXPLAIN コマンドでクエリを正常に処理できます。
  • 重複なし: 以前テンプレートの生成に使用されていないクエリ。
  • 参照されるすべてのテーブルとビューは nl_config のスコープ内にあります。

テンプレートを自動生成、確認、適用する手順は次のとおりです。

  1. クエリ履歴に基づいてテンプレートを生成するように AlloyDB にリクエストします。

    SELECT 
      alloydb_ai_nl.generate_templates(
        'my_app_config', 
    );
    

    指定されたビュー alloydb_ai_nl.generated_templates_view を使用して、generated_templates を確認します。

    次の出力は、生成されたテンプレートの数を示しています。

    -[ RECORD 1 ]------+--
    generate_templates | 1
    
  2. generated_templates_view ビューを使用して、生成されたテンプレートを確認します。

    SELECT * 
    FROM alloydb_ai_nl.generated_templates_view;
    

    返される出力の例を次に示します。

    -[ RECORD 1 ]----------------------------------------------------------------
    id          | 1
    config      | my_app_config
    type        | Template
    manifest    | How many clients have a birth year of a given number?
    nl          | How many clients have a birth year of 1997?
    sql         | select count(*) from public.client as T where  
                 to_char(T.birth_date::timestamp, 'YYYY') = '1997';
    intent      | How many clients have a birth year of 1997?
    psql        | select count(*) from public.client as T where  
                 to_char(T.birth_date::timestamp, 'YYYY') = $1;
    pintent     | How many clients have a birth year of $1?
    comment     |
    explanation |
    weight      | 1
    
  3. 生成されたテンプレートを更新するには、次のサンプル ステートメントを実行します。

    SELECT alloydb_ai_nl.update_generated_template(
      id => 1,
      manifest => 'How many clients are born in a given year?',
      nl => 'How many clients are born in 1997?',
      intent => 'How many clients are born in 1997?',
      pintent => 'How many clients are born in $1?'
    
    );
    
  4. テンプレートを適用します。適用したテンプレートはすぐにテンプレート ストアに追加され、確認ビューから削除されます。

    -- For all templates generated under the nl config.
    SELECT
      alloydb_ai_nl.apply_generated_templates('my_app_config');
    

自然言語用のセキュリティを構成する

AlloyDB AI の自然言語用のセキュリティを構成するには、パラメータ化されたセキュアビューを使用してアプリケーション データのセキュリティを管理するをご覧ください。

コンセプト タイプと値インデックスを定義する

コンセプト タイプと値インデックスを定義して、質問の詳細を把握します。コンセプト タイプとは、単語やフレーズの単なる文字列ではなく、その文脈における意味を識別するエンティティのカテゴリまたはクラスです。

たとえば、一方の国名が大文字(USA など)で、もう一方の国名が小文字(usa など)であっても 2 つの国名は同一のものである場合があります。この場合、国名はコンセプト タイプになります。コンセプト タイプの他の例としては、人名、都市名、日付などがあります。

値インデックスとは、各列に関連付けられたコンセプト タイプに基づいて、自然言語構成 nl_config の一部である列の値の上にあるインデックスのことです。値インデックスを使用すると、質問の値のフレーズとデータベース内の値を効率的に照合できます。

コンセプト タイプと値インデックスを定義するには、次の手順でサンプルを使用します。これらの例では、列をコンセプト タイプに関連付け、値インデックスを作成して更新し、類義語セットを使用して値検索を実行します。

  1. 列をコンセプト タイプに関連付けるには、次のクエリを実行します。

    SELECT
      alloydb_ai_nl.associate_concept_type(
        column_names_in => 'my_schema.country.country_name',
        concept_type_in => 'country_name',
        nl_config_id_in => 'my_app_config'
      );
    
  2. 自然言語構成の一部であり、コンセプト タイプに関連付けられているすべての列に基づいて値インデックスを作成するには、次のステートメントを実行します。

    SELECT
      alloydb_ai_nl.create_value_index(
        nl_config_id_in => 'my_app_config'
      );
    
  3. コンセプト タイプを新しい列に関連付けたら、値インデックスを更新して変更を反映します。

    SELECT
      alloydb_ai_nl.refresh_value_index(
        nl_config_id_in => 'my_app_config'
      );
    
  4. AlloyDB AI 自然言語で値の類義語を照合するには、次のサンプル ステートメントを実行します。

    SELECT
      alloydb_ai_nl.insert_synonym_set(
        ARRAY [
          'USA',
          'US',
          'United States',
          'United States of America'
        ]
      );
    

    テーブルのデータで特定の値が使用される場合があります(たとえば、United States が国を識別するために使用されている場合)。United States のすべての類義語を含む類義語セットを定義できます。自然言語の質問に同義語が含まれている場合、AlloyDB AI 自然言語は同義語をテーブル内の値と照合します。

  5. 値の検索を実行して、値のフレーズ配列から正しいデータベース値を見つけます。

    SELECT
      alloydb_ai_nl.get_concept_and_value(
        value_phrases_in => ARRAY['United States'],
        nl_config_id_in  => 'my_app_config'
      );
    

    たとえば、ユーザーが次の get_sql クエリを使用する「米国の人口は?」のような質問をした場合、AlloyDB AI 自然言語は、値のフレーズ United States を指定した get_concept_and_value 関数を使用して、値インデックスにファジー検索を実行します。ファジー検索とは、検索語句が対応するデータと完全に一致しない場合でも一致を検出する検索手法です。

    自然言語は、検索クエリに近い結果(値 USA)を見つけ、その結果を使用して SQL クエリを生成します。

    SELECT
      alloydb_ai_nl.get_sql(
        nl_config_id    => 'my_app_config',
        nl_question     => 'What is the population of the United States?',
        additional_info => json_build_object('enrich_nl_question', TRUE)
      ) ->> 'sql';
    

    AlloyDB AI 自然言語で定義された組み込みコンセプト タイプを次の表に示します。

    コンセプト名 説明
    generic_entity_name 一般的なエンティティ名には、単一の文字列型列を使用できます。例:
      SELECT alloydb_ai_nl.associate_concept_type('public.item.item_name', 'generic_entity_name')
      
    country_namecity_nameregion_name 国、都市、地域の名前。使用方法は、generic_entity_name コンセプト タイプとまったく同じです。
    full_person_name 氏名(名、姓、ミドルネーム)。個人のフルネームには、最大 3 つの文字列型列を使用できます。名前列を full_person_name に関連付けるときは、任意の列をスキップできます。例:
      SELECT alloydb_ai_nl.associate_concept_type('public.person.last_name,public.person.first_name,public.person.middle_name','full_person_name')
      
    ssn 社会保障番号を含む単一の文字列の列。例:
      SELECT alloydb_ai_nl.associate_concept_type('public.person.ssn','ssn')
     
    date 日付またはタイムスタンプ。例:
     SELECT alloydb_ai_nl.associate_concept_type('public.person.date_col','date')
     

自然言語入力から SQL ステートメントを生成する

AlloyDB AI の自然言語を使用して、自然言語入力から SQL ステートメントを生成できます。生成された SQL ステートメントを実行すると、自然言語の質問に回答するために必要なデータがデータベースから提供されます。

  1. 自然言語を使用して alloydb_ai_nl.get_sql 関数でデータベースから結果を取得するには、次の例を使用します。

    SELECT
      alloydb_ai_nl.get_sql(
        'my_app_config', -- nl_config
        'What is the sum that client number 4''s account has following transaction 851?' -- nl question
      );
    

    次の JSON 出力が返されます。

    {
      "sql": "SELECT T3.balance FROM public.client AS T1 INNER JOIN public.account AS T2 ON T1.district_id = T2.district_id INNER JOIN public.trans AS T3 ON T2.account_id = T3.account_id WHERE T1.client_id = 4 AND T3.trans_id = 851",
      "prompt": "",
      "retries": 0,
      "error_msg": "",
      "nl_question": "What is the sum that client number 4's account has following transaction 851?"
    }
    
  2. 省略可: 生成された SQL クエリをテキスト文字列として抽出するには、->>'sql' を追加します。

    SELECT
      alloydb_ai_nl.get_sql(
        'my_app_config', -- nl_config
        'What is the sum that client number 4''s account has following transaction 851?' -- nl question
      ) ->> 'sql';
    

    ->> 演算子は、JSON 値をテキストとして抽出するために使用されます。alloydb_ai_nl.get_sql 関数は JSON オブジェクトを返します。これは、キー sql に関連付けられた値を取得するステートメントの一部です。この値は、生成された SQL クエリです。

テストして改善する

自動生成クエリを改善するには、より適切なコンテキストクエリ テンプレート値インデックスを追加し、目的の結果が得られるまで反復処理します。

次のステップ