Un million de vecteurs, zéro boucle : générer des embeddings à grande échelle avec AlloyDB

1. Présentation

Dans cet atelier de programmation, vous allez créer une application de recherche de base de connaissances évolutive. Au lieu de gérer un pipeline ETL complexe avec des scripts Python et des boucles pour générer des embeddings vectoriels, vous allez utiliser AlloyDB AI pour gérer la génération d'embeddings de manière native dans la base de données à l'aide d'une seule commande SQL.

d4324260c68d4a70.png

Ce que vous allez faire

Une application de base de données de connaissances "consultable" hautes performances.

Points abordés

Vous allez apprendre à effectuer les tâches suivantes :

  • Provisionner un cluster AlloyDB et activer les extensions d'IA
  • Générer des données synthétiques (plus de 50 000 lignes) à l'aide de SQL
  • Rétroremplissez les embeddings vectoriels pour l'ensemble de données complet à l'aide du traitement par lot.
  • Configurez des déclencheurs incrémentiels en temps réel pour intégrer automatiquement les nouvelles données.
  • Effectuez une recherche hybride (filtres vectoriels et SQL) pour "Flexing Context".

Conditions requises

  • Un navigateur (Chrome ou Firefox, par exemple)
  • Un projet Google Cloud avec facturation activée.
  • Connaître les principes de base de SQL

2. Avant de commencer

Créer un projet

  1. Dans la console Google Cloud, sur la page du sélecteur de projet, sélectionnez ou créez un projet Google Cloud.
  2. Assurez-vous que la facturation est activée pour votre projet Cloud. Découvrez comment vérifier si la facturation est activée sur un projet.
  3. Vous allez utiliser Cloud Shell, un environnement de ligne de commande exécuté dans Google Cloud. Cliquez sur "Activer Cloud Shell" en haut de la console Google Cloud.

Image du bouton "Activer Cloud Shell"

  1. Une fois connecté à Cloud Shell, vérifiez que vous êtes déjà authentifié et que le projet est défini sur votre ID de projet à l'aide de la commande suivante :
gcloud auth list
  1. Exécutez la commande suivante dans Cloud Shell pour vérifier que la commande gcloud reconnaît votre projet :
gcloud config list project
  1. Si votre projet n'est pas défini, utilisez la commande suivante pour le définir :
gcloud config set project <YOUR_PROJECT_ID>
  1. Activez les API requises : suivez ce lien et activez les API.

Vous pouvez également utiliser la commande gcloud pour cela. Consultez la documentation pour connaître les commandes gcloud ainsi que leur utilisation.

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

Problèmes et dépannage

Le syndrome du "projet fantôme"

Vous avez exécuté gcloud config set project, mais vous consultez un autre projet dans l'interface utilisateur de la console. Vérifiez l'ID du projet dans le menu déroulant en haut à gauche.

La barricade de la facturation

Vous avez activé le projet, mais vous avez oublié le compte de facturation. AlloyDB est un moteur hautes performances. Il ne démarrera pas si le "réservoir" (la facturation) est vide.

Délai de propagation de l'API

Vous avez cliqué sur "Activer les API", mais la ligne de commande indique toujours Service Not Enabled. Patientez 60 secondes. Le cloud a besoin d'un moment pour réveiller ses neurones.

Quota Quags

Si vous utilisez un tout nouveau compte d'essai, vous risquez d'atteindre un quota régional pour les instances AlloyDB. Si us-central1 échoue, essayez us-east1.

Agent de service "masqué"

Il arrive que l'agent de service AlloyDB ne se voie pas automatiquement attribuer le rôle aiplatform.user. Si vos requêtes SQL ne peuvent pas communiquer avec Gemini par la suite, c'est généralement à cause de cela.

3. Configuration de la base de données

Dans cet atelier, nous allons utiliser AlloyDB comme base de données pour les données de test. Il utilise des clusters pour stocker toutes les ressources, telles que les bases de données et les journaux. Chaque cluster possède une instance principale qui fournit un point d'accès aux données. Les tables contiendront les données réelles.

