1. Introducción
En este codelab, aprenderás a usar AlloyDB AI combinando la búsqueda vectorial con los embeddings de Vertex AI. Este lab forma parte de una colección de labs dedicados a las funciones de AlloyDB AI. Puedes obtener más información en la página de AlloyDB AI en la documentación.

Requisitos previos
- Conocimientos básicos sobre Google Cloud y la consola
- Habilidades básicas con la interfaz de línea de comandos y Cloud Shell
Qué aprenderás
- Cómo implementar un clúster y una instancia principal de AlloyDB
- Cómo conectarse a AlloyDB desde una VM de Google Compute Engine
- Cómo crear una base de datos y habilitar AlloyDB AI
- Cómo cargar datos en la base de datos
- Cómo usar AlloyDB Studio
- Cómo usar el modelo de incorporación de Gemini Enterprise Agent Platform en AlloyDB
- Cómo usar Gemini Enterprise Agent Platform Studio
- Cómo enriquecer el resultado con el modelo generativo de Gemini Enterprise Agent Platform
- Cómo mejorar el rendimiento con el índice de vectores
Requisitos
- Una cuenta de Google Cloud y un proyecto de Google Cloud
- Un navegador web, como Chrome
2. Configuración y requisitos
Configuración del proyecto
- Accede a la consola de Google Cloud. Si aún no tienes una cuenta de Gmail o de Google Workspace, debes crear una.
Usa una cuenta personal en lugar de una cuenta laboral o educativa.
- Crea un proyecto nuevo o reutiliza uno existente. Para crear un proyecto nuevo en la consola de Google Cloud, haz clic en el botón Seleccionar un proyecto del encabezado, que abrirá una ventana emergente.

En la ventana Select a project, presiona el botón New Project, que abrirá un cuadro de diálogo para el proyecto nuevo.

En el cuadro de diálogo, ingresa el nombre del proyecto que prefieras y elige la ubicación.

- El Nombre del proyecto es el nombre visible de los participantes de este proyecto. El nombre del proyecto no se usa en las APIs de Google y se puede cambiar en cualquier momento.
- El ID del proyecto es único en todos los proyectos de Google Cloud y es inmutable (no se puede cambiar después de configurarlo). La consola de Google Cloud genera automáticamente un ID único, pero puedes personalizarlo. Si no te gusta el ID generado, puedes generar otro aleatorio o proporcionar el tuyo para verificar su disponibilidad. En la mayoría de los codelabs, deberás hacer referencia al ID del proyecto, que suele identificarse con el marcador de posición PROJECT_ID.
- Recuerda que hay un tercer valor, un número de proyecto, que usan algunas APIs. Obtén más información sobre estos tres valores en la documentación.
Habilitar facturación
Configura una cuenta de facturación personal
Si configuraste la facturación con créditos de Google Cloud, puedes omitir este paso.
Para configurar una cuenta de facturación personal, ve aquí para habilitar la facturación en la consola de Cloud.
Algunas notas:
- Completar este lab debería costar menos de USD 3 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.
Inicia Cloud Shell
Si bien Google Cloud y Spanner se pueden operar de manera remota desde tu laptop, en este codelab usarás Google Cloud Shell, un entorno de línea de comandos que se ejecuta en la nube.
En Google Cloud Console, haz clic en el ícono de Cloud Shell en la barra de herramientas en la parte superior derecha:

También puedes presionar G y, luego, S. Esta secuencia activará Cloud Shell si estás en la consola de Google Cloud o usas este vínculo.
El aprovisionamiento y la conexión al entorno deberían tomar solo unos minutos. Cuando termine el proceso, debería ver algo como lo siguiente:

