자연어 질문을 사용하여 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 프로젝트에 다음 Identity and Access Management (IAM) 역할이 있어야 합니다.

자세한 내용은 표준 인증으로 PostgreSQL 사용자 관리를 참고하세요.

개발 환경 준비

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

alloydb_nl_ai 확장 프로그램 설치

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

alloydb_ai_nl 확장 프로그램을 설치하려면 데이터베이스에 연결하고 google_ml_integrationalloydb_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)이더라도 두 국가 이름이 동일할 수 있습니다. 이 경우 국가 이름이 개념 유형입니다. 개념 유형의 다른 예로는 사람 이름, 도시 이름, 날짜가 있습니다.

값 색인은 자연 언어 구성 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 쿼리입니다.

테스트 및 조정

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

다음 단계