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

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

이 Codelab 정보

subject최종 업데이트: 4월 22, 2025
account_circle작성자: Gleb Otochkin

1. 소개

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

30b7c4dcdd8bb68f.png

기본 요건

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

학습할 내용

  • MySQL용 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

MySQL용 Cloud SQL 인스턴스 만들기

cloudsql_vector 플래그는 인스턴스를 만들 때 사용 설정할 수 있습니다. 벡터 지원은 현재 MySQL 8.0 R20241208.01_00 이상에서 사용할 수 있습니다.

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

gcloud sql instances create my-cloudsql-instance \
--database-version=MYSQL_8_4 \
--tier=db-custom-2-8192 \
--region=us-central1 \
--enable-google-ml-integration \
--edition=ENTERPRISE \
--root-password=$CLOUDSQL_PASSWORD

Cloud Shell에서 실행되는 연결을 확인할 수 있습니다.

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

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

예상 출력:

$gcloud sql connect my-cloudsql-instance --user=root
Allowlisting your IP for incoming connection for 5 minutes...done.                                                                                                                           
Connecting to database with SQL user [root].Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 71
Server version: 8.4.4-google (Google)

Copyright (c) 2000, 2025, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

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라는 이름으로 데이터베이스를 만듭니다 .이렇게 하려면 MySQL용 mysql, SDK 또는 Cloud SQL 스튜디오와 같은 명령줄 데이터베이스 클라이언트와 같은 다양한 옵션이 있습니다. 데이터베이스를 만들 때 SDK (gcloud)를 사용합니다.

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

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

6. 데이터 로드

이제 데이터베이스에 객체를 만들고 데이터를 로드해야 합니다. 가상의 Cymbal 스토어 데이터를 사용합니다. 데이터는 SQL (스키마의 경우) 및 CSV 형식 (데이터의 경우)으로 제공됩니다.

Cloud Shell은 데이터베이스에 연결하고, 모든 객체를 만들고, 데이터를 로드하는 기본 환경입니다.

먼저 Cloud SQL 인스턴스의 승인된 네트워크 목록에 Cloud Shell 공개 IP를 추가해야 합니다. Cloud Shell에서 다음을 실행합니다.

gcloud sql instances patch my-cloudsql-instance --authorized-networks=$(curl ifconfig.me)

세션이 손실되거나 재설정되었거나 다른 도구에서 작업하는 경우 CLOUDSQL_PASSWORD 변수를 다시 내보냅니다.

export CLOUDSQL_PASSWORD=...your password defined for the instance...

이제 데이터베이스에 필요한 모든 객체를 만들 수 있습니다. 이를 위해 MySQL mysql 유틸리티와 공개 소스에서 데이터를 가져오는 curl 유틸리티를 함께 사용합니다.

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

export INSTANCE_IP=$(gcloud sql instances describe my-cloudsql-instance --format="value(ipAddresses.ipAddress)")
curl -LJ https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/infrastructure/cymbal-store-embeddings/cymbal_mysql_schema.sql | mysql --host=$INSTANCE_IP --user=root --password=$CLOUDSQL_PASSWORD quickstart_db

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

다음 단계는 cymbal_products 데이터를 로드하는 것입니다. 동일한 curlmysql 유틸리티를 사용합니다.

curl -LJ https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/infrastructure/cymbal-store-embeddings/cymbal_products.csv | mysql --enable-local-infile --host=$INSTANCE_IP --user=root --password=$CLOUDSQL_PASSWORD quickstart_db -e "LOAD DATA LOCAL INFILE '/dev/stdin'  INTO TABLE cymbal_products FIELDS TERMINATED BY ','  OPTIONALLY ENCLOSED BY '\"'  LINES TERMINATED BY '\n'  IGNORE 1 LINES;"

그런 다음 cymbal_stores를 계속 진행합니다.

curl -LJ https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/infrastructure/cymbal-store-embeddings/cymbal_stores.csv | mysql --enable-local-infile --host=$INSTANCE_IP --user=root --password=$CLOUDSQL_PASSWORD quickstart_db -e "LOAD DATA LOCAL INFILE '/dev/stdin'  INTO TABLE cymbal_stores FIELDS TERMINATED BY ','  OPTIONALLY ENCLOSED BY '\"'  LINES TERMINATED BY '\n'  IGNORE 1 LINES;"

각 매장의 각 제품 수가 포함된 cymbal_inventory로 완성합니다.

