AI 함수를 사용하여 지능형 SQL 쿼리 실행

문서 버전을 선택합니다.

이 페이지에서는 AlloyDB Omni AI 쿼리 엔진을 사용하고 AI 함수를 사용하여 지능형 SQL 쿼리를 실행하는 방법을 보여줍니다.

AlloyDB AI 함수는 Gemini와 같은 대규모 언어 모델 (LLM)을 AlloyDB Omni 데이터와 직접 통합하여 지능형 데이터 작업을 실행합니다. 이 기능에는 다음을 위한 기본 제공 함수가 포함되어 있습니다.

  • 필터링 (ai.if)
  • 시맨틱 순위 지정 (ai.rank)
  • 텍스트 생성 (ai.generate)

이러한 AI 함수는 AlloyDB AI 쿼리 엔진을 사용하여 애플리케이션이 단일 행 응답에서 대규모 데이터베이스 작업에 이르기까지 다양한 규모로 인공 지능 모델을 사용하여 데이터를 처리하도록 지원합니다. ai.if, ai.rank, ai.generate 연산자를 사용하여 자연어를 SQL 쿼리와 결합할 수 있습니다. AlloyDB AI는 ai 스키마를 예약하고 만듭니다.

입력 데이터 및 메모리 할당을 처리하는 방식에 따라 스칼라, 배열 기반, 커서 함수라는 세 가지 카테고리의 AI 함수가 있습니다. 적절한 AI 함수를 선택하는 것은 데이터 규모와 성능 요구사항에 따라 달라집니다. 다음 표를 사용하여 이러한 함수와 사용 사례를 알아보세요.

카테고리

설명

권장 사용 사례

스칼라

기본적인 일대일 처리를 위해 설계되었습니다. 단일 입력을 가져와 단일 출력을 반환합니다.

스칼라 함수 호출을 소수(50개 미만)로 만드는 쿼리에 허용 가능한 성능을 제공하는 기본 함수를 원하는 경우 사용합니다.

배열 기반

단일 함수 호출에서 데이터를 행 배열로 처리합니다. 배열을 입력으로 가져와 배열을 출력으로 반환합니다.

적격 행의 전체 배열이 메모리 제한 내에 들어갈 수 있는 중소규모 데이터 세트에 사용합니다. 이렇게 하면 집합 기반 작업에 높은 처리량을 제공할 수 있습니다.

커서

커서를 입력으로 가져와 커서를 출력으로 반환합니다.

대규모 행(예: 10,000개 행)을 처리하는 데 사용합니다.

시작하기 전에

  1. Vertex AI 모델에 대한 사용자 액세스 권한을 구성합니다.
  2. 최신 버전의 google_ml_integration이 설치되어 있는지 확인합니다.

    1. 설치된 버전을 확인하려면 다음 명령어를 실행합니다.

      SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';
      extversion 
      ------------
      1.5.2
      (1 row)
    2. 확장 프로그램이 설치되지 않았거나 설치된 버전이 1.5.2 이전이면 확장 프로그램을 업데이트합니다.

      CREATE EXTENSION IF NOT EXISTS google_ml_integration;
      ALTER EXTENSION google_ml_integration UPDATE;

      위 명령어를 실행할 때 문제가 발생하거나 위 명령어를 실행한 후에도 확장 프로그램이 1.5.2 버전으로 업데이트되지 않으면 Google Cloud 지원팀에 문의하세요.

  3. AlloyDB AI 쿼리 엔진 기능을 사용하려면 google_ml_integration.enable_ai_query_engine 플래그를 on으로 설정합니다.

    SQL

    1. 현재 세션에 AI 쿼리 엔진을 사용 설정합니다.

      SET google_ml_integration.enable_ai_query_engine = on;
    2. 세션 간에 특정 데이터베이스 기능을 사용 설정합니다.

      ALTER DATABASE DATABASE_NAME SET google_ml_integration.enable_ai_query_engine = 'on';
    3. 세션 과 데이터베이스 전반에서 특정 사용자에 AI 쿼리 엔진을 사용 설정합니다.

      ALTER ROLE postgres SET google_ml_integration.enable_ai_query_engine = 'on';

해당 리전에서 지원되는 Gemini 모델 사용

AlloyDB Omni 클러스터가 gemini-2.5-flash-lite가 지원되지 않는 리전에 있는 경우 model_id parameter를 사용하여 해당 리전에서 사용할 수 있는 다른 Gemini 모델 중 하나를 사용할 수 있습니다.

또는 Gemini 모델 엔드포인트를 등록하고 해당 모델 ID를 AI 연산자에 제공할 수 있습니다. 자세한 내용은 모델 엔드포인트 관리를 사용하여 원격 AI 모델 등록 및 호출을 참조하세요.

다음 예시에서는 다른 Gemini 엔드포인트를 등록하는 방법을 보여줍니다. 이 예시에서 두 번째 Gemini 엔드포인트는 gemini-2.5-flash-lite의 전역 엔드포인트입니다. `model_id => 'gemini-2.5-flash-lite-global'`을 추가 인수로 전달하여 AI 연산자와 함께 등록된 이 모델을 사용할 수 있습니다.

CALL
  google_ml.create_model(
    model_id => 'gemini-2.5-flash-lite-global',
    model_type => 'llm',
    model_provider => 'google',
    model_qualified_name => 'gemini-2.5-flash-lite',
    model_request_url =>  'https://aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/global/publishers/google/models/gemini-2.5-flash-lite:generateContent',
    model_auth_type => 'alloydb_service_agent_iam'
);

Gemini 3.0 모델 사용

gemini-3.0-pro-preview와 같은 일부 Gemini 모델은 전역 엔드포인트를 통해서만 사용할 수 있습니다. 이러한 모델은 다음과 같이 등록해야 합니다.

CALL
  google_ml.create_model(
    model_id => 'gemini-3-preview-model',
    model_request_url => 'https://aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/global/publishers/google/models/gemini-3-pro-preview:generateContent',
    model_qualified_name => 'gemini-3-pro-preview',
    model_provider => 'google',
    model_type => 'llm',
    model_auth_type => 'alloydb_service_agent_iam'
);

PROJECT_ID를 Vertex AI 모델을 사용할 수 있는 프로젝트의 ID로 바꿉니다. AlloyDB Omni 서비스 계정에는 해당 프로젝트의 Vertex AI 사용자 역할이 있어야 합니다.

모델을 등록한 후 다음과 같이 AI 함수에서 사용할 수 있습니다.

SELECT ai.generate(prompt => 'What is AlloyDB?', model_id => 'gemini-3-preview-model');

쿼리에서 필터 사용

AlloyDB AI는 ai.if 및 ai.rank 연산자를 비롯해 데이터베이스 쿼리 내에서 직접 자연어 처리 및 LLM을 사용할 수 있는 AI 기반 SQL 함수를 제공합니다.

스칼라 함수를 사용하여 필터링 실행

자연어로 명시된 조건이 충족되는지 평가하려면 ai.if/google_ml.if 연산자를 사용하세요. 이 함수는 불리언 참 또는 거짓 값을 반환하며, 출력이 명확하게 감지되지 않으면 false를 반환합니다.

- Function signature
FUNCTION ai.if(prompt TEXT, model_id VARCHAR(100) DEFAULT NULL) RETURNS bool

다음 예시는 ai.if 연산자를 필터로 사용하여 긍정적 리뷰가 500개를 초과하고 인구가 100,000명을 초과하는 도시에 있는 레스토랑을 찾는 방법을 보여줍니다. 이 예시에서는 restaurant_reviews를 사용하며 리뷰 및 도시 위치와 같은 데이터를 포함합니다. ai.if 연산자를 사용하면 리뷰 감정을 파악하고 데이터베이스의 위치를 해당 위치의 인구에 관한 Gemini 일반 지식과 결합할 수 있습니다.

SELECT r.name, r.location_city
FROM restaurant_reviews r
WHERE
  AI.IF(r.location_city || ' has a population OF more than 100,000 AND the following is a positive review; Review: ' || r.review)
GROUP BY r.name, r.location_city
HAVING COUNT(*) > 500;

다음은 해당 리전에서 지원되는 Gemini 모델 사용에 등록한 모델을 사용하여 동일한 예시를 보여줍니다.

SELECT r.name, r.location_city
FROM restaurant_reviews r
WHERE
  AI.IF(r.location_city || ' has a population of more than 100,000 AND the following is a positive review; Review: ' || r.review, model_id => 'gemini-2.5-flash-lite')
