Premiers pas avec les représentations vectorielles continues dans Cloud SQL pour PostgreSQL

1. Introduction

Dans cet atelier de programmation, vous allez apprendre à utiliser l'intégration de l'IA Cloud SQL pour PostgreSQL en combinant la recherche vectorielle avec les embeddings Vertex AI.

8aa6ba3bc12a1593.png

Prérequis

  • Connaissances de base concernant la console Google Cloud
  • Compétences de base concernant l'interface de ligne de commande et Cloud Shell

Points abordés

  • Déployer une instance Cloud SQL pour PostgreSQL
  • Créer une base de données et activer l'intégration de l'IA Cloud SQL
  • Charger des données dans la base de données
  • Utiliser Cloud SQL Studio
  • Utiliser le modèle d'embedding Vertex AI dans Cloud SQL
  • Utiliser Vertex AI Studio
  • Enrichir les résultats à l'aide du modèle génératif Vertex AI
  • Améliorer les performances à l'aide de l'index vectoriel

Prérequis

  • Un compte Google Cloud et un projet Google Cloud
  • Un navigateur Web tel que Chrome compatible avec la console Google Cloud et Cloud Shell

2. Préparation

Configuration du projet

  1. Connectez-vous à la console Google Cloud. (Si vous ne possédez pas encore de compte Gmail ou Google Workspace, vous devez en créer un.)

Utilisez un compte personnel au lieu d'un compte professionnel ou scolaire.

  1. Créez un projet ou réutilisez-en un. Pour créer un projet dans la console Google Cloud, cliquez sur le bouton "Sélectionner un projet" dans l'en-tête. Une fenêtre pop-up s'ouvre.

295004821bab6a87.png

Dans la fenêtre "Sélectionner un projet", cliquez sur le bouton "Nouveau projet" pour ouvrir une boîte de dialogue pour le nouveau projet.

37d264871000675d.png

Dans la boîte de dialogue, saisissez le nom de projet de votre choix et sélectionnez l'emplacement.

96d86d3d5655cdbe.png

  • Le nom du projet est le nom à afficher pour les participants au projet. Le nom du projet n'est pas utilisé par les API Google et peut être modifié à tout moment.
  • L'ID du projet est unique parmi tous les projets Google Cloud et non modifiable une fois défini. La console Google Cloud génère automatiquement un ID unique, mais vous pouvez le personnaliser. Si l'ID généré ne vous convient pas, vous pouvez en générer un autre de manière aléatoire ou fournir le vôtre pour vérifier sa disponibilité. Dans la plupart des ateliers de programmation, vous devrez indiquer l'ID de votre projet, généralement identifié par le code de substitution PROJECT_ID.
  • Pour information, il existe une troisième valeur (le numéro de projet) que certaines API utilisent. Pour en savoir plus sur ces trois valeurs, consultez la documentation.

Activer la facturation

Pour activer la facturation, deux options s'offrent à vous. Vous pouvez utiliser votre compte de facturation personnel ou échanger des crédits en suivant les étapes ci-dessous.

Utiliser 5 $de crédits Google Cloud (facultatif)

Pour suivre cet atelier, vous avez besoin d'un compte de facturation avec un certain crédit. Si vous prévoyez d'utiliser votre propre facturation, vous pouvez ignorer cette étape.

  1. Cliquez sur ce lien et connectez-vous avec un compte Google personnel.
  2. Le résultat qui s'affiche doit ressembler à ceci :

f54628965f465486.png

  1. Cliquez sur le bouton CLIQUEZ ICI POUR ACCÉDER À VOS CRÉDITS. Vous serez redirigé vers une page vous permettant de configurer votre profil de facturation. Si un écran d'inscription à un essai sans frais s'affiche, cliquez sur "Annuler", puis continuez à associer la facturation.

20e88842cf2a732e.png

  1. Cliquez sur "Confirmer". Vous êtes maintenant connecté à un compte de facturation d'essai Google Cloud Platform.

cdc87f1c57777951.png

Configurer un compte de facturation personnel

Si vous configurez la facturation à l'aide de crédits Google Cloud, vous pouvez ignorer cette étape.

Pour configurer un compte de facturation personnel, cliquez ici pour activer la facturation dans la console Cloud.