Esta máquina virtual está cargada con todas las herramientas de desarrollo que necesitarás. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que permite mejorar considerablemente el rendimiento de la red y la autenticación. Todo tu trabajo en este codelab se puede hacer en un navegador. No es necesario que instales nada.
3. Antes de comenzar
Habilita la API
Resultado:
Para usar AlloyDB, Compute Engine, servicios de redes y Gemini Enterprise Agent Platform, debes habilitar sus respectivas APIs en tu proyecto de Google Cloud.
Habilita las API
En Cloud Shell, en la terminal, asegúrate de que tu ID del proyecto esté configurado:
gcloud config set project [YOUR-PROJECT-ID]
Configura la variable de entorno PROJECT_ID:
PROJECT_ID=$(gcloud config get-value project)
Habilita todas las APIs necesarias:
gcloud services enable alloydb.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
servicenetworking.googleapis.com \
aiplatform.googleapis.com
Resultado esperado
student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417
Updated property [core/project].
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project)
Your active configuration is: [cloudshell-14650]
student@cloudshell:~ (test-project-001-402417)$
student@cloudshell:~ (test-project-001-402417)$ gcloud services enable alloydb.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
servicenetworking.googleapis.com \
aiplatform.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.
Puedes leer sobre cada API habilitada en la documentación.
4. Implementa AlloyDB
Antes de crear un clúster de AlloyDB, asigna un rango de IP privada disponible en tu VPC para que lo utilice la instancia futura de AlloyDB. Si no la tienes, debes crearla, asignarla para que la usen los servicios internos de Google y, luego, podrás crear el clúster y la instancia.
Crea un rango de IP privada
Debes establecer la configuración del acceso privado a servicios en nuestra VPC para AlloyDB. Aquí, suponemos que tienes la red de VPC “predeterminada” en el proyecto y que se utilizará para todas las acciones.
Crea el rango de IP privada:
gcloud compute addresses create psa-range \
--global \
--purpose=VPC_PEERING \
--prefix-length=24 \
--description="VPC private service access" \
--network=default
Crea una conexión privada con el rango de IP asignado:
gcloud services vpc-peerings connect \
--service=servicenetworking.googleapis.com \
--ranges=psa-range \
--network=default
Resultado esperado en la consola:
student@cloudshell:~ (test-project-402417)$ gcloud compute addresses create psa-range \
--global \
--purpose=VPC_PEERING \
--prefix-length=24 \
--description="VPC private service access" \
--network=default
Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/global/addresses/psa-range].
student@cloudshell:~ (test-project-402417)$ gcloud services vpc-peerings connect \
--service=servicenetworking.googleapis.com \
--ranges=psa-range \
--network=default
Operation "operations/pssn.p24-4470404856-595e209f-19b7-4669-8a71-cbd45de8ba66" finished successfully.
student@cloudshell:~ (test-project-402417)$
Crea un clúster de AlloyDB
Crea un clúster de AlloyDB en la región us-central1
Define la contraseña para el usuario de postgres. Puedes definir tu propia contraseña o usar una función aleatoria para generar una.
export PGPASSWORD=`openssl rand -hex 16`
Resultado esperado en la consola:
student@cloudshell:~ (test-project-402417)$ export PGPASSWORD=`openssl rand -hex 12`
Toma nota de la contraseña de PostgreSQL para utilizarla más adelante:
echo $PGPASSWORD
Necesitarás esa contraseña en el futuro para conectarte a la instancia como el usuario postgres. Guarda esta contraseña para usarla en los pasos posteriores.
Resultado esperado en la consola:
student@cloudshell:~ (test-project-402417)$ echo $PGPASSWORD bbefbfde7601985b0dee5723 (Note: Yours will be different!)
Crea un clúster de prueba gratuita
Si nunca usaste AlloyDB, puedes crear un clúster de prueba gratuito:
Configura las variables de entorno para la región y el nombre del clúster:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
Ejecuta el comando para crear el clúster:
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION \
--subscription-type=TRIAL
Resultado esperado en la consola:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION \
--subscription-type=TRIAL
Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4
Creating cluster...done.
Crea una instancia principal de AlloyDB para tu clúster en la misma sesión de Cloud Shell. Si te desconectas, deberás volver a definir las variables de entorno de la región y el nombre del clúster.
gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=8 \
--region=$REGION \
--cluster=$ADBCLUSTER
Resultado esperado en la consola:
student@cloudshell:~ (test-project-402417)$ gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=8 \
--region=$REGION \
--availability-type ZONAL \
--cluster=$ADBCLUSTER
Operation ID: operation-1697659203545-6080315c6e8ee-391805db-25852721
Creating instance...done.
Crea un clúster estándar de AlloyDB
Si no es tu primer clúster de AlloyDB en el proyecto, continúa con la creación de un clúster estándar. Si ya creaste un clúster de prueba gratuita, omite este paso.
Configura las variables de entorno para la región y el nombre del clúster:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
Ejecuta el comando para crear el clúster:
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION
Resultado esperado en la consola:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION
Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4
Creating cluster...done.
Crea una instancia principal de AlloyDB para tu clúster en la misma sesión de Cloud Shell. Si te desconectas, deberás volver a definir las variables de entorno de la región y el nombre del clúster.
gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=2 \
--region=$REGION \
--cluster=$ADBCLUSTER
Resultado esperado en la consola:
student@cloudshell:~ (test-project-402417)$ gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=2 \
--region=$REGION \
--availability-type ZONAL \
--cluster=$ADBCLUSTER
Operation ID: operation-1697659203545-6080315c6e8ee-391805db-25852721
Creating instance...done.
5. Conectarte a AlloyDB
AlloyDB se implementa con una conexión solo privada, por lo que necesitas una VM de Compute Engine con el cliente de PostgreSQL instalado para trabajar con la base de datos.
Implementa la VM de GCE
Crea una VM de GCE en la misma región y VPC que el clúster de AlloyDB.
En Cloud Shell, ejecuta el siguiente comando:
export ZONE=us-central1-a
gcloud compute instances create instance-1 \
--zone=$ZONE \
--create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-13 AND family!=debian-13-arm64" --format="value(name)") \
--scopes=https://www.googleapis.com/auth/cloud-platform
Resultado esperado en la consola:
student@cloudshell:~ (test-project-402417)$ export ZONE=us-central1-a
gcloud compute instances create instance-1 \
--zone=$ZONE \
--create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-13 AND family!=debian-13-arm64" --format="value(name)") \
--scopes=https://www.googleapis.com/auth/cloud-platform
Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/zones/us-central1-a/instances/instance-1].
NAME: instance-1
ZONE: us-central1-a
MACHINE_TYPE: n1-standard-1
PREEMPTIBLE:
INTERNAL_IP: 10.128.0.2
EXTERNAL_IP: 34.71.192.233
STATUS: RUNNING
Instala el cliente de Postgres
Instala el software del cliente de PostgreSQL en la VM implementada
Conéctate a la VM:
gcloud compute ssh instance-1 --zone=us-central1-a
Resultado esperado en la consola:
student@cloudshell:~ (test-project-402417)$ gcloud compute ssh instance-1 --zone=us-central1-a Updating project ssh metadata...working..Updated [https://www.googleapis.com/compute/v1/projects/test-project-402417]. Updating project ssh metadata...done. Waiting for SSH key to propagate. Warning: Permanently added 'compute.5110295539541121102' (ECDSA) to the list of known hosts. Linux instance-1 6.12.101+deb13-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.101-1 (2026-08-05) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. student@instance-1:~$
Instala el comando de ejecución de software dentro de la VM:
sudo apt-get update
sudo apt-get install --yes postgresql-client
Resultado esperado en la consola:
student@instance-1:~$ sudo apt-get update sudo apt-get install --yes postgresql-client Get:1 file:/etc/apt/mirrors/debian.list Mirrorlist [30 B] Get:2 file:/etc/apt/mirrors/debian-security.list Mirrorlist [39 B] Hit:3 https://deb.debian.org/debian trixie InRelease Get:4 https://deb.debian.org/debian trixie-updates InRelease [47.3 kB] Get:5 https://deb.debian.org/debian trixie-backports InRelease [54.0 kB] Get:6 https://deb.debian.org/debian-security trixie-security InRelease [43.4 kB] Hit:10 https://packages.cloud.google.com/apt google-compute-engine-trixie-stable InRelease ...redacted... update-alternatives: using /usr/share/postgresql/17/man/man1/psql.1.gz to provide /usr/share/man/man1/psql.1.gz (psql.1.gz) in auto mode Setting up postgresql-client (17+278) ... Processing triggers for man-db (2.13.1-1) ... Processing triggers for libc-bin (2.41-12+deb13u3) ...
Conéctate a la instancia
Conéctate a la instancia principal desde la VM usando psql.
En la misma pestaña de Cloud Shell con la sesión de SSH abierta en tu VM instance-1
Usa el valor de la contraseña de AlloyDB (PGPASSWORD) que se indicó y el ID del clúster de AlloyDB para conectarte a AlloyDB desde la VM de GCE:
export PGPASSWORD=<Noted password>
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
export INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)")
psql "host=$INSTANCE_IP user=postgres sslmode=require"
Resultado esperado en la consola:
student@instance-1:~$ export PGPASSWORD=CQhOi5OygD4ps6ty student@instance-1:~$ export PROJECT_ID=$(gcloud config get-value project) export REGION=us-central1 export ADBCLUSTER=alloydb-aip-01 export INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)") psql "host=$INSTANCE_IP user=postgres sslmode=require" psql (17.10 (Debian 17.10-0+deb13u1), server 17.9) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off, ALPN: postgresql) Type "help" for help. postgres=>
Cierra la sesión de psql:
exit
6. Prepara la base de datos
Crea una base de datos, habilita la integración de IA de Agent Platform, crea objetos de base de datos y, luego, importa datos.
Otorga los permisos necesarios a AlloyDB
Agrega permisos de Gemini Enterprise Agent Platform al agente de servicio de AlloyDB.
Abre otra pestaña de Cloud Shell con el signo "+" en la parte superior.

