Comienza a usar la búsqueda híbrida en AlloyDB

1. Introducción

En este codelab, aprenderás a realizar búsquedas híbridas en AlloyDB con la extensión de método de actualización de clasificación (RUM) y el índice de vecino más cercano escalable (ScaNN). 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 la consola de Google Cloud
  • Habilidades básicas de la interfaz de línea de comandos y de Google 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
  • Genera incorporaciones con Vertex AI
  • Cómo crear un índice de vectores de ScaNN para mejorar la búsqueda de vectores
  • Cómo crear un wrapper de datos externo (FDW) para Elasticsearch
  • Realiza una búsqueda híbrida combinando la búsqueda semántica en AlloyDB con la búsqueda en el texto completo en Elastic.

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.

Usar una cuenta personal en lugar de una cuenta laboral o educativa

Crea un proyecto de Google Cloud

  1. En la página del selector de proyectos de la consola de Google Cloud, selecciona o crea un proyecto de Google Cloud.
  2. Asegúrate de que la facturación esté habilitada para tu proyecto de Cloud. Obtén información para verificar si la facturación está habilitada en un proyecto.

Habilitar facturación

Para habilitar la facturación, tienes dos opciones. Puedes usar tu cuenta de facturación personal o canjear créditos siguiendo los pasos que se indican a continuació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 se puede 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.

Cloud Shell es un entorno de línea de comandos que se ejecuta en Google Cloud y que viene precargado con las herramientas necesarias.

  1. Haz clic en Activar Cloud Shell en la parte superior de la consola de Google Cloud.
  2. Una vez que te conectes a Cloud Shell, verifica tu autenticación:
    gcloud auth list
    
  3. Confirma que tu proyecto esté configurado:
    gcloud config get project
    
  4. Si tu proyecto no está configurado como se esperaba, configúralo:
    export PROJECT_ID=<YOUR_PROJECT_ID>
    gcloud config set project $PROJECT_ID
    

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 Vertex AI, debes habilitar sus APIs respectivas 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 \
                       secretmanager.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 \
                       secretmanager.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.

Presentamos las APIs

  • La API de AlloyDB (alloydb.googleapis.com) te permite crear, administrar y escalar clústeres de AlloyDB para PostgreSQL. Proporciona un servicio de base de datos completamente administrado y compatible con PostgreSQL diseñado para cargas de trabajo empresariales transaccionales y analíticas exigentes.
  • La API de Compute Engine (compute.googleapis.com) te permite crear y administrar máquinas virtuales (VM), discos persistentes y parámetros de configuración de red. Proporciona la base de infraestructura como servicio (IaaS) principal necesaria para ejecutar tus cargas de trabajo y alojar la infraestructura subyacente de muchos servicios administrados.
  • La API de Resource Manager (cloudresourcemanager.googleapis.com) te permite administrar de forma programática los metadatos y la configuración de tu proyecto de Google Cloud. Te permite organizar recursos, controlar políticas de Identity and Access Management (IAM) y validar permisos en toda la jerarquía del proyecto.
  • La API de Service Networking (servicenetworking.googleapis.com) te permite automatizar la configuración de la conectividad privada entre tu red de nube privada virtual (VPC) y los servicios administrados de Google. Se requiere específicamente para establecer el acceso a la IP privada para servicios como AlloyDB, de modo que puedan comunicarse de forma segura con tus otros recursos.
  • La API de Vertex AI (aiplatform.googleapis.com) permite que tus aplicaciones compilen, implementen y escalen modelos de aprendizaje automático. Proporciona la interfaz unificada para todos los servicios de IA de Google Cloud, incluido el acceso a modelos de IA generativa (como Gemini) y el entrenamiento de modelos personalizados.
  • La API de Secret Manager (secretmanager.googleapis.com) es un servicio de administración de credenciales y secretos que te permite almacenar y administrar datos sensibles, como claves de API, nombres de usuario, contraseñas, certificados y mucho más.

Opcionalmente, puedes configurar tu región predeterminada para usar los modelos de incorporación de Vertex AI. Obtén más información sobre las ubicaciones disponibles para Vertex AI. En el ejemplo, usamos la región us-central1.

gcloud config set compute/region us-central1

4. Implementa AlloyDB

Antes de crear un clúster de AlloyDB, necesitamos un rango de IP privada disponible en nuestra VPC para que lo utilice la instancia futura de AlloyDB. Si no lo tenemos, debemos crearlo, asignarlo para que lo usen los servicios internos de Google y, luego, podremos crear el clúster y la instancia.