curl -LJ https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/infrastructure/cymbal-store-embeddings/cymbal_inventory.csv | mysql --enable-local-infile --host=$INSTANCE_IP --user=root --password=$CLOUDSQL_PASSWORD quickstart_db -e "LOAD DATA LOCAL INFILE '/dev/stdin'  INTO TABLE cymbal_inventory FIELDS TERMINATED BY ','  OPTIONALLY ENCLOSED BY '\"'  LINES TERMINATED BY '\n'  IGNORE 1 LINES;"

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

7. 임베딩 만들기

다음 단계는 Google Vertex AI의 textembedding-005 모델을 사용하여 제품 설명의 임베딩을 빌드하고 cymbal_products 테이블의 새 열에 저장하는 것입니다.

벡터 데이터를 저장하려면 Cloud SQL 인스턴스에서 벡터 기능을 사용 설정해야 합니다. Cloud Shell에서 다음을 실행합니다.

gcloud sql instances patch my-cloudsql-instance \
--database-flags=cloudsql_vector=on

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

mysql --host=$INSTANCE_IP --user=root --password=$CLOUDSQL_PASSWORD quickstart_db

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

ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) using varbinary;
UPDATE cymbal_products SET embedding = mysql.ml_embedding('text-embedding-005', product_description);

2, 000개의 행에 대한 벡터 임베딩을 생성하는 데는 일반적으로 5분 미만이 소요되지만 약간 더 오래 걸릴 수도 있으며, 종종 훨씬 더 빨리 완료됩니다.

8. 유사성 검색 실행

이제 설명에 대해 계산된 벡터 값과 동일한 임베딩 모델을 사용하여 요청에 대해 생성한 벡터 값을 기반으로 유사성 검색을 사용하여 검색을 실행할 수 있습니다.

SQL 쿼리는 동일한 명령줄 인터페이스에서 실행하거나 Cloud SQL Studio에서 실행할 수도 있습니다. 행이 여러 개 있거나 복잡한 쿼리는 Cloud SQL Studio에서 관리하는 것이 좋습니다.

사용자 만들기

Cloud SQL Studio를 사용할 수 있는 새 사용자가 필요합니다. 루트 사용자에 사용한 것과 동일한 비밀번호를 사용하여 기본 제공 유형 사용자 학생을 만들겠습니다.

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

gcloud sql users create student  --instance=my-cloudsql-instance --password=$CLOUDSQL_PASSWORD --host=%

Cloud SQL Studio 시작

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

667b658dbf98eb0b.png

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

a879e8ac914a8ce9.png

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

  • 데이터베이스: quickstart_db
  • 사용자: student
  • 비밀번호: 사용자의 비밀번호

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

36e6036847333d18.png

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

d803b7b6a798094f.png

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

쿼리 실행

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

cosine_distance 함수를 사용하여 요청에 가장 적합한 첫 번째 항목 5개를 선택하는 쿼리는 다음과 같습니다.