Remarques :

  • Cet atelier devrait vous coûter moins de 3 USD en ressources Cloud.
  • Vous pouvez suivre les étapes à la fin de cet atelier pour supprimer les ressources et éviter ainsi que des frais supplémentaires ne vous soient facturés.
  • Les nouveaux utilisateurs peuvent bénéficier d'un essai sans frais pour un crédit de 300$.

Démarrer Cloud Shell

Bien que Google Cloud puisse être utilisé à distance depuis votre ordinateur portable, nous allons nous servir de Google Cloud Shell pour cet atelier de programmation, un environnement de ligne de commande exécuté dans le cloud.

Dans la console Google Cloud, cliquez sur l'icône Cloud Shell dans la barre d'outils supérieure :

Activer Cloud Shell

Vous pouvez également appuyer sur G, puis sur S. Cette séquence activera Cloud Shell si vous êtes dans la console Google Cloud ou si vous utilisez ce lien.

Le provisionnement et la connexion à l'environnement prennent quelques instants seulement. Une fois l'opération terminée, le résultat devrait ressembler à ceci :

Capture d'écran du terminal Google Cloud Shell montrant que l'environnement est connecté

Cette machine virtuelle contient tous les outils de développement nécessaires. Elle comprend 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. Vous pouvez effectuer toutes les tâches de cet atelier de programmation dans un navigateur. Vous n'avez rien à installer.

3. Avant de commencer

Activer l'API

Résultat :

Pour utiliser Cloud SQL, Compute Engine, les services réseau et Vertex AI, vous devez activer leurs API respectives dans votre projet Google Cloud.

Dans le terminal Cloud Shell, assurez-vous que l'ID de votre projet est configuré :

gcloud config set project [YOUR-PROJECT-ID]

Définissez la variable d'environnement PROJECT_ID :

PROJECT_ID=$(gcloud config get-value project)

Activez tous les services nécessaires :

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

Résultat attendu

student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417
Updated property [core/project].
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project)
Your active configuration is: [cloudshell-14650]
student@cloudshell:~ (test-project-001-402417)$ 
student@cloudshell:~ (test-project-001-402417)$ gcloud services enable sqladmin.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.

Présentation des API

  • L'API Cloud SQL Admin (sqladmin.googleapis.com) vous permet de créer, de configurer et de gérer des instances Cloud SQL de manière programmatique. Il fournit le plan de contrôle du service de base de données relationnelle entièrement géré de Google (compatible avec MySQL, PostgreSQL et SQL Server), qui gère des tâches telles que le provisionnement, les sauvegardes, la haute disponibilité et le scaling.
  • L'API Compute Engine (compute.googleapis.com) vous permet de créer et de gérer des machines virtuelles (VM), des disques persistants et des paramètres réseau. Elle fournit la base IaaS (Infrastructure as a Service) requise pour exécuter vos charges de travail et héberger l'infrastructure sous-jacente de nombreux services gérés.
  • L'API Cloud Resource Manager (cloudresourcemanager.googleapis.com) vous permet de gérer de façon programmatique les métadonnées et la configuration de votre projet Google Cloud. Il vous permet d'organiser les ressources, de gérer les stratégies IAM (Identity and Access Management) et de valider les autorisations dans la hiérarchie des projets.
  • L'API Service Networking (servicenetworking.googleapis.com) vous permet d'automatiser la configuration de la connectivité privée entre votre réseau Virtual Private Cloud (VPC) et les services gérés de Google. Il est spécifiquement requis pour établir un accès par adresse IP privée pour des services tels qu'AlloyDB, afin qu'ils puissent communiquer de manière sécurisée avec vos autres ressources.
  • L'API Vertex AI (aiplatform.googleapis.com) permet à vos applications de créer, de déployer et de mettre à l'échelle des modèles de machine learning. Elle fournit une interface unifiée pour tous les services d'IA de Google Cloud, y compris l'accès aux modèles d'IA générative (comme Gemini) et l'entraînement de modèles personnalisés.

4. Créer une instance Cloud SQL

Créez une instance Cloud SQL avec l'intégration de la base de données à Vertex AI.

Créer un mot de passe pour la base de données

Définissez le mot de passe de l'utilisateur de base de données par défaut. Vous pouvez définir votre propre mot de passe ou utiliser une fonction aléatoire pour en générer un :

export CLOUDSQL_PASSWORD=`openssl rand -hex 12`

Notez la valeur générée pour le mot de passe :

echo $CLOUDSQL_PASSWORD

Créer une instance Cloud SQL pour PostgreSQL

Il existe différentes façons de créer des instances Cloud SQL, par exemple à l'aide de la console Google Cloud, d'outils d'automatisation comme Terraform ou du SDK Google Cloud. Dans cet atelier, nous allons principalement utiliser l'outil gcloud du SDK Google Cloud. Vous pouvez consulter la documentation pour savoir comment créer une instance à l'aide d'autres outils.

Dans la session Cloud Shell, exécutez :

gcloud sql instances create my-cloudsql-instance \
--database-version=POSTGRES_17 \
--tier=db-custom-1-3840 \
--region=us-central1 \
--edition=ENTERPRISE \
--enable-google-ml-integration \
--database-flags cloudsql.enable_google_ml_integration=on

Après avoir créé l'instance, nous devons définir un mot de passe pour l'utilisateur par défaut de l'instance et vérifier si nous pouvons nous connecter avec ce mot de passe.

gcloud sql users set-password postgres \
    --instance=my-cloudsql-instance \
    --password=$CLOUDSQL_PASSWORD

Exécutez la commande gcloud sql connect telle qu'elle est affichée dans la zone, puis saisissez votre mot de passe dans l'invite lorsqu'elle est prête à se connecter.

gcloud sql connect my-cloudsql-instance --user=postgres

Quittez la session psql pour le moment à l'aide du raccourci clavier Ctrl+D ou en exécutant la commande exit.

exit

Activer l'intégration à Vertex AI

Accordez les droits d'accès nécessaires au compte de service Cloud SQL interne pour pouvoir utiliser l'intégration Vertex AI.

Recherchez l'adresse e-mail du compte de service interne Cloud SQL et exportez-la en tant que variable.

SERVICE_ACCOUNT_EMAIL=$(gcloud sql instances describe my-cloudsql-instance --format="value(serviceAccountEmailAddress)")
echo $SERVICE_ACCOUNT_EMAIL

Accordez l'accès à Vertex AI au compte de service Cloud SQL :

PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
  --role="roles/aiplatform.user"

Pour en savoir plus sur la création et la configuration d'instances, consultez la documentation Cloud SQL ici.

5. Préparer la base de données

Nous devons maintenant créer une base de données et activer la prise en charge des vecteurs.

Créer une base de données

Créez une base de données nommée quickstart_db .Pour ce faire, vous disposez de différentes options, comme les clients de base de données en ligne de commande (psql pour PostgreSQL, par exemple), le SDK ou Cloud SQL Studio. Nous utiliserons le SDK (gcloud) pour créer des bases de données et nous connecter à l'instance.

Dans Cloud Shell, exécutez la commande pour créer la base de données.

gcloud sql databases create quickstart_db --instance=my-cloudsql-instance

Activer les extensions

Pour pouvoir utiliser Vertex AI et les vecteurs, nous devons activer deux extensions dans la base de données que nous avons créée.

Dans Cloud Shell, exécutez la commande pour vous connecter à la base de données créée (vous devrez fournir votre mot de passe).

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

Une fois la connexion établie, vous devez exécuter deux commandes dans la session SQL :

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

Quittez la session SQL :

exit;

6. Charger des données

Nous devons maintenant créer des objets dans la base de données et charger des données. Nous allons utiliser des données fictives de Cymbal Store. Les données sont disponibles au format CSV dans le bucket Google Storage public.

Nous devons d'abord créer tous les objets requis dans notre base de données. Pour ce faire, nous allons utiliser les commandes gcloud sql connect et gcloud storage que nous connaissons déjà pour télécharger et importer les objets de schéma dans notre base de données.

Dans Cloud Shell, exécutez la commande et saisissez le mot de passe noté lors de la création de l'instance :

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

Qu'avons-nous fait exactement dans la commande précédente ? Nous nous sommes connectés à notre base de données et avons exécuté le code SQL téléchargé, ce qui a créé des tables, des index et des séquences.

L'étape suivante consiste à charger les données. Pour ce faire, nous devons télécharger les fichiers CSV depuis Google Cloud Storage.

gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv .
gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv .
gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv .

Nous devons ensuite nous connecter à la base de données.

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

Importez ensuite les données à partir de vos fichiers CSV.

\copy cymbal_products from 'cymbal_products.csv' csv header
\copy cymbal_inventory from 'cymbal_inventory.csv' csv header
\copy cymbal_stores from 'cymbal_stores.csv' csv header

Si vous disposez de vos propres données et que vos fichiers CSV sont compatibles avec l'outil d'importation Cloud SQL disponible dans la console Cloud, vous pouvez l'utiliser à la place de l'approche en ligne de commande.

7. Créer des embeddings

L'étape suivante consiste à créer des embeddings pour nos descriptions de produits à l'aide du modèle textembedding-004 de Google Vertex AI et à les stocker sous forme de données vectorielles.

Connectez-vous à la base de données (si vous l'avez quittée ou si votre session précédente est déconnectée) :

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

Créez une colonne virtuelle embedding dans notre table cymbal_products à l'aide de la fonction d'embedding. Cette commande crée une colonne virtuelle "embedding" qui stocke nos vecteurs avec des embeddings générés à partir de la colonne "product_description". Il crée également des embeddings pour toutes les lignes existantes de la table. Le modèle est défini comme premier paramètre de la fonction d'embedding et les données sources comme deuxième paramètre.

ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-005',product_description)) STORED;

Cela peut prendre un certain temps, mais pour 900 à 1 000 lignes, cela ne devrait pas prendre plus de cinq minutes. En général, c'est beaucoup plus rapide.

Lorsque nous insérons une nouvelle ligne dans le tableau ou que nous mettons à jour la description d'un produit dans une ligne existante, les données de la colonne virtuelle embedding sont à nouveau générées en fonction de la colonne product_description.

8. Exécuter une recherche de similarités

Nous pouvons maintenant exécuter notre recherche à l'aide de la recherche par similarité basée sur les valeurs vectorielles calculées pour les descriptions et la valeur vectorielle que nous obtenons pour notre requête.

La requête SQL peut être exécutée à partir de la même interface de ligne de commande à l'aide de gcloud sql connect ou, à la place, à partir de Cloud SQL Studio. Il est préférable de gérer les requêtes complexes et comportant plusieurs lignes dans Cloud SQL Studio.

Démarrer Cloud SQL Studio

Dans la console, cliquez sur l'instance Cloud SQL que nous avons créée précédemment.

903eeb9bbaf4a419.png

Lorsque le panneau de droite est ouvert, nous pouvons voir Cloud SQL Studio. Cliquez dessus.

7874a11b28519b71.png

Une boîte de dialogue s'ouvre, dans laquelle vous devez indiquer le nom de la base de données et vos identifiants :

  • Base de données : quickstart_db
  • Utilisateur : postgres
  • Mot de passe : mot de passe que vous avez noté pour l'utilisateur principal de la base de données

Cliquez ensuite sur le bouton "AUTHENTICATE" (AUTHENTIFIER).

d5ee9e56dfef3905.png

La fenêtre suivante s'ouvre. Cliquez sur l'onglet "Editor" (Éditeur) sur la droite pour ouvrir l'éditeur SQL.

19a6ebd18ef6ae34.png

Nous sommes maintenant prêts à exécuter nos requêtes.

Exécuter la requête

Exécutez une requête pour obtenir la liste des produits disponibles qui correspondent le mieux à la demande d'un client. La requête que nous allons transmettre à Vertex AI pour obtenir la valeur vectorielle ressemble à "Quels types d'arbres fruitiers poussent bien ici ?"

Voici la requête que vous pouvez exécuter pour choisir les 10 premiers éléments les plus adaptés à votre demande :

SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        (cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) as distance
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        distance ASC
LIMIT 10;

Copiez et collez la requête dans l'éditeur Cloud SQL Studio, puis cliquez sur le bouton "RUN" (EXÉCUTER). Vous pouvez également la coller dans votre session de ligne de commande connectée à la base de données quickstart_db.

a8a2f83593aa5f37.png

Voici une liste de produits sélectionnés correspondant à la requête.

product_name       |                                   description                                    | sale_price | zip_code |      distance       
-------------------------+----------------------------------------------------------------------------------+------------+----------+---------------------
 Cherry Tree             | This is a beautiful cherry tree that will produce delicious cherries. It is an d |      75.00 |    93230 | 0.43922018972266397
 Meyer Lemon Tree        | Meyer Lemon trees are California's favorite lemon tree! Grow your own lemons by  |         34 |    93230 |  0.4685112926118228
 Toyon                   | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e |      10.00 |    93230 |  0.4835677149651668
 California Lilac        | This is a beautiful lilac tree that can grow to be over 10 feet tall. It is an d |       5.00 |    93230 |  0.4947204525907498
 California Peppertree   | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e |      25.00 |    93230 |  0.5054166905547247
 California Black Walnut | This is a beautiful walnut tree that can grow to be over 80 feet tall. It is a d |     100.00 |    93230 |  0.5084219510932597
 California Sycamore     | This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is  |     300.00 |    93230 |  0.5140519790508755
 Coast Live Oak          | This is a beautiful oak tree that can grow to be over 100 feet tall. It is an ev |     500.00 |    93230 |  0.5143126438081371
 Fremont Cottonwood      | This is a beautiful cottonwood tree that can grow to be over 100 feet tall. It i |     200.00 |    93230 |  0.5174774727252058
 Madrone                 | This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an |      50.00 |    93230 |  0.5227400803389093
(10 rows)

9. Améliorer la réponse du LLM à l'aide des données récupérées

Nous pouvons améliorer la réponse du LLM d'IA générative à une application cliente en utilisant le résultat de la requête exécutée et préparer une sortie pertinente en utilisant les résultats de la requête fournie dans le cadre du prompt à un modèle de langage de fondation génératif Vertex AI.

Pour ce faire, nous devons générer un fichier JSON contenant les résultats de notre recherche vectorielle, puis utiliser ce fichier JSON généré en complément d'une requête pour un modèle LLM dans Vertex AI afin de créer un résultat pertinent. Dans la première étape, nous générons le JSON, puis nous le testons dans Vertex AI Studio. Dans la dernière étape, nous l'intégrons à une instruction SQL qui peut être utilisée dans une application.

Générer une sortie au format JSON

Modifiez la requête pour générer la sortie au format JSON et ne renvoyer qu'une seule ligne à transmettre à Vertex AI.

Cloud SQL pour PostgreSQL

Voici un exemple de requête :

WITH trees as (
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id as product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

Voici le code JSON attendu dans le résultat :

[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]

Exécuter le prompt dans Vertex AI Studio

Nous pouvons utiliser le fichier JSON généré pour l'inclure dans la requête du modèle de texte d'IA générative dans Vertex AI Studio.

Ouvrez Vertex AI Studio dans la console cloud.

d48549b1b0f449b4.png

Il peut vous demander d'activer d'autres API, mais vous pouvez ignorer la demande. Nous n'avons besoin d'aucune API supplémentaire pour terminer notre atelier.

Saisissez une requête dans Studio.

2a6f5a338fefd229.png

Voici le prompt que nous allons utiliser :

You are a friendly advisor helping to find a product based on the customer's needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
[place your JSON here]
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information.
Do not ask any additional questions and assume location based on the zip code provided in the list of products.

Voici à quoi cela ressemble lorsque nous remplaçons l'espace réservé JSON par la réponse à la requête :

You are a friendly advisor helping to find a product based on the customer's needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information.
Do not ask any additional questions and assume location based on the zip code provided in the list of products.

Voici le résultat lorsque nous exécutons la requête avec nos valeurs JSON :

a0f7ead40d0a1d62.png

Voici la réponse que nous avons obtenue du modèle dans cet exemple. Notez que votre réponse peut être différente en raison des modifications apportées au modèle et aux paramètres au fil du temps :

"OBased on the zip code provided in our product list (93230), it looks like you are located in the Hanford, California area.1346 This region, located in the San Joaquin Valley, is actually one of the premier locations in the country for growing stone fruits.

Pour répondre à votre question, le meilleur arbre de notre sélection qui pousse dans votre région est le cerisier.

Voici les détails :

Produit : Cherry Tree

Prix : 75,00 $

Description : il s'agit d'un magnifique cerisier qui produira de délicieuses cerises.2

Pourquoi cette variété pousse-t-elle mieux ici ? Le climat de la vallée de San Joaquin offre les conditions spécifiques dont les cerisiers ont besoin pour prospérer : de longues et chaudes journées d'été pour le développement des fruits, et des nuits fraîches.5 Hanford se trouvant dans un important centre agricole réputé pour sa production de fruits à noyau, vous pouvez vous attendre à ce que cet arbre soit très productif dans votre sol local. Veillez simplement à le planter dans un endroit ensoleillé avec un sol bien drainé pour obtenir la meilleure récolte."

Exécuter la requête dans PSQL

Nous pouvons également utiliser l'intégration de l'IA Cloud SQL avec Vertex AI pour obtenir une réponse similaire à partir d'un modèle génératif à l'aide de SQL directement dans la base de données. Toutefois, pour utiliser le modèle gemini-2.0-flash-exp, nous devons d'abord l'enregistrer.

Exécuter dans Cloud SQL pour PostgreSQL

Mettez à niveau l'extension vers la version 1.4.2 ou ultérieure (si la version actuelle est antérieure). Connectez-vous à la base de données quickstart_db à partir de gcloud sql connect comme indiqué précédemment (ou utilisez Cloud SQL Studio), puis exécutez la commande suivante :

SELECT extversion from pg_extension where extname='google_ml_integration';

Si la valeur renvoyée est inférieure à 1.4.3, exécutez la commande suivante :

ALTER EXTENSION google_ml_integration UPDATE TO '1.4.3';

Nous devons ensuite définir le flag de base de données google_ml_integration.enable_model_support sur "on". Pour vérifier les paramètres actuels, exécutez

show google_ml_integration.enable_model_support;

Le résultat attendu de la session psql est "on" :

quickstart_db => show google_ml_integration.enable_model_support;
 google_ml_integration.enable_model_support 
--------------------------------------------
 on
(1 row)

Si l'option est désactivée, nous devons mettre à jour l'indicateur de base de données. Pour ce faire, vous pouvez utiliser l'interface de la console Web ou exécuter la commande gcloud suivante.

gcloud sql instances patch my-cloudsql-instance \
--database-flags google_ml_integration.enable_model_support=on,cloudsql.enable_google_ml_integration=on

L'exécution de la commande en arrière-plan prend environ une à trois minutes. Vous pouvez ensuite vérifier le nouvel indicateur dans la session psql ou à l'aide de Cloud SQL Studio en vous connectant à la base de données quickstart_db.

show google_ml_integration.enable_model_support;

Le résultat attendu de la session psql est "on" :

quickstart_db => show google_ml_integration.enable_model_support;
 google_ml_integration.enable_model_support 
--------------------------------------------
 on
(1 row)

Nous devons ensuite enregistrer deux modèles. Le premier est le modèle text-embedding-005 déjà utilisé. Il doit être enregistré, car nous avons activé les fonctionnalités d'enregistrement de modèles.

Pour enregistrer l'exécution du modèle dans psql ou Cloud SQL Studio, utilisez le code suivant :

CALL
  google_ml.create_model(
    model_id => 'text-embedding-005',
    model_provider => 'google',
    model_qualified_name => 'text-embedding-005',
    model_type => 'text_embedding',
    model_auth_type => 'cloudsql_service_agent_iam',
    model_in_transform_fn => 'google_ml.vertexai_text_embedding_input_transform',
    model_out_transform_fn => 'google_ml.vertexai_text_embedding_output_transform');

Le prochain modèle que nous devons enregistrer est gemini-2.0-flash-001, qui sera utilisé pour générer la sortie conviviale.

CALL
  google_ml.create_model(
    model_id => 'gemini-2.5-flash',
    model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/us-central1/publishers/google/models/gemini-2.5-flash:streamGenerateContent',
    model_provider => 'google',
    model_auth_type => 'cloudsql_service_agent_iam');

Vous pouvez toujours vérifier la liste des modèles enregistrés en sélectionnant des informations dans google_ml.model_info_view.

select model_id,model_type from google_ml.model_info_view;

Voici un exemple de résultat :

quickstart_db=> select model_id,model_type from google_ml.model_info_view;
               model_id               |   model_type   
--------------------------------------+----------------
 textembedding-gecko                  | text_embedding
 textembedding-gecko@001              | text_embedding
 gemini-1.5-pro:streamGenerateContent | generic
 gemini-1.5-pro:generateContent       | generic
 gemini-1.0-pro:generateContent       | generic
 text-embedding-005                   | text_embedding
 gemini-2.5-flash                     | generic

Nous pouvons maintenant utiliser le JSON généré dans une sous-requête pour le fournir dans la requête au modèle de texte d'IA générative à l'aide de SQL.

Dans la session psql ou Cloud SQL Studio de la base de données, exécutez la requête.

WITH trees AS (
SELECT
        cp.product_name,
        cp.product_description AS description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id AS product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci ON
        ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON
        cs.store_id = ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.embedding <=> google_ml.embedding('text-embedding-005',
        'What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1),
prompt AS (
SELECT
        'You are a friendly advisor helping to find a product based on the customer''s needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","product_description":"some description","sale_price":10}
Here is the list of products:' || json_agg(trees) || 'The customer asked "What kind of fruit trees grow well here?"
You should give information about the product, price and some supplemental information' AS prompt_text
FROM
        trees),
response AS (
SELECT
        json_array_elements(google_ml.predict_row( model_id =>'gemini-2.5-flash',
        request_body => json_build_object('contents',
        json_build_object('role',
        'user',
        'parts',
        json_build_object('text',
        prompt_text)))))->'candidates'->0->'content'->'parts'->0->'text' AS resp
FROM
        prompt)
SELECT
        string_agg(resp::text,
        ' ')
FROM
        response;

Voici le résultat attendu. Votre résultat peut être différent selon la version et les paramètres du modèle :

"That's a great question! It sounds like you're looking to add some delicious fruit to your garden.\n\nBased on the products we have that are closely related to your search, I can tell you about a fantastic option:\n\n**Cherry Tree**" "\n* **Description:** This beautiful deciduous tree will produce delicious cherries. It grows to be about 15 feet tall, with dark green leaves in summer that turn a beautiful red in the fall. Cherry trees are known for their beauty, shade, and privacy. They prefer a cool, moist climate and sandy soil." "\n* **Price:** $75.00\n* **Grows well in:** USDA Zones 4-9.\n\nTo confirm if this Cherry Tree will thrive in your specific location, you might want to check which USDA Hardiness Zone your area falls into. If you're in zones 4-9, this" " could be a wonderful addition to your yard!"

10. Créer un index des plus proches voisins

Notre ensemble de données est assez petit et le temps de réponse dépend principalement des interactions avec les modèles d'IA. Toutefois, lorsque vous avez des millions de vecteurs, la recherche vectorielle peut prendre une part importante de notre temps de réponse et exercer une forte charge sur le système. Pour améliorer cela, nous pouvons créer un index au-dessus de nos vecteurs.

Créer un index HNSW

Nous allons essayer le type d'index HNSW pour notre test. HNSW signifie Hierarchical Navigable Small World (petit monde navigable hiérarchique) et représente un index de graphique multicouche.

Pour créer l'index de notre colonne d'intégration, nous devons définir notre colonne d'intégration, notre fonction de distance et, éventuellement, des paramètres tels que m ou ef_constructions. Pour en savoir plus sur les paramètres, consultez la documentation.

CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

Résultat attendu :

quickstart_db=> CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);
CREATE INDEX
quickstart_db=>

Comparer la réponse

Nous pouvons maintenant exécuter la requête de recherche vectorielle en mode EXPLAIN et vérifier si l'index a été utilisé.

EXPLAIN (analyze) 
WITH trees as (
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id as product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

Résultat attendu :

 Aggregate  (cost=779.12..779.13 rows=1 width=32) (actual time=1.066..1.069 rows=1 loops=1)
   ->  Subquery Scan on trees  (cost=769.05..779.12 rows=1 width=142) (actual time=1.038..1.041 rows=1 loops=1)
         ->  Limit  (cost=769.05..779.11 rows=1 width=158) (actual time=1.022..1.024 rows=1 loops=1)
               ->  Nested Loop  (cost=769.05..9339.69 rows=852 width=158) (actual time=1.020..1.021 rows=1 loops=1)
                     ->  Nested Loop  (cost=768.77..9316.48 rows=852 width=945) (actual time=0.858..0.859 rows=1 loops=1)
                           ->  Index Scan using cymbal_products_embeddings_hnsw on cymbal_products cp  (cost=768.34..2572.47 rows=941 width=941) (actual time=0.532..0.539 rows=3 loops=1)
                                 Order By: (embedding <=> '[0.008864171,0.03693164,-0.024245683,...
<redacted>
...,0.017593635,-0.040275685,-0.03914233,-0.018452475,0.00826032,-0.07372604
]'::vector)
                           ->  Index Scan using product_inventory_pkey on cymbal_inventory ci  (cost=0.42..7.17 rows=1 width=37) (actual time=0.104..0.104 rows=0 loops=3)
                                 Index Cond: ((store_id = 1583) AND (uniq_id = (cp.uniq_id)::text))
                                 Filter: (inventory > 0)
                                 Rows Removed by Filter: 1
                     ->  Materialize  (cost=0.28..8.31 rows=1 width=8) (actual time=0.133..0.134 rows=1 loops=1)
                           ->  Index Scan using product_stores_pkey on cymbal_stores cs  (cost=0.28..8.30 rows=1 width=8) (actual time=0.129..0.129 rows=1 loops=1)
                                 Index Cond: (store_id = 1583)
 Planning Time: 112.398 ms
 Execution Time: 1.221 ms

Le résultat indique clairement que la requête utilisait "Index Scan using cymbal_products_embeddings_hnsw".

Et si nous exécutons la requête sans l'expliquer :

WITH trees as (
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id as product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

Résultat attendu (il peut varier selon le modèle et l'index) :

[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]

Nous pouvons constater que le résultat est le même et renvoyer le même cerisier qui figurait en tête de notre recherche sans index. En fonction des paramètres et du type d'index, il est possible que le résultat soit légèrement différent et renvoie un autre enregistrement en haut de l'arborescence. Lors de mes tests, la requête indexée a renvoyé des résultats en 131,301 ms contre 167,631 ms sans index. Cependant, nous travaillions avec un très petit ensemble de données et la différence serait plus importante sur des données plus volumineuses.

Vous pouvez essayer différents index disponibles pour les vecteurs, ainsi que d'autres ateliers et exemples avec l'intégration de LangChain disponibles dans la documentation.

11. Nettoyer l'environnement

Supprimez l'instance Cloud SQL.

Détruisez l'instance Cloud SQL une fois l'atelier terminé.

Dans Cloud Shell, définissez le projet et les variables d'environnement si vous avez été déconnecté et que tous les paramètres précédents sont perdus :

export INSTANCE_NAME=my-cloudsql-instance
export PROJECT_ID=$(gcloud config get-value project)

Supprimez l'instance :

gcloud sql instances delete $INSTANCE_NAME --project=$PROJECT_ID

Résultat attendu sur la console :

student@cloudshell:~$ gcloud sql instances delete $INSTANCE_NAME --project=$PROJECT_ID
All of the instance data will be lost when the instance is deleted.

Do you want to continue (Y/n)?  y

Deleting Cloud SQL instance...done.                                                                                                                
Deleted [https://sandbox.googleapis.com/v1beta4/projects/test-project-001-402417/instances/my-cloudsql-instance].

12. Félicitations

Bravo ! Vous avez terminé cet atelier de programmation.

Cet atelier fait partie du parcours de formation "IA prête pour la production avec Google Cloud".

  • Explorez le programme complet pour combler le fossé entre le prototype et la production.
  • Partagez votre progression avec le hashtag #ProductionReadyAI.

Points abordés

  • Déployer une instance Cloud SQL pour PostgreSQL
  • Créer une base de données et activer l'intégration de l'IA Cloud SQL
  • Charger des données dans la base de données
  • Utiliser Cloud SQL Studio
  • Utiliser le modèle d'embedding Vertex AI dans Cloud SQL
  • Utiliser Vertex AI Studio
  • Enrichir les résultats à l'aide du modèle génératif Vertex AI
  • Améliorer les performances à l'aide de l'index vectoriel

Essayez un atelier de programmation similaire pour AlloyDB avec un index ScaNN au lieu d'un index HNSW.

13. Enquête

Résultat :

Comment allez-vous utiliser ce tutoriel ?

Je vais le lire uniquement Je vais le lire et effectuer les exercices