Crea un rango de IP privada

Debemos establecer la configuración del acceso privado a servicios en nuestra VPC para AlloyDB. Aquí, suponemos que tenemos 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 \
    --export-custom-routes

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

En esta sección, crearemos 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 12`

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 usuario de postgres. Te sugiero que la copies en una ubicación segura (es decir, un administrador de contraseñas).

Resultado esperado en la consola:

student@cloudshell:~ (test-project-402417)$ echo $PGPASSWORD
<generated password>

Crea un clúster de AlloyDB

Define la región y el nombre del clúster de AlloyDB. Usaremos la región us-central1 y alloydb-hybrid-search como nombre del clúster:

export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search

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-hybrid-search
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 nuestro 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:~ (alloydb-hybrid-search)$ 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 necesitamos una VM con el cliente de PostgreSQL instalado para trabajar con la base de datos. También usaremos esta VM para ejecutar una instancia de Elasticsearch.

Implementa la VM de GCE

Crea una VM de GCE en la misma región y VPC que el clúster de AlloyDB. Asegúrate de que el disco de arranque sea lo suficientemente grande como para ejecutar Elastic. Aquí especificamos un disco de arranque de 20 GB en la marca --create-disk.

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,size=20,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \
    --scopes=https://www.googleapis.com/auth/cloud-platform

Resultado esperado en la consola:

student@cloudshell:~ (alloydb-hybrid-search)$ export ZONE=us-central1-a
student@cloudshell:~ (talloydb-hybrid-search)$ 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-12 AND family!=debian-12-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:~ (alloydb-hybrid-search)$ gcloud compute ssh instance-1 --zone=us-central1-a
Updating project ssh metadata...working..Updated [https://www.googleapis.com/compute/v1/projects/alloydb-hybrid-search].                                                                                                                                                         
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.us-central1-a.c.gleb-test-short-001-418811.internal 6.1.0-18-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) 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 https://packages.cloud.google.com/apt google-compute-engine-bullseye-stable InRelease [5146 B]
Get:2 https://packages.cloud.google.com/apt cloud-sdk-bullseye InRelease [6406 B]   
Hit:3 https://deb.debian.org/debian bullseye InRelease  
Get:4 https://deb.debian.org/debian-security bullseye-security InRelease [48.4 kB]
Get:5 https://packages.cloud.google.com/apt google-compute-engine-bullseye-stable/main amd64 Packages [1930 B]
Get:6 https://deb.debian.org/debian bullseye-updates InRelease [44.1 kB]
Get:7 https://deb.debian.org/debian bullseye-backports InRelease [49.0 kB]
...redacted...
update-alternatives: using /usr/share/postgresql/13/man/man1/psql.1.gz to provide /usr/share/man/man1/psql.1.gz (psql.1.gz) in auto mode
Setting up postgresql-client (13+225) ...
Processing triggers for man-db (2.9.4-2) ...
Processing triggers for libc-bin (2.31-13+deb11u7) ...

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-hybrid-search
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=<noted password>
student@instance-1:~$ ADBCLUSTER=alloydb-aip-01
student@instance-1:~$ REGION=us-central1
student@instance-1:~$ INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)")
gleb@instance-1:~$ psql "host=$INSTANCE_IP user=postgres sslmode=require"
psql (15.6 (Debian 15.6-0+deb12u1), server 15.5)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

postgres=>

Cierra la sesión de psql:

exit

6. Prepara la base de datos

Debemos crear una base de datos, habilitar la integración de Vertex AI, crear objetos de base de datos y, luego, importar los datos.

Otorga los permisos necesarios a AlloyDB

Agrega permisos de Vertex AI al agente de servicio de AlloyDB.

Abre otra pestaña de Cloud Shell con el signo "+" en la parte superior.

abc505ac4d41f24e.png

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 haciendo clic en “X” o ejecutando el comando:

exit

Crea la base de datos

Crea una base de datos llamada quickstart.

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:~$ gcloud storage 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:~$ 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"
COPY 941
student@instance-1:~$ 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"
COPY 263861
student@instance-1:~$ 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"
COPY 4654
student@instance-1:~$

A continuación, estableceremos las marcas de base de datos necesarias. Puedes usar la consola web y administrar marcas en la instancia principal, o bien usar el comando de gcloud de la siguiente manera:

export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
gcloud beta alloydb instances update $ADBCLUSTER-pr \
   --database-flags google_ml_integration.enable_faster_embedding_generation=on,scann.enable_preview_features=on,google_ml_integration.enable_preview_ai_functions=on,google_ml_integration.enable_ai_query_engine=on \
   --region=$REGION \
   --cluster=$ADBCLUSTER \
   --project=$PROJECT_ID \
   --update-mode=FORCE_APPLY

Resultado esperado en la consola

export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
gcloud beta alloydb instances update $ADBCLUSTER-pr \
   --database-flags google_ml_integration.enable_faster_embedding_generation=on,scann.enable_preview_features=on,google_ml_integration.enable_preview_ai_functions=on,google_ml_integration.enable_ai_query_engine=on \
   --region=$REGION \
   --cluster=$ADBCLUSTER \
   --project=$PROJECT_ID \
   --update-mode=FORCE_APPLY
Your active configuration is: [cloudshell-724]
Operation ID: operation-1775159889986-64e7f9ea9858a-b031e866-4c7c36df

Habilitar las marcas de base de datos requiere que se reinicie la instancia y tardará unos minutos. Una vez que se complete, el estado de la instancia de AlloyDB indicará “Lista”.

7. Genera embeddings de vectores

Después de importar los datos, tenemos las siguientes tablas: cymbal_products, que almacena información sobre los productos; cymbal_inventory, que hace un seguimiento del stock de artículos en cada tienda; y cymbal_stores, que es una lista de tiendas. Para realizar una búsqueda semántica en nuestros productos, debemos generar embeddings de vectores de las descripciones de los productos con la función initialize_embeddings. Usaremos la integración de Vertex AI para calcular los datos de vectores según las descripciones de nuestros productos y agregarlos a la tabla. Puedes obtener más información sobre la tecnología utilizada en la documentación.

Para usar la integración, conéctate a la base de datos con AlloyDB Studio o 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.5.2
(1 row)

La versión predeterminada debe ser la 1.5.2 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.

Instala la extensión de vectores y crea una columna nueva para almacenar embeddings en cymbal_products

CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE cymbal_products ADD COLUMN product_embedding vector(768);

Resultado esperado en la consola:

quickstart_db=> ALTER TABLE cymbal_products ADD COLUMN product_embedding vector(768);
ALTER TABLE
quickstart_db=>

Usaremos la generación de incorporaciones por lotes para mejorar la eficiencia. Puedes obtener más información sobre las diferentes opciones y técnicas de generación de incorporaciones en la guía. Anteriormente, habilitamos la marca goole_ml_integration.enable_faster_embedding_generation, que nos permite generar incorporaciones por lotes.

Por último, también queremos que los embeddings se actualicen a medida que se modifican los valores de las columnas, por lo que incluimos el argumento incremental_refresh_mode en la llamada a función. Esto genera una sobrecarga en nuestra base de datos, pero es una compensación que hacemos para mantener automáticamente las incorporaciones sincronizadas con el contenido. Si deseas actualizar manualmente las incorporaciones, puedes encontrar las instrucciones en la documentación.

Ahora, para unir todo y generar embeddings, usamos la función initialize_embeddings y pasamos batch_size de 50 como sugerencia de lote y establecemos incremental_refresh_mode en transactional.

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'
);

Ahora, si insertamos una fila nueva en la tabla con el valor NULL para la columna product_embedding

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") 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);

Ahora, cuando consultemos la fila que acabamos de insertar, veremos que la columna product_embedding se actualiza automáticamente.

SELECT uniq_id, (product_embedding::real[])[1:5] as product_embedding  FROM cymbal_products WHERE uniq_id='fd604542e04b470f9e6348e640cff794';

El resultado debe verse de la siguiente manera:

quickstart_db=> SELECT uniq_id,(product_embedding::real[])[1:5] as product_embedding  FROM cymbal_products WHERE uniq_id='fd604542e04b470f9e6348e640cff794';
             uniq_id              |                      product_embedding                       
----------------------------------+---------------------------------------------------------------
 fd604542e04b470f9e6348e640cff794 | {0.015003494,-0.005349732,-0.059790313,-0.0087091,-0.0271452}
(1 row)

Time: 3.295 ms

8. Crea un índice vectorial

Para mejorar el rendimiento de la búsqueda de vectores, agregaremos un índice ScaNN.

Crea un índice de ScaNN

Para compilar el índice de SCANN, debemos habilitar una extensión más. La extensión alloydb_scann proporciona una interfaz para trabajar con el índice de vectores de tipo ANN usando el algoritmo ScaNN de Google.

CREATE EXTENSION IF NOT EXISTS alloydb_scann;

Resultado esperado:

quickstart_db=> CREATE EXTENSION IF NOT EXISTS alloydb_scann;
CREATE EXTENSION
Time: 27.468 ms
quickstart_db=>

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. En nuestro caso, no tenemos suficientes filas para crear el índice en el modo AUTO, por lo que lo crearemos como MANUAL y, luego, incluiremos parámetros de ajuste. Puedes obtener información sobre el ajuste de los parámetros del índice en la documentación.

CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
  USING scann (product_embedding cosine)
  WITH (mode='MANUAL', num_leaves=31, max_num_levels = 2);

Resultado esperado:

quickstart_db=> CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
  USING scann (product_embedding cosine)
  WITH (num_leaves=31, max_num_levels = 2);
CREATE INDEX
quickstart_db=>

Inspecciona el uso del índice

Ahora podemos ejecutar la consulta de búsqueda vectorial en el modo EXPLAIN y verificar si se está usando el í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.product_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=16.59..16.60 rows=1 width=32) (actual time=2.875..2.877 rows=1 loops=1)
-> Subquery Scan on trees (cost=8.42..16.59 rows=1 width=142) (actual time=2.860..2.862 rows=1 loops=1)
-> Limit (cost=8.42..16.58 rows=1 width=158) (actual time=2.855..2.856 rows=1 loops=1)
-> Nested Loop (cost=8.42..6489.19 rows=794 width=158) (actual time=2.854..2.855 rows=1 loops=1)
-> Nested Loop (cost=8.13..6466.99 rows=794 width=938) (actual time=2.742..2.743 rows=1 loops=1)
-> Index Scan using cymbal_products_embeddings_scann on cymbal_products cp (cost=7.71..111.99 rows=876 width=934) (actual time=2.724..2.724 rows=1 loops=1)
Order By: (embedding <=> '[0.008864171,0.03693164,-0.024245683,-0.00355923,0.0055611245,0.015985578,...<redacted>...5685,-0.03914233,-0.018452475,0.00826032,-0.07372604]'::vector)
...

En el resultado, se puede ver claramente que la consulta usó "Index Scan using cymbal_products_embeddings_scann on cymbal_products".

9. Crea una instancia elástica

Elasticsearch es una marca comercial de Elastic NV y no está afiliada a Google LLC. Usaremos Elasticsearch para la parte de búsqueda en el texto completo (FTS) de la búsqueda híbrida. Si tienes una instancia de Elasticsearch, puedes omitir los siguientes pasos y crear una clave de API personal o de usuario de solo lectura que AlloyDB pueda usar para acceder a tu clúster de Elasticsearch. De lo contrario, puedes iniciar una instancia de Elasticsearch en la VM que creaste anteriormente.

Establece una conexión SSH con la VM e instala Docker

sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Ahora puedes modificar el comando de Docker para que lo ejecute tu usuario.

sudo usermod -aG docker $USER
newgrp docker

En la terminal de la VM, ejecuta el siguiente comando para crear el contenedor elástico:

curl -fsSL https://elastic.co/start-local | sh

Resultado esperado (oculto)

🎉 Congrats, Elasticsearch and Kibana are installed and running in Docker!

🌐 Open your browser at http://localhost:5601

   Username: elastic
   Password: [password_value]

🔌 Elasticsearch API endpoint: http://localhost:9200
🔑 API key: [API Key]

Learn more at https://github.com/elastic/start-local

Copia el resultado y pégalo en el siguiente archivo.

nano elastic-last-run.txt

Presiona Ctrl + O, Intro y Ctrl + X para guardar y salir.

De forma predeterminada, el contenedor de Docker escuchará en http://localhost:9200 y podría tener problemas para recibir la solicitud externa de AlloyDB. Debemos configurar docker-compose.yml para que escuche en 9200:9200.

Después de ejecutar la secuencia de comandos, se debería crear un directorio elastic-start-local nuevo. Navega a este directorio y edita el Dockerfile.

cd elastic-start-local/
nano docker-compose.yml

Cerca de la parte superior, encontrarás

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:${ES_LOCAL_VERSION}
    container_name: ${ES_LOCAL_CONTAINER_NAME}
    volumes:
      - dev-elasticsearch:/usr/share/elasticsearch/data
    ports:
      - localhost:9200

Modifica el campo ports para que sea

    ports:
      - 9200:9200

Guarda y sal con Ctrl + O, Intro y, luego, Ctrl + X. Ahora, reinicia la pila.

docker compose up -d

Ahora, propagaremos la instancia de Elastic con nombres y descripciones de productos. Copia el CSV de productos de Cloud Storage a la VM.

gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv .

Resultado esperado

gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv .
Copying gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv to file://./cymbal_products.csv
  Completed files 1/1 | 1.4MiB/1.4MiB                                                                       

Average throughput: 147.9MiB/s

Ahora, crea una secuencia de comandos de Python para extraer el archivo CSV y darle formato a los datos en NDJSON para la carga masiva.

nano convert.py

Pega lo siguiente en el archivo:

import csv
import json

# Configuration
input_file = 'cymbal_products.csv'
output_file = 'products.json'
index_name = 'elasticindexdemo'

def convert():
    try:
        with open(input_file, mode='r', encoding='utf-8') as f_in, \
             open(output_file, mode='w', encoding='utf-8') as f_out:
            
            reader = csv.DictReader(f_in)
            
            count = 0
            for row in reader:
                metadata = {
                    "index": {
                        "_index": index_name,
                        "_id": row['uniq_id'].strip()
                    }
                }
                
                # 2. Data/Source line
                document = {
                    "uniq_id": row['uniq_id'].strip(),
                    "product_name": row['product_name'].strip(),
                    "product_description": row['product_description'].strip()
                }
                
                # Write to file
                f_out.write(json.dumps(metadata) + '\n')
                f_out.write(json.dumps(document) + '\n')
                count += 1
                
            print(f"Success: Processed {count} products.")
            print(f"Output saved to: {output_file}")

    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == "__main__":
    convert()

Guarda el archivo y ejecútalo

python3 convert.py

Resultado esperado

~$ python3 convert.py
Success: Processed 941 products.
Output saved to: products.json

Para la carga masiva de datos, debemos tomar la clave de API de nuestro archivo de ejecución anterior y usarla para autorizar el acceso a la instancia. Luego, se pasa el archivo JSON creado anteriormente. En situaciones de producción, es mejor definir el índice y los tipos de datos en Elasticsearch. Dado que el conjunto de datos de este codelab es pequeño, dejamos que Elasticsearch controle los datos. Primero, toma la clave de API del archivo y guárdala en una variable.

AUTH_HDR=$(grep "API key" elastic-last-run.txt | sed -e "s/^.*API key:[[:space:]]*/ApiKey /g")

Con la variable que guardamos, ejecuta el siguiente comando curl que sube los datos del JSON.

curl -s -X POST "localhost:9200/elasticindexdemo/_bulk?pretty" \
  -H "Content-Type: application/x-ndjson" \
  -H "Authorization: $AUTH_HDR" \
  --data-binary "@products.json"

Resultado esperado

~$ curl -s -X POST "localhost:9200/elasticindexdemo/_bulk?pretty" \
  -H "Content-Type: application/x-ndjson" \
  -H "Authorization: $AUTH_HDR" \
  --data-binary "@products.json"
{
  "errors" : false,
  "took" : 1003,
  "items" : [
    {
      "index" : {
        "_index" : "elasticindexdemo",
        "_id" : "a73d5f754f225ecb9fdc64232a57bc37",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 0,
        "_primary_term" : 1,
        "status" : 201
      }
    },
...]
}
Done

Por último, debemos obtener la clave de API de la instancia de Elasticsearch para poder guardarla y que AlloyDB la use. Ejecuta el siguiente comando y copia el valor de la clave de API.

cat elastic-last-run.txt

Con la clave de API, debemos crear un secreto en Secret Manager. En Cloud Shell, ejecuta el siguiente comando con tu clave de API:

echo -n "[YOUR_API_KEY_VALUE]" | \
gcloud secrets create elasticsearch \
    --replication-policy="automatic" \
    --data-file=-

10. Cómo crear un wrapper de datos externos en AlloyDB

Duración: 20:00

Para consultar los datos almacenados en Elasticsearch desde AlloyDB, debemos crear un wrapper de datos externos (FDW) para Elastic y una tabla externa. Anteriormente, almacenaste la clave de la API de Elastic en Secret Manager. Para que AlloyDB acceda al secreto, otorga a la cuenta de servicio el permiso requerido.

En Cloud Shell, otorga acceso a la cuenta de servicio al secreto elasticsearch.

gcloud secrets add-iam-policy-binding elasticsearch \
    --member="serviceAccount:service-$(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')@gcp-sa-alloydb.iam.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"

Resultado esperado

gcloud secrets add-iam-policy-binding elasticsearch \
    --member="serviceAccount:service-$(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')@gcp-sa-alloydb.iam.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"
Updated IAM policy for secret [elasticsearch].
bindings:
- members:
  - serviceAccount:service-257907437930@gcp-sa-alloydb.iam.gserviceaccount.com
  role: roles/secretmanager.secretAccessor
etag: BwZOghJiP5U=
version: 1

Navega al clúster de AlloyDB y abre AlloyDB Studio (también puedes usar psql para conectarte desde la VM). Accede a quickstart_db como el usuario postgres.

Habilita la extensión FDW

CREATE EXTENSION external_search_fdw;

Resultado esperado

Statement executed successfully

Para acceder a Elasticsearch, crea un servidor de datos externo. La dirección IP interna de la VM se puede encontrar en Compute Engine > Instancias de VM. Para la ruta de acceso al secreto, navega a Secret Manager y selecciona tu secreto. La ruta de acceso debería estar en la parte superior. Asegúrate de incluir /versions/latest para obtener la versión más reciente del secreto.

CREATE SERVER elastic_demo_server
FOREIGN DATA WRAPPER external_search_fdw
OPTIONS(
    server 'http://[VM INTERNAL IP ADDRESS]:9200',
    search_provider 'elastic',
    auth_method 'ApiKey',
    secret_path '[SECRET PATH]/versions/latest'
);

A continuación, define la tabla externa. Después de los metadatos, proporciona la definición del esquema de campo de Elasticsearch para que coincida con los datos cargados anteriormente. En la tabla remota, especifica el nombre del índice de Elastic.

CREATE FOREIGN TABLE elasticindexdemo (
    metadata external_search_fdw_schema.OpaqueMetadata,
    uniq_id TEXT,
    product_name TEXT,
    product_description TEXT
)
SERVER elastic_demo_server
OPTIONS(
    remote_table_name 'elasticindexdemo'
);

Crea una asignación de usuarios para el servidor

CREATE USER MAPPING FOR CURRENT_USER SERVER elastic_demo_server;

Ahora puedes probar la tabla externa

SELECT uniq_id, product_name
FROM elasticindexdemo
ORDER BY metadata <@> 'product_description:lamp' DESC
limit 10;

Resultado esperado

"uniq_id","product_name"
"59c05332f09426c23d8d005528e3c12e","CVL Mini Vintage Metal Lamp Shade: Black Metal with Punched Pattern"
"c24dd78c0d570105256e1bf1cb2fea9d","Better Homes & Gardens Tapered Drum Shade, White Box Pleat"
"7ba20db2bcfab28f88fc714d73af1eb8","4 Pack E27 Wireless Remote Control Light Lamp Bulb Holder Cap Socket Switch 30m"
"0fad1469ea9dfa80b35cfe5266b8bfe7","Star Projector Lamp, 360 Degree Star Night Light Romantic Room Rotating Cosmos Star Projuctor With USB Cable, Light Lamp Starry Moon Sky Night Projector Kid Bedroom Lamp"
"70b37e483ef3678078236d36954525ce","Lucille 10.5\""h Duck Egg Blue Empire Stitched Lamp Shade 7x10x8"
"b7a4b9151598f4cae7707cbedabe3c1b","10x12x8\"" SLIP UNO FITTER Hardback Shallow Drum Lamp Shade Textured Slate"
"5962cf47b88186eed76d14f6376882df","E27 To E14 Lampshade Lamp Light Shades Socket Reducing Ring Adapter Washer"
"7c54fdebfe0b1dd3f649741b8928a95b","iMounTEK LED Projector Lamp Kids Night Light Star Moon Projection Night Lamp 360\u00b0 Rotation Timer for Children Bedroom"
"4531201095c2653530747e215fcc1435","Home Concept Inc 11 Classics Brass Empire Lamp Shade"
"350527adb4299a015bcce74dee97805e","6 Colors LED Star Projector Lamp 360 Degree Romantic Rotating Night Cosmos Star Sky Moon Projector Kids Sleep Night Light For Children Gift Bedroom Decor"

11. Cómo usar la búsqueda híbrida

Duración: 15:00

Ahora que todo está configurado, podemos usar la función ai.hybrid_search() para combinar la búsqueda de vectores y la búsqueda de texto completo. Puedes obtener más información sobre la búsqueda híbrida en la documentación. Cuando se usa la búsqueda híbrida, de forma predeterminada, los resultados de la búsqueda usan el algoritmo de fusión de clasificación recíproca para ordenar los resultados de clasificación de varias búsquedas. Primero, probemos la búsqueda vectorial y la búsqueda híbrida de forma independiente para analizar sus diferencias.

La siguiente consulta realiza una búsqueda de vectores para encontrar productos similares a la cereza. El array proporciona una lista de búsquedas que se deben realizar. En este caso, solo usamos la búsqueda de vectores, pero más adelante proporcionaremos la búsqueda de vectores y la FTS.

SELECT id, score, cymbal_products.product_name, cymbal_products.product_description
FROM ai.hybrid_search(
  ARRAY[
      '{
        "data_type": "vector",
        "table_name": "cymbal_products",
        "key_column": "uniq_id",
        "vec_column": "product_embedding",
        "distance_operator": "public.<=>",
        "limit": 3,
        "query_vector": "ai.embedding(''text-embedding-005'', ''cherry'')::vector"
      }'::JSONB
  ]
) JOIN cymbal_products ON id = cymbal_products.uniq_id;

En el resultado, el cerezo es el primer resultado, pero observa que los dos siguientes también son árboles frutales. Esto se debe a que, cuando usamos la búsqueda de vectores en la columna product_description, encontramos coincidencias semánticas con nuestra condición de búsqueda.

"id","score","product_name","product_description"
"d536e9e823296a2eba198e52dd23e712","0.01639344262295082","Cherry Tree","This is a beautiful cherry tree that will produce delicious cherries. It is an deciduous tree that grows to be about 15 feet tall. The leaves are dark green in the summer and turn a beautiful red in the fall. Cherry trees are known for their beauty and their ability to provide shade and privacy. Cherry trees prefer a cool, moist climate and sandy soil. They are best suited for USDA zones 4-9."
"b70c44b1a38c0a2329fa583c9109a80f","0.016129032258064516","Peach Tree","This is a beautiful peach tree that will produce delicious peaches. It is an evergreen tree that grows to be about 20 feet tall. The leaves are dark green in the summer and turn a beautiful yellow in the fall. Peach trees are known for their beauty and their ability to provide shade and privacy. Peach trees prefer a cool, moist climate and sandy soil. They are best suited for USDA zones 2-9."
"23e41a71d63d8bbc9bdfa1d118cfddc5","0.015873015873015872","Apple Tree","This is a beautiful apple tree that will produce delicious apples. It is a deciduous tree that grows to be about 30 feet tall. The leaves are dark green in the summer and turn a beautiful red, orange, and yellow in the fall. Apple trees are known for their strength and durability. They are also a popular choice for shade trees. Apple trees prefer a cool, moist climate and loamy soil. They are best suited for USDA zones 4-8."

Para realizar una búsqueda de texto completo, ejecuta la siguiente consulta:

SELECT id, score, cymbal_products.product_name, cymbal_products.product_description
FROM ai.hybrid_search(
  ARRAY[
      '{
        "limit": 3,
        "data_type": "external_search_fdw",
        "table_name": "elasticindexdemo",
        "key_column": "uniq_id",
        "query_text_input": "product_description:(cherry)"
      }'::JSONB
  ]
) JOIN cymbal_products ON id = cymbal_products.uniq_id;

Observa en los resultados que, dado que la búsqueda de texto completo usa la concordancia exacta, los resultados muestran todo lo que contiene la palabra "cereza" en la descripción del producto.

"id","score","product_name","product_description"
"d536e9e823296a2eba198e52dd23e712","0.01639344262295082","Cherry Tree","This is a beautiful cherry tree that will produce delicious cherries. It is an deciduous tree that grows to be about 15 feet tall. The leaves are dark green in the summer and turn a beautiful red in the fall. Cherry trees are known for their beauty and their ability to provide shade and privacy. Cherry trees prefer a cool, moist climate and sandy soil. They are best suited for USDA zones 4-9."
"390cf08feac229e7b752709fd1f943b3","0.016129032258064516","Woven Round Placemat, Set of Twelve, Grass","...These placemats are great for special occasions and holidays, but are also perfect to accessorize your everyday place settings.|Measurements. 15-inch round diameter is the perfect size for most table sizes and shapes.|Pop Colors. Choose from 7 pop woven color placemats including: Black, Cherry, Grass, Taupe, Navy, Sun and Graphite."
"2c9aa7ac98c30abf78dd9c62a68a34e6","0.015873015873015872","48 Scented Wax Melts Wax Cubes: Jelly Belly Jelly Beans Candy Bulk Soy Wax Melts For Candle Warmer, Wax Warmers, Wax Melt Warmers In 8 Pack Set","...From These Flavors: Lemon Drop, Mixed Berry Smoothie, Sizzling Cinnamon, Crushed Pineapple, Juicy Pear, Cotton Candy, Toasted Marshmallow, French Vanilla, Watermelon, Red Apple, Very Cherry, Buttered Popcorn..."

Ahora puedes combinar la búsqueda semántica y la FTS para obtener resultados más significativos. Supongamos que queremos buscar un árbol que pueda crecer más que una casa y que sea de California. Dividimos la búsqueda para aprovechar la intención semántica en lugar de la coincidencia literal. La búsqueda de vectores se encarga de la parte descriptiva: "árbol que puede crecer más que una casa", ya que comprende el concepto de altura y escala sin necesidad de palabras clave exactas. Mientras tanto, la búsqueda de texto completo maneja "California" como un filtro estricto para garantizar que obtengamos una concordancia geográfica exacta en lugar de solo algo conceptualmente similar.

SELECT id, score, cymbal_products.product_name, cymbal_products.product_description
FROM ai.hybrid_search(
  ARRAY[
    '{
        "data_type": "vector",
        "table_name": "cymbal_products",
        "key_column": "uniq_id",
        "vec_column": "product_embedding",
        "distance_operator": "public.<=>",
        "limit": 3,
        "query_vector": "ai.embedding(''text-embedding-005'', ''tree that can grow taller than a house'')::vector"
      }'::JSONB,
      '{
        "limit": 3,
        "data_type": "external_search_fdw",
        "table_name": "elasticindexdemo",
        "key_column": "uniq_id",
        "query_text_input": "product_description:(California)"
      }'::JSONB
  ]
) JOIN cymbal_products ON id = cymbal_products.uniq_id;

Resultados esperados:

"id","score","product_name","product_description"
"a589fd36a8a20fd9472d2403d6ed692a","0.00819672631147241","California Redwood","This is a beautiful redwood tree that can grow to be over 300 feet tall. It is an evergreen tree that grows in the coastal forests of California. Redwoods are known for their beauty and their strength. They are best suited for USDA zones 7-10."
"ef9432802da24041594c2cf368dfb4d2","0.008064521129029258","Madrone","This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an evergreen tree that grows in the coastal forests of California. Madronas are known for their beauty and their bark. They are best suited for USDA zones 7-10."
"1360d8642bc218e4ea28e9c32b2e1721","0.007936512936504936","California Sycamore","This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is an deciduous tree that grows in the valleys and foothills of California. California sycamores are known for their beauty and their shade. They are best suited for USDA zones 7-10."

12. 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

Si usaste la versión de prueba de AlloyDB No borres el clúster de prueba si planeas probar otros labs y recursos con él. No podrás crear otro clúster de prueba en el mismo proyecto.

El clúster se destruye con la opción force que también borra todas las instancias que pertenecen al clúster.

En Cloud Shell, define el proyecto y las variables de entorno si te desconectaste y se perdieron todos los parámetros de configuración anteriores:

gcloud config set project <your project id>
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
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

13. Felicitaciones

¡Felicitaciones por completar el codelab!

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
  • Genera incorporaciones con Vertex AI
  • Cómo crear un índice de vectores de ScaNN para mejorar la búsqueda de vectores
  • Cómo crear un wrapper de datos externo (FDW) para Elasticsearch
  • Realiza una búsqueda híbrida combinando la búsqueda semántica en AlloyDB con la búsqueda en el texto completo en Elastic.

Próximos pasos

Puedes explorar más codelabs de AlloyDB en el sitio oficial de codelabs.