Un millón de vectores, cero bucles: Generación de embeddings a gran escala con AlloyDB

1. Descripción general

En este codelab, compilarás una aplicación de búsqueda de base de conocimiento escalable. En lugar de administrar una canalización de ETL compleja con bucles y secuencias de comandos de Python para generar embeddings de vectores, usarás AlloyDB AI para controlar la generación de embeddings de forma nativa en la base de datos con un solo comando de SQL.

d4324260c68d4a70.png

Qué compilarás

Una aplicación de base de datos de conocimiento "con capacidad de búsqueda" de alto rendimiento.

Qué aprenderás

Aprenderás a hacer lo siguiente:

  • Aprovisionar un clúster de AlloyDB y habilitar las extensiones de IA
  • Generar datos sintéticos (más de 50,000 filas) con SQL
  • Rellena los embeddings de vectores para todo el conjunto de datos con el procesamiento por lotes.
  • Configura activadores incrementales en tiempo real para incorporar automáticamente datos nuevos.
  • Realiza una búsqueda híbrida (filtros de vectores y SQL) para "Flexing Context".

Requisitos

  • Un navegador, como Chrome o Firefox
  • Un proyecto de Google Cloud con facturación habilitada.
  • Conocimientos básicos de SQL

2. Antes de comenzar

Crea un proyecto

  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.
  3. Usarás Cloud Shell, un entorno de línea de comandos que se ejecuta en Google Cloud. Haz clic en Activar Cloud Shell en la parte superior de la consola de Google Cloud.

Imagen del botón Activar Cloud Shell

  1. Una vez que te conectes a Cloud Shell, verifica que ya te autenticaste y que el proyecto se configuró con tu ID del proyecto con el siguiente comando:
gcloud auth list
  1. En Cloud Shell, ejecuta el siguiente comando para confirmar que el comando gcloud conoce tu proyecto.
gcloud config list project
  1. Si tu proyecto no está configurado, usa el siguiente comando para hacerlo:
gcloud config set project <YOUR_PROJECT_ID>
  1. Habilita las APIs necesarias: Sigue el vínculo y habilita las APIs.

Como alternativa, puedes usar el comando de gcloud para esto. Consulta la documentación para ver los comandos y el uso de gcloud.

gcloud services enable \
  alloydb.googleapis.com \
  compute.googleapis.com \
  cloudresourcemanager.googleapis.com \
  servicenetworking.googleapis.com \
  aiplatform.googleapis.com

Problemas potenciales y solución de problemas

El síndrome del "proyecto fantasma"

Ejecutaste gcloud config set project, pero estás viendo un proyecto diferente en la IU de la consola. Verifica el ID del proyecto en el menú desplegable de la parte superior izquierda.

La barricada de la facturación

Habilitaste el proyecto, pero olvidaste la cuenta de facturación. AlloyDB es un motor de alto rendimiento; no se iniciará si el "tanque de gasolina" (la facturación) está vacío.

Retraso en la propagación de la API

Hiciste clic en "Habilitar APIs", pero la línea de comandos aún dice Service Not Enabled. Espera 60 segundos. La nube necesita un momento para despertar sus neuronas.

Cuota Quags

Si usas una cuenta de prueba nueva, es posible que alcances una cuota regional para las instancias de AlloyDB. Si us-central1 falla, prueba con us-east1.

Agente de servicio "oculto"

A veces, al agente de servicio de AlloyDB no se le otorga automáticamente el rol aiplatform.user. Si tus consultas en SQL no pueden comunicarse con Gemini más adelante, este suele ser el motivo.

3. Configuración de la base de datos

En este lab, usaremos AlloyDB como la base de datos para los datos de prueba. Usa clústeres para contener todos los recursos, como bases de datos y registros. Cada clúster tiene una instancia principal que proporciona un punto de acceso a los datos. Las tablas contendrán los datos reales.

Creemos un clúster, una instancia y una tabla de AlloyDB en los que se cargará el conjunto de datos de prueba.

  1. Haz clic en el botón o copia el siguiente vínculo en el navegador en el que accediste con el usuario de la consola de Google Cloud.

  1. Una vez que se complete este paso, el repositorio se clonará en tu editor de Cloud Shell local y podrás ejecutar el siguiente comando desde la carpeta del proyecto (es importante que te asegures de estar en el directorio del proyecto):
sh run.sh
  1. Ahora, usa la IU (haz clic en el vínculo de la terminal o en el vínculo "Vista previa en la Web" de la terminal).
  2. Ingresa los detalles del ID del proyecto, el clúster y los nombres de las instancias para comenzar.
  3. Ve a tomar un café mientras se desplazan los registros y puedes leer cómo se hace esto en segundo plano aquí. Esto puede tardar entre 10 y 15 minutos.

Problemas potenciales y solución de problemas

El problema de la "paciencia"

Los clústeres de bases de datos son infraestructura pesada. Si actualizas la página o finalizas la sesión de Cloud Shell porque "parece bloqueada", es posible que obtengas una instancia "fantasma" que se aprovisione de forma parcial y que no se pueda borrar sin intervención manual.

Discrepancia de región

Si habilitaste las APIs en us-central1, pero intentas aprovisionar el clúster en asia-south1, es posible que tengas problemas de cuota o demoras en los permisos de la cuenta de servicio. Usa una sola región para todo el lab.

Clústeres zombies

Si ya usaste el mismo nombre para un clúster y no lo borraste, es posible que la secuencia de comandos indique que el nombre del clúster ya existe. Los nombres de los clústeres deben ser únicos dentro de un proyecto.

Tiempo de espera de Cloud Shell

Si tu pausa para el café dura 30 minutos, es posible que Cloud Shell entre en modo de suspensión y desconecte el proceso sh run.sh. Mantén la pestaña activa.

4. Aprovisionamiento de esquemas

En este paso, abordaremos lo siguiente:

879263c907f3cac6.png

Una vez que tu clúster y tu instancia de AlloyDB estén en ejecución, ve al editor de SQL de AlloyDB Studio para habilitar las extensiones de IA y aprovisionar el esquema.

1e3ac974b18a8113.png

Es posible que debas esperar a que se termine de crear la instancia. Una vez que lo esté, accede a AlloyDB con las credenciales que creaste cuando creaste el clúster. Usa los siguientes datos para autenticarte en PostgreSQL:

  • Nombre de usuario : "postgres"
  • Base de datos : "postgres"
  • Contraseña : "alloydb" (o la que hayas establecido en el momento de la creación)

Una vez que te autentiques correctamente en AlloyDB Studio, los comandos de SQL se ingresarán en el Editor. Puedes agregar varias ventanas del Editor con el signo más que se encuentra a la derecha de la última ventana.

28cb9a8b6aa0789f.png

Ingresarás comandos para AlloyDB en las ventanas del editor y usarás las opciones Run, Format y Clear según sea necesario.

Habilita las extensiones

Para compilar esta app, usaremos las extensiones pgvector y google_ml_integration. La extensión pgvector te permite almacenar y buscar embeddings de vectores. La extensión google_ml_integration proporciona funciones que usas para acceder a los extremos de predicción de Vertex AI y obtener predicciones en SQL. Habilita estas extensiones ejecutando los siguientes DDL:

CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;

Crea una tabla

Necesitamos un conjunto de datos para demostrar la escala. En lugar de importar un archivo CSV, generaremos 50,000 filas de "artículos de ayuda" sintéticos de forma instantánea con SQL.

Puedes crear una tabla con la siguiente sentencia DDL en AlloyDB Studio:

-- 1. Create the table
CREATE TABLE help_articles (
    id SERIAL PRIMARY KEY,
    title TEXT,
    category TEXT,
    product_version TEXT,
    content_body TEXT,
    embedding vector(768) -- Dimension for text-embedding-005
);

-- 2. Generate 50,000 rows of synthetic data
INSERT INTO help_articles (title, category, product_version, content_body)
SELECT
    'Help Article ' || i,
    CASE 
        WHEN i % 3 = 0 THEN 'Billing' 
        WHEN i % 3 = 1 THEN 'Technical' 
        ELSE 'General' 
    END,
    CASE 
        WHEN i % 2 = 0 THEN '2.0' 
        ELSE '1.0' 
    END,
    'This article covers common issues regarding ' || 
    CASE 
        WHEN i % 3 = 0 THEN 'payment failures, invoice disputes, and credit card updates.'
        WHEN i % 3 = 1 THEN 'connection timeouts, latency issues, and API errors.'
        ELSE 'account profile settings, password resets, and user roles.' 
    END
FROM generate_series(1, 50000) AS i;

La columna item_vector permitirá almacenar los valores vectoriales del texto.

Verifica los datos:

SELECT count(*) FROM help_articles;
-- Output: 50000

Habilita las marcas de base de datos

Ve a la consola de configuración de la instancia, haz clic en "Editar instancia principal", ve a Configuración avanzada y haz clic en "Agregar marcas de base de datos".

  1. Verifica que la marca google_ml_integration.enable_model_support esté activada:

De lo contrario, ingrésala en el menú desplegable de marcas, establécela en "ACTIVADA" y actualiza la instancia.

  1. Verifica que la marca google_ml_integration.enable_faster_embedding_generation esté activada:

Si no es así, ingrésala en el menú desplegable de marcas, establécela en "ACTIVADA" y actualiza la instancia.

Sigue estos pasos para configurar las marcas de base de datos:

  1. En la consola de Google Cloud, ve a la página Clústeres.

Ir a los clústeres

  1. Haz clic en un clúster en la columna Nombre del recurso.
  2. En la página Descripción general, ve a Instancias en tu clúster, selecciona una instancia y, luego, haz clic en Editar.
  3. Agrega, modifica o borra una marca de base de datos de tu instancia:

Cómo agregar una marca

  1. Para agregar una marca de base de datos a tu instancia, haz clic en Agregar marca.
  2. Selecciona una marca de la lista Nueva marca de base de datos.
  3. Proporciona un valor para la marca.
  4. Haz clic en Listo.
  5. Haz clic en Actualizar instancia.
  6. Verifica que la extensión google_ml_integration sea la versión 1.5.2 o una posterior:

Para verificar la versión de tu extensión, ejecuta el siguiente comando:

SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';

Si necesitas actualizar la extensión a una versión posterior, usa el siguiente comando:

ALTER EXTENSION google_ml_integration UPDATE;

Otorgar permiso

  1. Para permitir que un usuario administre la generación de incorporaciones automáticas, otorga permisos INSERT, UPDATE y DELETE en las tablas google_ml.embed_gen_progress y google_ml.embed_gen_settings:
GRANT INSERT, UPDATE, DELETE ON google_ml.embed_gen_progress TO postgres;

"postgres" es el USER_NAME para el que se otorgan los permisos.

  1. Ejecuta la siguiente sentencia para otorgar el permiso de ejecución en la función "embedding":
GRANT EXECUTE ON FUNCTION embedding TO postgres;

Otorga el rol de usuario de Vertex AI a la cuenta de servicio de AlloyDB

En la consola de IAM de Google Cloud, otorga a la cuenta de servicio de AlloyDB (que se ve así: service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com) acceso al rol "Usuario de Vertex AI". PROJECT_NUMBER tendrá tu número de proyecto.

Como alternativa, puedes ejecutar el siguiente comando desde la terminal de Cloud Shell:

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"

Problemas potenciales y solución de problemas

El bucle de la "amnesia de contraseñas"

Si usaste la configuración de "Un clic" y no recuerdas tu contraseña, ve a la página de información básica de la instancia en la consola y haz clic en "Editar" para restablecer la contraseña de postgres.

Error "No se encontró la extensión"

Si CREATE EXTENSION falla, suele deberse a que la instancia aún se encuentra en un estado de "Mantenimiento" o "Actualización" desde el aprovisionamiento inicial. Verifica si se completó el paso de creación de la instancia y espera unos segundos si es necesario.

5. Generación de vectores "One-Shot"

Esta es la parte central del lab. En lugar de escribir un bucle de Python para procesar estas 50,000 filas, usaremos la función ai.initialize_embeddings.

Este comando único realiza dos acciones:

  1. Rellena todas las filas existentes.
  2. Crea un activador para incorporar automáticamente las filas futuras.

Ejecuta la siguiente sentencia de SQL desde el editor de consultas de AlloyDB

CALL ai.initialize_embeddings(
  model_id => 'text-embedding-005',
  table_name => 'help_articles',
  content_column => 'content_body',
  embedding_column => 'embedding',
  incremental_refresh_mode => 'transactional'
);

Verifica los embeddings

Verifica que la columna embedding ahora esté propagada:

SELECT id, left(content_body, 30), substring(embedding::text, 1, 30) as vector_partial 
FROM help_articles;

Deberías ver un resultado similar al siguiente:

a872b8926a164275.png

¿Qué acaba de suceder?

  1. Relleno a gran escala: Revisa automáticamente las 50,000 filas existentes y genera incorporaciones a través de Vertex AI.
  2. Automatización: Al configurar incremental_refresh_mode => 'transactional', AlloyDB configura automáticamente los activadores internos. Cualquier fila nueva que se inserte en help_articles tendrá su embedding generado de forma instantánea.
  3. De manera opcional, puedes establecer incremental_refresh_mode => ‘None' para que solo puedas obtener la sentencia para realizar actualizaciones en forma masiva y llamar de forma manual a ai.refresh_embeddings() para actualizar todas las incorporaciones de filas.

Acabas de reemplazar una cola de Kafka, un trabajador de Python y una secuencia de comandos de migración por 6 líneas de SQL. Aquí tienes la documentación oficial detallada de todos los atributos.

Prueba de activadores en tiempo real

Verifiquemos que la automatización "Zero Loop" funcione para los datos nuevos.

  1. Inserta una fila nueva:
INSERT INTO help_articles (title, category, product_version, content_body)
VALUES ('New Scaling Guide', 'Technical', '2.0', 'How to scale AlloyDB to millions of transactions.');
  1. Verifica de inmediato:
SELECT embedding FROM help_articles WHERE title = 'New Scaling Guide';

Resultado:

Deberías ver el vector generado de forma instantánea sin ejecutar ninguna secuencia de comandos externa.

Ajusta el tamaño del lote

Actualmente, AlloyDB establece el tamaño de lote predeterminado en 50 de forma predeterminada. Si bien los valores predeterminados funcionan muy bien desde el principio, AlloyDB les brinda a los usuarios el control para ajustar la configuración perfecta para tu modelo y conjunto de datos únicos.

CALL ai.initialize_embeddings(
  model_id => 'text-embedding-005',
  table_name => 'help_articles',
  content_column => 'content_body',
  embedding_column => 'embedding',
  incremental_refresh_mode => 'transactional',
  batch_size => 20
);

Sin embargo, los usuarios deben tener en cuenta los límites de cuota que pueden limitar el rendimiento. Para revisar las cuotas recomendadas de AlloyDB, consulta la sección "Antes de comenzar" en la documentación.

Problemas potenciales y solución de problemas

La brecha de propagación de IAM

Ejecutaste el comando de IAM gcloud, pero el comando CALL de SQL sigue fallando con un error de permiso. Los cambios de IAM pueden tardar un poco en propagarse por la red troncal de Google. No te compliques.

Discrepancia de dimensiones de vectores

La tabla help_articles se establece en VECTOR(768) en la columna content_body. Si intentas usar un modelo diferente (como un modelo de 1,536 dimensiones) más adelante, tus inserciones fallarán. Se adhiere a text-embedding-005.

6. Búsqueda de contexto flexible

Ahora, realizaremos una búsqueda híbrida. Combinamos la comprensión semántica (vector) con la lógica empresarial (filtros de SQL).

Ejecuta esta consulta para encontrar problemas de facturación específicos de la versión 2.0 del producto:

SELECT
  title,
  left(content_body, 100) as content_snippet,
  1 - (embedding <=> embedding('text-embedding-005', 'Invoice did not go through')::vector) as relevance
FROM help_articles
WHERE category = 'Billing'  -- Hard SQL Filter
  AND product_version = '2.0' -- Hard SQL Filter
ORDER BY relevance DESC
LIMIT 5;

Este es el contexto de Flexing. La búsqueda se "flexibiliza" para comprender la intención del usuario ("problemas de facturación") y, al mismo tiempo, respetar las restricciones comerciales rígidas (versión 2.0).

f0fdb50d6195c462.png

Por qué es una ventaja para las startups y las migraciones

  1. Cero deuda de infraestructura: No creaste una base de datos vectorial independiente (Pinecone o Milvus). No escribiste un trabajo de ETL independiente. Todo está en Postgres.
  2. Actualizaciones en tiempo real: Con el modo "transaccional", tu índice de la Búsqueda nunca queda desactualizado. En el momento en que se confirman los datos, están listos para los vectores.
  3. Escalabilidad: AlloyDB se basa en la infraestructura de Google. Puede controlar la generación masiva de millones de vectores más rápido de lo que podría hacerlo tu secuencia de comandos de Python.

Problemas potenciales y solución de problemas

Problema potencial de rendimiento en producción

Problema: Es rápido para 50,000 filas. Muy lento para 1 millón de filas si el filtro de categoría no es lo suficientemente selectivo.Solución:Agrega un índice de vectores: Para la escala de producción, debes crear un índice:CREATE INDEX ON help_articles USING hnsw (embedding vector_cosine_ops);Verifica el uso del índice: Ejecuta EXPLAIN ANALYZE SELECT ... para asegurarte de que la base de datos use el índice y no realice un análisis secuencial.

El desastre de la "falta de coincidencia de modelos"

Problema: Inicializaste la columna con text-embedding-005 en el procedimiento CALL. Si usas accidentalmente un modelo diferente (p.ej., text-embedding-004 o un modelo de OSS) en la función de consulta SELECT embedding('model-name', ...), las dimensiones podrían coincidir (768), pero el espacio vectorial será totalmente diferente.La consulta se ejecuta sin errores, pero los resultados son completamente irrelevantes (puntuaciones de relevancia sin sentido).Solución de problemas:Asegúrate de que el model_id en ai.initialize_embeddings coincida exactamente con el model_id en tu consulta SELECT.

El resultado "Vacío silencioso" (filtrado excesivo)

Problema: La búsqueda híbrida es una operación "AND". Requiere Coincidencia semántica Y Coincidencia de SQL.Si un usuario busca "Ayuda con la facturación", pero la columna product_version tiene ‘2.0.1' en lugar de ‘2.0', el resultado es cero filas, incluso si la coincidencia de vectores es del 99%.Solución de problemas:

  • Ejecuta la consulta sin la ordenación de vectores primero para ver si los filtros de SQL (WHERE category...) realmente devuelven datos.
  • Verifica si se distingue entre mayúsculas y minúsculas (Billing frente a billing).

4. Errores de permisos o cuotas (el error 500)

Problema:La función embedding() en la cláusula SELECT realiza una llamada de red en tiempo real a Vertex AI.Si la cuenta de servicio de la base de datos pierde el rol de usuario de Vertex AI o si alcanzas la cuota de la API de Vertex AI (QPM), fallará toda la consulta en SQL.Solución de problemas:

  • Verifica Cloud Logging para AlloyDB.
  • Asegúrate de que el rol de IAM siga activo.
  • Une la función en un bloque TRY/CATCH en los procedimientos almacenados si se necesita una alta resiliencia.

5. Embeddings nulos

Problema:Si insertas datos antes de que el modelo se inicialice por completo o si falla el trabajador en segundo plano, es posible que algunas filas tengan NULL en la columna embedding.NULL <=> Vector devuelve NULL. Estas filas desaparecen del orden de clasificación.Solución de problemas:

  • Ejecuta SELECT count(*) FROM help_articles WHERE embedding IS NULL; para verificar que la cobertura sea del 100%.

7. Limpia

Cuando termines este lab, no olvides borrar el clúster y la instancia de AlloyDB.

Debería limpiar el clúster junto con sus instancias.

8. Felicitaciones

Creaste correctamente una aplicación de búsqueda de base de conocimiento escalable. En lugar de administrar una canalización de ETL compleja con bucles y secuencias de comandos de Python para generar embeddings de vectores, usaste AlloyDB AI para controlar la generación de embeddings de forma nativa en la base de datos con un solo comando de SQL.

Temas abordados

  • Eliminamos el "bucle for de Python" para el procesamiento de datos.
  • Generamos 50,000 vectores con un comando de SQL.
  • Automatizamos la generación de vectores futuros con activadores.
  • Realizamos una búsqueda híbrida.

Próximos pasos