PostgreSQL용 Cloud SQL에서 벡터 임베딩 시작하기

1. 소개

이 Codelab에서는 벡터 검색을 Vertex AI 임베딩과 결합하여 PostgreSQL용 Cloud SQL AI 통합을 사용하는 방법을 알아봅니다.

30b7c4dcdd8bb68f.png

기본 요건

  • Google Cloud, 콘솔에 관한 기본적인 이해
  • 명령줄 인터페이스 및 Cloud Shell의 기본 기술

학습할 내용

  • PostgreSQL용 Cloud SQL 인스턴스를 배포하는 방법
  • 데이터베이스를 만들고 Cloud SQL AI 통합을 사용 설정하는 방법
  • 데이터베이스에 데이터를 로드하는 방법
  • Cloud SQL에서 Vertex AI 임베딩 모델을 사용하는 방법
  • Vertex AI 생성형 모델을 사용하여 결과를 보강하는 방법
  • 벡터 색인을 사용하여 성능을 개선하는 방법

필요한 항목

  • Google Cloud 계정 및 Google Cloud 프로젝트
  • Google Cloud 콘솔 및 Cloud Shell을 지원하는 웹브라우저(예: Chrome)

2. 설정 및 요구사항

자습형 환경 설정

  1. Google Cloud Console에 로그인하여 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. 아직 Gmail이나 Google Workspace 계정이 없는 경우 계정을 만들어야 합니다.

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • 프로젝트 이름은 이 프로젝트 참가자의 표시 이름입니다. 이는 Google API에서 사용하지 않는 문자열이며 언제든지 업데이트할 수 있습니다.
  • 프로젝트 ID는 모든 Google Cloud 프로젝트에서 고유하며, 변경할 수 없습니다(설정된 후에는 변경할 수 없음). Cloud 콘솔은 고유한 문자열을 자동으로 생성합니다. 일반적으로는 신경 쓰지 않아도 됩니다. 대부분의 Codelab에서는 프로젝트 ID (일반적으로 PROJECT_ID로 식별됨)를 참조해야 합니다. 생성된 ID가 마음에 들지 않으면 다른 임의 ID를 생성할 수 있습니다. 또는 직접 시도해 보고 사용 가능한지 확인할 수도 있습니다. 이 단계 이후에는 변경할 수 없으며 프로젝트 기간 동안 유지됩니다.
  • 참고로 세 번째 값은 일부 API에서 사용하는 프로젝트 번호입니다. 이 세 가지 값에 대한 자세한 내용은 문서를 참고하세요.
  1. 다음으로 Cloud 리소스/API를 사용하려면 Cloud 콘솔에서 결제를 사용 설정해야 합니다. 이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 튜토리얼이 끝난 후에 요금이 청구되지 않도록 리소스를 종료하려면 만든 리소스 또는 프로젝트를 삭제하면 됩니다. Google Cloud 신규 사용자는 300달러(USD) 상당의 무료 체험판 프로그램에 참여할 수 있습니다.

Cloud Shell 시작

Google Cloud를 노트북에서 원격으로 실행할 수 있지만, 이 Codelab에서는 Cloud에서 실행되는 명령줄 환경인 Google Cloud Shell을 사용합니다.

Google Cloud Console의 오른쪽 상단 툴바에 있는 Cloud Shell 아이콘을 클릭합니다.

55efc1aaa7a4d3ad.png

환경을 프로비저닝하고 연결하는 데 몇 분 정도 소요됩니다. 완료되면 다음과 같이 표시됩니다.

7ffe5cbb04455448.png

가상 머신에는 필요한 개발 도구가 모두 들어있습니다. 영구적인 5GB 홈 디렉터리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 Codelab의 모든 작업은 브라우저 내에서 수행할 수 있습니다. 아무것도 설치할 필요가 없습니다.

3. 시작하기 전에

API 사용 설정

출력:

Cloud Shell 내에 프로젝트 ID가 설정되어 있는지 확인합니다.

gcloud config set project [YOUR-PROJECT-ID]

PROJECT_ID 환경 변수를 설정합니다.

PROJECT_ID=$(gcloud config get-value project)

필요한 모든 서비스를 사용 설정합니다.

gcloud services enable sqladmin.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.googleapis.com

예상 출력