En la nueva pestaña de Cloud Shell, ejecuta lo siguiente:
PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"
Resultado esperado en la consola:
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project) Your active configuration is: [cloudshell-11039] student@cloudshell:~ (test-project-001-402417)$ gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \ --role="roles/aiplatform.user" Updated IAM policy for project [test-project-001-402417]. bindings: - members: - serviceAccount:service-4470404856@gcp-sa-alloydb.iam.gserviceaccount.com role: roles/aiplatform.user - members: ... etag: BwYIEbe_Z3U= version: 1
Cierra la pestaña con el comando de ejecución “exit” en la pestaña:
exit
Crea la base de datos
Guía de inicio rápido para crear una base de datos
En la sesión de la VM de GCE, ejecuta lo siguiente:
Crea la base de datos:
psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db"
Resultado esperado en la consola:
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db" CREATE DATABASE student@instance-1:~$
Habilita la integración de Vertex AI
Habilita la integración en Vertex AI y las extensiones pgvector en la base de datos.
En la VM de GCE, ejecuta lo siguiente:
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE"
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector"
Resultado esperado en la consola:
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE" psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector" CREATE EXTENSION CREATE EXTENSION student@instance-1:~$
Importar datos
Descarga los datos preparados y, luego, impórtalos a la nueva base de datos.
En la VM de GCE, ejecuta lo siguiente:
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header"
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header"
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header"
Resultado esperado en la consola:
student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" SET SET SET SET SET set_config ------------ (1 row) SET SET SET SET SET SET CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE SEQUENCE ALTER TABLE ALTER SEQUENCE ALTER TABLE ALTER TABLE ALTER TABLE student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header" COPY 941 student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header" COPY 263861 student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header" COPY 4654 student@instance-1:~$
7. Cómo calcular embeddings
Después de importar los datos, tendrás los datos de productos en la tabla cymbal_products, el inventario que muestra la cantidad de productos disponibles en cada tienda en la tabla cymbal_inventory y la lista de las tiendas en la tabla cymbal_stores. Debes calcular los datos vectoriales en función de las descripciones de los productos y puedes usar funciones como google_ml.embedding para ello. Obtén más información sobre la tecnología utilizada en la documentación.
Es fácil generar embeddings para unas pocas filas, pero ¿cómo hacerlo de manera eficiente si tenemos miles? En esta sección, se explica cómo generar y administrar embeddings para tablas grandes. Obtén más información sobre las diferentes opciones y técnicas en la guía.
Habilita la generación rápida de embeddings
Conéctate a la base de datos con psql desde tu VM usando la IP de la instancia de AlloyDB y la contraseña de postgres:
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
Verifica la versión de la extensión google_ml_integration.
SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';
La versión debe ser 1.5.2 o superior. Este es un ejemplo del resultado:
quickstart_db=> SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration'; extversion ------------ 1.6 (1 row)
La versión predeterminada debe ser la 1.6 o una posterior, pero, si tu instancia muestra una versión anterior, es probable que deba actualizarse. Verifica si se inhabilitó el mantenimiento para la instancia.
Verifica que la marca de base de datos google_ml_integration.enable_faster_embedding_generation esté activada. En la misma sesión de psql, verifica el valor de la marca:
show google_ml_integration.enable_faster_embedding_generation;
Si la marca está en la posición correcta, el resultado esperado se verá de la siguiente manera:
quickstart_db=> show google_ml_integration.enable_faster_embedding_generation; google_ml_integration.enable_faster_embedding_generation ---------------------------------------------------------- on (1 row)
Si el valor de la marca muestra "off", debes actualizar la instancia. Hazlo con la consola web o el comando de gcloud como se describe en la documentación.
Sal de la sesión de psql:
exit;
Para actualizar la marca con gcloud, ejecuta el siguiente comando:
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
gcloud beta alloydb instances update $ADBCLUSTER-pr \
--database-flags google_ml_integration.enable_faster_embedding_generation=on \
--region=$REGION \
--cluster=$ADBCLUSTER \
--project=$PROJECT_ID \
--update-mode=FORCE_APPLY
Puede tardar unos minutos, pero, finalmente, el valor de la marca debería cambiar a "activado". Después, puedes continuar con los siguientes pasos.
Crea una columna de embedding
Conéctate a la base de datos con psql y crea una columna virtual con el tipo de datos vectoriales que usará la función de incorporación en la tabla cymbal_products.
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
En la sesión de psql, después de conectarte a la base de datos, ejecuta el siguiente comando:
ALTER TABLE cymbal_products ADD COLUMN embedding vector(768);
El comando crea una columna virtual para las futuras incorporaciones.
Resultado esperado en la consola:
quickstart_db=> ALTER TABLE cymbal_products ADD COLUMN embedding vector(768); ALTER TABLE quickstart_db=>
Genera embeddings en lotes de 50 filas. En la misma sesión de psql, ejecuta lo siguiente:
Habilita la sincronización para medir cuánto tiempo tardará:
\timing
Ejecuta el siguiente comando:
CALL ai.initialize_embeddings(
model_id => 'text-embedding-005',
table_name => 'cymbal_products',
content_column => 'product_description',
embedding_column => 'embedding',
batch_size => 50
);
Además, el resultado de la consola mostró menos de 2 segundos para la generación de la incorporación:
quickstart_db=> CALL ai.initialize_embeddings(
model_id => 'text-embedding-005',
table_name => 'cymbal_products',
content_column => 'product_description',
embedding_column => 'embedding',
batch_size => 50
);
NOTICE: Initialize embedding completed successfully for table cymbal_products
CALL
Time: 1458.704 ms (00:01.459)
quickstart_db=>
Puedes experimentar con diferentes tamaños de lote y ver si cambia el tiempo de ejecución.
De forma predeterminada, las incorporaciones no se actualizan si se actualiza la columna product_description correspondiente o se inserta una fila nueva completa. Sin embargo, puedes hacerlo configurando el parámetro incremental_refresh_mode.
Crea una columna "product_embeddings" y haz que se actualice automáticamente:
ALTER TABLE cymbal_products ADD COLUMN product_embedding vector(768);
CALL ai.initialize_embeddings(
model_id => 'text-embedding-005',
table_name => 'cymbal_products',
content_column => 'product_description',
embedding_column => 'product_embedding',
batch_size => 50,
incremental_refresh_mode => 'transactional'
);
Inserta una fila nueva en la tabla.
INSERT INTO "cymbal_products" ("uniq_id", "crawl_timestamp", "product_url", "product_name", "product_description", "list_price", "sale_price", "brand", "item_number", "gtin", "package_size", "category", "postal_code", "available", "product_embedding", "embedding") VALUES ('fd604542e04b470f9e6348e640cff794', NOW(), 'https://example.com/new_product', 'New Cymbal Product', 'This is a new cymbal product description.', 199.99, 149.99, 'Example Brand', 'EB123', '1234567890', 'Single', 'Cymbals', '12345', TRUE, NULL, NULL);
Consulta la tabla para comparar dos columnas de incorporación:
SELECT uniq_id,embedding, (product_embedding::real[])[1:5] as product_embedding FROM cymbal_products WHERE uniq_id='fd604542e04b470f9e6348e640cff794';
El resultado muestra que product_embedding se completa automáticamente, mientras que embedding permanece vacío:
quickstart_db=> SELECT uniq_id,embedding, (product_embedding::real[])[1:5] as product_embedding FROM cymbal_products WHERE uniq_id='fd604542e04b470f9e6348e640cff794';
uniq_id | embedding | product_embedding
----------------------------------+-----------+---------------------------------------------------------------
fd604542e04b470f9e6348e640cff794 | | {0.015003494,-0.005349732,-0.059790313,-0.0087091,-0.0271452}
(1 row)
Time: 3.295 ms
8. Ejecuta la búsqueda de similitud
Ejecuta una búsqueda de similitud basada en los embeddings de vectores generados con AlloyDB AI.
La consulta SQL se puede ejecutar desde la misma interfaz de línea de comandos de psql o, como alternativa, desde AlloyDB Studio. Cualquier resultado complejo y de varias filas funciona mejor en AlloyDB Studio.
Conéctate a AlloyDB Studio
Para abrir AlloyDB Studio, sigue estos pasos:
- En la consola de Google Cloud, ve a la página Clústeres de AlloyDB para PostgreSQL.
- Selecciona tu instancia principal para abrir su interfaz web.
3. Luego, haz clic en AlloyDB Studio a la izquierda:

