Questo tutorial mostra come integrare un'applicazione basata su un modello linguistico di grandi dimensioni (LLM) con generazione RAG (Retrieval-Augmented Generation) con file PDF che carichi in un bucket Cloud Storage.
Questa guida utilizza un database come motore di archiviazione e ricerca semantica che contiene le rappresentazioni (embedding) dei documenti caricati. Utilizzi il framework Langchain per interagire con gli incorporamenti e utilizzi i modelli Gemini disponibili tramite Vertex AI.
Langchain è un framework Python open source molto diffuso che semplifica molte attività di machine learning e dispone di interfacce per l'integrazione con diversi servizi di AI e database vettoriali.
Questo tutorial è destinato ad amministratori e architetti di piattaforme cloud, ingegneri ML e professionisti MLOps (DevOps) interessati al deployment di applicazioni LLM RAG in GKE e Cloud Storage.
Crea un cluster
Crea un cluster Qdrant, Elasticsearch o Postgres:
Qdrant
Segui le istruzioni riportate in Esegui il deployment di un database vettoriale Qdrant su GKE per creare un cluster Qdrant in esecuzione su un cluster GKE in modalità Autopilot o Standard.
Elasticsearch
Segui le istruzioni riportate in Esegui il deployment di un database vettoriale Elasticsearch su GKE per creare un cluster Elasticsearch in esecuzione su un cluster GKE in modalità Autopilot o Standard.
PGVector
Segui le istruzioni riportate in Esegui il deployment di un database vettoriale PostgreSQL su GKE per creare un cluster Postgres con PGVector in esecuzione su un cluster GKE in modalità Autopilot o standard.
Weaviate
Segui le istruzioni per eseguire il deployment di un database vettoriale Weaviate su GKE per creare un cluster Weaviate in esecuzione su un cluster GKE in modalità Autopilot o Standard.
Configura l'ambiente
Configura l'ambiente con Cloud Shell:
Imposta le variabili di ambiente per il tuo progetto:
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
Sostituisci
PROJECT_ID
con l'Google Cloud ID progetto.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
Sostituisci
PROJECT_ID
con l'Google Cloud ID progetto.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
Sostituisci
PROJECT_ID
con l'Google Cloud ID progetto.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
Sostituisci
PROJECT_ID
con l'Google Cloud ID progetto.Verifica che il cluster GKE sia in esecuzione:
gcloud container clusters list --project=${PROJECT_ID} --location=${CONTROL_PLANE_LOCATION}
L'output è simile al seguente:
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 il repository del codice campione da GitHub:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
Vai alla directory
databases
:cd kubernetes-engine-samples/databases
Prepara l'infrastruttura
Crea un repository Artifact Registry, crea immagini Docker ed esegui il push delle immagini Docker in Artifact Registry:
Crea un repository Artifact Registry:
gcloud artifacts repositories create ${KUBERNETES_CLUSTER_PREFIX}-images \ --repository-format=docker \ --location=${REGION} \ --description="Vector database images repository" \ --async
Imposta le autorizzazioni
storage.objectAdmin
eartifactregistry.admin
sul account di servizio Compute Engine per utilizzare Cloud Build per creare ed eseguire il push delle immagini Docker per i serviziembed-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"
Sostituisci
PROJECT_NUMBER
con il numero del tuo progettoGoogle Cloud .Crea immagini Docker per i servizi
embed-docs
echatbot
. L'immagineembed-docs
contiene il codice Python sia per l'applicazione che riceve le richieste di inoltro di Eventarc sia per il job di incorporamento.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 le immagini:
gcloud artifacts docker images list $DOCKER_REPO \ --project=$PROJECT_ID \ --format="value(IMAGE)"
L'output è simile al seguente:
$REGION-docker.pkg.dev/$PROJECT_ID/${KUBERNETES_CLUSTER_PREFIX}-images/chatbot $REGION-docker.pkg.dev/$PROJECT_ID/${KUBERNETES_CLUSTER_PREFIX}-images/embed-docs
Esegui il deployment di un service account Kubernetes con le autorizzazioni per eseguire i job 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 -
Quando utilizzi Terraform per creare il cluster GKE e hai impostato
create_service_account
su true, verrà creato e utilizzato un account di servizio separato dal cluster e dai nodi. Concedi il ruoloartifactregistry.serviceAgent
a questo account di servizio Compute Engine per consentire ai nodi di estrarre l'immagine da Artifact Registry creata perembed-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"
Se non concedi l'accesso al account di servizio, i tuoi nodi potrebbero riscontrare un problema di autorizzazione quando tentano di estrarre l'immagine da Artifact Registry durante il deployment dei servizi
embed-docs
echatbot
.Esegui il deployment di un deployment Kubernetes per i servizi
embed-docs
echatbot
. Un deployment è un oggetto API Kubernetes che ti consente di eseguire più repliche di pod distribuite tra i nodi di un 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 -
Abilita i trigger Eventarc per GKE:
gcloud eventarc gke-destinations init
Quando richiesto, inserisci
y
.Esegui il deployment del bucket Cloud Storage e crea un trigger Eventarc utilizzando 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 richiesto, digita
yes
. Il completamento del comando potrebbe richiedere diversi minuti.Terraform crea le seguenti risorse:
- Un bucket Cloud Storage in cui caricare i documenti
- Un trigger Eventarc
- Un Google Cloud service account denominato
service_account_eventarc_name
con l'autorizzazione a utilizzare Eventarc. - Un Google Cloud service account denominato
service_account_bucket_name
con l'autorizzazione a leggere il bucket e accedere ai modelli Vertex AI.
L'output è simile al seguente:
... # Several lines of output omitted Apply complete! Resources: 15 added, 0 changed, 0 destroyed. ... # Several lines of output omitted
Caricare documenti ed eseguire query del chatbot
Carica i documenti demo ed esegui query per cercare nei documenti demo utilizzando il chatbot:
Carica il documento di esempio
carbon-free-energy.pdf
nel bucket:gcloud storage cp vector-database/documents/carbon-free-energy.pdf gs://${PROJECT_ID}-${KUBERNETES_CLUSTER_PREFIX}-training-docs
Verifica che il job di incorporamento dei documenti sia stato completato correttamente:
kubectl get job -n ${DB_NAMESPACE}
L'output è simile al seguente:
NAME COMPLETIONS DURATION AGE docs-embedder1716570453361446 1/1 32s 71s
Ottieni l'indirizzo IP esterno del bilanciatore del carico:
export EXTERNAL_IP=$(kubectl -n ${DB_NAMESPACE} get svc chatbot --output jsonpath='{.status.loadBalancer.ingress[0].ip}') echo http://${EXTERNAL_IP}:80
Apri l'indirizzo IP esterno nel browser web:
http://EXTERNAL_IP
Il chatbot risponde con un messaggio simile al seguente:
How can I help you?
Fare domande sui contenuti dei documenti caricati. Se il chatbot non trova nulla, risponde
I don't know
. Ad esempio, potresti chiedere quanto segue:You: Hi, what are Google plans for the future?
Un esempio di output del chatbot è simile al seguente:
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.
Fare al chatbot una domanda che non riguarda il contesto del documento caricato. Ad esempio, potresti chiedere quanto segue:
You: What are Google plans to colonize Mars?
Un esempio di output del chatbot è simile al seguente:
Bot: I don't know. The provided context does not mention anything about Google's plans to colonize Mars.
Informazioni sul codice dell'applicazione
Questa sezione spiega come funziona il codice dell'applicazione. All'interno delle immagini Docker sono presenti tre script:
endpoint.py
: riceve gli eventi Eventarc a ogni caricamento del documento e avvia i job Kubernetes per elaborarli.embedding-job.py
: scarica i documenti dal bucket, crea gli embedding e li inserisce nel database vettoriale.chat.py
: esegue query sui contenuti dei documenti archiviati.
Il diagramma mostra il processo di generazione delle risposte utilizzando i dati dei documenti:
Nel diagramma, l'applicazione carica un file PDF, lo suddivide in blocchi, poi in vettori e infine invia i vettori a un database vettoriale. In un secondo momento, un utente pone una domanda al chatbot. La catena RAG utilizza la ricerca semantica per cercare nel database vettoriale, quindi restituisce il contesto insieme alla domanda all'LLM. L'LLM risponde alla domanda e la memorizza nella cronologia della chat.
Informazioni su endpoint.py
Questo file elabora i messaggi di Eventarc, crea un job Kubernetes per incorporare il documento e accetta richieste da qualsiasi posizione sulla porta 5001
Qdrant
Elasticsearch
PGVector
Weaviate
Informazioni su embedding-job.py
Questo file elabora i documenti e li invia al database vettoriale.
Qdrant
Elasticsearch
PGVector
Weaviate
Informazioni su chat.py
Questo file configura il modello in modo che risponda alle domande utilizzando solo il contesto fornito e le risposte precedenti. Se il contesto o la cronologia della conversazione non
corrispondono ad alcun dato, il modello restituisce I don't know
.