자연어 질문을 사용하여 SQL 쿼리 생성

이 페이지에서는 AlloyDB AI 자연어를 사용하여 SQL 문을 설정, 구성, 생성하는 방법을 설명합니다. 자연어를 사용하면 자연어를 사용하여 데이터베이스를 쿼리하는 사용자 대상 생성형 AI 애플리케이션을 만들 수 있습니다.

PostgreSQL용 AlloyDB 자연어 지원 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 프로젝트에 다음 ID 및 액세스 관리 (IAM) 역할이 있어야 합니다.

자세한 내용은 기본 제공되는 인증으로 PostgreSQL 사용자 관리를 참고하세요.

개발 환경 준비

자연어 쿼리를 생성하려면 필수 확장 프로그램을 설치하고, 구성을 만들고, 스키마를 등록해야 합니다.

alloydb_nl_ai 확장 프로그램 설치

alloydb_ai_nl 확장 프로그램은 Vertex AI의 Gemini 모델을 비롯한 대규모 언어 모델 (LLM)과 상호작용하는 google_ml_integration 확장 프로그램을 사용합니다.

alloydb_ai_nl 확장 프로그램을 설치하려면 데이터베이스에 연결하고 다음 명령어를 실행합니다.

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
    

    반환된 출력의 manifest은 일반 템플릿이거나 질문 유형 또는 실행할 수 있는 작업에 관한 광범위한 설명입니다. pintentintent의 매개변수화된 버전으로, 특정 값 (1997)을 자리표시자 ($1)로 대체하여 intent를 일반화합니다.

  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)인 경우에도 두 국가 이름이 동일할 수 있습니다. 이 경우 국가 이름은 개념 유형입니다. 개념 유형의 다른 예로는 사람 이름, 도시 이름, 날짜가 있습니다.

값 색인은 각 열과 연결된 개념 유형을 기반으로 자연어 구성 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_name, city_name, region_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 쿼리입니다.

테스트 및 개선

자동 생성된 쿼리를 개선하려면 더 나은 컨텍스트, 쿼리 템플릿, 값 색인을 수정하거나 추가한 다음 원하는 결과가 나올 때까지 반복합니다.

다음 단계