Créons un cluster, une instance et une table AlloyDB dans lesquels l'ensemble de données de test sera chargé.

  1. Cliquez sur le bouton ou copiez le lien ci-dessous dans le navigateur où vous êtes connecté à la console Google Cloud.

  1. Une fois cette étape terminée, le dépôt sera cloné dans votre éditeur Cloud Shell local et vous pourrez exécuter la commande ci-dessous à partir du dossier du projet (assurez-vous d'être dans le répertoire du projet) :
sh run.sh
  1. Utilisez maintenant l'interface utilisateur (en cliquant sur le lien dans le terminal ou sur le lien "Aperçu sur le Web" dans le terminal).
  2. Saisissez l'ID de votre projet, ainsi que les noms du cluster et de l'instance pour commencer.
  3. Allez prendre un café pendant que les journaux défilent. Vous pouvez lire comment cela se passe en arrière-plan ici. Cela peut prendre environ 10 à 15 minutes.

Problèmes et dépannage

Le problème de la "patience"

Les clusters de bases de données sont des infrastructures lourdes. Si vous actualisez la page ou mettez fin à la session Cloud Shell parce qu'elle "semble bloquée", vous risquez de vous retrouver avec une instance "fantôme" partiellement provisionnée et impossible à supprimer sans intervention manuelle.

Incompatibilité de région

Si vous avez activé vos API dans us-central1, mais que vous essayez de provisionner le cluster dans asia-south1, vous risquez de rencontrer des problèmes de quota ou des retards d'autorisation de compte de service. Utilisez une seule région pour l'ensemble de l'atelier.

Clusters zombies

Si vous avez déjà utilisé le même nom pour un cluster et que vous ne l'avez pas supprimé, le script peut indiquer que le nom du cluster existe déjà. Les noms de clusters doivent être uniques au sein d'un projet.

Délai d'expiration de Cloud Shell

Si votre pause café dure 30 minutes, Cloud Shell risque de se mettre en veille et de déconnecter le processus sh run.sh. Laissez l'onglet actif.

4. Provisionnement de schémas

Dans cette étape, nous allons aborder les points suivants :

879263c907f3cac6.png

Une fois que votre cluster et votre instance AlloyDB sont en cours d'exécution, accédez à l'éditeur SQL d'AlloyDB Studio pour activer les extensions d'IA et provisionner le schéma.

1e3ac974b18a8113.png

Vous devrez peut-être attendre que la création de votre instance soit terminée. Une fois l'instance créée, connectez-vous à AlloyDB à l'aide des identifiants que vous avez créés lors de la création du cluster. Utilisez les données suivantes pour vous authentifier auprès de PostgreSQL :

  • Nom d'utilisateur : "postgres"
  • Base de données : "postgres"
  • Mot de passe : "alloydb" (ou celui que vous avez défini lors de la création)

Une fois que vous vous êtes authentifié dans AlloyDB Studio, les commandes SQL sont saisies dans l'éditeur. Vous pouvez ajouter plusieurs fenêtres de l'éditeur à l'aide du signe plus situé à droite de la dernière fenêtre.

28cb9a8b6aa0789f.png

Vous saisirez des commandes pour AlloyDB dans les fenêtres de l'éditeur, en utilisant les options "Exécuter", "Format" et "Effacer" si nécessaire.

Activer les extensions

Pour créer cette application, nous utiliserons les extensions pgvector et google_ml_integration. L'extension pgvector vous permet de stocker et de rechercher des embeddings vectoriels. L'extension google_ml_integration fournit les fonctions que vous utilisez pour accéder aux points de terminaison de prédiction Vertex AI afin d'obtenir des prédictions en SQL. Activez ces extensions en exécutant les LDD suivantes :

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

Créer une table

Nous avons besoin d'un ensemble de données pour illustrer le scaling. Au lieu d'importer un fichier CSV, nous allons générer instantanément 50 000 lignes d'articles d'aide synthétiques à l'aide de SQL.

Vous pouvez créer une table à l'aide de l'instruction LDD ci-dessous dans 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 colonne item_vector permettra de stocker les valeurs vectorielles du texte.

Vérifiez les données :

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

Activer les indicateurs de base de données

Accédez à la console de configuration de l'instance, cliquez sur "Modifier l'instance principale", accédez à "Configuration avancée", puis cliquez sur "Ajouter des indicateurs de base de données".

  1. Vérifiez que le flag google_ml_integration.enable_model_support est activé :

Si ce n'est pas le cas, saisissez-le dans le menu déroulant des options, définissez-le sur "ON" et mettez à jour l'instance.

  1. Vérifiez que le flag google_ml_integration.enable_faster_embedding_generation est activé :

Si ce n'est pas le cas, saisissez-le dans le menu déroulant des options, définissez-le sur "ON" et mettez à jour l'instance.

Étapes à suivre pour configurer des indicateurs de base de données :

  1. Dans la console Google Cloud, accédez à la page "Clusters".

accéder aux clusters

  1. Cliquez sur un cluster dans la colonne Nom de la ressource.
  2. Sur la page Présentation, accédez à Instances dans votre cluster, sélectionnez une instance, puis cliquez sur Modifier.
  3. Ajoutez, modifiez ou supprimez un indicateur de base de données de votre instance :

Ajouter un indicateur

  1. Pour ajouter un indicateur de base de données à votre instance, cliquez sur Ajouter un indicateur.
  2. Sélectionnez un indicateur dans la liste "Nouvel indicateur de base de données".
  3. Indiquez une valeur pour l'option.
  4. Cliquez sur "OK".
  5. Cliquez sur Mettre à jour l'instance.
  6. Vérifiez que l'extension google_ml_integration est de version 1.5.2 ou ultérieure :

Pour vérifier la version de votre extension, exécutez la commande suivante :

SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';

Si vous devez mettre à jour l'extension vers une version ultérieure, utilisez la commande suivante :

ALTER EXTENSION google_ml_integration UPDATE;

Accorder l'autorisation

  1. Pour permettre à un utilisateur de gérer la génération automatique d'embeddings, accordez-lui les autorisations INSERT, UPDATE et DELETE sur les tables google_ml.embed_gen_progress et google_ml.embed_gen_settings :
GRANT INSERT, UPDATE, DELETE ON google_ml.embed_gen_progress TO postgres;

"postgres" est le USER_NAME auquel les autorisations sont accordées.

  1. Exécutez l'instruction ci-dessous pour accorder l'autorisation d'exécution sur la fonction "embedding" :
GRANT EXECUTE ON FUNCTION embedding TO postgres;

Attribuer le rôle Utilisateur Vertex AI au compte de service AlloyDB

Dans la console Google Cloud IAM, accordez au compte de service AlloyDB (qui ressemble à ceci : service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com) l'accès au rôle "Utilisateur Vertex AI". PROJECT_NUMBER sera remplacé par votre numéro de projet.

Vous pouvez également exécuter la commande ci-dessous à partir du terminal 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"

Problèmes et dépannage

La boucle "Oubli du mot de passe"

Si vous avez utilisé la configuration "en un clic" et que vous ne vous souvenez plus de votre mot de passe, accédez à la page d'informations de base de l'instance dans la console, puis cliquez sur "Modifier" pour réinitialiser le mot de passe postgres.

Erreur "Extension introuvable"

Si CREATE EXTENSION échoue, c'est souvent parce que l'instance est toujours dans un état "Maintenance" ou "Mise à jour" depuis le provisionnement initial. Vérifiez si l'étape de création de l'instance est terminée et attendez quelques secondes si nécessaire.

5. Génération de vecteurs "One-Shot"

C'est le cœur de l'atelier. Au lieu d'écrire une boucle Python pour traiter ces 50 000 lignes, nous allons utiliser la fonction ai.initialize_embeddings.

Cette commande unique effectue deux actions :

  1. Rétroremplit toutes les lignes existantes.
  2. Crée un déclencheur pour intégrer automatiquement les futures lignes.

Exécutez l'instruction SQL ci-dessous dans l'éditeur de requête 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'
);

