1. Introduction
Spanner est un service de base de données entièrement géré, évolutif horizontalement et distribué à l'échelle mondiale, idéal pour les charges de travail opérationnelles relationnelles et non relationnelles.
Spanner est compatible avec la recherche vectorielle intégrée, ce qui vous permet d'effectuer des recherches de similarité ou sémantiques et d'implémenter la génération augmentée par récupération (RAG) dans les applications d'IA générative à grande échelle, en utilisant les fonctionnalités de voisin le plus proche exact (KNN) ou de voisin le plus proche approximatif (ANN).
Les requêtes de recherche vectorielle de Spanner renvoient des données fraîches en temps réel dès que les transactions sont validées, comme toute autre requête sur vos données opérationnelles.
Dans cet atelier, vous allez configurer les fonctionnalités de base requises pour exploiter Spanner afin d'effectuer une recherche vectorielle, et accéder aux modèles d'embedding et de LLM du Model Garden de Vertex AI à l'aide de SQL.
L'architecture se présente comme suit:
Sur cette base, vous apprendrez à créer un indice vectoriel basé sur l'algorithme SCANN et à utiliser les fonctions de distance APPROX lorsque vos charges de travail sémantiques doivent être mises à l'échelle.
Ce que vous allez faire
Au cours de cet atelier, vous allez:
- Créer une instance Spanner
- Configurer le schéma de base de données de Spanner pour l'intégrer aux modèles d'embedding et de LLM dans Vertex AI
- Charger un ensemble de données sur le commerce
- Émettre des requêtes de recherche de similarité sur l'ensemble de données
- Fournissez un contexte au modèle LLM pour générer des recommandations spécifiques au produit.
- Modifiez le schéma et créez un index vectoriel.
- Modifiez les requêtes pour exploiter l'index vectoriel nouvellement créé.
Points abordés
- Configurer une instance Spanner
- Intégrer Vertex AI
- Utiliser Spanner pour effectuer une recherche vectorielle afin de trouver des articles similaires dans un ensemble de données de vente au détail
- Préparer votre base de données pour faire évoluer les charges de travail de recherche vectorielle à l'aide de la recherche ANN
Prérequis
2. Préparation
Créer un projet
Si vous ne possédez pas encore de compte Google (Gmail ou Google Apps), vous devez en créer un. Connectez-vous à la console Google Cloud Platform ( console.cloud.google.com) et créez un projet.
Si vous avez déjà un projet, cliquez sur le menu déroulant de sélection du projet dans l'angle supérieur gauche de la console :
Cliquez ensuite sur le bouton "NEW PROJECT" (NOUVEAU PROJET) dans la boîte de dialogue qui s'affiche pour créer un projet :
Si vous n'avez pas encore de projet, une boîte de dialogue semblable à celle-ci apparaîtra pour vous permettre d'en créer un :
La boîte de dialogue de création de projet suivante vous permet de saisir les détails de votre nouveau projet :
Notez l'ID du projet. Il s'agit d'un nom unique pour tous les projets Google Cloud, ce qui implique que le nom ci-dessus n'est plus disponible pour vous… Désolé ! Il sera désigné par le nom PROJECT_ID tout au long de cet atelier de programmation.
Ensuite, si ce n'est pas déjà fait, vous devez activer la facturation dans Developers Console afin de pouvoir utiliser les ressources Google Cloud puis activer l'API Spanner.
Suivre cet atelier de programmation ne devrait pas vous coûter plus d'un euro. Cependant, cela peut s'avérer plus coûteux si vous décidez d'utiliser davantage de ressources ou si vous n'interrompez pas les ressources (voir la section "Effectuer un nettoyage" à la fin du présent document). Les tarifs de Google Cloud Spanner sont décrits sur cette page.
Les nouveaux utilisateurs de Google Cloud Platform peuvent bénéficier d'un Essai gratuit avec 300 $ de crédits afin de suivre gratuitement le présent atelier.
Configuration de Google Cloud Shell
Bien que Google Cloud et Spanner puissent être utilisés à distance depuis votre ordinateur portable, nous allons utiliser Google Cloud Shell pour cet atelier de programmation, un environnement de ligne de commande exécuté dans le cloud.
Cette machine virtuelle basée sur Debian contient tous les outils de développement dont vous aurez besoin. Elle intègre un répertoire d'accueil persistant de 5 Go et s'exécute sur Google Cloud, ce qui améliore nettement les performances du réseau et l'authentification. Cela signifie que tout ce dont vous avez besoin pour cet atelier de programmation est un navigateur (oui, tout fonctionne sur un Chromebook).
- Pour activer Cloud Shell à partir de Cloud Console, cliquez simplement sur Activer Cloud Shell (le provisionnement de l'environnement et la connexion ne devraient prendre que quelques minutes).
Une fois connecté à Cloud Shell, vous êtes en principe authentifié, et le projet est déjà défini avec votre ID_PROJET.
gcloud auth list
Résultat de la commande
Credentialed accounts:
- <myaccount>@<mydomain>.com (active)
gcloud config list project
Résultat de la commande
[core]
project = <PROJECT_ID>
Si, pour une raison quelconque, le projet n'est pas défini, exécutez simplement la commande suivante :
gcloud config set project <PROJECT_ID>
Vous recherchez votre PROJECT_ID
? Vérifiez l'ID que vous avez utilisé pendant les étapes de configuration ou recherchez-le dans le tableau de bord Cloud Console :
Par défaut, Cloud Shell définit certaines variables d'environnement qui pourront s'avérer utiles pour exécuter certaines commandes dans le futur.
echo $GOOGLE_CLOUD_PROJECT
Résultat de la commande
<PROJECT_ID>
Activer l'API Spanner
gcloud services enable spanner.googleapis.com
Résumé
À cette étape, vous avez configuré votre projet si vous n'en aviez pas déjà un, activé Cloud Shell et activé les API requises.
Étape suivante
Vous allez ensuite configurer l'instance et la base de données Spanner.
3. Créer une instance et une base de données Spanner
Créer l'instance Spanner
À cette étape, nous allons configurer notre instance Spanner pour l'atelier de programmation. Pour ce faire, ouvrez Cloud Shell et exécutez la commande suivante:
export SPANNER_INSTANCE_ID=retail-demo
gcloud spanner instances create $SPANNER_INSTANCE_ID \
--config=regional-us-central1 \
--description="spanner AI retail demo" \
--nodes=1
Résultat de la commande :
$ gcloud spanner instances create $SPANNER_INSTANCE_ID \
--config=regional-us-central1 \
--description="spanner AI retail demo" \
--nodes=1
Creating instance...done.
Créer la base de données
Une fois votre instance en cours d'exécution, vous pouvez créer la base de données. Spanner permet de gérer plusieurs bases de données sur une seule instance.
C'est dans la base de données que vous définissez votre schéma. Vous pouvez également contrôler les utilisateurs ayant accès à la base de données, configurer le chiffrement personnalisé, configurer l'optimiseur et définir la période de conservation.
Pour créer la base de données, utilisez à nouveau l'outil de ligne de commande gcloud:
export SPANNER_DATABASE=cymbal-bikes
gcloud spanner databases create $SPANNER_DATABASE \
--instance=$SPANNER_INSTANCE_ID
Résultat de la commande :
$ gcloud spanner databases create $SPANNER_DATABASE \
--instance=$SPANNER_INSTANCE_ID
Creating database...done.
Résumé
À cette étape, vous avez créé l'instance et la base de données Spanner.
Étape suivante
Vous allez ensuite configurer le schéma et les données Spanner.
4. Charger le schéma et les données de Cymbal
Créer le schéma Cymbal
Pour configurer le schéma, accédez à Spanner Studio:
Le schéma se compose de deux parties. Commencez par ajouter la table products
. Copiez et collez cette instruction dans l'onglet vide.
Pour le schéma, copiez et collez ce DDL dans la zone:
CREATE TABLE products (
categoryId INT64 NOT NULL,
productId INT64 NOT NULL,
productName STRING(MAX) NOT NULL,
productDescription STRING(MAX) NOT NULL,
productDescriptionEmbedding ARRAY<FLOAT32>,
createTime TIMESTAMP NOT NULL OPTIONS (
allow_commit_timestamp = true
),
inventoryCount INT64 NOT NULL,
priceInCents INT64,
) PRIMARY KEY(categoryId, productId);
Cliquez ensuite sur le bouton run
et attendez quelques secondes que votre schéma soit créé.
Vous allez ensuite créer les deux modèles et les configurer pour les points de terminaison de modèle Vertex AI.
Le premier modèle est un modèle d'embedding qui permet de générer des représentations vectorielles continues à partir de texte, et le second est un modèle LLM qui permet de générer des réponses en fonction des données de Spanner.
Collez le schéma suivant dans un nouvel onglet de Spanner Studio:
CREATE MODEL EmbeddingsModel INPUT(
content STRING(MAX),
) OUTPUT(
embeddings STRUCT<statistics STRUCT<truncated BOOL, token_count FLOAT32>, values ARRAY<FLOAT32>>,
) REMOTE OPTIONS (
endpoint = '//aiplatform.googleapis.com/projects/<PROJECT_ID>/locations/us-central1/publishers/google/models/text-embedding-004'
);
CREATE MODEL LLMModel INPUT(
prompt STRING(MAX),
) OUTPUT(
content STRING(MAX),
) REMOTE OPTIONS (
endpoint = '//aiplatform.googleapis.com/projects/<PROJECT_ID>/locations/us-central1/publishers/google/models/gemini-pro',
default_batch_size = 1
);
Cliquez ensuite sur le bouton run
et patientez quelques secondes pour que vos modèles soient créés.
Dans le volet de gauche de Spanner Studio, vous devriez voir les tables et les modèles suivants:
Charger les données
Vous allez maintenant insérer des produits dans votre base de données. Ouvrez un nouvel onglet dans Spanner Studio, puis copiez et collez les instructions d'insertion suivantes:
INSERT INTO products (categoryId, productId, productName, productDescription, createTime, inventoryCount, priceInCents)
VALUES (1, 1, "Cymbal Helios Helmet", "Safety meets style with the Cymbal children's bike helmet. Its lightweight design, superior ventilation, and adjustable fit ensure comfort and protection on every ride. Stay bright and keep your child safe under the sun with Cymbal Helios!", PENDING_COMMIT_TIMESTAMP(), 100, 10999),
(1, 2, "Cymbal Sprout", "Let their cycling journey begin with the Cymbal Sprout, the ideal balance bike for beginning riders ages 2-4 years. Its lightweight frame, low seat height, and puncture-proof tires promote stability and confidence as little ones learn to balance and steer. Watch them sprout into cycling enthusiasts with Cymbal Sprout!", PENDING_COMMIT_TIMESTAMP(), 10, 13999),
(1, 3, "Cymbal Spark Jr.", "Light, vibrant, and ready for adventure, the Spark Jr. is the perfect first bike for young riders (ages 5-8). Its sturdy frame, easy-to-use brakes, and puncture-resistant tires inspire confidence and endless playtime. Let the spark of cycling ignite with Cymbal!", PENDING_COMMIT_TIMESTAMP(), 34, 13900),
(1, 4, "Cymbal Summit", "Conquering trails is a breeze with the Summit mountain bike. Its lightweight aluminum frame, responsive suspension, and powerful disc brakes provide exceptional control and comfort for experienced bikers navigating rocky climbs or shredding downhill. Reach new heights with Cymbal Summit!", PENDING_COMMIT_TIMESTAMP(), 0, 79999),
(1, 5, "Cymbal Breeze", "Cruise in style and embrace effortless pedaling with the Breeze electric bike. Its whisper-quiet motor and long-lasting battery let you conquer hills and distances with ease. Enjoy scenic rides, commutes, or errands with a boost of confidence from Cymbal Breeze!", PENDING_COMMIT_TIMESTAMP(), 72, 129999),
(1, 6, "Cymbal Trailblazer Backpack", "Carry all your essentials in style with the Trailblazer backpack. Its water-resistant material, multiple compartments, and comfortable straps keep your gear organized and accessible, allowing you to focus on the adventure. Blaze new trails with Cymbal Trailblazer!", PENDING_COMMIT_TIMESTAMP(), 24, 7999),
(1, 7, "Cymbal Phoenix Lights", "See and be seen with the Phoenix bike lights. Powerful LEDs and multiple light modes ensure superior visibility, enhancing your safety and enjoyment during day or night rides. Light up your journey with Cymbal Phoenix!", PENDING_COMMIT_TIMESTAMP(), 87, 3999),
(1, 8, "Cymbal Windstar Pump", "Flat tires are no match for the Windstar pump. Its compact design, lightweight construction, and high-pressure capacity make inflating tires quick and effortless. Get back on the road in no time with Cymbal Windstar!", PENDING_COMMIT_TIMESTAMP(), 36, 24999),
(1, 9,"Cymbal Odyssey Multi-Tool","Be prepared for anything with the Odyssey multi-tool. This handy gadget features essential tools like screwdrivers, hex wrenches, and tire levers, keeping you ready for minor repairs and adjustments on the go. Conquer your journey with Cymbal Odyssey!", PENDING_COMMIT_TIMESTAMP(), 52, 999),
(1, 10,"Cymbal Nomad Water Bottle","Stay hydrated on every ride with the Nomad water bottle. Its sleek design, BPA-free construction, and secure lock lid make it the perfect companion for staying refreshed and motivated throughout your adventures. Hydrate and explore with Cymbal Nomad!", PENDING_COMMIT_TIMESTAMP(), 42, 1299);
Cliquez sur le bouton run
pour insérer les données.
Résumé
À cette étape, vous avez créé le schéma et chargé des données de base dans la base de données cymbal-bikes
.
Étape suivante
Vous allez ensuite intégrer le modèle d'embedding pour générer des embeddings pour les descriptions de produits, et convertir une requête de recherche textuelle en embeddings pour rechercher des produits pertinents.
5. Utiliser des embeddings
Générer des embeddings vectoriels pour les descriptions de produits
Pour que la recherche de similarité fonctionne sur les produits, vous devez générer des embeddings pour les descriptions des produits.
Avec l'EmbeddingsModel
créé dans le schéma, il s'agit d'une instruction DML UPDATE
simple.
UPDATE products p1
SET productDescriptionEmbedding =
(SELECT embeddings.values from ML.PREDICT(MODEL EmbeddingsModel,
(SELECT productDescription as content FROM products p2 where p2.productId=p1.productId)))
WHERE categoryId=1;
Cliquez sur le bouton run
pour mettre à jour les descriptions des produits.
Utiliser la recherche vectorielle
Dans cet exemple, vous allez envoyer une requête de recherche en langage naturel via une requête SQL. Cette requête transforme la requête de recherche en embeddings, puis recherche des résultats similaires en fonction des embeddings stockés des descriptions de produits générés à l'étape précédente.
-- Use Spanner's vector search, and integration with embedding and LLM models to
-- return items that are semantically relevant and available in inventory based on
-- real-time data.
SELECT productName, productDescription, inventoryCount, COSINE_DISTANCE(
productDescriptionEmbedding,
( SELECT embeddings.values
FROM ML.PREDICT(
MODEL EmbeddingsModel,
(SELECT "I'd like to buy a starter bike for my 3 year old child" as content)
)
)
) as distance
FROM products
WHERE inventoryCount > 0
ORDER BY distance
LIMIT 5;
Cliquez sur le bouton run
pour trouver les produits similaires. Les résultats doivent se présenter comme suit:
Notez que des filtres supplémentaires sont utilisés dans la requête, par exemple pour ne sélectionner que les produits en stock (inventoryCount > 0
).
Résumé
Au cours de cette étape, vous avez créé des embeddings de description de produit et un embedding de requête de recherche à l'aide de SQL, en exploitant l'intégration de Spanner aux modèles de Vertex AI. Vous avez également effectué une recherche vectorielle pour trouver des produits similaires correspondant à la requête de recherche.
Étapes suivantes
Ensuite, utilisons les résultats de recherche pour les transmettre à un LLM afin de générer une réponse personnalisée pour chaque produit.
6. Utiliser un LLM
Spanner facilite l'intégration aux modèles LLM diffusés à partir de Vertex AI. Cela permet aux développeurs d'utiliser SQL pour interagir directement avec les LLM, au lieu de demander à l'application d'effectuer la logique.
Par exemple, nous avons les résultats de la requête SQL précédente de l'utilisateur "I'd like to buy a starter bike for my 3 year old child".
.
Le développeur souhaite indiquer pour chaque résultat si le produit convient à l'utilisateur à l'aide de l'invite suivante:
"Answer with ‘Yes' or ‘No' and explain why: Is this a good fit for me? I'd like to buy a starter bike for my 3 year old child"
Voici la requête que vous pouvez utiliser:
-- Use an LLM to analyze this list and provide a recommendation on whether each
-- product is a good fit for the user. We use the vector search and real time
-- inventory data to first filter the products to reduce the size of the prompt to
-- the LLM.
SELECT productName, productDescription, inventoryCount, content AS LLMResponse
FROM ML.PREDICT(
MODEL LLMModel,
( SELECT
inventoryCount,
productName,
productDescription,
CONCAT(
"Answer with ‘Yes' or ‘No' and explain why: Is this a good fit for me?",
"I'd like to buy a starter bike for my 3 year old child \n",
"Product Name: ", productName, "\n",
"Product Description:", productDescription) AS prompt,
FROM products
WHERE inventoryCount > 0
ORDER by COSINE_DISTANCE(
productDescriptionEmbedding,
( SELECT embeddings.values
FROM ML.PREDICT(
MODEL EmbeddingsModel,
( SELECT "I'd like to buy a starter bike for my 3 year old child" as content)
)
)
) LIMIT 5
),
STRUCT(256 AS maxOutputTokens)
);
Cliquez sur le bouton run
pour envoyer la requête. Les résultats doivent se présenter comme suit:
Le premier produit convient à un enfant de trois ans en raison de la tranche d'âge indiquée dans la description du produit (2 à 4 ans). Les autres produits ne sont pas adaptés.
Résumé
Dans cette étape, vous avez utilisé un LLM pour générer des réponses de base aux requêtes d'un utilisateur.
Étapes suivantes
Nous allons maintenant découvrir comment utiliser les ANN pour mettre à l'échelle la recherche vectorielle.
7. Évoluer la recherche vectorielle
Les exemples de recherche vectorielle précédents utilisaient la recherche vectorielle KNN exacte. Cela est très utile lorsque vous pouvez interroger des sous-ensembles très spécifiques de vos données Spanner. Ces types de requêtes sont considérés comme très partitionnables.
Si vos charges de travail ne sont pas très partitionnables et que vous disposez d'une grande quantité de données, vous devez utiliser la recherche vectorielle par ANN en exploitant l'algorithme ScaNN pour améliorer les performances de recherche.
Pour ce faire dans Spanner, vous devez effectuer deux opérations:
- Créer un index vectoriel
- Modifiez votre requête pour utiliser les fonctions de distance APPROX.
Créer l'index vectoriel
Pour créer un indice vectoriel sur cet ensemble de données, nous devons d'abord modifier la colonne productDescriptionEmbeddings
afin de définir la longueur de chaque vecteur. Pour ajouter la longueur du vecteur à une colonne, vous devez supprimer la colonne d'origine et la recréer.
ALTER TABLE `products` DROP COLUMN `productDescriptionEmbedding`;
ALTER TABLE
`products` ADD COLUMN `productDescriptionEmbedding` ARRAY<FLOAT32>(vector_length=>768);
Ensuite, créez à nouveau les représentations vectorielles continues à partir de l'étape Generate Vector embedding
que vous avez précédemment exécutée.
UPDATE products p1
SET productDescriptionEmbedding =
(SELECT embeddings.values from ML.PREDICT(MODEL EmbeddingsModel,
(SELECT productDescription as content FROM products p2 where p2.productId=p1.productId)))
WHERE categoryId=1;
Une fois la colonne créée, créez l'index:
CREATE VECTOR INDEX ProductDescriptionEmbeddingIndex
ON products(productDescriptionEmbedding)
WHERE productDescriptionEmbedding IS NOT NULL
OPTIONS (
distance_type = 'COSINE'
);
Utiliser le nouvel index
Pour utiliser le nouvel index vectoriel, vous devrez modifier légèrement la requête d'embedding précédente.
Voici la requête d'origine :
SELECT productName, productDescription, inventoryCount, COSINE_DISTANCE(
productDescriptionEmbedding,
( SELECT embeddings.values
FROM ML.PREDICT(
MODEL EmbeddingsModel,
(SELECT "I'd like to buy a starter bike for my 3 year old child" as content)
)
)
) as distance
FROM products
WHERE inventoryCount > 0
ORDER BY distance
LIMIT 5;
Vous devez apporter les modifications suivantes:
- Utilisez une indication d'index pour le nouvel index vectoriel:
@{force_index=ProductDescriptionEmbeddingIndex}
- Remplacez l'appel de fonction
COSINE_DISTANCE
parAPPROX_COSINE_DISTANCE
. Notez que les options JSON de la requête finale ci-dessous sont également obligatoires. - Générez les représentations vectorielles continues à partir de la fonction ML.PREDICT séparément.
- Copiez les résultats des représentations vectorielles continues dans la requête finale.
Générer les embeddings
-- Generate the prompt embeddings
SELECT embeddings.values
FROM ML.PREDICT(
MODEL EmbeddingsModel,
(SELECT "I'd like to buy a starter bike for my 3 year old child" as content)
)
)
Mettez en surbrillance les résultats de la requête, puis copiez-les.
Remplacez ensuite <VECTOR>
dans la requête suivante en collant les représentations vectorielles continues que vous avez copiées.
-- Embedding query now using the vector index
SELECT productName, productDescription, inventoryCount,
APPROX_COSINE_DISTANCE(productDescriptionEmbedding, array<float32>[@VECTOR], options => JSON '{\"num_leaves_to_search\": 10}')
FROM products @{force_index=ProductDescriptionEmbeddingIndex}
WHERE productDescriptionEmbedding IS NOT NULL AND inventoryCount > 0
ORDER BY distance
LIMIT 5;
Voici un exemple :
Résumé
Au cours de cette étape, vous avez converti votre schéma pour créer un indice vectoriel. Vous avez ensuite réécrit la requête d'embedding pour effectuer une recherche ANN à l'aide de l'index vectoriel. Il s'agit d'une étape importante à mesure que vos données augmentent pour faire évoluer les charges de travail de recherche vectorielle.
Étapes suivantes
Ensuite, il est temps de nettoyer !
8. Nettoyer (facultatif)
Pour nettoyer, accédez simplement à la section Cloud Spanner de Cloud Console et supprimez l'instance retail-demo
que nous avons créée dans l'atelier de programmation.
9. Félicitations !
Félicitations, vous avez effectué une recherche de similarité à l'aide de la recherche vectorielle intégrée de Spanner. Vous avez également vu à quel point il est facile de travailler avec des modèles d'embedding et de LLM pour fournir des fonctionnalités d'IA générative directement à l'aide de SQL.
Enfin, vous avez appris à effectuer une recherche ANN avec l'algorithme ScaNN pour faire évoluer les charges de travail de recherche vectorielle.
Étape suivante
Pour en savoir plus sur la fonctionnalité de voisin le plus proche exacte (recherche vectorielle KNN) de Spanner, consultez https://cloud.google.com/spanner/docs/find-k-nearest-neighbors.
Pour en savoir plus sur la fonctionnalité de recherche des plus proches voisins approximatifs (ANN vector search) de Spanner, consultez https://cloud.google.com/spanner/docs/find-approximate-nearest-neighbors.
Pour en savoir plus sur l'exécution de prédictions en ligne avec SQL à l'aide de l'intégration Vertex AI de Spanner, consultez la page https://cloud.google.com/spanner/docs/ml.