- Selecciona la base de datos
quickstart_db, el usuario postgres, proporciona la contraseña que se indicó y haz clic en Autenticar.

Esta acción abrirá la interfaz de AlloyDB Studio.
- Selecciona la pestaña Consulta sin título para abrir el editor de SQL.

Se abrirá un editor en el que podrás ejecutar comandos de SQL, como se muestra en la siguiente imagen:

Si prefieres usar psql desde la línea de comandos, sigue la ruta alternativa y conéctate a la base de datos desde la sesión SSH de tu VM, como se describió en los capítulos anteriores.
Ejecuta la búsqueda de similitud
Ejecuta una búsqueda para obtener una lista de los productos disponibles que se relacionan más estrechamente con la solicitud de un cliente. La frase de búsqueda que se pasó al modelo de embedding en Gemini Enterprise Agent Platform (la misma que usamos para generar embeddings para nuestros productos) para obtener el valor del vector de "¿Qué tipo de árboles frutales crecen bien aquí?".
Ejecuta la consulta:
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
(cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) as distance
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
distance ASC
LIMIT 10;
Y este es el resultado esperado:
quickstart_db=> SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
(cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) as distance
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
distance ASC
LIMIT 10;
product_name | description | sale_price | zip_code | distance
-------------------------+----------------------------------------------------------------------------------+------------+----------+---------------------
Cherry Tree | This is a beautiful cherry tree that will produce delicious cherries. It is an d | 75.00 | 93230 | 0.43922018972266397
Meyer Lemon Tree | Meyer Lemon trees are California's favorite lemon tree! Grow your own lemons by | 34 | 93230 | 0.4685112926118228
Toyon | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e | 10.00 | 93230 | 0.4835677149651668
California Lilac | This is a beautiful lilac tree that can grow to be over 10 feet tall. It is an d | 5.00 | 93230 | 0.4947204525907498
California Peppertree | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e | 25.00 | 93230 | 0.5054166905547247
California Black Walnut | This is a beautiful walnut tree that can grow to be over 80 feet tall. It is a d | 100.00 | 93230 | 0.5084219510932597
California Sycamore | This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is | 300.00 | 93230 | 0.5140519790508755
Coast Live Oak | This is a beautiful oak tree that can grow to be over 100 feet tall. It is an ev | 500.00 | 93230 | 0.5143126438081371
Fremont Cottonwood | This is a beautiful cottonwood tree that can grow to be over 100 feet tall. It i | 200.00 | 93230 | 0.5174774727252058
Madrone | This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an | 50.00 | 93230 | 0.5227400803389093
Obtendrás 10 productos con descripciones semánticamente cercanas a la frase de búsqueda, ordenados por la distancia, con los más similares en la parte superior.
9. Mejora la respuesta
Puedes mejorar la respuesta a una aplicación cliente usando el resultado de la búsqueda y preparar una salida significativa usando los resultados de la búsqueda proporcionados como parte de la instrucción a un modelo de lenguaje generativo de base.
Para lograrlo, generas un JSON con los principales resultados de la búsqueda vectorial y, luego, usas ese JSON generado como complemento de una instrucción para un modelo de IA generativa en Agent Platform para crear un resultado significativo. El primer paso genera el JSON, luego se prueba en Agent Platform Studio y el último paso incorpora todo en una sentencia de SQL que se puede usar en una aplicación.
Genera resultados en formato JSON
Modifica la consulta para generar el resultado en formato JSON y devolver solo una fila para pasar a Agent Platform.
Ejecuta la consulta:
WITH trees as (
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
cp.uniq_id as product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
El JSON en el resultado:
[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]
Ejecuta la instrucción en Vertex AI Studio
Usa el JSON generado para proporcionarlo como parte del mensaje al modelo de IA generativa en Vertex AI Studio.
Abre Gemini Enterprise Agent Platform Studio en la consola de Google Cloud.

Escribe tu instrucción en la interfaz:

Escribe la siguiente instrucción:
You are a friendly advisor helping to find a product based on the customer's needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information

Y este es el resultado cuando ejecutamos la instrucción :

La respuesta incluye el precio, la descripción y la información complementaria que el modelo obtiene de fuentes externas en función de la información sobre el árbol y la ubicación.
Ejecuta la instrucción en PSQL
Puedes obtener un resultado similar ejecutando la integración de AlloyDB AI con Gemini Enterprise Agent Platform para obtener la misma respuesta de un modelo generativo con SQL directamente en la base de datos. Antes de usar el modelo gemini-3.6-flash, debes registrarlo.
Registra el modelo gemini-3.6-flash:
En la ejecución de AlloyDB Studio, haz lo siguiente:
CALL google_ml.create_model(
model_id => 'gemini-3.6-flash',
model_request_url => 'https://aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/global/publishers/google/models/gemini-3.6-flash:generateContent',
model_provider => 'google',
model_type => 'llm'
);
Siempre puedes verificar la lista de modelos registrados seleccionando información de google_ml.model_info_view.
SELECT model_id,model_type FROM google_ml.model_info_view WHERE model_id ILIKE '%flash%';
Este es un ejemplo de resultado:
quickstart_db=> SELECT model_id,model_type FROM google_ml.model_info_view WHERE model_id ILIKE '%flash%';
model_id | model_type
-----------------------+------------
gemini-3.6-flash | llm
gemini-2.0-flash | llm
gemini-2.5-flash | llm
gemini-2.0-flash-lite | llm
gemini-2.5-flash-lite | llm
(5 rows)
Ahora puedes usar el JSON generado en una subconsulta como parte de la instrucción para el modelo gemini-3.6-flash con SQL.
En tu sesión de psql o AlloyDB Studio, ejecuta la siguiente consulta:
WITH trees AS (
SELECT
cp.product_name,
cp.product_description AS description,
cp.sale_price,
cs.zip_code,
cp.uniq_id AS product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci ON
ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON
cs.store_id = ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-005',
'What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1),
prompt AS (
SELECT
'You are a friendly advisor helping to find a product based on the customer''s needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","product_description":"some description","sale_price":10}
Here is the list of products:' || json_agg(trees) || 'The customer asked "What kind of fruit trees grow well here?"
You should give information about the product, price and some supplemental information' AS prompt_text
FROM
trees),
response AS (
SELECT
google_ml.predict_row( model_id =>'gemini-3.6-flash',
request_body => json_build_object('contents',
json_build_object('role',
'user',
'parts',
json_build_object('text',
prompt_text))))->'candidates'->0->'content'->'parts'->0->'text' AS resp
FROM
prompt)
SELECT
REPLACE(resp::text, '\n', CHR(10))
FROM
response;
Y este es el resultado esperado. El resultado podría ser diferente debido a la naturaleza no determinística de los modelos de IA generativa:
"Hello there! I'd be delighted to help you pick out a wonderful fruit tree for your space. Based on our local selection, a fantastic option that grows very well is the **Cherry Tree**! Here are the details on this beautiful tree: * **Product:** Cherry Tree * **Price:** $75.00 ### Why it's a great choice: * **Delicious Harvest:** It produces tasty, fresh cherries right in your backyard. * **Size & Benefits:** It's a deciduous tree that grows to about 15 feet tall, making it ideal for providing both lovely shade and a bit of privacy. * **Year-Round Beauty:** It features lush, dark green leaves throughout the summer that transform into a stunning red in the autumn. * **Growing Requirements:** Cherry trees thrive best in cool, moist climates with sandy soil, and are perfectly suited for USDA hardiness zones 4 through 9. Please let me know if you have any questions about planting or if you'd like help adding this to your order!"
10. Crear índice vectorial
Dado que este conjunto de datos es pequeño, los tiempos de respuesta dependen principalmente de las interacciones con los modelos en Gemini Enterprise Agent Platform. Sin embargo, cuando consultas millones de vectores, la búsqueda de vectores en sí puede consumir una parte significativa del tiempo de respuesta y aumentar la carga en tu base de datos. Para mejorar el rendimiento de la búsqueda, puedes compilar un índice de vectores.
Crea un índice de ScaNN
Para compilar un índice de ScaNN, debes habilitar una extensión adicional. La extensión alloydb_scann proporciona una interfaz para trabajar con índices de vectores de vecino más cercano aproximado (ANN) con el algoritmo ScaNN de Google.
Ejecuta el código en AlloyDB Studio:
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
El índice se puede crear en modo MANUAL o AUTO. El modo MANUAL está habilitado de forma predeterminada y puedes crear un índice y mantenerlo como cualquier otro índice. Sin embargo, si habilitas el modo AUTO, podrás crear el índice que no requiere mantenimiento de tu parte. Puedes leer en detalle sobre todas las opciones en la documentación. No tenemos suficientes filas para crear el índice en el modo AUTOMÁTICO, por lo que lo crearás como MANUAL.
Ejecuta el siguiente comando en AlloyDB Studio:
CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
USING scann (embedding cosine)
WITH (num_leaves=10, max_num_levels = 1);
Puedes obtener información sobre el ajuste de los parámetros del índice en la documentación.
Resultado esperado:
quickstart_db=> CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products USING scann (embedding cosine) WITH (num_leaves=10, max_num_levels = 1); CREATE INDEX quickstart_db=>
Comparar respuesta
Repite la consulta que usamos para obtener el valor superior en la búsqueda semántica:
WITH trees as (
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
cp.uniq_id as product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
Resultado esperado:
[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]
El mismo "Cherry Tree" en el resultado.
Verifica el uso del índice:
EXPLAIN (analyze)
WITH trees as (
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
cp.uniq_id as product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
Resultado esperado (oculto para mayor claridad):
...
Aggregate (cost=27.24..27.25 rows=1 width=32) (actual time=0.964..0.965 rows=1 loops=1)
-> Subquery Scan on trees (cost=18.91..27.23 rows=1 width=142) (actual time=0.953..0.954 rows=1 loops=1)
-> Limit (cost=18.91..27.22 rows=1 width=158) (actual time=0.948..0.949 rows=1 loops=1)
-> Nested Loop (cost=18.91..7126.86 rows=855 width=158) (actual time=0.948..0.948 rows=1 loops=1)
-> Nested Loop (cost=18.63..7103.59 rows=855 width=907) (actual time=0.931..0.931 rows=1 loops=1)
-> Index Scan using cymbal_products_embeddings_scann on cymbal_products cp (cost=18.21..343.15 rows=942 width=903) (actual time=0.906..0.908 rows=2 loops=1)
Order By: (embedding <=> '[-0.106554024,0.035774965,-0.027267234,-0.045653425,-0.03286045,0.02124319...
En el resultado, puedes ver que la consulta usó "Index Scan using cymbal_products_embeddings_scann on cymbal_products".
La consulta devuelve el mismo árbol de cerezo que apareció en la parte superior de los resultados de la búsqueda antes de que crearas el índice. Dado que los índices de vecino más cercano aproximado (ANN) sacrifican la exactitud absoluta por la velocidad de búsqueda, es posible que, en ocasiones, las búsquedas basadas en índices muestren resultados principales ligeramente diferentes a los de una búsqueda exacta sin indexar. Sin embargo, el índice de vectores proporciona un aumento significativo del rendimiento y, al mismo tiempo, mantiene una alta precisión.
Para explorar más, puedes probar otros tipos de índices de vectores o encontrar más labs y ejemplos con la integración de LangChain en la página de documentación.
11. Limpia el entorno
Cuando termines el lab, destruye las instancias y el clúster de AlloyDB.
Borra el clúster de AlloyDB y todas las instancias
El clúster se destruye con la opción force, que también borra todas las instancias que pertenecen al clúster.
Si se desconectó tu terminal, vuelve a conectarte y define las variables de entorno y del proyecto en Cloud Shell:
gcloud config set project <YOUR_PROJECT_ID>
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
export PROJECT_ID=$(gcloud config get-value project)
Borra el clúster:
gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force
Resultado esperado en la consola:
student@cloudshell:~ (test-project-001-402417)$ gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force All of the cluster data will be lost when the cluster is deleted. Do you want to continue (Y/n)? Y Operation ID: operation-1697820178429-6082890a0b570-4a72f7e4-4c5df36f Deleting cluster...done.
Borra las copias de seguridad de AlloyDB
Borra todas las copias de seguridad de AlloyDB del clúster:
for i in $(gcloud alloydb backups list \
--filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" \
--format="value(name)" \
--sort-by=~createTime) ; do \
gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done
Resultado esperado en la consola:
student@cloudshell:~ (test-project-001-402417)$ for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done Operation ID: operation-1697826266108-60829fb7b5258-7f99dc0b-99f3c35f Deleting backup...done.
Ahora podemos destruir nuestra VM
Borra la VM de GCE
En Cloud Shell, ejecuta el siguiente comando:
export GCEVM=instance-1
export ZONE=us-central1-a
gcloud compute instances delete $GCEVM \
--zone=$ZONE \
--quiet
Resultado esperado en la consola:
student@cloudshell:~ (test-project-001-402417)$ export GCEVM=instance-1
export ZONE=us-central1-a
gcloud compute instances delete $GCEVM \
--zone=$ZONE \
--quiet
Deleted
12. Felicitaciones
Felicitaciones por completar el codelab.
Este lab forma parte de la ruta de aprendizaje de IA lista para producción con Google Cloud.
- Explora el plan de estudios completo para cerrar la brecha entre el prototipo y la producción.
- Comparte tu progreso con el hashtag
#ProductionReadyAI.
Temas abordados
- Cómo implementar un clúster y una instancia principal de AlloyDB
- Cómo conectarse a AlloyDB desde una VM de Google Compute Engine
- Cómo crear una base de datos y habilitar AlloyDB AI
- Cómo cargar datos en la base de datos
- Cómo usar AlloyDB Studio
- Cómo usar el modelo de incorporación de Gemini Enterprise Agent Platform en AlloyDB
- Cómo usar Gemini Enterprise Agent Platform Studio
- Cómo enriquecer el resultado con el modelo generativo de Gemini Enterprise Agent Platform
- Cómo mejorar el rendimiento con el índice de vectores
13. Encuesta
Resultado: