Générer des embeddings vectoriels pour des données textuelles de manière groupée à l'aide d'une instruction LMD partitionnée

Ce document explique comment générer et compléter des embeddings vectoriels de manière groupée pour les données textuelles (STRING ou JSON) stockées dans Spanner à l'aide de SQL et des modèles de représentation vectorielle continue de texte Vertex AI.

Prérequis

Vous devez disposer d'une table dans votre base de données Spanner contenant des données textuelles (STRING ou JSON). Pour en savoir plus sur l'importation de données, consultez la présentation de l'importation et de l'exportation Spanner.

Exemple d'utilisation

Supposons que vous disposiez d'une table dans Spanner avec le schéma suivant. Cette table contient des millions d'enregistrements.

GoogleSQL

CREATE TABLE Products (
  product_id INT64 NOT NULL,
  name STRING(MAX),
  description STRING(MAX)
) PRIMARY KEY(product_id);

PostgreSQL

CREATE TABLE Products (
  product_id INT8 NOT NULL,
  name TEXT,
  description TEXT,
  PRIMARY KEY(product_id)
);

Votre objectif est de générer des représentations vectorielles continues pour la colonne description de ce tableau afin de trouver des articles similaires à recommander aux clients pour améliorer leur expérience d'achat à l'aide de la recherche vectorielle.

Enregistrer un modèle d'embedding

GoogleSQL

Enregistrez un modèle d'embedding de texte avec le point de terminaison de modèle Vertex AI dans votre base de données Spanner :

CREATE MODEL MODEL_NAME
INPUT(
  content STRING(MAX)
)
OUTPUT(
  embeddings STRUCT<values ARRAY<FLOAT32>>
)
REMOTE OPTIONS(
    endpoint = '//aiplatform.googleapis.com/projects/PROJECT/locations/LOCATION/publishers/google/models/$MODEL_NAME',
  default_batch_size = 5
)

Remplacez l'élément suivant :

  • MODEL_NAME : nom du modèle d'embedding textuel Vertex AI
  • PROJECT : projet hébergeant le point de terminaison Vertex AI
  • LOCATION : emplacement du point de terminaison Vertex AI

PostgreSQL

Dans le dialecte PostgreSQL, il n'est pas nécessaire d'enregistrer le modèle. Vous transmettez le nom du point de terminaison directement à l'appel de la fonction spanner.ML_PREDICT_ROW.

Pour connaître les bonnes pratiques, tenez compte des points suivants :

  • Pour maintenir l'isolation des quotas, utilisez un point de terminaison dans un projet différent pour générer et remplir les embeddings que le point de terminaison de production. Réservez le point de terminaison de production pour diffuser le trafic de production.
  • Assurez-vous que le point de terminaison du modèle accepte la valeur default_batch_size. Vous pouvez remplacer default_batch_size par l'indication de requête @{remote_udf_max_rows_per_rpc=NEW_NUMBER}. Pour en savoir plus sur la limite default_batch_size pour chaque région, consultez Obtenir des embeddings textuels pour un extrait de texte.
  • Définissez le point de terminaison avec une version de modèle spécifique (par exemple, @003) au lieu de @latest. En effet, les vecteurs d'embedding générés pour le même extrait de texte peuvent différer selon la version du modèle que vous utilisez. C'est pourquoi vous devez éviter d'utiliser différentes versions de modèle pour générer des embeddings dans le même ensemble de données. De plus, la mise à jour de la version du modèle dans l'instruction de définition du modèle ne met pas à jour les embeddings déjà générés avec ce modèle. Pour gérer la version du modèle pour les embeddings, vous pouvez créer une colonne supplémentaire dans le tableau qui stocke la version du modèle.
  • Les modèles d'embedding de texte personnalisés ne sont pas compatibles avec les fonctions ML.PREDICT de GoogleSQL et spanner.ML_PREDICT_ROW de PostgreSQL.

Tester l'intégration de bout en bout du modèle d'embeddings

Vous pouvez exécuter une requête pour vérifier que le modèle d'embedding est correctement configuré et que les embeddings sont récupérés. Par exemple, exécutez la requête suivante :

GoogleSQL

SELECT embeddings.values
FROM SAFE.ML.PREDICT(
  MODEL MODEL_NAME,
  (SELECT description AS content FROM products LIMIT 10)
);

Remplacez l'élément suivant :

  • MODEL_NAME : nom du modèle d'embedding textuel Vertex AI

PostgreSQL

SELECT spanner.ML_PREDICT_ROW(
    'projects/PROJECT/locations/LOCATION/publishers/google/models/$MODEL_NAME',
    JSONB_BUILD_OBJECT('instances', JSONB_BUILD_ARRAY(JSONB_BUILD_OBJECT('content', description))))
FROM Products
LIMIT 10;

Remplacez l'élément suivant :

  • PROJECT : projet hébergeant le point de terminaison Vertex AI
  • LOCATION : emplacement du point de terminaison Vertex AI
  • MODEL_NAME : nom du modèle d'embedding textuel Vertex AI

Mettre à jour la table source pour inclure des colonnes supplémentaires permettant de stocker les embeddings

Ensuite, mettez à jour le schéma de la table source pour inclure une colonne supplémentaire de type de données ARRAY<FLOAT32> afin de stocker les embeddings générés :

GoogleSQL

ALTER TABLE TABLE_NAME
ADD COLUMN EMBEDDING_COLUMN_NAME ARRAY<FLOAT32>;

Remplacez l'élément suivant :

  • TABLE_NAME : nom de la table source
  • EMBEDDING_COLUMN_NAME : nom de la colonne dans laquelle vous souhaitez ajouter les embeddings générées

PostgreSQL

ALTER TABLE TABLE_NAME
ADD COLUMN EMBEDDING_COLUMN_NAME real[];

Remplacez l'élément suivant :

  • TABLE_NAME : nom de la table source
  • EMBEDDING_COLUMN_NAME : nom de la colonne dans laquelle vous souhaitez ajouter les embeddings générées

Par exemple, en utilisant l'exemple de tableau products, exécutez :

GoogleSQL

ALTER TABLE Products
ADD COLUMN desc_embed ARRAY<FLOAT32>;

PostgreSQL

ALTER TABLE Products
ADD COLUMN desc_embed real[];

Vous pouvez ajouter une autre colonne pour gérer la version du modèle d'intégration.

GoogleSQL

ALTER TABLE Products
ADD COLUMN desc_embed_model_version INT64;

PostgreSQL

ALTER TABLE Products
ADD COLUMN desc_embed_model_version INT8;

Augmenter le quota pour Vertex AI

Vous devrez peut-être augmenter le quota de l'API Vertex AI pour la région qui utilise le modèle d'embedding de texte. Pour demander une augmentation, consultez la section Augmentations de quota de Vertex AI.

Pour en savoir plus, consultez Quotas et limites de Vertex AI.

Représentations vectorielles de remplissage

Enfin, exécutez l'instruction UPDATE suivante à l'aide du LMD partitionné pour générer des embeddings pour la colonne de données textuelles et les stocker dans votre base de données. Vous pouvez stocker la version du modèle avec les embeddings. Nous vous recommandons d'exécuter cette requête pendant une période de faible trafic dans votre base de données.

GoogleSQL

UPDATE TABLE_NAME
SET
  TABLE_NAME.EMBEDDING_COLUMN_NAME = (
    SELECT embeddings.values
    FROM SAFE.ML.PREDICT(
      MODEL MODEL_NAME,
      (SELECT TABLE_NAME.DATA_COLUMN_NAME AS content)
    ) @{remote_udf_max_rows_per_rpc=MAX_ROWS}
  ),
  TABLE_NAME.EMBEDDING_VERSION_COLUMN = MODEL_VERSION
WHERE FILTER_CONDITION;

Remplacez l'élément suivant :

  • TABLE_NAME : nom de la table contenant les données textuelles
  • EMBEDDING_COLUMN_NAME : nom de la colonne dans laquelle vous souhaitez ajouter les embeddings générées
  • DATA_COLUMN_NAME : nom de la colonne contenant les données textuelles
  • MODEL_NAME : nom du modèle d'embedding Vertex AI
  • MAX_ROWS : nombre maximal de lignes par RPC
  • EMBEDDING_VERSION_COLUMN : colonne qui gère la version du modèle d'embedding utilisé pour compléter vos embeddings
  • MODEL_VERSION : version du modèle d'embedding de texte
  • FILTER_CONDITION : condition de filtre partitionnable que vous souhaitez appliquer

L'utilisation de SAFE.ML.PREDICT renvoie NULL pour les requêtes ayant échoué. Vous pouvez également utiliser SAFE.ML.PREDICT en combinaison avec un filtre WHERE embedding_column IS NULL pour réexécuter votre requête sans calculer les embeddings pour les champs qui l'ont déjà été.

PostgreSQL

UPDATE TABLE_NAME
SET
  EMBEDDING_COLUMN_NAME = spanner.FLOAT32_ARRAY(spanner.ML_PREDICT_ROW(
    'projects/PROJECT/locations/LOCATION/publishers/google/models/$MODEL_NAME',
    JSONB_BUILD_OBJECT('instances', JSONB_BUILD_ARRAY(JSONB_BUILD_OBJECT('content', DATA_COLUMN_NAME)))
  ) /*@ remote_udf_max_rows_per_rpc=MAX_ROWS */ ->'predictions'->0->'embeddings'->'values'),
  EMBEDDING_VERSION_COLUMN = MODEL_VERSION
WHERE FILTER_CONDITION;

Remplacez l'élément suivant :

  • TABLE_NAME : nom de la table contenant les données textuelles
  • EMBEDDING_COLUMN_NAME : nom de la colonne dans laquelle vous souhaitez ajouter les embeddings générées
  • DATA_COLUMN_NAME : nom de la colonne contenant les données textuelles
  • PROJECT : projet hébergeant le point de terminaison Vertex AI
  • LOCATION : emplacement du point de terminaison Vertex AI
  • MODEL_NAME : nom du modèle d'embedding Vertex AI
  • MODEL_VERSION : version du modèle d'embedding Vertex AI
  • MAX_ROWS : nombre maximal de lignes par RPC
  • EMBEDDING_VERSION_COLUMN : colonne qui gère la version du modèle d'embedding de texte utilisé pour compléter vos embeddings
  • FILTER_CONDITION : condition de filtre partitionnable que vous souhaitez appliquer

Exemple de requête de remplissage pour la table products :

GoogleSQL

UPDATE products
SET
  products.desc_embed = (
    SELECT embeddings.values
    FROM SAFE.ML.PREDICT(
      MODEL embedding_model,
      (SELECT products.description AS content)
    ) @{remote_udf_max_rows_per_rpc=200}
  ),
  products.desc_embed_model_version = 3
WHERE products.desc_embed IS NULL;

PostgreSQL

UPDATE products
SET
  desc_embed = spanner.FLOAT32_ARRAY(spanner.ML_PREDICT_ROW(
    'projects/PROJECT/locations/LOCATION/publishers/google/models/$MODEL_NAME',
    JSONB_BUILD_OBJECT('instances', JSONB_BUILD_ARRAY(JSONB_BUILD_OBJECT('content', description)))
  ) /*@ remote_udf_max_rows_per_rpc=200 */ ->'predictions'->0->'embeddings'->'values'),
  desc_embed_model_version = 3
WHERE desc_embed IS NULL;

Pour connaître les bonnes pratiques, tenez compte des points suivants :

Performances et autres considérations

Tenez compte des points suivants pour optimiser les performances lorsque vous complétez des données d'intégration.

Nombre de nœuds

Le LMD partitionné exécute l'instruction LMD donnée sur différentes partitions en parallèle. Pour les instances comportant un grand nombre de nœuds, vous pouvez observer des erreurs de quota lors de l'exécution du LMD partitionné. Si les requêtes d'API Vertex AI sont limitées en raison des limites de quota de l'API Vertex AI, Spanner réessaie ces échecs en mode transactionnel LMD partitionné jusqu'à 20 fois. Si vous constatez un taux élevé d'erreurs de quota dans Vertex AI, augmentez le quota pour Vertex AI. Vous pouvez également ajuster le parallélisme à l'aide de l'indication au niveau de l'instruction @{pdml_max_parallelism=DESIRED_NUMBER} lorsque vous utilisez GoogleSQL. L'exemple suivant définit le parallélisme sur "5" :

GoogleSQL

@{pdml_max_parallelism=5} UPDATE products
SET products.desc_embed =(
  SELECT embeddings.values
  FROM SAFE.ML.PREDICT(MODEL embedding_model, (
        SELECT products.value AS CONTENT
        )
  )
      @{remote_udf_max_rows_per_rpc=200}
),
products.desc_embed_model_version = MODEL_VERSION
WHERE products.desc_embed IS NULL;

Taille du texte dans la colonne de données

Le modèle d'embedding Vertex AI limite le nombre maximal de jetons pour chaque entrée de texte. Les limites de jetons varient selon les versions du modèle. Chaque requête Vertex AI peut comporter plusieurs champs de texte d'entrée, mais le nombre de jetons dans une même requête est limité. Pour les bases de données GoogleSQL, si vous rencontrez une erreur INVALID_ARGUMENT avec le message "La requête est trop volumineuse", essayez de réduire la taille du lot pour éviter l'erreur. Pour ce faire, vous pouvez configurer default_batch_size ou utiliser l'indication de requête @{remote_udf_max_outstanding_rpcs} lors de l'enregistrement du modèle.

Nombre de requêtes API envoyées à Vertex AI

Vous pouvez utiliser l'indication de requête @{remote_udf_max_outstanding_rpcs} pour augmenter ou diminuer le nombre de requêtes envoyées à Vertex AI depuis Spanner. Sachez que l'augmentation de cette limite peut accroître l'utilisation du processeur et de la mémoire de l'instance Spanner. Pour les bases de données GoogleSQL, l'utilisation de cet indice de requête remplace le default_batch_size configuré pour votre modèle.

Suivre la progression du remplissage

Vous pouvez surveiller le nombre de requêtes, la latence et les octets réseau envoyés à Vertex AI depuis Spanner à l'aide du tableau de bord "Insights système".

Étapes suivantes