student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417
Updated property [core/project].
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project)
Your active configuration is: [cloudshell-14650]
student@cloudshell:~ (test-project-001-402417)$ 
student@cloudshell:~ (test-project-001-402417)$ gcloud services enable sqladmin.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.

4. Cloud SQL 인스턴스 만들기

Vertex AI와 데이터베이스 통합을 통해 Cloud SQL 인스턴스를 만듭니다.

데이터베이스 비밀번호 만들기

기본 데이터베이스 사용자의 비밀번호를 정의합니다. 자체 비밀번호를 정의하거나 랜덤 함수를 사용하여 비밀번호를 생성할 수 있습니다.

export CLOUDSQL_PASSWORD=`openssl rand -hex 12`

생성된 비밀번호 값을 확인합니다.

echo $CLOUDSQL_PASSWORD

PostgreSQL용 Cloud SQL 인스턴스 만들기

Cloud Shell 세션에서 다음을 실행합니다.

gcloud sql instances create my-cloudsql-instance \
--database-version=POSTGRES_16 \
--tier=db-custom-1-3840 \
--region=us-central1 \
--edition=ENTERPRISE \
--enable-google-ml-integration \
--database-flags cloudsql.enable_google_ml_integration=on

인스턴스를 만든 후에는 인스턴스의 기본 사용자 비밀번호를 설정하고 이 비밀번호로 연결할 수 있는지 확인해야 합니다.

gcloud sql users set-password postgres \
    --instance=my-cloudsql-instance \
    --password=$CLOUDSQL_PASSWORD

명령어를 실행하고 연결할 준비가 되면 프롬프트에 비밀번호를 입력합니다.

gcloud sql connect my-cloudsql-instance --user=postgres

Vertex AI 통합 사용 설정

Vertex AI 통합을 사용할 수 있도록 내부 Cloud SQL 서비스 계정에 필요한 권한을 부여합니다.

Cloud SQL 내부 서비스 계정 이메일을 찾아 변수로 내보냅니다.

SERVICE_ACCOUNT_EMAIL=$(gcloud sql instances describe my-cloudsql-instance --format="value(serviceAccountEmailAddress)")
echo $SERVICE_ACCOUNT_EMAIL

Cloud SQL 서비스 계정에 Vertex AI 액세스 권한을 부여합니다.

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
  --role="roles/aiplatform.user"

인스턴스 생성 및 구성에 관한 자세한 내용은 여기에서 Cloud SQL 문서를 참고하세요.

5. 데이터베이스 준비

이제 데이터베이스를 만들고 벡터 지원을 사용 설정해야 합니다.

데이터베이스 만들기

quickstart_db라는 이름으로 데이터베이스를 만듭니다 .이렇게 하려면 PostgreSQL용 psql, SDK 또는 Cloud SQL 스튜디오와 같은 명령줄 데이터베이스 클라이언트와 같은 다양한 옵션이 있습니다. 데이터베이스를 만들고 인스턴스에 연결하는 데 SDK (gcloud)를 사용합니다.

Cloud Shell에서 데이터베이스를 만들기 위한 명령어를 실행합니다.

gcloud sql databases create quickstart_db --instance=my-cloudsql-instance

확장 프로그램 사용 설정

Vertex AI 및 벡터를 사용할 수 있도록 하려면 생성된 데이터베이스에서 두 가지 확장 프로그램을 사용 설정해야 합니다.

Cloud Shell에서 명령어를 실행하여 생성된 데이터베이스에 연결합니다 (비밀번호를 입력해야 함).

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

그런 다음 연결이 완료되면 sql 세션에서 다음 두 명령어를 실행해야 합니다.

CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector CASCADE;

SQL 세션을 종료합니다.

exit;

6. 데이터 로드

이제 데이터베이스에 객체를 만들고 데이터를 로드해야 합니다. 가상의 심벌 스토어 데이터를 사용합니다. 데이터는 공개 Google Storage 버킷에서 CSV 형식으로 제공됩니다.

먼저 데이터베이스에 필요한 모든 객체를 만들어야 합니다. 이를 위해 이미 익숙한 gcloud sql connect 및 gcloud storage 명령어를 사용하여 스키마 객체를 다운로드하고 데이터베이스로 가져옵니다.