Vérifier les embeddings

Vérifiez que la colonne embedding est désormais renseignée :

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

Un résultat semblable à celui-ci doit s'afficher :

a872b8926a164275.png

Que s'est-il passé ?

  1. Remplissage à grande échelle : il parcourt automatiquement vos 50 000 lignes existantes et génère des embeddings via Vertex AI.
  2. Automatisation : en définissant incremental_refresh_mode => 'transactional', AlloyDB configure automatiquement les déclencheurs internes. L'embedding de toute nouvelle ligne insérée dans help_articles sera généré instantanément.
  3. Vous pouvez éventuellement définir incremental_refresh_mode => 'None' pour que l'instruction n'effectue que des mises à jour groupées et appeler manuellement ai.refresh_embeddings() pour mettre à jour les embeddings de toutes les lignes.

Vous venez de remplacer une file d'attente Kafka, un worker Python et un script de migration par six lignes de code SQL. Voici la documentation officielle détaillée pour tous les attributs.

Test de déclencheur en temps réel

Vérifions que l'automatisation "Zero Loop" fonctionne pour les nouvelles données.

  1. Insérer une nouvelle ligne :
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. Vérifier immédiatement :
SELECT embedding FROM help_articles WHERE title = 'New Scaling Guide';

Résultat :

Le vecteur devrait être généré instantanément sans exécuter de script externe.

