이 튜토리얼에서는 검색 증강 생성(RAG)을 기반으로 하는 대규모 언어 모델(LLM) 애플리케이션을 Cloud Storage 버킷에 업로드하는 PDF 파일과 통합하는 방법을 보여줍니다.
이 가이드에서는 데이터베이스를 업로드된 문서의 표현(임베딩)을 보유하는 스토리지 및 시맨틱 검색엔진으로 사용합니다. Langchain 프레임워크를 사용하여 임베딩과 상호작용하고 Vertex AI를 통해 제공되는 Gemini 모델을 사용합니다.
Langchain은 여러 머신러닝 태스크를 간소화하고 다양한 벡터 데이터베이스 및 AI 서비스와 통합할 수 있는 인터페이스가 있는 인기 있는 오픈소스 Python 프레임워크입니다.
이 튜토리얼은 GKE 및 Cloud Storage에 RAG LLM 애플리케이션을 배포하는 데 관심이 있는 클라우드 플랫폼 관리자 및 설계자, ML 엔지니어, MLOps(DevOps) 전문가를 대상으로 합니다.
목표
이 튜토리얼에서는 다음을 수행하는 방법을 알아봅니다.
- 벡터 데이터베이스에 문서 임베딩을 만들고 저장하는 애플리케이션을 빌드하고 배포합니다.
- Cloud Storage 버킷에 새 문서 업로드를 트리거하도록 애플리케이션을 자동화합니다.
- 시맨틱 검색을 사용하여 문서 콘텐츠를 기반으로 질문에 답하는 챗봇 애플리케이션을 배포합니다.
배포 아키텍처
이 튜토리얼에서는 Cloud Storage 버킷, Eventarc 트리거와 다음 서비스를 만듭니다.
embed-docs
: 사용자가 Cloud Storage 버킷에 새 문서를 업로드할 때마다 Eventarc가 이 서비스를 트리거합니다. 서비스는 업로드된 문서의 임베딩을 만들고 벡터 데이터베이스에 임베딩을 삽입하는 Kubernetes 작업을 시작합니다.chatbot
: 이 서비스는 시맨틱 검색 및 Gemini API를 사용하여 업로드된 문서에 관한 자연어 질문에 답변합니다.
다음 다이어그램은 문서를 업로드하고 벡터화하는 프로세스를 보여줍니다.
다이어그램에서 사용자는 Cloud Storage 버킷에 파일을 업로드합니다.
Eventarc는 버킷의 객체 metadataUpdated
이벤트를 구독하고 Kubernetes 워크로드인 Eventarc의 이벤트 전달자를 사용하여 새 문서를 업로드할 때 embed-docs
서비스를 호출합니다. 그러면 서비스에서 업로드된 문서의 임베딩을 만듭니다. embed-docs
서비스는 Vertex AI 임베딩 모델을 사용하여 벡터 데이터베이스에 임베딩을 저장합니다.
다음 다이어그램은 chatbot
서비스를 사용하여 업로드된 문서 콘텐츠에 관해 질문하는 프로세스를 보여줍니다.
사용자는 자연어를 사용하여 질문할 수 있으며 챗봇은 업로드된 파일의 콘텐츠만을 기반으로 답변을 생성합니다. 챗봇은 시맨틱 검색을 사용하여 벡터 데이터베이스에서 컨텍스트를 가져온 다음 질문과 컨텍스트를 Gemini로 전송합니다.
비용
이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.
프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요.
이 문서에 설명된 태스크를 완료했으면 만든 리소스를 삭제하여 청구가 계속되는 것을 방지할 수 있습니다. 자세한 내용은 삭제를 참조하세요.
시작하기 전에
이 튜토리얼에서는 Cloud Shell을 사용하여 명령어를 실행합니다. Cloud Shell은 Google Cloud에서 호스팅되는 리소스를 관리하는 데 사용되는 셸 환경입니다. Cloud Shell에는 Google Cloud CLI, kubectl, Terraform 명령줄 도구가 사전 설치되어 있습니다. Cloud Shell을 사용하지 않는 경우 Google Cloud CLI를 설치합니다.
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
Create or select a Google Cloud project.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_ID
with a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_ID
with your Google Cloud project name.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Vertex AI, Cloud Build, Eventarc, Artifact Registry APIs:
gcloud services enable aiplatform.googleapis.com
cloudbuild.googleapis.com eventarc.googleapis.com artifactregistry.googleapis.com - Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
Create or select a Google Cloud project.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_ID
with a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_ID
with your Google Cloud project name.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Vertex AI, Cloud Build, Eventarc, Artifact Registry APIs:
gcloud services enable aiplatform.googleapis.com
cloudbuild.googleapis.com eventarc.googleapis.com artifactregistry.googleapis.com -
Grant roles to your user account. Run the following command once for each of the following IAM roles:
eventarc.admin
gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
- Replace
PROJECT_ID
with your project ID. -
Replace
USER_IDENTIFIER
with the identifier for your user account. For example,user:myemail@example.com
. - Replace
ROLE
with each individual role.
- Replace
클러스터 만들기
Qdrant, Elasticsearch 또는 Postgres 클러스터를 만듭니다.
Qdrant
GKE에 Qdrant 벡터 데이터베이스 배포의 안내에 따라 Autopilot 모드 또는 Standard 모드 GKE 클러스터에서 실행되는 Qdrant 클러스터를 만듭니다.
Elasticsearch
GKE에 Elasticsearch 벡터 데이터베이스 배포의 안내에 따라 Autopilot 모드 또는 Standard 모드 GKE 클러스터에서 실행되는 Elasticsearch 클러스터를 만듭니다.
PGVector
GKE에 PostgreSQL 벡터 데이터베이스 배포의 안내에 따라 Autopilot 모드 또는 Standard 모드 GKE 클러스터에서 PGVector가 실행되는 Postgres 클러스터를 만듭니다.
Weaviate
안내에 따라 GKE에 Weaviate 벡터 데이터베이스를 배포하여 Autopilot 또는 Standard 모드 GKE 클러스터에서 실행되는 Weaviate 클러스터를 만듭니다.
환경 설정하기
Cloud Shell로 환경을 설정합니다.
프로젝트의 환경 변수를 설정합니다.
Qdrant
export PROJECT_ID=PROJECT_ID export KUBERNETES_CLUSTER_PREFIX=qdrant export REGION=us-central1 export DB_NAMESPACE=qdrant
PROJECT_ID
를 Google Cloud 프로젝트 ID로 바꿉니다.Elasticsearch
export PROJECT_ID=PROJECT_ID export KUBERNETES_CLUSTER_PREFIX=elasticsearch export REGION=us-central1 export DB_NAMESPACE=elastic
PROJECT_ID
를 Google Cloud 프로젝트 ID로 바꿉니다.PGVector
export PROJECT_ID=PROJECT_ID export KUBERNETES_CLUSTER_PREFIX=postgres export REGION=us-central1 export DB_NAMESPACE=pg-ns
PROJECT_ID
를 Google Cloud 프로젝트 ID로 바꿉니다.Weaviate
export PROJECT_ID=PROJECT_ID export KUBERNETES_CLUSTER_PREFIX=weaviate export REGION=us-central1 export DB_NAMESPACE=weaviate
PROJECT_ID
를 Google Cloud 프로젝트 ID로 바꿉니다.GKE 클러스터 실행 여부를 확인합니다.
gcloud container clusters list --project=${PROJECT_ID} --region=${REGION}
출력은 다음과 비슷합니다.
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS [KUBERNETES_CLUSTER_PREFIX]-cluster us-central1 1.30.1-gke.1329003 <EXTERNAL IP> e2-standard-2 1.30.1-gke.1329003 6 RUNNING
GitHub에서 샘플 코드 저장소를 클론합니다.
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
databases
디렉터리로 이동합니다.cd kubernetes-engine-samples/databases
인프라 준비
Artifact Registry 저장소를 만들고 Docker 이미지를 빌드한 후 Docker 이미지를 Artifact Registry에 푸시합니다.
Artifact Registry 저장소를 만듭니다.
gcloud artifacts repositories create ${KUBERNETES_CLUSTER_PREFIX}-images \ --repository-format=docker \ --location=${REGION} \ --description="Vector database images repository" \ --async
Compute Engine 서비스 계정에
storage.objectAdmin
및artifactregistry.admin
권한을 설정하여 Cloud Build를 사용하여embed-docs
및chatbot
서비스의 Docker 이미지를 빌드하고 푸시합니다.export PROJECT_NUMBER=PROJECT_NUMBER gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \ --role="roles/storage.objectAdmin" gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \ --role="roles/artifactregistry.admin"
PROJECT_NUMBER
를 Google Cloud 프로젝트 번호로 바꿉니다.embed-docs
및chatbot
서비스의 Docker 이미지를 빌드합니다.embed-docs
이미지에는 Eventarc 전달자 요청을 수신하는 애플리케이션과 임베딩 작업 모두에 관한 Python 코드가 포함되어 있습니다.Qdrant
export DOCKER_REPO="${REGION}-docker.pkg.dev/${PROJECT_ID}/${KUBERNETES_CLUSTER_PREFIX}-images" gcloud builds submit qdrant/docker/chatbot --region=${REGION} \ --tag ${DOCKER_REPO}/chatbot:1.0 --async gcloud builds submit qdrant/docker/embed-docs --region=${REGION} \ --tag ${DOCKER_REPO}/embed-docs:1.0 --async
Elasticsearch
export DOCKER_REPO="${REGION}-docker.pkg.dev/${PROJECT_ID}/${KUBERNETES_CLUSTER_PREFIX}-images" gcloud builds submit elasticsearch/docker/chatbot --region=${REGION} \ --tag ${DOCKER_REPO}/chatbot:1.0 --async gcloud builds submit elasticsearch/docker/embed-docs --region=${REGION} \ --tag ${DOCKER_REPO}/embed-docs:1.0 --async
PGVector
export DOCKER_REPO="${REGION}-docker.pkg.dev/${PROJECT_ID}/${KUBERNETES_CLUSTER_PREFIX}-images" gcloud builds submit postgres-pgvector/docker/chatbot --region=${REGION} \ --tag ${DOCKER_REPO}/chatbot:1.0 --async gcloud builds submit postgres-pgvector/docker/embed-docs --region=${REGION} \ --tag ${DOCKER_REPO}/embed-docs:1.0 --async
Weaviate
export DOCKER_REPO="${REGION}-docker.pkg.dev/${PROJECT_ID}/${KUBERNETES_CLUSTER_PREFIX}-images" gcloud builds submit weaviate/docker/chatbot --region=${REGION} \ --tag ${DOCKER_REPO}/chatbot:1.0 --async gcloud builds submit weaviate/docker/embed-docs --region=${REGION} \ --tag ${DOCKER_REPO}/embed-docs:1.0 --async
이미지를 확인합니다.
gcloud artifacts docker images list $DOCKER_REPO \ --project=$PROJECT_ID \ --format="value(IMAGE)"
출력은 다음과 비슷합니다.
$REGION-docker.pkg.dev/$PROJECT_ID/${KUBERNETES_CLUSTER_PREFIX}-images/chatbot $REGION-docker.pkg.dev/$PROJECT_ID/${KUBERNETES_CLUSTER_PREFIX}-images/embed-docs
Kubernetes 작업을 실행할 권한이 있는 Kubernetes 서비스 계정을 배포합니다.
Qdrant
sed "s/<PROJECT_ID>/$PROJECT_ID/;s/<CLUSTER_PREFIX>/$KUBERNETES_CLUSTER_PREFIX/" qdrant/manifests/05-rag/service-account.yaml | kubectl -n qdrant apply -f -
Elasticsearch
sed "s/<PROJECT_ID>/$PROJECT_ID/;s/<CLUSTER_PREFIX>/$KUBERNETES_CLUSTER_PREFIX/" elasticsearch/manifests/05-rag/service-account.yaml | kubectl -n elastic apply -f -
PGVector
sed "s/<PROJECT_ID>/$PROJECT_ID/;s/<CLUSTER_PREFIX>/$KUBERNETES_CLUSTER_PREFIX/" postgres-pgvector/manifests/03-rag/service-account.yaml | kubectl -n pg-ns apply -f -
Weaviate
sed "s/<PROJECT_ID>/$PROJECT_ID/;s/<CLUSTER_PREFIX>/$KUBERNETES_CLUSTER_PREFIX/" weaviate/manifests/04-rag/service-account.yaml | kubectl -n weaviate apply -f -
Terraform을 사용하여 GKE 클러스터를 만들고
create_service_account
를 true로 설정하면 클러스터와 노드에서 별도의 서비스 계정이 생성되고 사용됩니다. 이 Compute Engine 서비스 계정에artifactregistry.serviceAgent
역할을 부여하여 노드가embed-docs
및chatbot
용으로 생성된 Artifact Registry에서 이미지를 가져올 수 있도록 합니다.export CLUSTER_SERVICE_ACCOUNT=$(gcloud container clusters describe ${KUBERNETES_CLUSTER_PREFIX}-cluster \ --region=${REGION} \ --format="value(nodeConfig.serviceAccount)") gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:${CLUSTER_SERVICE_ACCOUNT}" \ --role="roles/artifactregistry.serviceAgent"
서비스 계정에 액세스 권한을 부여하지 않으면
embed-docs
및chatbot
서비스를 배포할 때 Artifact Registry에서 이미지를 가져오려고 할 때 노드에 권한 문제가 발생할 수 있습니다.embed-docs
및chatbot
서비스용 Kubernetes 배포를 배포합니다.Qdrant
sed "s|<DOCKER_REPO>|$DOCKER_REPO|" qdrant/manifests/05-rag/chatbot.yaml | kubectl -n qdrant apply -f - sed "s|<DOCKER_REPO>|$DOCKER_REPO|" qdrant/manifests/05-rag/docs-embedder.yaml | kubectl -n qdrant apply -f -
Elasticsearch
sed "s|<DOCKER_REPO>|$DOCKER_REPO|" elasticsearch/manifests/05-rag/chatbot.yaml | kubectl -n elastic apply -f - sed "s|<DOCKER_REPO>|$DOCKER_REPO|" elasticsearch/manifests/05-rag/docs-embedder.yaml | kubectl -n elastic apply -f -
PGVector
sed "s|<DOCKER_REPO>|$DOCKER_REPO|" postgres-pgvector/manifests/03-rag/chatbot.yaml | kubectl -n pg-ns apply -f - sed "s|<DOCKER_REPO>|$DOCKER_REPO|" postgres-pgvector/manifests/03-rag/docs-embedder.yaml | kubectl -n pg-ns apply -f -
Weaviate
sed "s|<DOCKER_REPO>|$DOCKER_REPO|" weaviate/manifests/04-rag/chatbot.yaml | kubectl -n weaviate apply -f - sed "s|<DOCKER_REPO>|$DOCKER_REPO|" weaviate/manifests/04-rag/docs-embedder.yaml | kubectl -n weaviate apply -f -
GKE에 Eventarc 트리거를 사용 설정합니다.
gcloud eventarc gke-destinations init
메시지가 표시되면
y
를 입력합니다.Cloud Storage 버킷을 배포하고 Terraform을 사용하여 Eventarc 트리거를 만듭니다.
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token) terraform -chdir=vector-database/terraform/cloud-storage init terraform -chdir=vector-database/terraform/cloud-storage apply \ -var project_id=${PROJECT_ID} \ -var region=${REGION} \ -var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX} \ -var db_namespace=${DB_NAMESPACE}
메시지가 표시되면
yes
를 입력합니다. 명령어가 완료되는 데 몇 분 정도 걸릴 수 있습니다.Terraform에서 다음 리소스를 만듭니다.
- 문서를 업로드할 Cloud Storage 버킷
- Eventarc 트리거
- Eventarc를 사용할 권한이 있는
service_account_eventarc_name
이라는 Google Cloud 서비스 계정 - 버킷을 읽고 Vertex AI 모델에 액세스할 수 있는 권한이 있는
service_account_bucket_name
이라는 Google Cloud 서비스 계정
출력은 다음과 비슷합니다.
... # Several lines of output omitted Apply complete! Resources: 15 added, 0 changed, 0 destroyed. ... # Several lines of output omitted
문서 로드 및 챗봇 쿼리 실행
데모 문서를 업로드하고 쿼리를 실행하여 챗봇을 사용하여 데모 문서를 검색합니다.
버킷에 예시
carbon-free-energy.pdf
문서를 업로드합니다.gsutil cp vector-database/documents/carbon-free-energy.pdf gs://${PROJECT_ID}-${KUBERNETES_CLUSTER_PREFIX}-training-docs
문서 삽입기 작업이 성공적으로 완료되었는지 확인합니다.
kubectl get job -n ${DB_NAMESPACE}
출력은 다음과 비슷합니다.
NAME COMPLETIONS DURATION AGE docs-embedder1716570453361446 1/1 32s 71s
부하 분산기의 외부 IP 주소를 가져옵니다.
export EXTERNAL_IP=$(kubectl -n ${DB_NAMESPACE} get svc chatbot --output jsonpath='{.status.loadBalancer.ingress[0].ip}') echo http://${EXTERNAL_IP}:80
웹브라우저에서 외부 IP 주소를 엽니다.
http://EXTERNAL_IP
챗봇은 다음과 유사한 메시지로 응답합니다.
How can I help you?
업로드된 문서의 콘텐츠에 관해 질문합니다. 챗봇이 아무것도 찾을 수 없는 경우
I don't know
로 응답합니다. 예를 들어 다음과 같이 질문할 수 있습니다.You: Hi, what are Google plans for the future?
챗봇의 출력 예시는 다음과 같습니다.
Bot: Google intends to run on carbon-free energy everywhere, at all times by 2030. To achieve this, it will rely on a combination of renewable energy sources, such as wind and solar, and carbon-free technologies, such as battery storage.
업로드된 문서의 맥락과 관련 없는 내용을 챗봇에 질문합니다. 예를 들어 다음과 같이 질문할 수 있습니다.
You: What are Google plans to colonize Mars?
챗봇의 출력 예시는 다음과 같습니다.
Bot: I don't know. The provided context does not mention anything about Google's plans to colonize Mars.
애플리케이션 코드 정보
이 섹션에서는 애플리케이션 코드가 작동하는 방식을 설명합니다. Docker 이미지 내부에는 세 가지 스크립트가 있습니다.
endpoint.py
: 각 문서 업로드 시 Eventarc 이벤트를 수신하고 이를 처리하기 위한 Kubernetes 작업을 시작합니다.embedding-job.py
: 버킷에서 문서를 다운로드하고, 임베딩을 생성하고, 벡터 데이터베이스에 임베딩을 삽입합니다.chat.py
: 저장된 문서의 콘텐츠에 대해 쿼리를 실행합니다.
다음 다이어그램은 문서 데이터를 사용하여 답변을 생성하는 과정을 보여줍니다.
다이어그램에서 애플리케이션은 PDF 파일을 로드하고 파일을 청크로 분할한 다음 벡터로 변환한 후 벡터를 벡터 데이터베이스로 전송합니다. 나중에 사용자가 챗봇에 질문합니다. RAG 체인은 시맨틱 검색을 사용하여 벡터 데이터베이스를 검색한 후 질문과 함께 컨텍스트를 LLM에 반환합니다. LLM은 질문에 답변하고 질문을 채팅 기록에 저장합니다.
endpoint.py
정보
이 파일은 Eventarc의 메시지를 처리하고, 문서를 임베딩하기 위한 Kubernetes 작업을 만들고, 포트 5001에서 어디서나 요청을 수락합니다.
Qdrant
Elasticsearch
PGVector
Weaviate
embedding-job.py
정보
이 파일은 문서를 처리하고 벡터 데이터베이스로 전송합니다.
Qdrant
Elasticsearch
PGVector
Weaviate
chat.py
정보
이 파일은 제공된 컨텍스트와 이전 답변만 사용하여 질문에 답변하도록 모델을 구성합니다. 컨텍스트 또는 대화 기록이 데이터와 일치하지 않으면 모델은 I don't know
를 반환합니다.
Qdrant
Elasticsearch
PGVector
Weaviate
삭제
이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.
프로젝트 삭제
청구되지 않도록 하는 가장 쉬운 방법은 튜토리얼에서 만든 프로젝트를 삭제하는 것입니다.
Delete a Google Cloud project:
gcloud projects delete PROJECT_ID
프로젝트를 삭제하면 정리가 완료됩니다. 프로젝트를 삭제하지 않은 경우 개별 리소스 삭제를 진행합니다.
개별 리소스 삭제
Artifact Registry 저장소를 삭제합니다.
gcloud artifacts repositories delete ${KUBERNETES_CLUSTER_PREFIX}-images \ --location=${REGION} \ --async
메시지가 표시되면
y
를 입력합니다.Cloud Storage 버킷과 Eventarc 트리거를 삭제합니다.
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token) terraform -chdir=vector-database/terraform/cloud-storage destroy \ -var project_id=${PROJECT_ID} \ -var region=${REGION} \ -var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX} \ -var db_namespace=${DB_NAMESPACE}
메시지가 표시되면
yes
를 입력합니다.Eventarc를 사용하려면 생성 시와 삭제 시 모두 유효한 엔드포인트 타겟이 있어야 합니다.
다음 단계
- GKE의 데이터베이스 배포 권장사항 알아보기
- GKE를 사용하여 데이터 집약적인 워크로드를 실행하기 위한 솔루션 살펴보기