1. Introduction
Dans cet atelier de programmation, vous allez apprendre à utiliser AlloyDB AI en combinant la recherche vectorielle avec des représentations vectorielles continues Vertex AI.
Prérequis
- Connaissances de base de la console Google Cloud
- Connaissances de base sur l'interface de ligne de commande et Google Shell
Points abordés
- Déployer un cluster AlloyDB et une instance principale
- Se connecter à AlloyDB depuis une VM Google Compute Engine
- Créer une base de données et activer AlloyDB AI
- Charger des données dans la base de données
- Utiliser le modèle de représentation vectorielle continue Vertex AI dans AlloyDB
- Enrichir les résultats à l'aide d'un modèle génératif Vertex AI
- Améliorer les performances à l'aide d'un index vectoriel
Prérequis
- Un compte Google Cloud et un projet Google Cloud
- Un navigateur Web tel que Chrome
2. Préparation
Configuration de l'environnement au rythme de chacun
- Connectez-vous à la console Google Cloud, puis créez un projet ou réutilisez un projet existant. Si vous n'avez pas encore de compte Gmail ou Google Workspace, vous devez en créer un.
- Le nom du projet est le nom à afficher pour les participants au projet. Il s'agit d'une chaîne de caractères non utilisée par les API Google. Vous pourrez toujours le modifier.
- L'ID du projet est unique parmi tous les projets Google Cloud et non modifiable une fois défini. La console Cloud génère automatiquement une chaîne unique (en général, vous n'y accordez d'importance particulière). Dans la plupart des ateliers de programmation, vous devrez indiquer l'ID de votre projet (généralement identifié par
PROJECT_ID
). Si l'ID généré ne vous convient pas, vous pouvez en générer un autre de manière aléatoire. Vous pouvez également en spécifier un et voir s'il est disponible. Après cette étape, l'ID n'est plus modifiable et restera donc le même pour toute la durée du projet. - 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.
- Vous devez ensuite activer la facturation dans la console Cloud pour utiliser les ressources/API Cloud. L'exécution de cet atelier de programmation est très peu coûteuse, voire sans frais. Pour désactiver les ressources et éviter ainsi que des frais ne vous soient facturés après ce tutoriel, vous pouvez supprimer le projet ou les ressources que vous avez créées. Les nouveaux utilisateurs de Google Cloud peuvent participer au programme d'essai sans frais pour bénéficier d'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 :
Le provisionnement et la connexion à l'environnement prennent quelques instants seulement. Une fois l'opération terminée, le résultat devrait ressembler à ceci :
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
Sortie :
Dans 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 alloydb.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 alloydb.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.
Configurez votre région par défaut pour utiliser les modèles d'embedding Vertex AI. En savoir plus sur les emplacements disponibles pour Vertex AI Dans cet exemple, nous utilisons la région us-central1.
gcloud config set compute/region us-central1
4. Déployer AlloyDB
Avant de créer un cluster AlloyDB, nous avons besoin d'une plage d'adresses IP privées disponible dans notre VPC, qui sera utilisée par la future instance AlloyDB. Si nous n'en avons pas, nous devons le créer et l'attribuer pour que les services internes de Google l'utilisent. Ensuite, nous serons en mesure de créer le cluster et l'instance.
Créer une plage d'adresses IP privées
Nous devons configurer l'accès au service privé dans notre VPC pour AlloyDB. L'hypothèse ici est que nous avons le réseau VPC "par défaut" dans le projet et qu'il sera utilisé pour toutes les actions.
Créez la plage d'adresses IP privées :
gcloud compute addresses create psa-range \
--global \
--purpose=VPC_PEERING \
--prefix-length=24 \
--description="VPC private service access" \
--network=default
Créez une connexion privée à l'aide de la plage d'adresses IP allouée :
gcloud services vpc-peerings connect \
--service=servicenetworking.googleapis.com \
--ranges=psa-range \
--network=default
Résultat attendu sur la console :
student@cloudshell:~ (test-project-402417)$ gcloud compute addresses create psa-range \ --global \ --purpose=VPC_PEERING \ --prefix-length=24 \ --description="VPC private service access" \ --network=default Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/global/addresses/psa-range]. student@cloudshell:~ (test-project-402417)$ gcloud services vpc-peerings connect \ --service=servicenetworking.googleapis.com \ --ranges=psa-range \ --network=default Operation "operations/pssn.p24-4470404856-595e209f-19b7-4669-8a71-cbd45de8ba66" finished successfully. student@cloudshell:~ (test-project-402417)$
Créer un cluster AlloyDB
Créez un cluster AlloyDB dans la région us-central1.
Définissez le mot de passe de l'utilisateur postgres. Vous pouvez définir votre propre mot de passe ou utiliser une fonction aléatoire pour en générer un.
export PGPASSWORD=`openssl rand -hex 12`
Résultat attendu sur la console :
student@cloudshell:~ (test-project-402417)$ export PGPASSWORD=`openssl rand -hex 12`
Notez le mot de passe PostgreSQL (il vous servira plus tard) :
echo $PGPASSWORD
Résultat attendu sur la console :
student@cloudshell:~ (test-project-402417)$ echo $PGPASSWORD bbefbfde7601985b0dee5723
Définissez la région et le nom du cluster AlloyDB. Nous allons utiliser le nom de cluster "us-central1 region" et "alloydb-aip-01" :
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
Exécutez la commande suivante pour créer le cluster :
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION
Résultat attendu sur la console :
export REGION=us-central1 export ADBCLUSTER=alloydb-aip-01 gcloud alloydb clusters create $ADBCLUSTER \ --password=$PGPASSWORD \ --network=default \ --region=$REGION Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4 Creating cluster...done.
Créer une instance principale AlloyDB
Créez une instance principale AlloyDB pour notre cluster dans la même session Cloud Shell. Si vous êtes déconnecté, vous devrez définir à nouveau les variables d'environnement de la région et du nom du cluster.
gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=2 \
--region=$REGION \
--cluster=$ADBCLUSTER
Résultat attendu sur la console :
student@cloudshell:~ (test-project-402417)$ gcloud alloydb instances create $ADBCLUSTER-pr \ --instance-type=PRIMARY \ --cpu-count=2 \ --region=$REGION \ --availability-type ZONAL \ --cluster=$ADBCLUSTER Operation ID: operation-1697659203545-6080315c6e8ee-391805db-25852721 Creating instance...done.
5. Se connecter à AlloyDB
AlloyDB est déployé à l'aide d'une connexion privée uniquement. Nous avons donc besoin d'une VM avec le client PostgreSQL installé pour utiliser la base de données.
Déployer une VM GCE
Créez une VM GCE dans la même région et dans le même VPC que le cluster AlloyDB.
Dans Cloud Shell, exécutez :
export ZONE=us-central1-a
gcloud compute instances create instance-1 \
--zone=$ZONE \
--create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \
--scopes=https://www.googleapis.com/auth/cloud-platform
Résultat attendu sur la console :
student@cloudshell:~ (test-project-402417)$ export ZONE=us-central1-a student@cloudshell:~ (test-project-402417)$ export ZONE=us-central1-a gcloud compute instances create instance-1 \ --zone=$ZONE \ --create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-12 AND family!=debian-12-arm64" --format="value(name)") \ --scopes=https://www.googleapis.com/auth/cloud-platform Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/zones/us-central1-a/instances/instance-1]. NAME: instance-1 ZONE: us-central1-a MACHINE_TYPE: n1-standard-1 PREEMPTIBLE: INTERNAL_IP: 10.128.0.2 EXTERNAL_IP: 34.71.192.233 STATUS: RUNNING
Installer le client Postgres
Installez le logiciel client PostgreSQL sur la VM déployée.
Connectez-vous à la VM.
gcloud compute ssh instance-1 --zone=us-central1-a
Résultat attendu sur la console :
student@cloudshell:~ (test-project-402417)$ gcloud compute ssh instance-1 --zone=us-central1-a Updating project ssh metadata...working..Updated [https://www.googleapis.com/compute/v1/projects/test-project-402417]. Updating project ssh metadata...done. Waiting for SSH key to propagate. Warning: Permanently added 'compute.5110295539541121102' (ECDSA) to the list of known hosts. Linux instance-1.us-central1-a.c.gleb-test-short-001-418811.internal 6.1.0-18-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. student@instance-1:~$
Installez la commande logicielle en cours d'exécution dans la VM :
sudo apt-get update
sudo apt-get install --yes postgresql-client
Résultat attendu sur la console :
student@instance-1:~$ sudo apt-get update sudo apt-get install --yes postgresql-client Get:1 https://packages.cloud.google.com/apt google-compute-engine-bullseye-stable InRelease [5146 B] Get:2 https://packages.cloud.google.com/apt cloud-sdk-bullseye InRelease [6406 B] Hit:3 https://deb.debian.org/debian bullseye InRelease Get:4 https://deb.debian.org/debian-security bullseye-security InRelease [48.4 kB] Get:5 https://packages.cloud.google.com/apt google-compute-engine-bullseye-stable/main amd64 Packages [1930 B] Get:6 https://deb.debian.org/debian bullseye-updates InRelease [44.1 kB] Get:7 https://deb.debian.org/debian bullseye-backports InRelease [49.0 kB] ...redacted... update-alternatives: using /usr/share/postgresql/13/man/man1/psql.1.gz to provide /usr/share/man/man1/psql.1.gz (psql.1.gz) in auto mode Setting up postgresql-client (13+225) ... Processing triggers for man-db (2.9.4-2) ... Processing triggers for libc-bin (2.31-13+deb11u7) ...
Se connecter à l'instance
Connectez-vous à l'instance principale depuis la VM à l'aide de psql.
Dans le même onglet Cloud Shell avec la session SSH ouverte sur votre VM instance-1.
Utilisez le mot de passe AlloyDB indiqué (PGPASSWORD) et l'ID de cluster AlloyDB pour vous connecter à AlloyDB à partir de la VM GCE:
export PGPASSWORD=<Noted password>
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
export INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)")
psql "host=$INSTANCE_IP user=postgres sslmode=require"
Résultat attendu sur la console :
student@instance-1:~$ export PGPASSWORD=CQhOi5OygD4ps6ty student@instance-1:~$ ADBCLUSTER=alloydb-aip-01 student@instance-1:~$ REGION=us-central1 student@instance-1:~$ INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)") gleb@instance-1:~$ psql "host=$INSTANCE_IP user=postgres sslmode=require" psql (15.6 (Debian 15.6-0+deb12u1), server 15.5) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off) Type "help" for help. postgres=>
Fermez la session psql:
exit
6. Préparer la base de données
Nous devons créer une base de données, activer l'intégration de Vertex AI, créer des objets de base de données et importer les données.
Accorder les autorisations nécessaires à AlloyDB
Ajoutez des autorisations Vertex AI à l'agent de service AlloyDB.
Ouvrez un autre onglet Cloud Shell à l'aide du signe "+" situé en haut.
Dans le nouvel onglet Cloud Shell, exécutez :
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"
Résultat attendu sur la console :
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project) Your active configuration is: [cloudshell-11039] student@cloudshell:~ (test-project-001-402417)$ 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" Updated IAM policy for project [test-project-001-402417]. bindings: - members: - serviceAccount:service-4470404856@gcp-sa-alloydb.iam.gserviceaccount.com role: roles/aiplatform.user - members: ... etag: BwYIEbe_Z3U= version: 1
Fermez l'onglet en exécutant la commande "exit" dans l'onglet :
exit
Créer une base de données
Créez un tutoriel de démarrage rapide pour créer une base de données.
Dans la session de la VM GCE, exécutez :
Créez une base de données:
psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db"
Résultat attendu sur la console :
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db" CREATE DATABASE student@instance-1:~$
Activer l'intégration de Vertex AI
Activez l'intégration de Vertex AI et les extensions pgvector dans la base de données.
Dans la VM GCE, exécutez :
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE"
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector"
Résultat attendu sur la console :
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE" psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector" CREATE EXTENSION CREATE EXTENSION student@instance-1:~$
Importer des données
Téléchargez les données préparées et importez-les dans la nouvelle base de données.
Dans la VM GCE, exécutez :
gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header"
gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header"
gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header"
Résultat attendu sur la console :
student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" SET SET SET SET SET set_config ------------ (1 row) SET SET SET SET SET SET CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE SEQUENCE ALTER TABLE ALTER SEQUENCE ALTER TABLE ALTER TABLE ALTER TABLE student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header" COPY 941 student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header" COPY 263861 student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header" COPY 4654 student@instance-1:~$
7. Calculer des représentations vectorielles continues
Après avoir importé les données, nous avons récupéré nos données produit dans la table cymbal_products, l'inventaire indiquant le nombre de produits disponibles dans chaque magasin dans la table cymbal_inventory et la liste des magasins dans la table cymbal_stores. Nous devons calculer les données vectorielles en fonction des descriptions de nos produits. Pour cela, nous allons utiliser la représentation vectorielle continue des fonctions. À l'aide de la fonction, nous allons utiliser l'intégration de Vertex AI pour calculer des données vectorielles à partir des descriptions de nos produits et les ajouter au tableau. Pour en savoir plus sur la technologie utilisée, consultez la documentation.
Créer une colonne de représentations vectorielles continues
Connectez-vous à la base de données à l'aide de psql et créez une colonne virtuelle avec les données vectorielles à l'aide de la fonction de représentation vectorielle continue de la table cymbal_products. La fonction d'encapsulation renvoie les données vectorielles de Vertex AI en fonction des données fournies dans la colonne "description_produit".
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
Dans la session psql après la connexion à la base de données, exécutez la commande suivante:
ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-004',product_description)) STORED;
La commande créera la colonne virtuelle et la remplira avec des données vectorielles.
Résultat attendu sur la console :
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" psql (13.11 (Debian 13.11-0+deb11u1), server 14.7) WARNING: psql major version 13, server major version 14. Some psql features might not work. SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) Type "help" for help. quickstart_db=> ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-004',product_description)) STORED; ALTER TABLE quickstart_db=>
8. Exécuter une recherche de similarité
Nous pouvons maintenant exécuter notre recherche à l'aide d'une recherche par similarité, basée sur les valeurs vectorielles calculées pour les descriptions et la valeur vectorielle obtenue pour notre requête.
La requête SQL peut être exécutée à partir de la même interface de ligne de commande psql ou, à la place, à partir d'AlloyDB Studio. Toute sortie complexe et multiligne peut avoir un meilleur rendu dans AlloyDB Studio.
Se connecter à AlloyDB Studio
Dans les chapitres suivants, toutes les commandes SQL nécessitant une connexion à la base de données peuvent être exécutées dans AlloyDB Studio. Pour exécuter la commande, vous devez ouvrir l'interface de la console Web de votre cluster AlloyDB en cliquant sur l'instance principale.
Cliquez ensuite sur AlloyDB Studio à gauche:
Choisissez la base de données quickstart_db, l'utilisateur postgres et indiquez le mot de passe noté lors de la création du cluster. Cliquez ensuite sur le bouton « S'authentifier » .
L'interface AlloyDB Studio s'ouvre. Pour exécuter les commandes dans la base de données, cliquez sur l'Éditeur 1. à droite.
Il ouvre une interface dans laquelle vous pouvez exécuter des commandes SQL.
Si vous préférez utiliser la ligne de commande psql, suivez la procédure alternative et connectez-vous à la base de données depuis la session SSH de votre VM, comme indiqué dans les chapitres précédents.
Exécuter une recherche de similarité à partir de psql
Si votre session de base de données a été déconnectée, reconnectez-vous à la base de données à l'aide de psql ou d'AlloyDB Studio.
Connectez-vous à la base de données :
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
Exécutez une requête pour obtenir la liste des produits disponibles étroitement liés à la requête d'un client. La requête que nous allons transmettre à Vertex AI pour obtenir la valeur du vecteur 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 à notre requête :
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
(cp.embedding <=> embedding('text-embedding-004','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;
Et voici le résultat attendu:
quickstart_db=> SELECT cp.product_name, left(cp.product_description,80) as description, cp.sale_price, cs.zip_code, (cp.embedding <=> embedding('text-embedding-004','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; 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
9. Améliorer la réponse
Vous pouvez améliorer la réponse à une application cliente à l'aide du résultat de la requête et préparer une sortie pertinente à l'aide des résultats de la requête fournis dans l'invite adressée au modèle de langage de base génératif de Vertex AI.
Pour ce faire, nous prévoyons de générer un fichier JSON avec les résultats de la recherche vectorielle, puis d'utiliser ce fichier JSON généré en plus d'une invite pour un modèle LLM de texte dans Vertex AI afin de créer une sortie pertinente. Dans la première étape, nous générons le fichier JSON, puis nous le testons dans Vertex AI Studio. Enfin, nous l'intégrons à une instruction SQL pouvant ê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.
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-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
Et voici le code JSON attendu dans la sortie:
[{"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 la requête 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.
Vous serez peut-être invité à activer des API supplémentaires, mais vous pouvez ignorer cette demande. Nous n'avons pas besoin d'API supplémentaires pour terminer cet atelier.
Voici l'invite que nous allons utiliser :
Vous êtes un conseiller amical qui aide à trouver un produit en fonction des besoins du client.
Suite à la demande du client, nous avons chargé une liste de produits étroitement liés à la recherche.
Liste au format JSON avec une liste de valeurs comme {"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Voici la liste des produits:
[emplacement de notre fichier JSON]
Le client a demandé : "Quel arbre pousse le mieux ici ?"
Vous devez fournir des informations sur le produit, le prix et d'autres informations complémentaires."
Voici le résultat lorsque nous exécutons l'invite avec nos valeurs JSON et en utilisant le modèle gemini-1.5-flash :
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 :
"Je vois que vous cherchez un arbre qui prospère dans votre région. Au vu de votre code postal, 93230, le cerisier semble être une excellente option !
Il est décrit comme un arbre magnifique produisant de délicieuses cerises. Il est actuellement disponible au prix de 75,00 €.
Je n'ai pas d'informations précises sur leur taux de croissance dans votre région, mais je peux vous dire que les cerisiers préfèrent généralement un sol bien drainé et le plein soleil.
Pour obtenir les meilleurs résultats, je vous recommande de consulter un pépiniériste ou un expert en jardinage local qui pourra vous fournir des conseils plus adaptés à votre région et aux conditions du sol. Ils peuvent également vous aider à choisir la variété la plus adaptée à vos besoins et vous donner des conseils sur la plantation et l'entretien."
Exécuter l'invite dans PSQL
Nous pouvons utiliser l'intégration de l'IA AlloyDB avec Vertex AI pour obtenir la même réponse d'un modèle génératif à l'aide de SQL directement dans la base de données. Mais pour utiliser le modèle gemini-1.5-flash, nous devons d'abord l'enregistrer.
Mettez à niveau l'extension vers la version 1.4.1 (si la version actuelle est antérieure). Connectez-vous à la base de données quickstart_db à partir de psql comme indiqué précédemment (ou utilisez AlloyDB 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.1, exécutez :
ALTER EXTENSION google_ml_integration UPDATE TO '1.4.1';
Nous devons ensuite définir l'option de base de données google_ml_integration.enable_model_support sur "on". Pour ce faire, vous pouvez utiliser l'interface de la console Web AlloyDB ou exécuter la commande gcloud suivante.
PROJECT_ID=$(gcloud config get-value project)
REGION=us-central1
ADBCLUSTER=alloydb-aip-01
gcloud beta alloydb instances update $ADBCLUSTER-pr \
--database-flags google_ml_integration.enable_model_support=on \
--region=$REGION \
--cluster=$ADBCLUSTER \
--project=$PROJECT_ID \
--update-mode=FORCE_APPLY
L'exécution de la commande en arrière-plan prend environ trois à cinq minutes. Vous pouvez ensuite vérifier le nouveau flag dans la session psql ou à l'aide d'AlloyDB 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" :
postgres=> 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-004 déjà utilisé. Il doit être enregistré, car nous avons activé les fonctionnalités d'enregistrement de modèles.
Pour enregistrer le modèle, exécutez le code suivant dans psql ou AlloyDB Studio:
CALL
google_ml.create_model(
model_id => 'text-embedding-004',
model_provider => 'google',
model_qualified_name => 'text-embedding-004',
model_type => 'text_embedding',
model_auth_type => 'alloydb_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 à enregistrer, gemini-1.5-flash-002, servira à générer une sortie conviviale.
CALL
google_ml.create_model(
model_id => 'gemini-1.5-flash-002',
model_request_url => 'https://$REGION-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/publishers/google/models/gemini-1.5-flash-002:streamGenerateContent',
model_provider => 'google',
model_auth_type => 'alloydb_service_agent_iam');
Vous pouvez toujours vérifier la liste des modèles enregistrés en sélectionnant des informations dans la vue 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 text-embedding-004 | text_embedding gemini-1.5-flash-001 | generic (4 rows)
Nous pouvons maintenant utiliser le JSON généré dans une sous-requête pour le fournir dans la requête du modèle de texte d'IA générative à l'aide de SQL.
Dans la session psql ou AlloyDB Studio vers 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 <=> embedding('text-embedding-004',
'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-1.5-flash-002',
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. Le résultat peut varier en fonction de la version et des paramètres du modèle :
"That" "'s a great question! Based on your location (assuming you're" " in zip code 93230), I have a suggestion for a" " fruit tree that should thrive.\n\nWe have the **Cherry Tree** available.\n\n**Product Name:** Cherry Tree\n\n**Description:** This is a beautiful cherry" " tree that will produce delicious cherries. It's a deciduous tree (meaning it loses its leaves in the fall) growing to about 15 feet tall." " The leaves are dark green in summer, turning a beautiful red in the fall. Cherry trees are known for their beauty, shade, and privacy.\n\n**Sale Price:** $75.00\n\n**Important Considerations for Growing" " Cherry Trees:**\n\n* **Climate:** Cherry trees prefer a cool, moist climate, and 93230 falls within a suitable range (USDA zones 4-9). However, it's always a good idea to" " check the specific microclimate of your property (sun exposure, drainage etc.).\n* **Soil:** They do best in sandy soil. If your soil is different, you may need to amend it to improve drainage.\n* **Pollination:** Many cherry varieties require a second, compatible cherry tree for proper pollination" ". Check the specific pollination needs of this variety before purchase if you want a significant cherry yield.\n\nThis cherry tree is a beautiful addition to any yard and will provide you with delicious cherries if you can meet its needs. Would you like to know more about its pollination requirements, or perhaps see if we have any other" " fruit trees suitable for your area?\n" ""
10. Créer un index vectoriel
Notre ensemble de données est relativement petit, et le temps de réponse dépend principalement de l'interaction avec les modèles d'IA. Mais lorsque vous avez des millions de vecteurs, la partie de recherche vectorielle peut utiliser une partie importante de notre temps de réponse et imposer une charge élevée au système. Pour améliorer cela, nous pouvons créer un index basé sur nos vecteurs.
Créer un index ScaNN
Pour créer l'index SCANN, nous devons activer une autre extension. L'extension alloydb_scann fournit une interface permettant de travailler avec l'index vectoriel de type ANN à l'aide de l'algorithme Google ScANN.
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
Résultat attendu :
quickstart_db=> CREATE EXTENSION IF NOT EXISTS alloydb_scann; CREATE EXTENSION Time: 27.468 ms quickstart_db=>
Nous pouvons maintenant créer l'index. Dans l'exemple suivant, je laisse la plupart des paramètres par défaut et ne fournit qu'un certain nombre de partitions (num_leaves) pour l'index:
CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
USING scann (embedding cosine)
WITH (num_leaves=31, max_num_levels = 2);
Pour en savoir plus sur le réglage des paramètres d'index, consultez la documentation.
Résultat attendu :
quickstart_db=> CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products USING scann (embedding cosine) WITH (num_leaves=31, max_num_levels = 2); 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-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
Résultat attendu :
Aggregate (cost=16.59..16.60 rows=1 width=32) (actual time=2.875..2.877 rows=1 loops=1) -> Subquery Scan on trees (cost=8.42..16.59 rows=1 width=142) (actual time=2.860..2.862 rows=1 loops=1) -> Limit (cost=8.42..16.58 rows=1 width=158) (actual time=2.855..2.856 rows=1 loops=1) -> Nested Loop (cost=8.42..6489.19 rows=794 width=158) (actual time=2.854..2.855 rows=1 loops=1) -> Nested Loop (cost=8.13..6466.99 rows=794 width=938) (actual time=2.742..2.743 rows=1 loops=1) -> Index Scan using cymbal_products_embeddings_scann on cymbal_products cp (cost=7.71..111.99 rows=876 width=934) (actual time=2.724..2.724 rows=1 loops=1) Order By: (embedding <=> '[0.008864171,0.03693164,-0.024245683,-0.00355923,0.0055611245,0.015985578,...<redacted>...5685,-0.03914233,-0.018452475,0.00826032,-0.07372604]'::vector) -> Index Scan using walmart_inventory_pkey on cymbal_inventory ci (cost=0.42..7.26 rows=1 width=37) (actual time=0.015..0.015 rows=1 loops=1) Index Cond: ((store_id = 1583) AND (uniq_id = (cp.uniq_id)::text))
La sortie indique clairement que la requête utilisait "Index Scan using cymbal_products_embeddings_scann on cymbal_products".
Et si nous exécutons la requête sans explication :
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-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
Résultat attendu :
[{"product_name":"Meyer Lemon Tree","description":"Meyer Lemon trees are California's favorite lemon tree! Grow your own lemons by ","sale_price":34,"zip_code":93230,"product_id":"02056727942aeb714dc9a2313654e1b0"}]
Nous pouvons constater que le résultat est légèrement différent et ne renvoie pas le cerisier qui était en haut de notre recherche sans index, mais le deuxième choix, le citronnier Meyer. L'indice est donc suffisamment performant, tout en étant suffisamment précis pour produire de bons résultats.
Vous pouvez essayer différents index disponibles pour les vecteurs, ainsi que d'autres ateliers et exemples d'intégration de Langchain disponibles sur la page de documentation.
11. Nettoyer l'environnement
Détruisez les instances et le cluster AlloyDB une fois l'atelier terminé.
Supprimer le cluster AlloyDB et toutes les instances
Le cluster est détruit avec l'option "force", qui supprime également toutes les instances appartenant au cluster.
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 :
gcloud config set project <your project id>
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
export PROJECT_ID=$(gcloud config get-value project)
Supprimez le cluster :
gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force
Résultat attendu sur la console :
student@cloudshell:~ (test-project-001-402417)$ gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force All of the cluster data will be lost when the cluster is deleted. Do you want to continue (Y/n)? Y Operation ID: operation-1697820178429-6082890a0b570-4a72f7e4-4c5df36f Deleting cluster...done.
Supprimer les sauvegardes AlloyDB
Supprimez toutes les sauvegardes AlloyDB du cluster :
for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done
Résultat attendu sur la console :
student@cloudshell:~ (test-project-001-402417)$ for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done Operation ID: operation-1697826266108-60829fb7b5258-7f99dc0b-99f3c35f Deleting backup...done.
Nous pouvons maintenant détruire notre VM.
Supprimer la VM GCE
Dans Cloud Shell, exécutez :
export GCEVM=instance-1
export ZONE=us-central1-a
gcloud compute instances delete $GCEVM \
--zone=$ZONE \
--quiet
Résultat attendu sur la console :
student@cloudshell:~ (test-project-001-402417)$ export GCEVM=instance-1 export ZONE=us-central1-a gcloud compute instances delete $GCEVM \ --zone=$ZONE \ --quiet Deleted
12. Félicitations
Bravo ! Vous avez terminé cet atelier de programmation.
Points abordés
- Déployer un cluster AlloyDB et une instance principale
- Se connecter à AlloyDB depuis une VM Google Compute Engine
- Créer une base de données et activer AlloyDB AI
- Charger des données dans la base de données
- Utiliser le modèle de représentation vectorielle continue Vertex AI dans AlloyDB
- Enrichir les résultats à l'aide d'un modèle génératif Vertex AI
- Améliorer les performances à l'aide d'un index vectoriel
13. Enquête
Résultat :