Taille du lot de réglage

Actuellement, AlloyDB définit par défaut la taille de lot sur 50. Bien que les paramètres par défaut fonctionnent parfaitement, AlloyDB permet toujours aux utilisateurs de définir la configuration idéale pour leur modèle et leur ensemble de données uniques.

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

Toutefois, les utilisateurs doivent être conscients des limites de quota qui peuvent limiter les performances. Pour consulter les quotas AlloyDB recommandés, consultez la section "Avant de commencer" de la documentation.

Problèmes et dépannage

Le délai de propagation IAM

Vous avez exécuté la commande IAM gcloud, mais la commande SQL CALL échoue toujours avec une erreur d'autorisation. La propagation des modifications IAM via le réseau backbone de Google peut prendre un certain temps. Inspirez, expirez.

Incompatibilité de dimension vectorielle

La table help_articles est définie sur VECTOR(768) dans la colonne content_body. Si vous essayez d'utiliser un autre modèle (comme un modèle à 1 536 dimensions) plus tard, vos insertions échoueront. Utilisez text-embedding-005.

6. Recherche contextuelle flexible

Nous allons maintenant effectuer une recherche hybride. Nous combinons la compréhension sémantique (Vector) avec la logique métier (filtres SQL).

Exécutez cette requête pour identifier les problèmes de facturation spécifiques à la version 2.0 du produit :

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;

C'est ce qu'on appelle le "contexte flexible". La recherche s'adapte pour comprendre l'intention de l'utilisateur ("problèmes de facturation") tout en respectant les contraintes métier rigides (version 2.0).

f0fdb50d6195c462.png

Pourquoi cette solution est idéale pour les start-up et les migrations

  1. Zéro dette d'infrastructure : vous n'avez pas créé de base de données vectorielle distincte (Pinecone/Milvus). Vous n'avez pas écrit de job ETL distinct. Tout est dans Postgres.
  2. Mises à jour en temps réel : en utilisant le mode "transactionnel", votre index de recherche n'est jamais obsolète. Dès que les données sont validées, elles sont prêtes pour les vecteurs.
  3. Évolutivité : AlloyDB est basé sur l'infrastructure de Google. Il peut gérer la génération groupée de millions de vecteurs plus rapidement que votre script Python.

Problèmes et dépannage

Problème de performances en production

Problème : rapide pour 50 000 lignes. Très lent pour un million de lignes si le filtrage par catégorie n'est pas assez sélectif.Solution : Ajoutez un index vectoriel. Pour une mise à l'échelle en production, vous devez créer un index : CREATE INDEX ON help_articles USING hnsw (embedding vector_cosine_ops);Vérifiez l'utilisation de l'index : exécutez EXPLAIN ANALYZE SELECT ... pour vous assurer que la base de données utilise l'index et n'effectue pas d'analyse séquentielle.

La catastrophe de l'incompatibilité de modèle

Problème : vous avez initialisé la colonne à l'aide de text-embedding-005 dans la procédure CALL. Si vous utilisez accidentellement un autre modèle (par exemple, text-embedding-004 ou un modèle OSS) dans la fonction de requête SELECT embedding('model-name', ...), les dimensions peuvent correspondre (768), mais l'espace vectoriel sera totalement différent. La requête s'exécute sans erreur, mais les résultats ne sont pas du tout pertinents (scores de pertinence inutiles). Dépannage : assurez-vous que le model_id dans ai.initialize_embeddings correspond exactement au model_id de votre requête SELECT.

Le résultat "Vide silencieux" (surfiltrage)

Problème : la recherche hybride est une opération "ET". Elle nécessite une correspondance sémantique ET une correspondance SQL.Si un utilisateur recherche "Aide à la facturation", mais que la colonne product_version contient ‘2.0.1' au lieu de ‘2.0', le résultat est de zéro ligne, même si la correspondance vectorielle est de 99 %.Dépannage :

  • Exécutez d'abord la requête sans le tri vectoriel pour vérifier si les filtres SQL (WHERE category...) renvoient bien des données.
  • Vérifiez la sensibilité à la casse (Billing ou billing).

4. Erreurs d'autorisation/de quota (erreur 500)

Problème : La fonction embedding() dans la clause SELECT effectue un appel réseau en temps réel vers Vertex AI.Si le compte de service de la base de données perd le rôle Utilisateur Vertex AI ou si vous atteignez le quota de l'API Vertex AI (RPM), l'intégralité de la requête SQL échouera.Dépannage :

  • Consultez Cloud Logging pour AlloyDB.
  • Assurez-vous que le rôle IAM est toujours actif.
  • Encapsulez la fonction dans un bloc TRY/CATCH dans les procédures stockées si une résilience élevée est nécessaire.

5. Embeddings nuls

Problème : Si vous insérez des données avant que le modèle ne soit complètement initialisé ou si le nœud de calcul en arrière-plan échoue, certaines lignes peuvent contenir NULL dans la colonne embedding. NULL <=> Vector renvoie NULL. Ces lignes disparaissent de l'ordre de tri.Dépannage :

  • Exécutez SELECT count(*) FROM help_articles WHERE embedding IS NULL; pour vérifier que la couverture est de 100 %.

7. Effectuer un nettoyage

Une fois cet atelier terminé, n'oubliez pas de supprimer le cluster et l'instance AlloyDB.

Le cluster et ses instances devraient être nettoyés.

8. Félicitations

Vous avez créé une application de recherche de base de connaissances évolutive. Au lieu de gérer un pipeline ETL complexe avec des scripts et des boucles Python pour générer des embeddings vectoriels, vous avez utilisé AlloyDB AI pour gérer la génération d'embeddings de manière native dans la base de données à l'aide d'une seule commande SQL.

Ce que vous avez appris

  • Nous avons supprimé la boucle "for" Python pour le traitement des données.
  • Nous avons généré 50 000 vecteurs avec une seule commande SQL.
  • Nous avons automatisé la génération de futurs vecteurs à l'aide de déclencheurs.
  • Nous avons effectué une recherche hybride.

Étapes suivantes