Neste tutorial, mostramos como integrar um aplicativo de modelo de linguagem grande (LLM, na sigla em inglês) baseado na geração aumentada de recuperação (RAG, na sigla em inglês) com arquivos PDF que você faz upload para um bucket do Cloud Storage.
Este guia usa um banco de dados como um mecanismo de armazenamento e de pesquisa semântica que armazena as representações (embeddings) dos documentos enviados. Você usa o framework Langchain para interagir com os embeddings e usa modelos do Gemini disponíveis na Vertex AI.
O Langchain é um framework Python de código aberto conhecido que simplifica muitas tarefas de machine learning e tem interfaces para integração com diferentes bancos de dados vetoriais e serviços de IA.
Este tutorial é destinado a administradores e arquitetos da plataforma de nuvem, engenheiros de ML e profissionais de MLOps (DevOps) interessados em implantar aplicativos RAG LLM no GKE e no Cloud Storage.
Criar um cluster
Crie um cluster do Qdrant, do Elasticsearch ou do Postgres:
Qdrant
Siga as instruções em Implantar um banco de dados de vetores Qdrant no GKE para criar um cluster do Qdrant em execução no modo Autopilot ou no modo padrão do cluster do GKE.
Elasticsearch
Siga as instruções em Implantar um banco de dados de vetores do Elasticsearch no GKE para criar um cluster do Elasticsearch em execução em um cluster do GKE no modo Autopilot ou padrão.
PGVector
Siga as instruções em Implantar um banco de dados de vetores PostgreSQL no GKE para criar um cluster do Postgres com o PGVector em execução em um cluster do GKE no modo Autopilot ou Standard.
Weaviate
Siga as instruções para implantar um banco de dados de vetores do Weaviate no GKE e criar um cluster do Weaviate em execução em um cluster do GKE no modo Autopilot ou Padrão.
Configurar o ambiente
Configure o ambiente com o Cloud Shell:
Defina as variáveis de ambiente do projeto:
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
Substitua
PROJECT_ID
pelo Google Cloud ID do projeto.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
Substitua
PROJECT_ID
pelo Google Cloud ID do projeto.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
Substitua
PROJECT_ID
pelo Google Cloud ID do projeto.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
Substitua
PROJECT_ID
pelo Google Cloud ID do projeto.Verifique se o cluster do GKE está em execução:
gcloud container clusters list --project=${PROJECT_ID} --location=${CONTROL_PLANE_LOCATION}
O resultado será assim:
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
Clone o repositório de exemplo de código do GitHub:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
Navegue até o diretório
databases
:cd kubernetes-engine-samples/databases
Preparar sua infraestrutura
Crie um repositório do Artifact Registry, gere imagens do Docker e envie imagens Docker para o Artifact Registry:
Crie um repositório do Artifact Registry:
gcloud artifacts repositories create ${KUBERNETES_CLUSTER_PREFIX}-images \ --repository-format=docker \ --location=${REGION} \ --description="Vector database images repository" \ --async
Defina as permissões
storage.objectAdmin
eartifactregistry.admin
na conta de serviço do Compute Engine para usar o Cloud Build para criar e enviar imagens Docker para os serviçosembed-docs
echatbot
.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"
Substitua
PROJECT_NUMBER
peloGoogle Cloud número do projeto.Crie imagens do Docker para os serviços
embed-docs
echatbot
. A imagemembed-docs
contém o código Python para o aplicativo que recebe solicitações de encaminhamento do Eventarc e o job de embedding.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
Verifique as imagens:
gcloud artifacts docker images list $DOCKER_REPO \ --project=$PROJECT_ID \ --format="value(IMAGE)"
O resultado será assim:
$REGION-docker.pkg.dev/$PROJECT_ID/${KUBERNETES_CLUSTER_PREFIX}-images/chatbot $REGION-docker.pkg.dev/$PROJECT_ID/${KUBERNETES_CLUSTER_PREFIX}-images/embed-docs
Implante uma conta de serviço do Kubernetes com permissões para executar jobs do 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 -
Ao usar o Terraform para criar o cluster do GKE e definir
create_service_account
como verdadeiro, uma conta de serviço separada será criada e usada pelo cluster e pelos nós. Conceda o papelartifactregistry.serviceAgent
a esta conta de serviço do Compute Engine para permitir que os nós extraiam a imagem do Artifact Registry criado paraembed-docs
echatbot
.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"
Sem o acesso à conta de serviço, os nós podem ter problemas de permissão ao tentar extrair a imagem do Artifact Registry ao implantar os serviços
embed-docs
echatbot
.Implante uma implantação do Kubernetes para os serviços
embed-docs
echatbot
. Uma implantação é um objeto da API Kubernetes que permite executar várias réplicas de pods distribuídos entre os nós de um cluster: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 -
Ative os gatilhos do Eventarc para o GKE:
gcloud eventarc gke-destinations init
Quando solicitado, digite
y
.Implante o bucket do Cloud Storage e crie um gatilho do Eventarc usando o Terraform:
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}
Quando solicitado, digite
yes
. O comando pode demorar uns minutos para ser executado.O Terraform cria os seguintes recursos:
- Um bucket do Cloud Storage para fazer upload dos documentos
- Um gatilho do Eventarc
- Uma conta de serviço do Google Cloud chamada
service_account_eventarc_name
com permissão para usar o Eventarc. - Uma conta de serviço do Google Cloud chamada
service_account_bucket_name
com permissão para ler o bucket e acessar modelos da Vertex AI.
O resultado será assim:
... # Several lines of output omitted Apply complete! Resources: 15 added, 0 changed, 0 destroyed. ... # Several lines of output omitted
Carregar documentos e executar consultas de chatbot
Faça upload dos documentos de demonstração e execute consultas para pesquisar nos documentos de demonstração usando o chatbot:
Faça upload do documento para o bucket
carbon-free-energy.pdf
:gcloud storage cp vector-database/documents/carbon-free-energy.pdf gs://${PROJECT_ID}-${KUBERNETES_CLUSTER_PREFIX}-training-docs
Verifique se o job de incorporação de documentos foi concluído:
kubectl get job -n ${DB_NAMESPACE}
O resultado será assim:
NAME COMPLETIONS DURATION AGE docs-embedder1716570453361446 1/1 32s 71s
Tenha o endereço IP externo do balanceador de carga:
export EXTERNAL_IP=$(kubectl -n ${DB_NAMESPACE} get svc chatbot --output jsonpath='{.status.loadBalancer.ingress[0].ip}') echo http://${EXTERNAL_IP}:80
Abra o endereço IP externo no navegador da Web:
http://EXTERNAL_IP
O chatbot responde com uma mensagem semelhante a esta:
How can I help you?
Faça perguntas sobre o conteúdo dos documentos enviados. Se o chatbot não encontrar nada, ele vai responder
I don't know
. Por exemplo, você pode perguntar o seguinte:You: Hi, what are Google plans for the future?
Um exemplo de saída do chatbot é semelhante ao seguinte:
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.
Faça uma pergunta ao chatbot que não esteja relacionada ao documento enviado. Por exemplo, pergunte:
You: What are Google plans to colonize Mars?
Um exemplo de saída do chatbot é semelhante ao seguinte:
Bot: I don't know. The provided context does not mention anything about Google's plans to colonize Mars.
Sobre o código do aplicativo
Esta seção explica como o código do aplicativo funciona. Há três scripts nas imagens Docker:
endpoint.py
: recebe eventos do Eventarc em cada upload de documento e inicia os jobs do Kubernetes para processá-los.embedding-job.py
: faz o download de documentos do bucket, cria embeddings e insere embeddings no banco de dados vetorial.chat.py
: executa consultas sobre o conteúdo dos documentos armazenados.
O diagrama mostra o processo de geração de respostas usando os dados dos documentos:
No diagrama, o aplicativo carrega um arquivo PDF, o divide em blocos, vetores e, em seguida, envia os vetores para um banco de dados de vetores. Mais tarde, um usuário faz uma pergunta ao chatbot. A cadeia RAG usa a pesquisa semântica para pesquisar o banco de dados de vetores e, em seguida, retorna o contexto com a pergunta para o LLM. O LLM responde à pergunta e a armazena no histórico de chat.
Sobre endpoint.py
Esse arquivo processa mensagens do Eventarc, cria um job do Kubernetes para incorporar o documento e aceita solicitações de qualquer lugar na porta 5001.
Qdrant
Elasticsearch
PGVector
Weaviate
Sobre embedding-job.py
Esse arquivo processa documentos e os envia para o banco de dados vetorial.
Qdrant
Elasticsearch
PGVector
Weaviate
Sobre chat.py
Esse arquivo configura o modelo para responder a perguntas usando apenas o contexto
fornecido e as respostas anteriores. Se o contexto ou o histórico de conversa não
corresponder a nenhum dado, o modelo vai retornar I don't know
.