Cloud Shell에서 인스턴스를 만들 때 기록한 비밀번호를 실행하고 입력합니다.

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

이전 명령어에서 정확히 무엇을 했나요? 데이터베이스에 연결하고 다운로드한 SQL 코드를 실행하여 테이블, 색인, 시퀀스를 만들었습니다.

다음 단계는 데이터를 로드하는 것이며 이를 위해 Google Cloud Storage에서 CSV 파일을 다운로드해야 합니다.

gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv .
gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv .
gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv .

그런 다음 데이터베이스에 연결해야 합니다.

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

CSV 파일에서 데이터를 가져옵니다.

\copy cymbal_products from 'cymbal_products.csv' csv header
\copy cymbal_inventory from 'cymbal_inventory.csv' csv header
\copy cymbal_stores from 'cymbal_stores.csv' csv header

SQL 세션을 종료합니다.

exit;

자체 데이터가 있고 CSV 파일이 Cloud 콘솔에서 제공하는 Cloud SQL 가져오기 도구와 호환되는 경우 명령줄 접근 방식 대신 이 도구를 사용할 수 있습니다.

7. 임베딩 만들기

다음 단계는 Google Vertex AI의 textembedding-004 모델을 사용하여 제품 설명의 임베딩을 빌드하고 벡터 데이터로 저장하는 것입니다.

데이터베이스에 연결합니다.

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

그리고 임베딩 함수를 사용하여 cymbal_products 테이블에 가상 열 embedding을 만듭니다.

ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-004',product_description)) STORED;

다소 시간이 걸릴 수 있지만 900~1,000개의 행인 경우 5분 이상 걸리지 않으며 일반적으로 훨씬 더 빠릅니다.

8. 유사성 검색 실행

이제 설명에 대해 계산된 벡터 값과 요청에 대해 가져온 벡터 값을 기반으로 유사성 검색을 사용하여 검색을 실행할 수 있습니다.

SQL 쿼리는 gcloud sql connect를 사용하여 동일한 명령줄 인터페이스에서 실행하거나, 또는 Cloud SQL Studio에서 실행할 수 있습니다. 행이 여러 개이고 복잡한 쿼리는 Cloud SQL Studio에서 관리하는 것이 좋습니다.

Cloud SQL Studio 시작

콘솔에서 이전에 만든 Cloud SQL 인스턴스를 클릭합니다.

b8d4844da1114a0b.png

오른쪽 패널에서 열면 Cloud SQL Studio가 표시됩니다. 새 템플릿을 클릭합니다.

ce3f27dc21367f2e.png

데이터베이스 이름과 사용자 인증 정보를 입력할 수 있는 대화상자가 열립니다.

  • 데이터베이스: quickstart_db
  • 사용자: postgres
  • 비밀번호: 기본 데이터베이스 사용자의 메모된 비밀번호

'AUTHENTICATE'(인증) 버튼을 클릭합니다.

2591c8bbc93e4e97.png

다음 창이 열리면 오른쪽에 있는 '편집기' 탭을 클릭하여 SQL 편집기를 엽니다.

74307cb101a3ba9d.png

이제 쿼리를 실행할 준비가 되었습니다.

쿼리 실행

쿼리를 실행하여 고객의 요청과 가장 밀접하게 관련된 사용 가능한 제품 목록을 가져옵니다. 벡터 값을 가져오기 위해 Vertex AI에 전달할 요청은 '여기에서 잘 자라는 과일나무는 어떤 종류인가요?'와 같습니다.

다음은 요청에 가장 적합한 첫 10개 항목을 선택하는 데 사용할 수 있는 쿼리입니다.

SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        (cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) as distance
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        distance ASC
LIMIT 10;

쿼리를 복사하여 Cloud SQL 스튜디오 편집기에 붙여넣고 '실행' 버튼을 누르거나 quickstart_db 데이터베이스에 연결하는 명령줄 세션에 붙여넣습니다.

cd07549522fd04c9.png

다음은 검색어와 일치하는 선택된 제품 목록입니다.