SELECT mysql.ML_EMBEDDING('text-embedding-005','What kind of fruit trees grow well here?') into @query_vector;
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cosine_distance(cp.embedding ,@query_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 5;

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

dffc70835901cf03.png

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

+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
| product_name    | description                                                                      | sale_price | zip_code | distance            |
+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
| Malus Domestica | Malus Domestica, the classic apple tree, brings beauty and delicious fruit to yo |     100.00 |    93230 | 0.37740096545831603 |
| Cerasus         | Cerasus: A beautiful cherry tree that brings delicious fruit and vibrant color t |      75.00 |    93230 |   0.405704177142419 |
| Persica         | Persica: Enjoy homegrown, delicious peaches with this beautiful peach tree. Reac |     150.00 |    93230 | 0.41031799106722877 |
| Meyer Lemon     | Grow your own juicy Meyer Lemons with this semi-dwarf tree, California's favorit |      34.00 |    93230 | 0.42823360959352186 |
| Acer            | Acer, the classic maple. Known for vibrant fall foliage in reds, oranges, and ye |     100.00 |    93230 | 0.42953897057301615 |
+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
5 rows in set (0.13 sec)

cosine_distance 함수를 사용한 쿼리 실행에는 0.13초가 걸렸습니다.

이제 approx_distance 함수를 사용하여 KNN 검색을 사용하는 동일한 쿼리를 실행합니다. 임베딩에 관한 ANN 색인이 없으면 백그라운드에서 자동으로 정확한 검색으로 되돌아갑니다.

SELECT mysql.ML_EMBEDDING('text-embedding-005','What kind of fruit trees grow well here?') into @query_vector;
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        approx_distance(cp.embedding ,@query_vector, 'distance_measure=cosine') 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 5;

다음은 쿼리에서 반환된 제품 목록입니다.

+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
| product_name    | description                                                                      | sale_price | zip_code | distance            |
+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
| Malus Domestica | Malus Domestica, the classic apple tree, brings beauty and delicious fruit to yo |     100.00 |    93230 | 0.37740096545831603 |
| Cerasus         | Cerasus: A beautiful cherry tree that brings delicious fruit and vibrant color t |      75.00 |    93230 |   0.405704177142419 |
| Persica         | Persica: Enjoy homegrown, delicious peaches with this beautiful peach tree. Reac |     150.00 |    93230 | 0.41031799106722877 |
| Meyer Lemon     | Grow your own juicy Meyer Lemons with this semi-dwarf tree, California's favorit |      34.00 |    93230 | 0.42823360959352186 |
| Acer            | Acer, the classic maple. Known for vibrant fall foliage in reds, oranges, and ye |     100.00 |    93230 | 0.42953897057301615 |
+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
5 rows in set, 1 warning (0.12 sec)

쿼리 실행에는 0.12초밖에 걸리지 않았습니다. cosine_distance 함수와 동일한 결과가 나왔습니다.

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

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

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

JSON 형식의 출력 생성

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

다음은 ANN 검색을 사용하는 쿼리의 예입니다.

SELECT mysql.ML_EMBEDDING('text-embedding-005','What kind of fruit trees grow well here?') into @query_vector;
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
        (approx_distance(cp.embedding ,@query_vector, 'distance_measure=cosine')) ASC
LIMIT 1)
SELECT json_arrayagg(json_object('product_name',product_name,'description',description,'sale_price',sale_price,'zip_code',zip_code,'product_id',product_id)) FROM trees;

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

[{"zip_code": 93230, "product_id": "23e41a71d63d8bbc9bdfa1d118cfddc5", "sale_price": 100.00, "description": "Malus Domestica, the classic apple tree, brings beauty and delicious fruit to yo", "product_name": "Malus Domestica"}]

Vertex AI Studio에서 프롬프트 실행

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

Cloud 콘솔에서 Vertex AI Studio 프롬프트를 엽니다.

411ffb9d164ac140.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:
{"zip_code": 93230, "product_id": "23e41a71d63d8bbc9bdfa1d118cfddc5", "sale_price": 100.00, "description": "Malus Domestica, the classic apple tree, brings beauty and delicious fruit to yo", "product_name": "Malus Domestica"}
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 모델을 사용했을 때의 결과는 다음과 같습니다.

9839af512686130d.png

이 예시에서 모델로부터 얻은 답변은 시맨틱 검색 결과와 언급된 우편번호에서 사용 가능한 가장 일치하는 제품을 사용하여 얻은 것입니다.

PSQL에서 프롬프트 실행

Cloud SQL AI와 Vertex AI의 통합을 사용하여 데이터베이스에서 직접 SQL을 사용하여 생성형 모델에서 유사한 응답을 가져올 수도 있습니다.

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

데이터베이스에 대한 mysql 또는 Cloud SQL Studio 세션에서 쿼리 실행

SELECT mysql.ML_EMBEDDING('text-embedding-005','What kind of fruit trees grow well here?') into @query_vector;
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
         (approx_distance(cp.embedding ,@query_vector, 'distance_measure=cosine')) ASC
