1. 소개
이 Codelab에서는 GKE에 AlloyDB Omni를 배포하고 동일한 Kubernetes 클러스터에 배포된 개방형 삽입 모델과 함께 사용하는 방법을 알아봅니다. 동일한 GKE 클러스터의 데이터베이스 인스턴스 옆에 모델을 배포하면 지연 시간과 서드 파티 서비스에 대한 종속 항목이 줄어듭니다. 또한 데이터가 조직 외부로 유출되어서는 안 되고 서드 파티 서비스의 사용이 허용되지 않는 경우 보안 요구사항에 따라 필요할 수 있습니다.
기본 요건
- Google Cloud, 콘솔에 관한 기본적인 이해
- 명령줄 인터페이스 및 Cloud Shell의 기본 기술
학습할 내용
- Google Kubernetes 클러스터에 AlloyDB Omni를 배포하는 방법
- AlloyDB Omni에 연결하는 방법
- AlloyDB Omni에 데이터를 로드하는 방법
- GKE에 공개 삽입 모델을 배포하는 방법
- AlloyDB Omni에서 임베딩 모델을 등록하는 방법
- 시맨틱 검색을 위한 임베딩을 생성하는 방법
- AlloyDB Omni에서 생성된 임베딩을 시맨틱 검색에 사용하는 방법
- AlloyDB에서 벡터 색인을 만들고 사용하는 방법
필요한 항목
- Google Cloud 계정 및 Google Cloud 프로젝트
- Google Cloud 콘솔 및 Cloud Shell을 지원하는 웹브라우저(예: Chrome)
2. 설정 및 요구사항
자습형 환경 설정
- Google Cloud Console에 로그인하여 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. 아직 Gmail이나 Google Workspace 계정이 없는 경우 계정을 만들어야 합니다.
- 프로젝트 이름은 이 프로젝트 참가자의 표시 이름입니다. 이는 Google API에서 사용하지 않는 문자열이며 언제든지 업데이트할 수 있습니다.
- 프로젝트 ID는 모든 Google Cloud 프로젝트에서 고유하며, 변경할 수 없습니다(설정된 후에는 변경할 수 없음). Cloud 콘솔은 고유한 문자열을 자동으로 생성합니다. 일반적으로는 신경 쓰지 않아도 됩니다. 대부분의 Codelab에서는 프로젝트 ID (일반적으로
PROJECT_ID
로 식별됨)를 참조해야 합니다. 생성된 ID가 마음에 들지 않으면 다른 임의 ID를 생성할 수 있습니다. 또는 직접 시도해 보고 사용 가능한지 확인할 수도 있습니다. 이 단계 이후에는 변경할 수 없으며 프로젝트 기간 동안 유지됩니다. - 참고로 세 번째 값은 일부 API에서 사용하는 프로젝트 번호입니다. 이 세 가지 값에 대한 자세한 내용은 문서를 참고하세요.
- 다음으로 Cloud 리소스/API를 사용하려면 Cloud 콘솔에서 결제를 사용 설정해야 합니다. 이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 튜토리얼이 끝난 후에 요금이 청구되지 않도록 리소스를 종료하려면 만든 리소스 또는 프로젝트를 삭제하면 됩니다. Google Cloud 신규 사용자는 300달러(USD) 상당의 무료 체험판 프로그램에 참여할 수 있습니다.
Cloud Shell 시작
Google Cloud를 노트북에서 원격으로 실행할 수 있지만, 이 Codelab에서는 Cloud에서 실행되는 명령줄 환경인 Google Cloud Shell을 사용합니다.
Google Cloud Console의 오른쪽 상단 툴바에 있는 Cloud Shell 아이콘을 클릭합니다.
환경을 프로비저닝하고 연결하는 데 몇 분 정도 소요됩니다. 완료되면 다음과 같이 표시됩니다.
가상 머신에는 필요한 개발 도구가 모두 들어있습니다. 영구적인 5GB 홈 디렉터리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 Codelab의 모든 작업은 브라우저 내에서 수행할 수 있습니다. 아무것도 설치할 필요가 없습니다.
3. 시작하기 전에
API 사용 설정
결과:
Cloud Shell 내에 프로젝트 ID가 설정되어 있는지 확인합니다.
PROJECT_ID=$(gcloud config get-value project)
echo $PROJECT_ID
Cloud Shell 구성에 정의되어 있지 않으면 다음 명령어를 사용하여 설정합니다.
export PROJECT_ID=<your project>
gcloud config set project $PROJECT_ID
필요한 모든 서비스를 사용 설정합니다.
gcloud services enable compute.googleapis.com
gcloud services enable container.googleapis.com
예상 출력
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=test-project-001-402417 student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417 Updated property [core/project]. student@cloudshell:~ (test-project-001-402417)$ gcloud services enable compute.googleapis.com gcloud services enable container.googleapis.com Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.
4. GKE에 AlloyDB Omni 배포
GKE에 AlloyDB Omni를 배포하려면 AlloyDB Omni 연산자 요구사항에 나열된 요구사항에 따라 Kubernetes 클러스터를 준비해야 합니다.
GKE 클러스터 만들기
AlloyDB Omni 인스턴스가 포함된 포드를 배포하기에 충분한 풀 구성으로 표준 GKE 클러스터를 배포해야 합니다. Omni를 사용하려면 최소 2개의 CPU와 8GB의 RAM이 필요하며 운영자 및 모니터링 서비스에 여유 공간이 있어야 합니다.
배포의 환경 변수를 설정합니다.
export PROJECT_ID=$(gcloud config get project)
export LOCATION=us-central1
export CLUSTER_NAME=alloydb-ai-gke
export MACHINE_TYPE=e2-standard-4
그런 다음 gcloud를 사용하여 GKE 표준 클러스터를 만듭니다.
gcloud container clusters create ${CLUSTER_NAME} \
--project=${PROJECT_ID} \
--region=${LOCATION} \
--workload-pool=${PROJECT_ID}.svc.id.goog \
--release-channel=rapid \
--machine-type=${MACHINE_TYPE} \
--num-nodes=1
예상되는 콘솔 출력:
student@cloudshell:~ (gleb-test-short-001-415614)$ export PROJECT_ID=$(gcloud config get project) export LOCATION=us-central1 export CLUSTER_NAME=alloydb-ai-gke export MACHINE_TYPE=n2-highmem-2 Your active configuration is: [gleb-test-short-001-415614] student@cloudshell:~ (gleb-test-short-001-415614)$ gcloud container clusters create ${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --region=${LOCATION} \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --release-channel=rapid \ --machine-type=${MACHINE_TYPE} \ --num-nodes=1 Note: The Kubelet readonly port (10255) is now deprecated. Please update your workloads to use the recommended alternatives. See https://cloud.google.com/kubernetes-engine/docs/how-to/disable-kubelet-readonly-port for ways to check usage and for migration instructions. Note: Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most 1008 node(s). Creating cluster alloydb-ai-gke in us-central1.. NAME: omni01 ZONE: us-central1-a MACHINE_TYPE: e2-standard-4 PREEMPTIBLE: INTERNAL_IP: 10.128.0.3 EXTERNAL_IP: 35.232.157.123 STATUS: RUNNING student@cloudshell:~ (gleb-test-short-001-415614)$
클러스터 준비하기
cert-manager 서비스와 같은 필수 구성요소를 설치해야 합니다. cert-manager 설치 문서의 단계를 따르세요.
Cloud Shell에 이미 설치된 Kubernetes 명령줄 도구인 kubectl을 사용합니다. 이 유틸리티를 사용하기 전에 클러스터의 사용자 인증 정보를 가져와야 합니다.
gcloud container clusters get-credentials ${CLUSTER_NAME} --region=${LOCATION}
이제 kubectl을 사용하여 cert-manager를 설치할 수 있습니다.
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.2/cert-manager.yaml
예상되는 콘솔 출력(수정됨):
student@cloudshell:~$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.2/cert-manager.yaml namespace/cert-manager created customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io created ... validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
AlloyDB Omni 설치
AlloyDB Omni 설치 연산자는 helm 유틸리티를 사용하여 설치할 수 있습니다.
다음 명령어를 실행하여 AlloyDB Omni 연산자를 설치합니다.
export GCS_BUCKET=alloydb-omni-operator
export HELM_PATH=$(gcloud storage cat gs://$GCS_BUCKET/latest)
export OPERATOR_VERSION="${HELM_PATH%%/*}"
gcloud storage cp gs://$GCS_BUCKET/$HELM_PATH ./ --recursive
helm install alloydbomni-operator alloydbomni-operator-${OPERATOR_VERSION}.tgz \
--create-namespace \
--namespace alloydb-omni-system \
--atomic \
--timeout 5m
예상되는 콘솔 출력(수정됨):
student@cloudshell:~$ gcloud storage cp gs://$GCS_BUCKET/$HELM_PATH ./ --recursive Copying gs://alloydb-omni-operator/1.2.0/alloydbomni-operator-1.2.0.tgz to file://./alloydbomni-operator-1.2.0.tgz Completed files 1/1 | 126.5kiB/126.5kiB student@cloudshell:~$ helm install alloydbomni-operator alloydbomni-operator-${OPERATOR_VERSION}.tgz \ > --create-namespace \ > --namespace alloydb-omni-system \ > --atomic \ > --timeout 5m NAME: alloydbomni-operator LAST DEPLOYED: Mon Jan 20 13:13:20 2025 NAMESPACE: alloydb-omni-system STATUS: deployed REVISION: 1 TEST SUITE: None student@cloudshell:~$
AlloyDB Omni 연산자가 설치되면 데이터베이스 클러스터 배포를 진행할 수 있습니다.
다음은 googleMLExtension 매개변수와 내부 (비공개) 부하 분산기가 사용 설정된 배포 매니페스트의 예입니다.
apiVersion: v1
kind: Secret
metadata:
name: db-pw-my-omni
type: Opaque
data:
my-omni: "VmVyeVN0cm9uZ1Bhc3N3b3Jk"
---
apiVersion: alloydbomni.dbadmin.goog/v1
kind: DBCluster
metadata:
name: my-omni
spec:
databaseVersion: "15.7.0"
primarySpec:
adminUser:
passwordRef:
name: db-pw-my-omni
features:
googleMLExtension:
enabled: true
resources:
cpu: 1
memory: 8Gi
disks:
- name: DataDisk
size: 20Gi
storageClass: standard
dbLoadBalancerOptions:
annotations:
networking.gke.io/load-balancer-type: "internal"
allowExternalIncomingTraffic: true
비밀번호의 보안 비밀 값은 비밀번호 단어 'VeryStrongPassword'의 Base64 표현입니다. 더 안정적인 방법은 Google Secret Manager를 사용하여 비밀번호 값을 저장하는 것입니다. 자세한 내용은 문서를 참고하세요.
매니페스트를 my-omni.yaml로 저장하여 다음 단계에서 적용합니다. Cloud Shell에 있는 경우 터미널 오른쪽 상단의 '편집기 열기' 버튼을 눌러 편집기를 사용하여 이 작업을 수행할 수 있습니다.
my-omni.yaml이라는 이름으로 파일을 저장한 후 '터미널 열기' 버튼을 눌러 터미널로 돌아갑니다.
kubectl 유틸리티를 사용하여 my-omni.yaml 매니페스트를 클러스터에 적용합니다.
kubectl apply -f my-omni.yaml
예상되는 콘솔 출력:
secret/db-pw-my-omni created dbcluster.alloydbomni.dbadmin.goog/my-omni created
kubectl 유틸리티를 사용하여 my-omni 클러스터 상태를 확인합니다.
kubectl get dbclusters.alloydbomni.dbadmin.goog my-omni -n default
배포 중에 클러스터는 여러 단계를 거치며 결국 DBClusterReady 상태로 종료됩니다.
예상되는 콘솔 출력:
$ kubectl get dbclusters.alloydbomni.dbadmin.goog my-omni -n default NAME PRIMARYENDPOINT PRIMARYPHASE DBCLUSTERPHASE HAREADYSTATUS HAREADYREASON my-omni 10.131.0.33 Ready DBClusterReady
AlloyDB Omni에 연결하기
Kubernetes 포드를 사용하여 연결
클러스터가 준비되면 AlloyDB Omni 인스턴스 팟에서 PostgreSQL 클라이언트 바이너리를 사용할 수 있습니다. 포드 ID를 찾은 다음 kubectl을 사용하여 포드에 직접 연결하고 클라이언트 소프트웨어를 실행합니다. 비밀번호는 my-omni.yaml의 해시를 통해 설정된 VeryStrongPassword입니다.
DB_CLUSTER_NAME=my-omni
DB_CLUSTER_NAMESPACE=default
DBPOD=`kubectl get pod --selector=alloydbomni.internal.dbadmin.goog/dbcluster=$DB_CLUSTER_NAME,alloydbomni.internal.dbadmin.goog/task-type=database -n $DB_CLUSTER_NAMESPACE -o jsonpath='{.items[0].metadata.name}'`
kubectl exec -ti $DBPOD -n $DB_CLUSTER_NAMESPACE -c database -- psql -h localhost -U postgres
샘플 콘솔 출력:
DB_CLUSTER_NAME=my-omni DB_CLUSTER_NAMESPACE=default DBPOD=`kubectl get pod --selector=alloydbomni.internal.dbadmin.goog/dbcluster=$DB_CLUSTER_NAME,alloydbomni.internal.dbadmin.goog/task-type=database -n $DB_CLUSTER_NAMESPACE -o jsonpath='{.items[0].metadata.name}'` kubectl exec -ti $DBPOD -n $DB_CLUSTER_NAMESPACE -c database -- psql -h localhost -U postgres Password for user postgres: psql (15.7) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_128_GCM_SHA256, compression: off) Type "help" for help. postgres=#
5. GKE에 AI 모델 배포
AlloyDB Omni AI와 로컬 모델의 통합을 테스트하려면 클러스터에 모델을 배포해야 합니다.
모델의 노드 풀 만들기
모델을 실행하려면 추론을 실행할 노드 풀을 준비해야 합니다. 성능 관점에서 가장 좋은 접근 방식은 L4 Nvidia 가속기가 있는 g2-standard-8과 같은 노드 구성을 사용하는 그래픽 가속기가 있는 풀입니다.
L4 가속기를 사용하여 노드 풀을 만듭니다.
export PROJECT_ID=$(gcloud config get project)
export LOCATION=us-central1
export CLUSTER_NAME=alloydb-ai-gke
gcloud container node-pools create gpupool \
--accelerator type=nvidia-l4,count=1,gpu-driver-version=latest \
--project=${PROJECT_ID} \
--location=${LOCATION} \
--node-locations=${LOCATION}-a \
--cluster=${CLUSTER_NAME} \
--machine-type=g2-standard-8 \
--num-nodes=1
예상 출력
student@cloudshell$ export PROJECT_ID=$(gcloud config get project) Your active configuration is: [pant] export LOCATION=us-central1 export CLUSTER_NAME=alloydb-ai-gke student@cloudshell$ gcloud container node-pools create gpupool \ > --accelerator type=nvidia-l4,count=1,gpu-driver-version=latest \ > --project=${PROJECT_ID} \ > --location=${LOCATION} \ > --node-locations=${LOCATION}-a \ > --cluster=${CLUSTER_NAME} \ > --machine-type=g2-standard-8 \ > --num-nodes=1 Note: Machines with GPUs have certain limitations which may affect your workflow. Learn more at https://cloud.google.com/kubernetes-engine/docs/how-to/gpus Note: Starting in GKE 1.30.1-gke.115600, if you don't specify a driver version, GKE installs the default GPU driver for your node's GKE version. Creating node pool gpupool...done. Created [https://container.googleapis.com/v1/projects/student-test-001/zones/us-central1/clusters/alloydb-ai-gke/nodePools/gpupool]. NAME MACHINE_TYPE DISK_SIZE_GB NODE_VERSION gpupool g2-standard-8 100 1.31.4-gke.1183000
배포 매니페스트 준비
모델을 배포하려면 배포 매니페스트를 준비해야 합니다.
Hugging Face의 BGE Base v1.5 임베딩 모델을 사용합니다. 여기에서 모델 카드를 확인할 수 있습니다. 모델을 배포하려면 Hugging Face에서 이미 준비된 안내와 GitHub의 배포 패키지를 사용하면 됩니다.
패키지 클론
git clone https://github.com/huggingface/Google-Cloud-Containers
cloud.google.com/gke-accelerator 값을 nvidia-l4로 바꾸고 리소스에 제한을 추가하여 매니페스트를 수정합니다.
vi Google-Cloud-Containers/examples/gke/tei-deployment/gpu-config/deployment.yaml
수정된 매니페스트는 다음과 같습니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: tei-deployment
spec:
replicas: 1
selector:
matchLabels:
app: tei-server
template:
metadata:
labels:
app: tei-server
hf.co/model: Snowflake--snowflake-arctic-embed-m
hf.co/task: text-embeddings
spec:
containers:
- name: tei-container
image: us-docker.pkg.dev/deeplearning-platform-release/gcr.io/huggingface-text-embeddings-inference-cu122.1-4.ubuntu2204:latest
resources:
requests:
nvidia.com/gpu: 1
limits:
nvidia.com/gpu: 1
env:
- name: MODEL_ID
value: Snowflake/snowflake-arctic-embed-m
- name: NUM_SHARD
value: "1"
- name: PORT
value: "8080"
volumeMounts:
- mountPath: /dev/shm
name: dshm
- mountPath: /data
name: data
volumes:
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 1Gi
- name: data
emptyDir: {}
nodeSelector:
cloud.google.com/gke-accelerator: nvidia-l4
모델 배포
배포를 위한 서비스 계정과 네임스페이스를 준비해야 합니다.
Kubernetes 네임스페이스 hf-gke-namespace를 만듭니다.
export NAMESPACE=hf-gke-namespace
kubectl create namespace $NAMESPACE
Kubernetes 서비스 계정 만들기
export SERVICE_ACCOUNT=hf-gke-service-account
kubectl create serviceaccount $SERVICE_ACCOUNT --namespace $NAMESPACE
모델 배포
kubectl apply -f Google-Cloud-Containers/examples/gke/tei-deployment/gpu-config
배포 확인
kubectl get pods
모델 서비스 확인
kubectl get service tei-service
실행 중인 서비스 유형 ClusterIP가 표시됩니다.
샘플 출력:
student@cloudshell$ kubectl get service tei-service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE tei-service ClusterIP 34.118.233.48 <none> 8080/TCP 10m
서비스의 CLUSTER-IP를 엔드포인트 주소로 사용합니다. 모델 삽입은 URI http://34.118.233.48:8080/embed로 응답할 수 있습니다. 나중에 AlloyDB Omni에 모델을 등록할 때 사용됩니다.
kubectl port-forward 명령어를 사용하여 노출하여 테스트할 수 있습니다.
kubectl port-forward service/tei-service 8080:8080
포트 전달은 하나의 Cloud Shell 세션에서 실행되며 이를 테스트하려면 다른 세션이 필요합니다.
맨 위에 있는 '+' 기호를 사용하여 다른 Cloud Shell 탭을 엽니다.
새 셸 세션에서 curl 명령어를 실행합니다.
curl http://localhost:8080/embed \
-X POST \
-d '{"inputs":"Test"}' \
-H 'Content-Type: application/json'
다음 샘플 출력과 같이 벡터 배열을 반환해야 합니다 (삭제됨).
curl http://localhost:8080/embed \ > -X POST \ > -d '{"inputs":"Test"}' \ > -H 'Content-Type: application/json' [[-0.018975832,0.0071419072,0.06347208,0.022992613,0.014205903 ... -0.03677433,0.01636146,0.06731572]]
6. AlloyDB Omni에 모델 등록
배포된 모델과 함께 AlloyDB Omni가 작동하는 방식을 테스트하려면 데이터베이스를 만들고 모델을 등록해야 합니다.
데이터베이스 만들기
GCE VM을 점프 박스로 만들고 클라이언트 VM에서 AlloyDB Omni에 연결한 후 데이터베이스를 만듭니다.
Omni용 GKE 외부 부하 분산기를 사용하면 비공개 IP 주소 지정을 통해 VPC에서 액세스할 수 있지만 VPC 외부에서 연결할 수는 없으므로 점프박스가 필요합니다. 일반적으로 더 안전하며 데이터베이스 인스턴스를 인터넷에 노출하지 않습니다. 다이어그램을 명확하게 확인하세요.
Cloud Shell 세션에서 VM을 만들려면 다음을 실행합니다.
export ZONE=us-central1-a
gcloud compute instances create instance-1 \
--zone=$ZONE
Cloud Shell에서 kubectl을 사용하여 AlloyDB Omni 엔드포인트 IP를 찾습니다.
kubectl get dbclusters.alloydbomni.dbadmin.goog my-omni -n default
PRIMARYENDPOINT를 기록합니다. 예를 들면 다음과 같습니다.
output:
student@cloudshell:~$ kubectl get dbclusters.alloydbomni.dbadmin.goog my-omni -n default NAME PRIMARYENDPOINT PRIMARYPHASE DBCLUSTERPHASE HAREADYSTATUS HAREADYREASON my-omni 10.131.0.33 Ready DBClusterReady student@cloudshell:~$
10.131.0.33은 예시에서 AlloyDB Omni 인스턴스에 연결하는 데 사용할 IP입니다.
gcloud를 사용하여 VM에 연결합니다.
gcloud compute ssh instance-1 --zone=$ZONE
SSH 키 생성 메시지가 표시되면 안내에 따라 진행합니다. 문서에서 SSH 연결에 관해 자세히 알아보세요.
VM의 SSH 세션에서 PostgreSQL 클라이언트를 설치합니다.
sudo apt-get update
sudo apt-get install --yes postgresql-client
다음 예와 같이 AlloyDB Omni 부하 분산기 IP를 내보냅니다 (IP를 부하 분산기 IP로 바꾸기).
export INSTANCE_IP=10.131.0.33
AlloyDB Omni에 연결합니다. 비밀번호는 my-omni.yaml의 해시를 통해 설정된 VeryStrongPassword입니다.
psql "host=$INSTANCE_IP user=postgres sslmode=require"
설정된 psql 세션에서 다음을 실행합니다.
create database demo;
세션을 종료하고 데이터베이스 데모에 연결합니다 (또는 동일한 세션에서 \c demo를 실행하면 됩니다).
psql "host=$INSTANCE_IP user=postgres sslmode=require dbname=demo"
변환 함수 만들기
서드 파티 임베딩 모델의 경우 입력과 출력을 모델 및 내부 함수에서 예상하는 형식으로 형식 지정하는 변환 함수를 만들어야 합니다.
다음은 입력을 처리하는 변환 함수입니다.
-- Input Transform Function corresponding to the custom model endpoint
CREATE OR REPLACE FUNCTION tei_text_input_transform(model_id VARCHAR(100), input_text TEXT)
RETURNS JSON
LANGUAGE plpgsql
AS $$
DECLARE
transformed_input JSON;
model_qualified_name TEXT;
BEGIN
SELECT json_build_object('inputs', input_text, 'truncate', true)::JSON INTO transformed_input;
RETURN transformed_input;
END;
$$;
샘플 출력에 표시된 대로 데모 데이터베이스에 연결된 상태에서 제공된 코드를 실행합니다.
demo=# -- Input Transform Function corresponding to the custom model endpoint CREATE OR REPLACE FUNCTION tei_text_input_transform(model_id VARCHAR(100), input_text TEXT) RETURNS JSON LANGUAGE plpgsql AS $$ DECLARE transformed_input JSON; model_qualified_name TEXT; BEGIN SELECT json_build_object('inputs', input_text, 'truncate', true)::JSON INTO transformed_input; RETURN transformed_input; END; $$; CREATE FUNCTION demo=#
다음은 모델의 응답을 실수 배열로 변환하는 출력 함수입니다.
-- Output Transform Function corresponding to the custom model endpoint
CREATE OR REPLACE FUNCTION tei_text_output_transform(model_id VARCHAR(100), response_json JSON)
RETURNS REAL[]
LANGUAGE plpgsql
AS $$
DECLARE
transformed_output REAL[];
BEGIN
SELECT ARRAY(SELECT json_array_elements_text(response_json->0)) INTO transformed_output;
RETURN transformed_output;
END;
$$;
동일한 세션에서 실행합니다.
demo=# -- Output Transform Function corresponding to the custom model endpoint CREATE OR REPLACE FUNCTION tei_text_output_transform(model_id VARCHAR(100), response_json JSON) RETURNS REAL[] LANGUAGE plpgsql AS $$ DECLARE transformed_output REAL[]; BEGIN SELECT ARRAY(SELECT json_array_elements_text(response_json->0)) INTO transformed_output; RETURN transformed_output; END; $$; CREATE FUNCTION demo=#
모델 등록
이제 데이터베이스에 모델을 등록할 수 있습니다.
다음은 이름이 bge-base-1.5인 모델을 등록하는 절차 호출입니다. IP 34.118.233.48을 모델 서비스 IP 주소 (kubectl get service tei-service의 출력)로 바꿉니다.
CALL
google_ml.create_model(
model_id => 'bge-base-1.5',
model_request_url => 'http://34.118.233.48:8080/embed',
model_provider => 'custom',
model_type => 'text_embedding',
model_in_transform_fn => 'tei_text_input_transform',
model_out_transform_fn => 'tei_text_output_transform');
데모 데이터베이스에 연결된 상태에서 제공된 코드를 실행합니다.
demo=# CALL google_ml.create_model( model_id => 'bge-base-1.5', model_request_url => 'http://34.118.233.48:8080/embed', model_provider => 'custom', model_type => 'text_embedding', model_in_transform_fn => 'tei_text_input_transform', model_out_transform_fn => 'tei_text_output_transform'); CALL demo=#
실수 배열을 반환해야 하는 다음 테스트 쿼리를 사용하여 레지스터 모델을 테스트할 수 있습니다.
select google_ml.embedding('bge-base-1.5','What is AlloyDB Omni?');
7. AlloyDB Omni에서 모델 테스트
데이터 로드
AlloyDB Omni이 배포된 모델과 함께 작동하는 방식을 테스트하려면 데이터를 로드해야 합니다. AlloyDB에서 벡터 검색을 위해 다른 Codelab 중 하나와 동일한 데이터를 사용했습니다.
데이터를 로드하는 한 가지 방법은 Google Cloud SDK와 PostgreSQL 클라이언트 소프트웨어를 사용하는 것입니다. 데모 데이터베이스를 만드는 데 사용한 것과 동일한 클라이언트 VM을 사용할 수 있습니다. VM 이미지에 기본값을 사용한 경우 Google Cloud SDK가 이미 설치되어 있어야 합니다. 하지만 Google SDK 없이 맞춤 이미지를 사용한 경우 문서에 따라 추가할 수 있습니다.
다음 예와 같이 AlloyDB Omni 부하 분산기 IP를 내보냅니다 (IP를 부하 분산기 IP로 바꾸기).
export INSTANCE_IP=10.131.0.33
데이터베이스에 연결하고 pgvector 확장 프로그램을 사용 설정합니다.
psql "host=$INSTANCE_IP user=postgres sslmode=require dbname=demo"
psql 세션에서 다음을 실행합니다.
CREATE EXTENSION IF NOT EXISTS vector;
psql 세션을 종료하고 명령줄 세션에서 명령어를 실행하여 데이터를 데모 데이터베이스에 로드합니다.
테이블을 만듭니다.
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=demo"
예상되는 콘솔 출력:
student@cloudshell:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=demo" Password for user postgres: SET SET SET SET SET set_config ------------ (1 row) SET SET SET SET SET SET CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE SEQUENCE ALTER TABLE ALTER SEQUENCE ALTER TABLE ALTER TABLE ALTER TABLE student@cloudshell:~$
생성된 테이블 목록은 다음과 같습니다.
psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\dt+"
출력:
student@cloudshell:~$ psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\dt+" Password for user postgres: List of relations Schema | Name | Type | Owner | Persistence | Access method | Size | Description --------+------------------+-------+----------+-------------+---------------+------------+------------- public | cymbal_embedding | table | postgres | permanent | heap | 8192 bytes | public | cymbal_inventory | table | postgres | permanent | heap | 8192 bytes | public | cymbal_products | table | postgres | permanent | heap | 8192 bytes | public | cymbal_stores | table | postgres | permanent | heap | 8192 bytes | (4 rows) student@cloudshell:~$
cymbal_products 테이블에 데이터를 로드합니다.
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_products from stdin csv header"
예상되는 콘솔 출력:
student@cloudshell:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_products from stdin csv header" COPY 941 student@cloudshell:~$
다음은 cymbal_products 테이블의 몇 행 샘플입니다.
psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT uniq_id,left(product_name,30),left(product_description,50),sale_price FROM cymbal_products limit 3"
출력:
student@cloudshell:~$ psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT uniq_id,left(product_name,30),left(product_description,50),sale_price FROM cymbal_products limit 3" Password for user postgres: uniq_id | left | left | sale_price ----------------------------------+--------------------------------+----------------------------------------------------+------------ a73d5f754f225ecb9fdc64232a57bc37 | Laundry Tub Strainer Cup | Laundry tub strainer cup Chrome For 1-.50, drain | 11.74 41b8993891aa7d39352f092ace8f3a86 | LED Starry Star Night Light La | LED Starry Star Night Light Laser Projector 3D Oc | 46.97 ed4a5c1b02990a1bebec908d416fe801 | Surya Horizon HRZ-1060 Area Ru | The 100% polypropylene construction of the Surya | 77.4 (3 rows) student@cloudshell:~$
cymbal_inventory 테이블에 데이터를 로드합니다.
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_inventory from stdin csv header"
예상되는 콘솔 출력:
student@cloudshell:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_inventory from stdin csv header" Password for user postgres: COPY 263861 student@cloudshell:~$
다음은 cymbal_inventory 테이블의 몇 개 행 샘플입니다.
psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT * FROM cymbal_inventory LIMIT 3"
출력:
student@cloudshell:~$ psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT * FROM cymbal_inventory LIMIT 3" Password for user postgres: store_id | uniq_id | inventory ----------+----------------------------------+----------- 1583 | adc4964a6138d1148b1d98c557546695 | 5 1490 | adc4964a6138d1148b1d98c557546695 | 4 1492 | adc4964a6138d1148b1d98c557546695 | 3 (3 rows) student@cloudshell:~$
cymbal_stores 테이블에 데이터를 로드합니다.
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_stores from stdin csv header"
예상되는 콘솔 출력:
student@cloudshell:~$ gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "\copy cymbal_stores from stdin csv header" Password for user postgres: COPY 4654 student@cloudshell:~$
다음은 cymbal_stores 테이블의 몇 행 샘플입니다.
psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT store_id, name, zip_code FROM cymbal_stores limit 3"
출력:
student@cloudshell:~$ psql "host=$INSTANCE_IP user=postgres dbname=demo" -c "SELECT store_id, name, zip_code FROM cymbal_stores limit 3" Password for user postgres: store_id | name | zip_code ----------+-------------------+---------- 1990 | Mayaguez Store | 680 2267 | Ware Supercenter | 1082 4359 | Ponce Supercenter | 780 (3 rows) student@cloudshell:~$
빌드 임베딩
psql을 사용하여 데모 데이터베이스에 연결하고 제품 이름 및 설명을 기반으로 cymbal_products 테이블에 설명된 제품의 임베딩을 빌드합니다.
데모 데이터베이스에 연결합니다.
psql "host=$INSTANCE_IP user=postgres sslmode=require dbname=demo"
열 임베딩이 있는 cymbal_embedding 테이블을 사용하여 임베딩을 저장하고 제품 설명을 함수의 텍스트 입력으로 사용합니다.
나중에 원격 모델과 비교할 수 있도록 쿼리의 타이밍을 사용 설정합니다.
\timing
쿼리를 실행하여 임베딩을 빌드합니다.
INSERT INTO cymbal_embedding(uniq_id,embedding) SELECT uniq_id, google_ml.embedding('bge-base-1.5',product_description)::vector FROM cymbal_products;
예상되는 콘솔 출력:
demo=# INSERT INTO cymbal_embedding(uniq_id,embedding) SELECT uniq_id, google_ml.embedding('bge-base-1.5',product_description)::vector FROM cymbal_products; INSERT 0 941 Time: 11069.762 ms (00:11.070) demo=#
이 예시에서는 941개의 레코드에 대한 임베딩을 빌드하는 데 약 11초가 걸렸습니다.
테스트 쿼리 실행
psql을 사용하여 데모 데이터베이스에 연결하고, 임베딩을 빌드할 때와 마찬가지로 타이밍을 사용 설정하여 쿼리의 실행 시간을 측정합니다.
코사인 거리를 벡터 검색 알고리즘으로 사용하여 '여기에서 잘 자라는 과일나무는 어떤 종류인가요?'와 같은 요청과 일치하는 상위 5개 제품을 찾아보겠습니다.
psql 세션에서 다음을 실행합니다.
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
(ce.embedding <=> google_ml.embedding('bge-base-1.5','What kind of fruit trees grow well here?')::vector) as distance
FROM
cymbal_products cp
JOIN cymbal_embedding ce on
ce.uniq_id=cp.uniq_id
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;
예상되는 콘솔 출력:
demo=# SELECT cp.product_name, left(cp.product_description,80) as description, cp.sale_price, cs.zip_code, (ce.embedding <=> google_ml.embedding('bge-base-1.5','What kind of fruit trees grow well here?')::vector) as distance FROM cymbal_products cp JOIN cymbal_embedding ce on ce.uniq_id=cp.uniq_id 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 -----------------------+----------------------------------------------------------------------------------+------------+----------+--------------------- California Sycamore | This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is | 300.00 | 93230 | 0.22753925487632942 Toyon | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e | 10.00 | 93230 | 0.23497374266229387 California Peppertree | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e | 25.00 | 93230 | 0.24215884459965364 California Redwood | This is a beautiful redwood tree that can grow to be over 300 feet tall. It is a | 1000.00 | 93230 | 0.24564130578287147 Cherry Tree | This is a beautiful cherry tree that will produce delicious cherries. It is an d | 75.00 | 93230 | 0.24846117929767153 (5 rows) Time: 28.724 ms demo=#
쿼리는 28ms 동안 실행되었으며 요청과 일치하고 매장에서 사용 가능한 인벤토리 번호가 1583인 cymbal_products 테이블의 나무 목록을 반환했습니다.
ANN 색인 빌드
데이터 세트가 작으면 모든 임베딩을 스캔하는 정확한 검색을 쉽게 사용할 수 있지만 데이터가 늘어나면 로드와 응답 시간도 늘어납니다. 성능을 개선하려면 임베딩 데이터에 색인을 생성하면 됩니다. 다음은 벡터 데이터에 Google ScaNN 색인을 사용하는 방법의 예입니다.
연결이 끊어진 경우 데모 데이터베이스에 다시 연결합니다.
psql "host=$INSTANCE_IP user=postgres sslmode=require dbname=demo"
alloydb_scann 확장 프로그램 사용 설정:
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
색인을 빌드합니다.
CREATE INDEX cymbal_embedding_scann ON cymbal_embedding USING scann (embedding cosine);
이전과 동일한 쿼리를 실행하고 결과를 비교해 보세요.
demo=# SELECT cp.product_name, left(cp.product_description,80) as description, cp.sale_price, cs.zip_code, (ce.embedding <=> google_ml.embedding('bge-base-1.5','What kind of fruit trees grow well here?')::vector) as distance FROM cymbal_products cp JOIN cymbal_embedding ce on ce.uniq_id=cp.uniq_id 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 -----------------------+----------------------------------------------------------------------------------+------------+----------+--------------------- California Sycamore | This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is | 300.00 | 93230 | 0.22753925487632942 Toyon | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e | 10.00 | 93230 | 0.23497374266229387 California Peppertree | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e | 25.00 | 93230 | 0.24215884459965364 California Redwood | This is a beautiful redwood tree that can grow to be over 300 feet tall. It is a | 1000.00 | 93230 | 0.24564130578287147 Fremont Cottonwood | This is a beautiful cottonwood tree that can grow to be over 100 feet tall. It i | 200.00 | 93230 | 0.2533482837690365 (5 rows) Time: 14.665 ms demo=#
쿼리 실행 시간이 약간 줄었고 이 이점은 대규모 데이터 세트에서 더 두드러집니다. 결과는 매우 유사하며 Cherry만 Fremont Cottonwood로 대체되었습니다.
다른 쿼리를 시도하고 문서에서 벡터 색인 선택에 관해 자세히 알아보세요.
AlloyDB Omni에는 더 많은 기능과 실험실이 있습니다.
8. 환경 정리
이제 AlloyDB Omni와 AI 모델을 사용하여 GKE 클러스터를 삭제할 수 있습니다.
GKE 클러스터 삭제
Cloud Shell에서 다음을 실행합니다.
export PROJECT_ID=$(gcloud config get project)
export LOCATION=us-central1
export CLUSTER_NAME=alloydb-ai-gke
gcloud container clusters delete ${CLUSTER_NAME} \
--project=${PROJECT_ID} \
--region=${LOCATION}
예상되는 콘솔 출력:
student@cloudshell:~$ gcloud container clusters delete ${CLUSTER_NAME} \ > --project=${PROJECT_ID} \ > --region=${LOCATION} The following clusters will be deleted. - [alloydb-ai-gke] in [us-central1] Do you want to continue (Y/n)? Y Deleting cluster alloydb-ai-gke...done. Deleted
VM 삭제
Cloud Shell에서 다음을 실행합니다.
export PROJECT_ID=$(gcloud config get project)
export ZONE=us-central1-a
gcloud compute instances delete instance-1 \
--project=${PROJECT_ID} \
--zone=${ZONE}
예상되는 콘솔 출력:
student@cloudshell:~$ export PROJECT_ID=$(gcloud config get project) export ZONE=us-central1-a gcloud compute instances delete instance-1 \ --project=${PROJECT_ID} \ --zone=${ZONE} Your active configuration is: [cloudshell-5399] The following instances will be deleted. Any attached disks configured to be auto-deleted will be deleted unless they are attached to any other instances or the `--keep-disks` flag is given and specifies them for keeping. Deleting a disk is irreversible and any data on the disk will be lost. - [instance-1] in [us-central1-a] Do you want to continue (Y/n)? Y Deleted
이 Codelab을 위해 새 프로젝트를 만든 경우 전체 프로젝트를 삭제할 수 있습니다. https://console.cloud.google.com/cloud-resource-manager
9. 축하합니다
축하합니다. Codelab을 완료했습니다.
학습한 내용
- Google Kubernetes 클러스터에 AlloyDB Omni를 배포하는 방법
- AlloyDB Omni에 연결하는 방법
- AlloyDB Omni에 데이터를 로드하는 방법
- GKE에 공개 삽입 모델을 배포하는 방법
- AlloyDB Omni에서 임베딩 모델을 등록하는 방법
- 시맨틱 검색을 위한 임베딩을 생성하는 방법
- AlloyDB Omni에서 생성된 임베딩을 시맨틱 검색에 사용하는 방법
- AlloyDB에서 벡터 색인을 만들고 사용하는 방법
AlloyDB Omni에서 AI를 사용하는 방법에 관한 자세한 내용은 문서를 참고하세요.
10. 설문조사
결과: