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 en la base de conocimiento escalable. En lugar de administrar una canalización de ETL compleja con secuencias de comandos y bucles de Python para generar embeddings de vectores, usarás AlloyDB AI para controlar la generación de embeddings de forma nativa dentro de la base de datos con un solo comando SQL.

d4324260c68d4a70.png

Qué compilarás

Aplicación de base de datos de conocimiento "buscable" y de alto rendimiento.

Qué aprenderás

Aprenderás a hacer lo siguiente:

  • Aprovisiona un clúster de AlloyDB y habilita las extensiones de IA.
  • Generar datos sintéticos (más de 50,000 filas) con SQL
  • Genera incorporaciones 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.
  1. 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 hayas conectado a Cloud Shell, verifica que ya te autenticaste y que el proyecto se configuró con tu ID de 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 "Proyecto Fantasma"

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

La barricada de facturación

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

Retraso de 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 activar sus neuronas.

Cuota de Quags

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

Agente de servicio"oculto"

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

3. Configuración de la base de datos

En este lab, usaremos AlloyDB como la base de datos para los datos de prueba. Utiliza 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 como usuario a la consola de Google Cloud.

  1. Una vez que se complete este paso, el repo se clonará en tu editor local de Cloud Shell 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 "preview on 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. Aquí puedes leer cómo se hace esto en segundo plano. 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 una infraestructura pesada. Si actualizas la página o finalizas la sesión de Cloud Shell porque "parece que se detuvo", es posible que termines con una instancia "fantasma" que se aprovisionó parcialmente y que es imposible borrar sin intervención manual.

Incongruencia de región

Si habilitaste tus 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. Mantén una sola región para todo el lab.

Clústeres de zombis

Si antes 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 descanso para tomar 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 tengas en funcionamiento tu clúster y tu instancia de AlloyDB, dirígete 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 termine de crearse la instancia. Una vez que lo hagas, 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 configurado en el momento de la creación)

Una vez que te autentiques correctamente en AlloyDB Studio, ingresa los comandos SQL 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 ventanas del editor, y usarás las opciones Ejecutar, Formatear y Borrar según sea necesario.

Habilitar 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 al instante con SQL.

Puedes crear una tabla con la siguiente instrucción 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á el almacenamiento de los valores vectoriales del texto.

Verifica los datos:

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

Cómo habilitar marcas de base de datos

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

  1. Verifica que la marca de verificación google_ml_integration.enable_model_support esté activada:

De lo contrario, ingrésalo en el menú desplegable de marcas, configúralo como "ON" y actualiza la instancia.

  1. Verifica que la marca de verificación google_ml_integration.enable_faster_embedding_generation esté activada:

De lo contrario, ingrésalo en el menú desplegable de marcas, configúralo como "ON" y actualiza la instancia.

Sigue estos pasos para configurar marcas de bases 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. Sigue estos pasos para agregar, modificar o borrar 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 New database flag.
  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, usa el siguiente comando:

SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';

Si necesitas actualizar la extensión a una más alta, usa el siguiente comando:

ALTER EXTENSION google_ml_integration UPDATE;

Otorgar permiso

  1. Para permitir que un usuario administre la generación automática de incorporaciones, otorga permisos de 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 instrucción para otorgar 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 de la siguiente manera: 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 "amnesia de contraseña"

Si usaste la configuración "Con 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.

El error "No se encontró la extensión"

Si CREATE EXTENSION falla, suele deberse a que la instancia aún se encuentra en estado de "Mantenimiento" o "Actualización" desde el aprovisionamiento inicial. Comprueba 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"

Este es el núcleo del lab. En lugar de escribir un bucle de Python para procesar estas 50,000 filas, usaremos la función ai.initialize_embeddings.

Este único comando realiza dos acciones:

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

Ejecuta la siguiente instrucción 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 las incorporaciones

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é pasó?

  1. Carga retroactiva a gran escala: Realiza un análisis automático de las 50,000 filas existentes y genera incorporaciones a través de Vertex AI.
  2. Automatización: Cuando se establece incremental_refresh_mode => "transactional", AlloyDB configura automáticamente los activadores internos. Cualquier fila nueva que se inserte en help_articles tendrá su incorporación generada al instante.
  3. De manera opcional, puedes establecer incremental_refresh_mode => "None" para que solo puedas obtener la instrucción para realizar actualizaciones masivas y llamar manualmente 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 con 6 líneas de SQL. Aquí se encuentra la documentación oficial detallada de todos los atributos.

Prueba de activador en tiempo real

Verifiquemos que la automatización de "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 lo siguiente:
SELECT embedding FROM help_articles WHERE title = 'New Scaling Guide';

Resultado:

Deberías ver el vector generado al instante sin ejecutar ninguna secuencia de comandos externa.

Cómo ajustar el tamaño del lote

Actualmente, AlloyDB establece el tamaño del lote en 50 de forma predeterminada. Si bien los valores predeterminados funcionan muy bien de inmediato, AlloyDB sigue brindando a los usuarios el control para ajustar la configuración perfecta para su 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 restringir 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 de SQL CALL sigue fallando con un error de permiso. Los cambios de IAM pueden tardar un poco en propagarse a través de la red troncal de Google. Respira.

Vector Dimension Mismatch

La tabla help_articles se establece en VECTOR(768)en la columna content_body. Si intentas usar un modelo diferente (como un modelo de 1536 dim) más adelante, tus inserciones se desbordarán. Mantén text-embedding-005.

6. Flexibilidad de la Búsqueda contextual

Ahora realizamos una búsqueda híbrida. Combinamos la comprensión semántica (Vector) con la lógica empresarial (filtros 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 flexibilidad. La búsqueda se "flexibiliza" para comprender la intención del usuario ("problemas de facturación") y, al mismo tiempo, respeta las restricciones comerciales rígidas (versión 2.0).

f0fdb50d6195c462.png

Por qué esta solución es ideal para las migraciones y las empresas emergentes

  1. Sin deuda de infraestructura: No creaste una base de datos de vectores independiente (Pinecone/Milvus). No escribiste un trabajo de ETL independiente. Todo está en Postgres.
  2. Actualizaciones en tiempo real: Si usas el modo "transaccional", tu índice de búsqueda nunca estará desactualizado. En el momento en que se confirman los datos, están listos para convertirse en 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 la producción

Problema: Es rápido para 50,000 filas. Es muy lento para 1 millón de filas si el filtro de categorías 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 esté usando el índice y no realizando un análisis secuencial.

El desastre de la "incompatibilidad 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 incorporación de la consulta SELECT embedding('model-name', …), es posible que las dimensiones coincidan (768), pero el espacio vectorial será completamente diferente. La consulta se ejecuta sin errores, pero los resultados son completamente irrelevantes (puntuaciones de relevancia basura). 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 de "Silent Empty" (filtrado excesivo)

Problema: La búsqueda híbrida es una operación "Y". Requiere concordancia semántica Y concordancia 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 concordancia de vectores es del 99%.Solución de problemas:

  • Primero, ejecuta la consulta sin la ordenación de vectores para ver si los filtros SQL (WHERE category...) realmente devuelven datos.
  • Comprueba si hay distinción entre mayúsculas y minúsculas (Billing frente a billing).

4. Errores de permisos o de cuota (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 SQL.Solución de problemas:

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

5. Incorporaciones nulas

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

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

Temas abordados

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

Próximos pasos