product_name       |                                   description                                    | sale_price | zip_code |      distance       
-------------------------+----------------------------------------------------------------------------------+------------+----------+---------------------
 Cherry Tree             | This is a beautiful cherry tree that will produce delicious cherries. It is an d |      75.00 |    93230 | 0.43922018972266397
 Meyer Lemon Tree        | Meyer Lemon trees are California's favorite lemon tree! Grow your own lemons by  |         34 |    93230 |  0.4685112926118228
 Toyon                   | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e |      10.00 |    93230 |  0.4835677149651668
 California Lilac        | This is a beautiful lilac tree that can grow to be over 10 feet tall. It is an d |       5.00 |    93230 |  0.4947204525907498
 California Peppertree   | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e |      25.00 |    93230 |  0.5054166905547247
 California Black Walnut | This is a beautiful walnut tree that can grow to be over 80 feet tall. It is a d |     100.00 |    93230 |  0.5084219510932597
 California Sycamore     | This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is  |     300.00 |    93230 |  0.5140519790508755
 Coast Live Oak          | This is a beautiful oak tree that can grow to be over 100 feet tall. It is an ev |     500.00 |    93230 |  0.5143126438081371
 Fremont Cottonwood      | This is a beautiful cottonwood tree that can grow to be over 100 feet tall. It i |     200.00 |    93230 |  0.5174774727252058
 Madrone                 | This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an |      50.00 |    93230 |  0.5227400803389093
(10 rows)

9. 검색된 데이터를 사용하여 LLM 응답 개선

실행된 쿼리의 결과를 사용하여 클라이언트 애플리케이션에 대한 생성형 AI LLM 응답을 개선하고 제공된 쿼리 결과를 Vertex AI 생성형 기반 언어 모델에 대한 프롬프트의 일부로 사용하여 의미 있는 출력을 준비할 수 있습니다.

이를 위해 벡터 검색 결과를 사용하여 JSON을 생성한 다음 생성된 JSON을 Vertex AI의 LLM 모델 프롬프트에 추가하여 의미 있는 출력을 만들어야 합니다. 첫 번째 단계에서는 JSON을 생성한 다음 Vertex AI 스튜디오에서 테스트하고 마지막 단계에서는 애플리케이션에서 사용할 수 있는 SQL 문에 JSON을 통합합니다.

JSON 형식의 출력 생성

JSON 형식으로 출력을 생성하고 Vertex AI에 전달할 행 하나만 반환하도록 쿼리를 수정합니다.

PostgreSQL용 Cloud SQL

다음은 쿼리의 예입니다.

