1. Introducción
En este codelab, aprenderás a implementar EmbeddingGemma, un potente modelo de incorporación de texto multilingüe, en Cloud Run con GPUs. Luego, usarás este servicio implementado para generar embeddings para una aplicación de búsqueda semántica.
A diferencia de los modelos de lenguaje grandes (LLM) tradicionales que generan texto, los modelos de embeddings convierten el texto en vectores numéricos. Estos vectores son fundamentales para compilar sistemas de generación mejorada por recuperación (RAG), que te permiten encontrar los documentos más relevantes para la búsqueda de un usuario.
Actividades
- Crea un contenedor para el modelo EmbeddingGemma con Ollama.
- Implementa el contenedor en Cloud Run con aceleración por GPU.
- Prueba el modelo implementado generando embeddings para un texto de ejemplo.
- Crea un sistema de búsqueda semántica ligero con el servicio implementado.
Requisitos
- Un proyecto de Google Cloud con facturación habilitada.
- Conocimientos básicos de Docker y la línea de comandos
2. Antes de comenzar
Configuración del proyecto
- Si aún no tienes una Cuenta de Google, debes crear una.
- Usar una cuenta personal en lugar de una cuenta laboral o educativa Es posible que las cuentas laborales y educativas tengan restricciones que te impidan habilitar las APIs necesarias para este lab.
- Accede a la consola de Google Cloud.
- Habilita la facturación en la consola de Cloud.
- Completar este lab debería costar menos de USD 1 en recursos de Cloud.
- Puedes seguir los pasos al final de este lab para borrar recursos y evitar cargos adicionales.
- Los usuarios nuevos pueden acceder a la prueba gratuita de USD 300.
- Crea un proyecto nuevo o elige reutilizar uno existente.
- Si ves un error sobre la cuota del proyecto, reutiliza un proyecto existente o bórralo para crear uno nuevo.
Inicie Cloud Shell
Cloud Shell es un entorno de línea de comandos que se ejecuta en Google Cloud y que viene precargado con las herramientas necesarias.
- Haz clic en Activar Cloud Shell en la parte superior de la consola de Google Cloud.
- Una vez que te conectes a Cloud Shell, verifica tu autenticación:
gcloud auth list - Confirma que tu proyecto esté seleccionado:
gcloud config get project - Establécela si es necesario:
gcloud config set project <YOUR_PROJECT_ID>
Habilita las APIs
Ejecuta este comando para habilitar todas las APIs requeridas:
gcloud services enable \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com
3. Crea un contenedor para el modelo
Para ejecutar EmbeddingGemma de forma sin servidores, debemos empaquetarlo en un contenedor. Usaremos Ollama, un framework ligero para ejecutar LLM, y Docker.
Crea el Dockerfile
En Cloud Shell, crea un directorio nuevo para tu proyecto y navega hasta él:
mkdir embedding-gemma-codelab
cd embedding-gemma-codelab
Crea un archivo llamado Dockerfile con el siguiente contenido:
FROM ollama/ollama:latest
# Listen on all interfaces, port 8080
ENV OLLAMA_HOST=0.0.0.0:8080
# Store model weight files in /models
ENV OLLAMA_MODELS=/models
# Reduce logging verbosity
ENV OLLAMA_DEBUG=false
# Never unload model weights from the GPU
ENV OLLAMA_KEEP_ALIVE=-1
# Store the model weights in the container image
ENV MODEL=embeddinggemma:latest
RUN ollama serve & sleep 5 && ollama pull $MODEL
# Start Ollama
ENTRYPOINT ["ollama", "serve"]
Este Dockerfile hace lo siguiente:
- Comienza con la imagen base oficial de Ollama.
- Configura Ollama para que escuche en el puerto 8080 (el valor predeterminado de Cloud Run).
- El comando
RUNinicia el servidorollamay descarga el modeloembeddinggemmadurante el proceso de compilación para que se incluya en la imagen. - Establece
OLLAMA_KEEP_ALIVE=-1para garantizar que el modelo permanezca cargado en la memoria de la GPU y, así, acelerar las solicitudes posteriores.
4. Compile e implemente
Usaremos la implementación de código fuente de Cloud Run para compilar e implementar nuestro contenedor en un solo paso. Este comando compila la imagen con Cloud Build, la almacena en Artifact Registry y la implementa en Cloud Run.
Ejecuta el siguiente comando para realizar la implementación:
gcloud run deploy embedding-gemma \
--source . \
--region europe-west1 \
--concurrency 4 \
--cpu 8 \
--set-env-vars OLLAMA_NUM_PARALLEL=4 \
--gpu 1 \
--gpu-type nvidia-l4 \
--max-instances 1 \
--memory 32Gi \
--no-allow-unauthenticated \
--no-cpu-throttling \
--no-gpu-zonal-redundancy \
--timeout=600 \
--labels dev-tutorial=codelab-embedding-gemma
Comprende la configuración
--source .especifica el directorio actual como la fuente de la compilación.--region europe-west1usamos una región que admite GPUs en Cloud Run.--concurrency 4se configura para que coincida con el valor de la variable de entorno OLLAMA_NUM_PARALLEL.--gpu 1con--gpu-type nvidia-l4asigna 1 GPU NVIDIA L4 a cada instancia de Cloud Run en el servicio.--max-instances 1especifica la cantidad máxima de instancias a las que se puede escalar. Debe ser igual o inferior a la cuota de GPU NVIDIA L4 de tu proyecto.--no-allow-unauthenticatedrestringe el acceso no autenticado al servicio. Si mantienes el servicio privado, puedes confiar en la autenticación integrada de Identity and Access Management (IAM) de Cloud Run para la comunicación entre servicios.- Se requiere
--no-cpu-throttlingpara habilitar la GPU. --no-gpu-zonal-redundancyestablece opciones de redundancia zonal según tus requisitos de conmutación por error zonal y la cuota disponible.
Consideraciones de región
Las GPUs en Cloud Run están disponibles en regiones específicas. Puedes consultar las regiones admitidas en la documentación.
Resultado de la implementación
Después de unos minutos, se completará la implementación y verás un mensaje como el siguiente:
Service [embedding-gemma] revision [embedding-gemma-12345-abc] has been deployed and is serving 100 percent of traffic. Service URL: https://embedding-gemma-123456789012.europe-west1.run.app
5. Prueba la implementación
Como implementamos el servicio con --no-allow-unauthenticated, no podemos simplemente curl la URL pública. Primero, debemos otorgarnos permiso para acceder al servicio y usar el token de autenticación en la solicitud.
- Otorga permiso a tu cuenta de usuario para llamar al servicio:
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \ --member=user:$(gcloud config get-value account) \ --role='roles/run.invoker' - Guarda tus credenciales de Google Cloud y el número de proyecto en variables de entorno para usarlos en la solicitud:
export PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format="value(projectNumber)") export ID_TOKEN=$(gcloud auth print-identity-token) - Ejecuta el siguiente comando para generar una incorporación para "Texto de ejemplo":
curl -X POST "https://embedding-gemma-$PROJECT_NUMBER.europe-west1.run.app/api/embed" \ -H "Authorization: Bearer $ID_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "model": "embeddinggemma", "input": "Sample text" }'
Deberías ver una respuesta JSON que contiene un vector (una lista larga de números) en el campo embedding. Esto confirma que tu modelo de incorporación sin servidores respaldado por GPU funciona.
La respuesta se verá similar a la siguiente: 
Cliente de Python
También puedes usar Python para interactuar con el servicio. Crea un archivo llamado test_client.py:
import urllib.request
import urllib.parse
import json
import os
# 1. Setup the URL and Payload
url = f"https://embedding-gemma-{os.environ['PROJECT_NUMBER']}.europe-west1.run.app/api/embed"
payload = {
"model": "embeddinggemma",
"input": "Sample text"
}
# 2. Create the Request object
# Note: Providing 'data' automatically makes this a POST request
req = urllib.request.Request(
url,
data=json.dumps(payload).encode("utf-8"),
headers={
"Authorization": f"Bearer {os.environ['ID_TOKEN']}",
"Content-Type": "application/json"
}
)
# 3. Execute and print the response
response = urllib.request.urlopen(req)
result = json.loads(response.read().decode("utf-8"))
print(result)
Ejecútalo:
python test_client.py
6. Crea una aplicación de búsqueda semántica
Ahora que tenemos un servicio de embeddings en funcionamiento, compilemos una aplicación simple de búsqueda semántica. Usaremos los embeddings generados para encontrar el documento más relevante para una búsqueda determinada.
Dependencias
Usaremos chromadb como nuestra base de datos de vectores y la biblioteca cliente ollama.
uv init semantic-search --description "Semantic Search Application"
cd semantic-search
uv add chromadb ollama
Crea la aplicación de búsqueda
Crea un archivo llamado semantic_search.py con el siguiente código:
import ollama
import chromadb
import os
# 1. Define our knowledge base
documents = [
"Poland is a country located in Central Europe.",
"The capital and largest city of Poland is Warsaw.",
"Poland's official language is Polish, which is a West Slavic language.",
"Marie Curie, the pioneering scientist who conducted groundbreaking research on radioactivity, was born in Warsaw, Poland.",
"Poland is famous for its traditional dish called pierogi, which are filled dumplings.",
"The Białowieża Forest in Poland is one of the last and largest remaining parts of the immense primeval forest that once stretched across the European Plain.",
]
print("Initializing Vector Database...")
client = chromadb.Client()
collection = client.create_collection(name="docs")
# Configure the client to point to our Cloud Run proxy
ollama_client = ollama.Client(
host=f"https://embedding-gemma-{os.environ['PROJECT_NUMBER']}.europe-west1.run.app",
headers={'Authorization': 'Bearer ' + os.environ['ID_TOKEN']}
)
print("Generating embeddings and indexing documents...")
# 2. Store each document in the vector database
for i, d in enumerate(documents):
# This calls our Cloud Run service to get the embedding
response = ollama_client.embed(model="embeddinggemma", input=d)
embeddings = response["embeddings"]
collection.add(ids=[str(i)], embeddings=embeddings, documents=[d])
print("Indexing complete.\n")
# 3. Perform a Semantic Search
question = "What is Poland's official language?"
print(f"Query: {question}")
# Generate an embedding for the question
response = ollama_client.embed(model="embeddinggemma", input=question)
# Query the database for the most similar document
results = collection.query(
query_embeddings=[response["embeddings"][0]],
n_results=1
)
best_match = results["documents"][0][0]
print(f"Best Match Document: {best_match}")
Cómo ejecutar la aplicación
Ejecute la siguiente secuencia de comandos:
uv run semantic_search.py
Deberías ver un resultado similar a esto:
Initializing Vector Database...
Generating embeddings and indexing documents...
Indexing complete.
Query: What is Poland's official language?
Best Match Document: Poland's official language is Polish, which is a West Slavic language.
En este instructivo, se muestra el núcleo de un sistema RAG: usar tu servicio EmbeddingGemma sin servidor para convertir documentos y búsquedas en vectores, lo que te permite encontrar la información exacta que necesitas para responder la pregunta de un usuario.
7. Limpia
Para evitar que se apliquen cargos a tu cuenta de Google Cloud, borra los recursos que creaste durante este codelab.
Borra el servicio de Cloud Run
gcloud run services delete embedding-gemma --region europe-west1 --quiet
Borra la imagen de contenedor
gcloud artifacts docker images delete \
europe-west1-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/cloud-run-source-deploy/embedding-gemma \
--quiet
8. Felicitaciones
¡Felicitaciones! Implementaste correctamente EmbeddingGemma en Cloud Run con GPUs y lo usaste para potenciar una aplicación de búsqueda semántica.
Ahora tienes una base escalable y sin servidores para crear aplicaciones de IA que requieren comprender el significado del texto.
Qué aprendiste
- Cómo organizar un modelo de Ollama en contenedores con Docker
- Cómo implementar un servicio habilitado para GPU en Cloud Run
- Cómo usar el modelo implementado para la búsqueda semántica (RAG)
Próximos pasos
- Explora otros modelos de la familia Gemma.
- Obtén más información sobre las GPUs de Cloud Run.
- Explora otros Codelabs de Cloud Run.
- Crea una canalización de RAG completa conectando este paso de recuperación a un modelo generativo.