LIMIT 1),
prompt AS (
SELECT
       CONCAT( '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_arrayagg(json_object('product_name',trees.product_name,'description',trees.description,'sale_price',trees.sale_price,'zip_code',trees.zip_code,'product_id',trees.product_id)) , '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
       mysql.ML_PREDICT_ROW('publishers/google/models/gemini-2.0-flash-001:generateContent',
        json_object('contents',
        json_object('role',
        'user',
        'parts',
        json_array(
        json_object('text',
        prompt_text))))) AS resp
FROM
        prompt)
SELECT
JSON_EXTRACT(resp, '$.candidates[0].content.parts[0].text')
FROM
        response;

다음은 샘플 출력입니다. 모델 버전 및 매개변수에 따라 출력이 다를 수 있습니다.

"Okay, I see you're looking for fruit trees that grow well in your area. Based on the available product, the **Malus Domestica** (Apple Tree) is a great option to consider!\n\n* **Product:** Malus Domestica (Apple Tree)\n* **Description:** This classic apple tree grows to about 30 feet tall and provides beautiful seasonal color with green leaves in summer and fiery colors in the fall. It's known for its strength and provides good shade. Most importantly, it produces delicious apples!\n* **Price:** \\$100.00\n* **Growing Zones:** This particular apple tree is well-suited for USDA zones 4-8. Since your zip code is 93230, you are likely in USDA zone 9a or 9b. While this specific tree is rated for zones 4-8, with proper care and variety selection, apple trees can still thrive in slightly warmer climates. You may need to provide extra care during heat waves.\n\n**Recommendation:** I would recommend investigating varieties of Malus Domestica suited to slightly warmer climates or contacting a local nursery/arborist to verify if it is a good fit for your local climate conditions.\n"

출력은 마크다운 형식으로 제공됩니다.

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

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

ScANN 색인 만들기

테스트에 ScANN 색인 유형을 사용해 보겠습니다.

임베딩 열의 색인을 빌드하려면 임베딩 열의 거리 측정항목을 정의해야 합니다. 매개변수에 관한 자세한 내용은 문서를 참고하세요.

CREATE VECTOR INDEX cymbal_products_embedding_idx ON cymbal_products(embedding) USING SCANN DISTANCE_MEASURE=COSINE;

응답 비교

이제 벡터 검색 쿼리를 다시 실행하고 결과를 확인할 수 있습니다.

SELECT mysql.ML_EMBEDDING('text-embedding-005','What kind of fruit trees grow well here?') into @query_vector;
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        approx_distance(cp.embedding ,@query_vector, 'distance_measure=cosine') 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 5;

예상 출력:

+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
| product_name    | description                                                                      | sale_price | zip_code | distance            |
+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
| Malus Domestica | Malus Domestica, the classic apple tree, brings beauty and delicious fruit to yo |     100.00 |    93230 | 0.37740096545831603 |
| Cerasus         | Cerasus: A beautiful cherry tree that brings delicious fruit and vibrant color t |      75.00 |    93230 |   0.405704177142419 |
| Persica         | Persica: Enjoy homegrown, delicious peaches with this beautiful peach tree. Reac |     150.00 |    93230 | 0.41031799106722877 |
| Meyer Lemon     | Grow your own juicy Meyer Lemons with this semi-dwarf tree, California's favorit |      34.00 |    93230 | 0.42823360959352186 |
| Acer            | Acer, the classic maple. Known for vibrant fall foliage in reds, oranges, and ye |     100.00 |    93230 | 0.42953897057301615 |
+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
5 rows in set (0.08 sec)

실행 시간은 약간만 다르지만, 이렇게 작은 데이터 세트에서는 예상되는 결과입니다. 수백만 개의 벡터가 있는 대규모 데이터 세트에서는 훨씬 더 눈에 띄게 나타납니다.

EXPLAIN 명령어를 사용하여 실행 계획을 확인할 수 있습니다.

SELECT mysql.ML_EMBEDDING('text-embedding-005','What kind of fruit trees grow well here?') into @query_vector;
EXPLAIN ANALYZE SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        approx_distance(cp.embedding ,@query_vector, 'distance_measure=cosine') 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 5;

실행 계획 (발췌):

...
-> Nested loop inner join  (cost=443 rows=5) (actual time=1.14..1.18 rows=5 loops=1)
                                -> Vector index scan on cp  (cost=441 rows=5) (actual time=1.1..1.1 rows=5 loops=1)
                                -> Single-row index lookup on cp using PRIMARY (uniq_id=cp.uniq_id)  (cost=0.25 rows=1) (actual time=0.0152..0.0152 rows=1 loops=5)

...

cp (cymbal_products 테이블의 별칭)에서 벡터 색인 스캔을 사용하고 있는 것을 확인할 수 있습니다.

자체 데이터를 실험하거나 다양한 검색어를 테스트하여 MySQL에서 시맨틱 검색이 작동하는 방식을 확인할 수 있습니다.

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을 완료했습니다.

학습한 내용

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

유사한 AlloyDB용 Codelab 또는 Postgres용 Cloud SQL Codelab을 사용해 보세요.

13. 설문조사

결과:

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