WITH trees as (
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id as product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

다음은 예상되는 출력의 JSON입니다.

[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]

Vertex AI Studio에서 프롬프트 실행

생성된 JSON을 사용하여 Vertex AI Studio의 생성형 AI 텍스트 모델에 프롬프트의 일부로 제공할 수 있습니다.

Cloud 콘솔에서 Vertex AI Studio Chat을 엽니다.

449b5959fa0e93bd.png

추가 API를 사용 설정하라는 메시지가 표시될 수 있지만 이 요청은 무시해도 됩니다. 실습을 완료하는 데는 추가 API가 필요하지 않습니다.

사용할 프롬프트는 다음과 같습니다.

You are a friendly advisor helping to find a product based on the customer's needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
[place your JSON here]
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information.
Do not ask any additional questions and assume location based on the zip code provided in the list of products.

JSON 자리표시자를 쿼리의 응답으로 대체하면 다음과 같이 표시됩니다.

You are a friendly advisor helping to find a product based on the customer's needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information.
Do not ask any additional questions and assume location based on the zip code provided in the list of products.

JSON 값을 사용하여 gemini-2.0-flash 모델을 사용해 프롬프트를 실행하면 다음과 같은 결과가 표시됩니다.

2c5145ebc04daae1.png

이 예시에서 모델로부터 받은 답변은 다음과 같습니다. 시간 경과에 따라 모델과 매개변수가 변경되므로 답변이 다를 수 있습니다.

"좋습니다. 사용 가능한 제품 목록을 살펴본 결과, 고객님 지역에서 잘 자랄 수 있는 나무는 벚나무입니다.

가격은 75.00달러입니다.

거주하시는 우편번호 (93230)의 정확한 재배 환경에 관한 구체적인 세부정보는 없지만, 일반적으로 체리나무는 온화한 기후와 배수가 잘 되는 토양에서 잘 자라는 것으로 알려져 있습니다. 일반적으로 과일을 생산하려면 일정 기간 겨울 추위가 필요하므로 이 점을 유의해야 합니다. 하지만 조건이 맞으면 정원에 멋진 장식과 맛있는 체리를 제공할 수 있습니다."

PSQL에서 프롬프트 실행

Cloud SQL AI와 Vertex AI의 통합을 사용하여 데이터베이스에서 직접 SQL을 사용하여 생성형 모델에서 유사한 응답을 가져올 수도 있습니다. 하지만 gemini-2.0-flash-exp 모델을 사용하려면 먼저 등록해야 합니다.

PostgreSQL용 Cloud SQL에서 실행

현재 버전이 낮은 경우 확장 프로그램을 버전 1.4.2 이상으로 업그레이드합니다. 앞에서 설명한 대로 gcloud sql connect에서 quickstart_db 데이터베이스에 연결하거나 Cloud SQL 스튜디오를 사용하고 다음을 실행합니다.

SELECT extversion from pg_extension where extname='google_ml_integration';

반환된 값이 1.4.2보다 작으면 다음을 실행합니다.

ALTER EXTENSION google_ml_integration UPDATE TO '1.4.2';

그런 다음 google_ml_integration.enable_model_support 데이터베이스 플래그를 'on'으로 설정해야 합니다. 이를 수행하려면 웹 콘솔 인터페이스를 사용하거나 다음 gcloud 명령어를 실행하면 됩니다.

gcloud sql instances patch my-cloudsql-instance \
--database-flags google_ml_integration.enable_model_support=on,cloudsql.enable_google_ml_integration=on

이 명령어는 백그라운드에서 실행하는 데 1~3분 정도 걸립니다. 그런 다음 psql 세션에서 새 플래그를 확인하거나 Cloud SQL Studio를 사용하여 quickstart_db 데이터베이스에 연결할 수 있습니다.

show google_ml_integration.enable_model_support;

psql 세션의 예상 출력은 'on'입니다.

quickstart_db => show google_ml_integration.enable_model_support;
 google_ml_integration.enable_model_support 
--------------------------------------------
 on
(1 row)

그런 다음 두 모델을 등록해야 합니다. 첫 번째는 이미 사용된 text-embedding-004 모델입니다. 모델 등록 기능을 사용 설정했으므로 등록해야 합니다.

psql 또는 Cloud SQL Studio에서 다음 코드를 실행하여 모델을 등록합니다.

CALL
  google_ml.create_model(
    model_id => 'text-embedding-004',
    model_provider => 'google',
    model_qualified_name => 'text-embedding-004',
    model_type => 'text_embedding',
    model_auth_type => 'cloudsql_service_agent_iam',
    model_in_transform_fn => 'google_ml.vertexai_text_embedding_input_transform',
    model_out_transform_fn => 'google_ml.vertexai_text_embedding_output_transform');

다음으로 등록해야 하는 모델은 사용자 친화적인 출력을 생성하는 데 사용되는 gemini-2.0-flash-001입니다.

CALL
  google_ml.create_model(
    model_id => 'gemini-2.0-flash-001',
    model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/us-central1/publishers/google/models/gemini-2.0-flash-001:streamGenerateContent',
    model_provider => 'google',
    model_auth_type => 'cloudsql_service_agent_iam');

google_ml.model_info_view에서 정보를 선택하여 언제든지 등록된 모델 목록을 확인할 수 있습니다.

select model_id,model_type from google_ml.model_info_view;

다음은 샘플 출력입니다.

quickstart_db=> select model_id,model_type from google_ml.model_info_view;
               model_id               |   model_type   
--------------------------------------+----------------
 textembedding-gecko                  | text_embedding
 textembedding-gecko@001              | text_embedding
 gemini-1.5-pro:streamGenerateContent | generic
 gemini-1.5-pro:generateContent       | generic
 gemini-1.0-pro:generateContent       | generic
 text-embedding-004                   | text_embedding
 gemini-2.0-flash-001                 | generic

이제 하위 쿼리 JSON에서 생성된 값을 사용하여 SQL을 사용하여 생성형 AI 텍스트 모델에 프롬프트의 일부로 제공할 수 있습니다.

데이터베이스의 psql 또는 Cloud SQL Studio 세션에서 쿼리 실행

WITH trees AS (
SELECT
        cp.product_name,
        cp.product_description AS description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id AS product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci ON
        ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON
        cs.store_id = ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.embedding <=> google_ml.embedding('text-embedding-004',
        'What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1),
prompt AS (
SELECT
        'You are a friendly advisor helping to find a product based on the customer''s needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","product_description":"some description","sale_price":10}
Here is the list of products:' || json_agg(trees) || 'The customer asked "What kind of fruit trees grow well here?"
You should give information about the product, price and some supplemental information' AS prompt_text
FROM
        trees),
response AS (
SELECT
        json_array_elements(google_ml.predict_row( model_id =>'gemini-2.0-flash-001',
        request_body => json_build_object('contents',
        json_build_object('role',
        'user',
        'parts',
        json_build_object('text',
        prompt_text)))))->'candidates'->0->'content'->'parts'->0->'text' AS resp
FROM
        prompt)
SELECT
        string_agg(resp::text,
        ' ')
FROM
        response;

예상되는 출력은 다음과 같습니다. 모델 버전 및 매개변수에 따라 출력이 다를 수 있습니다.

"That" "'s a great question! Based on your location (assuming you're" " in zip code 93230), I have a suggestion for a" " fruit tree that should thrive.\n\nWe have the **Cherry Tree** available.\n\n**Product Name:** Cherry Tree\n\n**Description:** This is a beautiful cherry" " tree that will produce delicious cherries. It's a deciduous tree (meaning it loses its leaves in the fall) growing to about 15 feet tall." " The leaves are dark green in summer, turning a beautiful red in the fall. Cherry trees are known for their beauty, shade, and privacy.\n\n**Sale Price:** $75.00\n\n**Important Considerations for Growing" " Cherry Trees:**\n\n* **Climate:** Cherry trees prefer a cool, moist climate, and 93230 falls within a suitable range (USDA zones 4-9). However, it's always a good idea to" " check the specific microclimate of your property (sun exposure, drainage etc.).\n* **Soil:** They do best in sandy soil. If your soil is different, you may need to amend it to improve drainage.\n* **Pollination:** Many cherry varieties require a second, compatible cherry tree for proper pollination" ". Check the specific pollination needs of this variety before purchase if you want a significant cherry yield.\n\nThis cherry tree is a beautiful addition to any yard and will provide you with delicious cherries if you can meet its needs. Would you like to know more about its pollination requirements, or perhaps see if we have any other" " fruit trees suitable for your area?\n" ""

10. 최근접 이웃 색인 만들기

데이터 세트는 매우 작으며 응답 시간은 주로 AI 모델과의 상호작용에 따라 달라집니다. 하지만 벡터가 수백만 개 있는 경우 벡터 검색이 응답 시간의 상당 부분을 차지하고 시스템에 높은 부하를 줄 수 있습니다. 이를 개선하기 위해 벡터 위에 색인을 빌드할 수 있습니다.

HNSW 색인 만들기

테스트에 HNSW 색인 유형을 사용해 보겠습니다. HNSW는 Hierarchical Navigable Small World의 약자이며 다층 그래프 색인을 나타냅니다.

임베딩 열의 색인을 빌드하려면 임베딩 열, 거리 함수, 선택적으로 m 또는 ef_constructions와 같은 매개변수를 정의해야 합니다. 매개변수에 관한 자세한 내용은 문서를 참고하세요.

CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

예상 출력:

quickstart_db=> CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);
CREATE INDEX
quickstart_db=>

응답 비교

이제 EXPLAIN 모드에서 벡터 검색 쿼리를 실행하고 색인이 사용되었는지 확인할 수 있습니다.

EXPLAIN (analyze) 
WITH trees as (
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id as product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

예상 출력:

 Aggregate  (cost=779.12..779.13 rows=1 width=32) (actual time=1.066..1.069 rows=1 loops=1)
   ->  Subquery Scan on trees  (cost=769.05..779.12 rows=1 width=142) (actual time=1.038..1.041 rows=1 loops=1)
         ->  Limit  (cost=769.05..779.11 rows=1 width=158) (actual time=1.022..1.024 rows=1 loops=1)
               ->  Nested Loop  (cost=769.05..9339.69 rows=852 width=158) (actual time=1.020..1.021 rows=1 loops=1)
                     ->  Nested Loop  (cost=768.77..9316.48 rows=852 width=945) (actual time=0.858..0.859 rows=1 loops=1)
                           ->  Index Scan using cymbal_products_embeddings_hnsw on cymbal_products cp  (cost=768.34..2572.47 rows=941 width=941) (actual time=0.532..0.539 rows=3 loops=1)
                                 Order By: (embedding <=> '[0.008864171,0.03693164,-0.024245683,...
<redacted>
...,0.017593635,-0.040275685,-0.03914233,-0.018452475,0.00826032,-0.07372604
]'::vector)
                           ->  Index Scan using product_inventory_pkey on cymbal_inventory ci  (cost=0.42..7.17 rows=1 width=37) (actual time=0.104..0.104 rows=0 loops=3)
                                 Index Cond: ((store_id = 1583) AND (uniq_id = (cp.uniq_id)::text))
                                 Filter: (inventory > 0)
                                 Rows Removed by Filter: 1
                     ->  Materialize  (cost=0.28..8.31 rows=1 width=8) (actual time=0.133..0.134 rows=1 loops=1)
                           ->  Index Scan using product_stores_pkey on cymbal_stores cs  (cost=0.28..8.30 rows=1 width=8) (actual time=0.129..0.129 rows=1 loops=1)
                                 Index Cond: (store_id = 1583)
 Planning Time: 112.398 ms
 Execution Time: 1.221 ms

출력에서 쿼리가 'cymbal_products_embeddings_hnsw를 사용한 색인 스캔'을 사용하고 있음을 명확하게 알 수 있습니다.

explain 없이 쿼리를 실행하면 다음과 같이 표시됩니다.

WITH trees as (
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id as product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

예상 출력:

[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]

결과가 동일하며 색인이 없는 검색에서 상단에 표시되었던 동일한 벚나무가 반환됩니다. 매개변수와 색인 유형에 따라 결과가 약간 다를 수 있습니다. 테스트 중에 색인이 있는 쿼리는 131.301ms의 결과를 반환했고 색인이 없는 쿼리는 167.631ms의 결과를 반환했습니다. 하지만 매우 작은 데이터 세트를 다루고 있었으며 더 큰 데이터에서는 차이가 더 클 것입니다.

문서에서 벡터에 사용할 수 있는 다양한 색인과 langchain 통합을 사용한 더 많은 실습 및 예시를 사용해 볼 수 있습니다.

11. 환경 정리

Cloud SQL 인스턴스를 삭제합니다.

실습이 끝나면 Cloud SQL 인스턴스 삭제

연결이 끊어지고 이전 설정이 모두 손실된 경우 Cloud Shell에서 프로젝트와 환경 변수를 정의합니다.

export INSTANCE_NAME=my-cloudsql-instance
export PROJECT_ID=$(gcloud config get-value project)

인스턴스를 삭제합니다.

gcloud sql instances delete $INSTANCE_NAME --project=$PROJECT_ID

예상되는 콘솔 출력:

student@cloudshell:~$ gcloud sql instances delete $INSTANCE_NAME --project=$PROJECT_ID
All of the instance data will be lost when the instance is deleted.

Do you want to continue (Y/n)?  y

Deleting Cloud SQL instance...done.                                                                                                                
Deleted [https://sandbox.googleapis.com/v1beta4/projects/test-project-001-402417/instances/my-cloudsql-instance].

12. 축하합니다

축하합니다. Codelab을 완료했습니다.

학습한 내용

  • PostgreSQL용 Cloud SQL 인스턴스를 배포하는 방법
  • 데이터베이스를 만들고 Cloud SQL AI 통합을 사용 설정하는 방법
  • 데이터베이스에 데이터를 로드하는 방법
  • Cloud SQL에서 Vertex AI 임베딩 모델을 사용하는 방법
  • Vertex AI 생성형 모델을 사용하여 결과를 보강하는 방법
  • 벡터 색인을 사용하여 성능을 개선하는 방법

HNSW 대신 ScaNN 색인을 사용하는 유사한 AlloyDB용 Codelab을 사용해 보세요.

13. 설문조사

결과:

본 튜토리얼을 어떻게 사용하실 계획인가요?

읽기만 할 계획입니다. 읽은 다음 연습 활동을 완료할 계획입니다.