이 튜토리얼에서는 검색 증강 생성(RAG)을 기반으로 하는 대규모 언어 모델(LLM) 애플리케이션을 Cloud Storage 버킷에 업로드하는 PDF 파일과 통합하는 방법을 보여줍니다.
이 가이드에서는 데이터베이스를 업로드된 문서의 표현(임베딩)을 보유하는 스토리지 및 시맨틱 검색엔진으로 사용합니다. Langchain 프레임워크를 사용하여 임베딩과 상호작용하고 Vertex AI를 통해 제공되는 Gemini 모델을 사용합니다.
Langchain은 여러 머신러닝 태스크를 간소화하고 다양한 벡터 데이터베이스 및 AI 서비스와 통합할 수 있는 인터페이스가 있는 인기 있는 오픈소스 Python 프레임워크입니다.
이 튜토리얼은 GKE 및 Cloud Storage에 RAG LLM 애플리케이션을 배포하는 데 관심이 있는 클라우드 플랫폼 관리자 및 설계자, ML 엔지니어, MLOps(DevOps) 전문가를 대상으로 합니다.
클러스터 만들기
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 CONTROL_PLANE_LOCATION=us-central1 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 CONTROL_PLANE_LOCATION=us-central1 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 CONTROL_PLANE_LOCATION=us-central1 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 CONTROL_PLANE_LOCATION=us-central1 export REGION=us-central1 export DB_NAMESPACE=weaviate
PROJECT_ID
를Google Cloud 프로젝트 ID로 바꿉니다.GKE 클러스터 실행 여부를 확인합니다.
gcloud container clusters list --project=${PROJECT_ID} --location=${CONTROL_PLANE_LOCATION}
출력은 다음과 비슷합니다.
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 \ --location=${CONTROL_PLANE_LOCATION} \ --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 배포를 배포합니다. 배포는 클러스터에서 노드 간에 배포되는 여러 포드 복제본을 실행할 수 있는 Kubernetes API 객체입니다.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를 사용할 권한이 있는 Google Cloud 서비스 계정(이름:
service_account_eventarc_name
) - 버킷을 읽고 Vertex AI 모델에 액세스할 수 있는 권한이 있는 Google Cloud 서비스 계정(이름:
service_account_bucket_name
)
출력은 다음과 비슷합니다.
... # Several lines of output omitted Apply complete! Resources: 15 added, 0 changed, 0 destroyed. ... # Several lines of output omitted
문서 로드 및 챗봇 쿼리 실행
데모 문서를 업로드하고 쿼리를 실행하여 챗봇을 사용하여 데모 문서를 검색합니다.
버킷에 예시
carbon-free-energy.pdf
문서를 업로드합니다.gcloud storage 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
를 반환합니다.