GROUP BY r.name, r.location_city
HAVING COUNT(*) > 500;

if 연산자를 사용하는 쿼리에서 조인 실행

조인 작업을 실행하려면 조인과 함께 ai.if/google_ml.if 연산자를 사용하세요. 다음 샘플 쿼리는 레스토랑 메뉴에서 각 메뉴 항목을 언급하는 리뷰 수를 찾습니다.

    SELECT item_name, COUNT(*)
    FROM menu_items JOIN user_reviews
      ON ai.if(
        prompt => 'Does the following user review talk about the menu item mentioned ? review: ' || user_reviews.review_text || ' menu item: ' || item_name)
    GROUP BY item_name;

배열 기반 함수를 사용하여 필터링 실행

다음 예에서는 AI 모델 (gemini-2.5-flash-lite)을 사용하여 리뷰 감정을 분석하고 결과를 필터링하여 긍정적 리뷰가 10개를 초과하는 레스토랑을 식별합니다. ARRAY_AGG 는 데이터의 개별 행을 구조화된 배열로 변환하는 데 사용되므로 AI 모델에서 한 번에 한 행씩이 아닌 일괄적으로 처리할 수 있습니다.

WITH initial_arrays AS (WITH initial_arrays AS (
  SELECT
    ARRAY_AGG(r.id ORDER BY r.id) AS review_ids,
    -- Assuming ai.if takes an array of prompts and returns a boolean array
    ai.if(
      prompts => ARRAY_AGG('Is the review positive: ' || r.review ORDER BY r.id)
      model_id => 'gemini-2.5-flash-lite',
      batch_size => 20
    ) AS truth_values
  FROM restaurant_reviews r
),
reviews AS (
SELECT
  initial_arrays.review_ids[i] AS review_id,
  initial_arrays.truth_values[i] AS truth_value
FROM
  initial_arrays,
  generate_series(1, array_length(initial_arrays.review_ids, 1)) AS i
)
SELECT rest_review.city, rest_review.name
FROM restaurant_reviews rest_review JOIN reviews review ON rest_review.id=review.review_id
WHERE review.truth_value = 't'
GROUP BY rest_review.city, rest_review.name
HAVING COUNT(*) > 10;

커서를 사용하여 필터링 실행

다음 예에서는 커서를 통해 스트리밍하여 대규모 레스토랑 리뷰를 필터링하는 방법을 보여줍니다.

CREATE TABLE filtered_results(input text, result bool);

DO $$
DECLARE
    prompt_cursor REFCURSOR;
    result_cursor REFCURSOR;
    rec RECORD;
BEGIN
    -- 1. Open a cursor for the input data
    OPEN prompt_cursor FOR
        SELECT r.location_city || ' has a population of > 100,000 and is a positive review; Review: ' || r.review
        FROM restaurant_reviews r;

    -- 2. Call the array-based function using the input cursor
    result_cursor := ai.if(
        'Is the given statement true? ',
        prompt_cursor,
        model_id => 'gemini-2.5-flash-lite'
    );

    -- 3. Fetch results from the output cursor and store them
    LOOP
        FETCH result_cursor INTO rec;
        EXIT WHEN NOT FOUND;
        INSERT INTO filtered_results VALUES(rec.input, rec.output);
    END LOOP;

    CLOSE result_cursor;
END $$;

텍스트 생성 및 요약

AlloyDB AI는 스칼라 ai.generate 및 배열 기반, 커서 기반 ai.generate와 같은 텍스트 생성 연산자를 제공합니다.

스칼라 함수를 사용하여 텍스트 생성 실행

ai.generate 함수는 제공된 데이터와 사용자의 프롬프트를 결합하여 텍스트를 생성합니다.

-- Function Signature
FUNCTION ai.generate(prompt TEXT, model_id VARCHAR(100) DEFAULT NULL) RETURNS TEXT

예를 들어 다음 쿼리를 사용하여 각 사용자 리뷰의 간결한 요약을 생성할 수 있습니다.

SELECT
  ai.generate(
    prompt => 'Summarize the review in 20 words or less. Review: ' || review) AS review_summary
FROM user_reviews;

배열 기반 함수를 사용하여 텍스트 생성 실행

다음 쿼리는 UNNEST 및 ai.generate를 사용하여 여러 리뷰를 효율적으로 요약합니다.

SELECT
  UNNEST(
    ai.generate(
      prompts => ARRAY_AGG('Summarize the review in 20 words or less. Review: ' || review),
      model_id => 'gemini-2.5-flash-lite',
    )
  ) AS review_summary
FROM user_reviews;

커서를 사용하여 텍스트 생성 실행

메모리 병목 현상을 일으키지 않고 수백만 개의 행에 대한 요약 또는 번역을 생성하려면 커서가 있는 일괄 생성 기능을 사용하세요.

CREATE TABLE summary_results(summary text);

DO $$
DECLARE
    prompt_cursor REFCURSOR;
    summary_cursor REFCURSOR;
    rec RECORD;
BEGIN
    OPEN prompt_cursor FOR SELECT review_text FROM user_reviews ORDER BY id;

    summary_cursor := ai.generate(
        'Summarize the review in 20 words or less. Review:',
        prompt_cursor,
    );

    LOOP
        FETCH summary_cursor INTO rec;
        EXIT WHEN NOT FOUND;
        INSERT INTO summary_results VALUES(rec.output);
    END LOOP;

    CLOSE summary_cursor;
END $$;

쿼리 결과 점수 매기기

커스텀 자연어 요청 사항을 사용하여 쿼리 결과를 정렬해야 하는 경우 ai.rank 연산자를 사용하세요.

스칼라 함수를 사용하여 점수 매기기 실행

다음 함수를 사용하면 순위 지정 기준을 설명하는 프롬프트를 제공하고 각 항목의 점수를 반환할 수 있습니다.

-- Function signature
FUNCTION ai.rank(prompt TEXT, model_id VARCHAR(100) DEFAULT NULL) RETURNS real

예를 들어 다음 쿼리는 LLM의 점수를 사용하여 상위 20개의 가장 긍정적인 레스토랑 리뷰를 가져옵니다.

SELECT review AS top20
FROM user_reviews
ORDER BY ai.rank(
  'Score the following review according to these rules:
  (1) Score OF 8 to 10 IF the review says the food IS excellent.
  (2) 4 to 7 IF the review says the food is ok.
  (3) 1 to 3 IF the review says the food is not good. Here is the review:' || review) DESC
LIMIT 20;

배열 기반 함수를 사용하여 점수 매기기 실행

이 ai.rank 함수를 사용하면 커스텀 자연어 요청 사항을 기반으로 쿼리 결과에 점수를 매기고 순위를 지정할 수 있습니다.

FUNCTION ai.rank(prompts TEXT[], model_id VARCHAR(100) DEFAULT NULL) RETURNS real[]

다음 쿼리는 UNNEST 및 ai.rank를 사용하여 여러 리뷰에 효율적으로 점수를 매깁니다.

SELECT
  UNNEST(
    ai.rank(
      ARRAY_AGG('Score the following review according to these rules:
  (1) Score OF 8 to 10 IF the review says the food IS excellent.
  (2) 4 to 7 IF the review says the food is ok.
  (3) 1 to 3 IF the review says the food is not good. Here is the review:' || review),
    )
  ) as review_scores
FROM user_reviews;

커서를 사용하여 점수 매기기 실행

이 함수는 메모리 제한을 초과하지 않고 대규모 데이터 세트에 점수를 매기는 데 사용됩니다.

FUNCTION ai.rank(context TEXT, input_cursor REFCURSOR, model_id VARCHAR(100) DEFAULT NULL) RETURNS REFCURSOR

다음 예에서는 특정 자연어 기준에 따라 대용량 텍스트에 점수를 매기는 방법을 보여줍니다.

CREATE TABLE scored_results(input text, score real);

DO $$
DECLARE
    prompt_cursor REFCURSOR;
    score_cursor REFCURSOR;
    rec RECORD;
BEGIN
    OPEN prompt_cursor FOR SELECT review FROM user_reviews ORDER BY id;

    score_cursor := ai.rank(
        'Score the following review: (1) 8-10 if excellent, (2) 4-7 if ok, (3) 1-3 if not good. Review:',
        prompt_cursor,
    );

    LOOP
        FETCH score_cursor INTO rec;
        EXIT WHEN NOT FOUND;
        INSERT INTO scored_results VALUES(rec.input, rec.output);
    END LOOP;

    CLOSE score_cursor;
END $$;

다음 단계