1. Introduction
Dans cet atelier de programmation, vous allez apprendre à utiliser l'intégration de l'IA dans Cloud SQL pour PostgreSQL en combinant la recherche vectorielle avec les embeddings Vertex AI.
Prérequis
- Connaissances de base de 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 le modèle d'embedding Vertex AI dans Cloud SQL
- Enrichir le résultat à 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 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 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.
4. Créer une instance Cloud SQL
Créez une instance Cloud SQL avec intégration de la base de données à Vertex AI.
Créer un mot de passe de 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
Dans la session Cloud Shell, exécutez:
gcloud sql instances create my-cloudsql-instance \
--database-version=POSTGRES_16 \
--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 et saisissez votre mot de passe dans l'invite lorsque l'appareil est prêt à se connecter.
gcloud sql connect my-cloudsql-instance --user=postgres
Activer l'intégration à Vertex AI
Accordez les droits 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, puis 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:
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.
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 avec le nom quickstart_db .Pour ce faire, vous avez le choix entre différents clients de base de données de ligne de commande tels que psql pour PostgreSQL, 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 travailler avec 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, exécutez 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 les 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 sur le magasin Cymbal. Les données sont disponibles au format CSV dans le bucket public Google Storage.
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 vous connaissez 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 suivante et indiquez 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é, 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 à partir de 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
et importer des données à partir de nos 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
Quittez la session SQL:
exit;
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 de 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, puis à les stocker sous forme de données vectorielles.
Connectez-vous à la base de données :
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 embedding.
ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-004',product_description)) STORED;
Cela peut prendre un certain temps, mais pour 900 à 1 000 lignes, cela ne devrait pas prendre plus de cinq minutes, et généralement, c'est beaucoup plus rapide.
8. Exécuter une recherche de similarité
Nous pouvons maintenant effectuer notre recherche à l'aide d'une recherche de 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 toute requête multiligne et complexe 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.
Lorsque le panneau de droite est ouvert, Cloud SQL Studio s'affiche. Cliquez dessus.
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 sur le bouton "AUTHENTIFIER".
La fenêtre suivante s'ouvre. Cliquez sur l'onglet "Éditeur" sur le côté droit pour ouvrir l'éditeur SQL.
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 les plus proches de la demande 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;
Copiez et collez la requête dans l'éditeur Cloud SQL Studio, puis appuyez sur le bouton "RUN" (EXÉCUTER) ou collez-la dans votre session de ligne de commande qui se connecte à la base de données quickstart_db.
Voici la liste des 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 à l'aide du résultat de la requête exécutée et préparer une sortie pertinente à l'aide des résultats de la requête fournie dans l'invite adressée à un modèle de langage de base génératif Vertex AI.
Pour ce faire, nous devons générer un fichier JSON avec les résultats de la recherche vectorielle, puis utiliser ce fichier JSON généré en plus d'une invite pour un modèle LLM 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.
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-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
Voici le résultat JSON attendu:
[{"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 le chat Vertex AI Studio dans la console Cloud.
Il se peut que vous soyez 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:
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 ressemble la réponse lorsque nous remplaçons l'espace réservé JSON par la réponse de 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 l'invite avec nos valeurs JSON et en utilisant le modèle gemini-2.0-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:
"D\'accord. D\'après la liste des produits disponibles, le meilleur arbre qui pourrait bien se développer dans votre région est le cerisier.
Son prix est de 75 $.
Je ne dispose pas d'informations spécifiques sur les conditions de culture dans votre code postal exact (93230), mais les cerisiers sont généralement connus pour prospérer dans les régions aux climats modérés et aux sols bien drainés. Elles ont généralement besoin d'une certaine période de froid hivernal pour produire des fruits. Gardez cela à l'esprit. Toutefois, elles peuvent être un ajout merveilleux à un jardin, offrant à la fois beauté et délicieuses cerises lorsque les conditions sont réunies."
Exécuter l'invite dans PSQL
Nous pouvons également utiliser l'intégration de l'IA Cloud SQL à Vertex AI pour obtenir la réponse similaire 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 à l'aide 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.2, exécutez:
ALTER EXTENSION google_ml_integration UPDATE TO '1.4.2';
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 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 nouveau flag 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-004 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, exécutez le code suivant:
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 => '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.0-flash-001',
model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/us-central1/publishers/google/models/gemini-2.0-flash-001: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-004 | text_embedding gemini-2.0-flash-001 | generic
Nous pouvons maintenant utiliser le JSON généré dans une sous-requête pour l'inclure dans la requête du 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-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-2.0-flash-001',
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 en fonction de la version du modèle et des paramètres :
"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 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 entraîner une charge élevée sur le système. Pour améliorer cela, nous pouvons créer un indice 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 hiérarchique et navigable) et représente un indice de graphique multicouche.
Pour créer l'index de notre colonne d'intégration, nous devons définir notre colonne d'intégration, la 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-004','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 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":"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 que le même cerisier qui était en haut de notre recherche sans index est renvoyé. Selon les paramètres et le type d'index, le résultat peut être légèrement différent. Lors de mes tests, la requête indexée a renvoyé des résultats en 131,301 ms contre 167,631 ms sans indice, mais nous avions affaire à un très petit ensemble de données, et la différence serait plus importante avec des données plus importantes.
Vous pouvez essayer différents index disponibles pour les vecteurs, et accéder à d'autres ateliers et exemples avec intégration Langchain dans la documentation.
11. Nettoyer l'environnement
Supprimez l'instance Cloud SQL.
Détruire 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.
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 le modèle d'embedding Vertex AI dans Cloud SQL
- Enrichir le résultat à 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 l'index ScaNN au lieu de HNSW.
13. Enquête
Résultat :