En este tutorial se muestra cómo integrar una aplicación de modelo de lenguaje extenso (LLM) basada en la generación aumentada por recuperación (RAG) con archivos PDF que subas a un segmento de Cloud Storage.
En esta guía se usa una base de datos como motor de almacenamiento y de búsqueda semántica que contiene las representaciones (incrustaciones) de los documentos subidos. Usas el framework Langchain para interactuar con las inserciones y los modelos de Gemini disponibles a través de Vertex AI.
Langchain es un popular framework de Python de código abierto que simplifica muchas tareas de aprendizaje automático y tiene interfaces para integrarse con diferentes bases de datos vectoriales y servicios de IA.
Este tutorial está dirigido a administradores y arquitectos de plataformas en la nube, ingenieros de aprendizaje automático y profesionales de MLOps (DevOps) que quieran desplegar aplicaciones de LLMs de RAG en GKE y Cloud Storage.
Crear un clúster
Crea un clúster de Qdrant, Elasticsearch o Postgres:
Qdrant
Sigue las instrucciones de Desplegar una base de datos de vectores Qdrant en GKE para crear un clúster de Qdrant que se ejecute en un clúster de GKE en modo Autopilot o Estándar.
Elasticsearch
Sigue las instrucciones de Desplegar una base de datos de vectores de Elasticsearch en GKE para crear un clúster de Elasticsearch que se ejecute en un clúster de GKE en modo Autopilot o Estándar.
PGVector
Sigue las instrucciones de Desplegar una base de datos de vectores de PostgreSQL en GKE para crear un clúster de PostgreSQL con PGVector en un clúster de GKE en modo Autopilot o Estándar.
Weaviate
Sigue las instrucciones para desplegar una base de datos de vectores de Weaviate en GKE y crear un clúster de Weaviate que se ejecute en un clúster de GKE en modo Autopilot o Estándar.
Configurar un entorno
Configura tu entorno con Cloud Shell:
Define las variables de entorno de tu proyecto:
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
Sustituye
PROJECT_ID
por elGoogle Cloud ID de tu proyecto.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
Sustituye
PROJECT_ID
por elGoogle Cloud ID de tu proyecto.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
Sustituye
PROJECT_ID
por elGoogle Cloud ID de tu proyecto.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
Sustituye
PROJECT_ID
por elGoogle Cloud ID de tu proyecto.Comprueba que tu clúster de GKE se esté ejecutando:
gcloud container clusters list --project=${PROJECT_ID} --location=${CONTROL_PLANE_LOCATION}
El resultado debería ser similar al siguiente:
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
Clona el repositorio de código de ejemplo de GitHub:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
Ve al directorio
databases
:cd kubernetes-engine-samples/databases
Preparar la infraestructura
Crea un repositorio de Artifact Registry, compila imágenes Docker y envíalas a Artifact Registry:
Crea un repositorio de Artifact Registry:
gcloud artifacts repositories create ${KUBERNETES_CLUSTER_PREFIX}-images \ --repository-format=docker \ --location=${REGION} \ --description="Vector database images repository" \ --async
Define los permisos
storage.objectAdmin
yartifactregistry.admin
en la cuenta de servicio de Compute Engine para usar Cloud Build con el fin de compilar y enviar imágenes Docker para los serviciosembed-docs
ychatbot
.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"
Sustituye
PROJECT_NUMBER
por elGoogle Cloud número de tu proyecto.Crea imágenes Docker para los servicios
embed-docs
ychatbot
. La imagenembed-docs
contiene código de Python para la aplicación que recibe solicitudes del reenviador de Eventarc y el trabajo de inserción.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
Verifica las imágenes:
gcloud artifacts docker images list $DOCKER_REPO \ --project=$PROJECT_ID \ --format="value(IMAGE)"
El resultado debería ser similar al siguiente:
$REGION-docker.pkg.dev/$PROJECT_ID/${KUBERNETES_CLUSTER_PREFIX}-images/chatbot $REGION-docker.pkg.dev/$PROJECT_ID/${KUBERNETES_CLUSTER_PREFIX}-images/embed-docs
Despliega una cuenta de servicio de Kubernetes con permisos para ejecutar trabajos de 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 -
Cuando se usa Terraform para crear el clúster de GKE y se define
create_service_account
como true, el clúster y los nodos crearán y usarán una cuenta de servicio independiente. Concede el rolartifactregistry.serviceAgent
a esta cuenta de servicio de Compute Engine para permitir que los nodos extraigan imágenes del registro de Artifact Registry creado paraembed-docs
ychatbot
.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"
Si no concedes acceso a la cuenta de servicio, es posible que tus nodos tengan problemas de permisos al intentar extraer imágenes de Artifact Registry al implementar los servicios
embed-docs
ychatbot
.Despliega un Deployment de Kubernetes para los servicios
embed-docs
ychatbot
. Un Deployment es un objeto de la API de Kubernetes que te permite ejecutar varias réplicas de pods distribuidas entre los nodos de un clúster: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 -
Habilita los activadores de Eventarc para GKE:
gcloud eventarc gke-destinations init
Cuando se te solicite, introduce
y
.Despliega el segmento de Cloud Storage y crea un activador de Eventarc con 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}
Cuando se te solicite, escribe
yes
. El comando puede tardar varios minutos en completarse.Terraform crea los siguientes recursos:
- Un segmento de Cloud Storage para subir los documentos
- Un activador de Eventarc
- Una Google Cloud cuenta de servicio
service_account_eventarc_name
con permiso para usar Eventarc. - Una Google Cloud cuenta de servicio
service_account_bucket_name
con permiso para leer el segmento y acceder a los modelos de Vertex AI.
El resultado debería ser similar al siguiente:
... # Several lines of output omitted Apply complete! Resources: 15 added, 0 changed, 0 destroyed. ... # Several lines of output omitted
Cargar documentos y ejecutar consultas de chatbot
Sube los documentos de demostración y ejecuta consultas para buscar en ellos con el chatbot:
Sube el documento de ejemplo
carbon-free-energy.pdf
a tu segmento:gcloud storage cp vector-database/documents/carbon-free-energy.pdf gs://${PROJECT_ID}-${KUBERNETES_CLUSTER_PREFIX}-training-docs
Verifica que el trabajo de insertador de documentos se haya completado correctamente:
kubectl get job -n ${DB_NAMESPACE}
El resultado debería ser similar al siguiente:
NAME COMPLETIONS DURATION AGE docs-embedder1716570453361446 1/1 32s 71s
Obtén la dirección IP externa del 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
Abre la dirección IP externa en tu navegador web:
http://EXTERNAL_IP
El chatbot responde con un mensaje similar al siguiente:
How can I help you?
Hacer preguntas sobre el contenido de los documentos subidos. Si el chatbot no encuentra nada, responde
I don't know
. Por ejemplo, puedes hacer las siguientes preguntas:You: Hi, what are Google plans for the future?
Un ejemplo de respuesta del chatbot sería similar al siguiente:
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.
Hazle al chatbot una pregunta que no esté relacionada con el documento subido. Por ejemplo, puedes hacer las siguientes preguntas:
You: What are Google plans to colonize Mars?
Un ejemplo de respuesta del chatbot sería similar al siguiente:
Bot: I don't know. The provided context does not mention anything about Google's plans to colonize Mars.
Acerca del código de aplicación
En esta sección se explica cómo funciona el código de la aplicación. Hay tres secuencias de comandos en las imágenes de Docker:
endpoint.py
: recibe eventos de Eventarc en cada documento que se sube e inicia los trabajos de Kubernetes para procesarlos.embedding-job.py
: descarga documentos del bucket, crea las inserciones e inserta las inserciones en la base de datos vectorial.chat.py
: ejecuta consultas sobre el contenido de los documentos almacenados.
En el diagrama se muestra el proceso de generación de respuestas a partir de los datos de los documentos:
En el diagrama, la aplicación carga un archivo PDF, lo divide en fragmentos y, a continuación, en vectores, y envía los vectores a una base de datos de vectores. Más adelante, un usuario le hace una pregunta al chatbot. La cadena RAG usa la búsqueda semántica para buscar en la base de datos de vectores y, a continuación, devuelve el contexto junto con la pregunta al LLM. El LLM responde a la pregunta y la almacena en el historial del chat.
Acerca de endpoint.py
Este archivo procesa mensajes de Eventarc, crea un trabajo de Kubernetes para insertar el documento y acepta solicitudes desde cualquier lugar en el puerto 5001.
Qdrant
Elasticsearch
PGVector
Weaviate
Acerca de embedding-job.py
Este archivo procesa documentos y los envía a la base de datos vectorial.
Qdrant
Elasticsearch
PGVector
Weaviate
Acerca de chat.py
Este archivo configura el modelo para que responda a las preguntas usando solo el contexto proporcionado y las respuestas anteriores. Si el contexto o el historial de la conversación no coinciden con ningún dato, el modelo devuelve I don't know
.