Premiers pas avec la recherche hybride dans AlloyDB

1. Introduction

Dans cet atelier de programmation, vous allez apprendre à effectuer une recherche hybride dans AlloyDB à l'aide de l'extension RUM (Ranking Update Method) et de l'index ScaNN (Scalable Nearest Neighbor). Cet atelier fait partie d'une collection d'ateliers consacrés aux fonctionnalités AlloyDB/AI. Pour en savoir plus, consultez la page AlloyDB AI dans la documentation.

Prérequis

  • Connaissances de base concernant la console Google Cloud
  • Compétences de base concernant 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 AlloyDB Studio
  • Générer des embeddings avec Vertex AI
  • Créer un index vectoriel ScaNN pour améliorer la recherche vectorielle
  • Créer un wrapper de données étrangères (FDW) pour Elasticsearch
  • Effectuez une recherche hybride en combinant la recherche sémantique dans AlloyDB et la recherche en texte intégral dans Elastic.

Prérequis

  • Un compte Google Cloud et un projet Google Cloud
  • Un navigateur Web (par exemple, Chrome)

2. Préparation

Configuration du projet

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.

Créer un projet Google Cloud

  1. Dans la console Google Cloud, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.
  2. Assurez-vous que la facturation est activée pour votre projet Cloud. Découvrez comment vérifier si la facturation est activée sur un projet.

Activer la facturation

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

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 des frais supplémentaires.
  • Les nouveaux utilisateurs peuvent bénéficier d'un 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.

Cloud Shell est un environnement de ligne de commande exécuté dans Google Cloud et fourni avec les outils nécessaires.

  1. Cliquez sur Activer Cloud Shell en haut de la console Google Cloud.
  2. Une fois connecté à Cloud Shell, vérifiez votre authentification :
    gcloud auth list
    
  3. Vérifiez que votre projet est configuré :
    gcloud config get project
    
  4. Si votre projet n'est pas défini comme prévu, définissez-le :
    export PROJECT_ID=<YOUR_PROJECT_ID>
    gcloud config set project $PROJECT_ID
    

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 AlloyDB, Compute Engine, les services réseau et Vertex AI, vous devez activer leurs API respectives dans votre projet Google Cloud.

Activer les API

Dans Cloud Shell, dans le terminal, 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 toutes les API nécessaires :

gcloud services enable alloydb.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.googleapis.com \
                       secretmanager.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 \
                       secretmanager.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.

Présentation des API

  • L'API AlloyDB (alloydb.googleapis.com) vous permet de créer, de gérer et de mettre à l'échelle des clusters AlloyDB pour PostgreSQL. Il s'agit d'un service de base de données entièrement géré et compatible avec PostgreSQL, conçu pour les charges de travail transactionnelles et analytiques d'entreprise exigeantes.
  • 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.
  • L'API Secret Manager (secretmanager.googleapis.com) est un service de gestion des secrets et des identifiants qui vous permet de stocker et de gérer des données sensibles telles que des clés API, des noms d'utilisateur, des mots de passe, des certificats, etc.

Vous pouvez également configurer 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 l'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 ne l'avons pas, nous devons le créer et l'attribuer pour qu'il soit utilisé par les services Google internes. Nous pourrons ensuite 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 \
    --export-custom-routes

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

Dans cette section, nous allons créer 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

Vous aurez besoin de ce mot de passe à l'avenir pour vous connecter à l'instance en tant qu'utilisateur postgres. Je vous suggère de le copier dans un endroit sûr (par exemple, un gestionnaire de mots de passe).

Résultat attendu sur la console :

student@cloudshell:~ (test-project-402417)$ echo $PGPASSWORD
<generated password>

Créer un cluster AlloyDB

Définissez la région et le nom du cluster AlloyDB. Nous allons utiliser la région us-central1 et alloydb-hybrid-search comme nom de cluster :

export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search

Exécutez la commande 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-hybrid-search
gcloud alloydb clusters create $ADBCLUSTER \
    --password=$PGPASSWORD \
    --network=default \
    --region=$REGION
Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4
Creating cluster...done.                                                                                                                                                                                                                                                           

Créez une instance principale AlloyDB pour le cluster dans la même session Cloud Shell. Si vous êtes déconnecté, vous devrez définir à nouveau les variables d'environnement pour la région et le 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:~ (alloydb-hybrid-search)$ 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. vous 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 pouvoir utiliser la base de données. Nous utiliserons également cette VM pour exécuter une instance Elasticsearch.

Déployer une VM GCE

Créez une VM GCE dans la même région et le même VPC que le cluster AlloyDB, et assurez-vous que le disque de démarrage est suffisamment grand pour exécuter Elastic. Ici, nous spécifions un disque de démarrage de 20 Go dans l'indicateur --create-disk.

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,size=20,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:~ (alloydb-hybrid-search)$ export ZONE=us-central1-a
student@cloudshell:~ (talloydb-hybrid-search)$ 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:~ (alloydb-hybrid-search)$ gcloud compute ssh instance-1 --zone=us-central1-a
Updating project ssh metadata...working..Updated [https://www.googleapis.com/compute/v1/projects/alloydb-hybrid-search].                                                                                                                                                         
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 que la session SSH ouverte sur votre VM instance-1.

Utilisez la valeur du mot de passe AlloyDB (PGPASSWORD) notée et l'ID du cluster AlloyDB pour vous connecter à AlloyDB depuis la VM GCE :

export PGPASSWORD=<Noted password>
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
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=<noted password>
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.

abc505ac4d41f24e.png

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 cliquant sur "X" ou en exécutant la commande :

exit

Créer une base de données

Créez une base de données nommée "quickstart".

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 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 :

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
gcloud storage 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"
gcloud storage 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"
gcloud storage 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:~$ gcloud storage 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:~$ gcloud storage 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:~$ gcloud storage 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:~$ gcloud storage 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:~$

Ensuite, définissons les indicateurs de base de données nécessaires. Vous pouvez utiliser la console Web et gérer les indicateurs dans l'instance principale, ou utiliser la commande gcloud comme suit :

export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
gcloud beta alloydb instances update $ADBCLUSTER-pr \
   --database-flags google_ml_integration.enable_faster_embedding_generation=on,scann.enable_preview_features=on,google_ml_integration.enable_preview_ai_functions=on,google_ml_integration.enable_ai_query_engine=on \
   --region=$REGION \
   --cluster=$ADBCLUSTER \
   --project=$PROJECT_ID \
   --update-mode=FORCE_APPLY

Résultat attendu sur la console

export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
gcloud beta alloydb instances update $ADBCLUSTER-pr \
   --database-flags google_ml_integration.enable_faster_embedding_generation=on,scann.enable_preview_features=on,google_ml_integration.enable_preview_ai_functions=on,google_ml_integration.enable_ai_query_engine=on \
   --region=$REGION \
   --cluster=$ADBCLUSTER \
   --project=$PROJECT_ID \
   --update-mode=FORCE_APPLY
Your active configuration is: [cloudshell-724]
Operation ID: operation-1775159889986-64e7f9ea9858a-b031e866-4c7c36df

L'activation des options de base de données nécessite un redémarrage de l'instance et prendra quelques minutes. Une fois l'opération terminée, l'état de l'instance AlloyDB indique "Prêt".

7. Générer des embeddings vectoriels

Après avoir importé les données, nous disposons des tables suivantes : cymbal_products, qui stocke des informations sur les produits, cymbal_inventory, qui suit le stock d'articles dans chaque magasin, et cymbal_stores, qui est une liste des magasins. Pour effectuer une recherche sémantique sur nos produits, nous devons générer des embeddings vectoriels de nos descriptions de produits avec la fonction initialize_embeddings. Nous utiliserons l'intégration Vertex AI pour calculer les données vectorielles en fonction de nos descriptions de produits et les ajouter au tableau. Pour en savoir plus sur la technologie utilisée, consultez la documentation.

Pour utiliser l'intégration, connectez-vous à la base de données avec AlloyDB Studio ou à l'aide de psql depuis votre VM en utilisant l'adresse IP de l'instance AlloyDB et le mot de passe postgres :

psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"

Vérifiez la version de l'extension google_ml_integration.

SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';

La version doit être 1.5.2 ou ultérieure. Voici un exemple de résultat :

quickstart_db=> SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';
 extversion
------------
 1.5.2
(1 row)

La version par défaut doit être la version 1.5.2 ou une version ultérieure. Si votre instance affiche une version antérieure, elle doit probablement être mise à jour. Vérifiez si la maintenance a été désactivée pour l'instance.

Installez l'extension vectorielle et créez une colonne pour stocker les embeddings dans cymbal_products.

CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE cymbal_products ADD COLUMN product_embedding vector(768);

Résultat attendu sur la console :

quickstart_db=> ALTER TABLE cymbal_products ADD COLUMN product_embedding vector(768);
ALTER TABLE
quickstart_db=>

Nous utiliserons la génération d'embeddings par lot pour améliorer l'efficacité. Pour en savoir plus sur les différentes options et techniques de génération d'embeddings, consultez le guide. Nous avons déjà activé l'indicateur goole_ml_integration.enable_faster_embedding_generation, qui nous permet de générer des embeddings par lots.

Enfin, nous souhaitons également que les embeddings soient actualisés lorsque les valeurs des colonnes sont modifiées. Pour ce faire, nous incluons l'argument incremental_refresh_mode dans l'appel de fonction. Cela introduit une surcharge dans notre base de données, mais c'est un compromis que nous faisons pour que les embeddings restent automatiquement synchronisés avec le contenu. Si vous souhaitez mettre à jour manuellement les embeddings, vous trouverez les instructions dans la documentation.

Maintenant, rassemblons tout et générons des embeddings. Nous utilisons la fonction initialize_embeddings et transmettons batch_size de 50 comme indication de lot et définissons incremental_refresh_mode sur transactional.

CALL ai.initialize_embeddings(
    model_id => 'text-embedding-005',
    table_name => 'cymbal_products',
    content_column => 'product_description',
    embedding_column => 'product_embedding',
    batch_size => 50,
    incremental_refresh_mode => 'transactional'
);

Maintenant, si nous insérons une nouvelle ligne dans le tableau avec la valeur NULL pour la colonne product_embedding

INSERT INTO "cymbal_products" ("uniq_id", "crawl_timestamp", "product_url", "product_name", "product_description", "list_price", "sale_price", "brand", "item_number", "gtin", "package_size", "category", "postal_code", "available", "product_embedding") VALUES ('fd604542e04b470f9e6348e640cff794', NOW(), 'https://example.com/new_product', 'New Cymbal Product', 'This is a new cymbal product description.', 199.99, 149.99, 'Example Brand', 'EB123', '1234567890', 'Single', 'Cymbals', '12345', TRUE, NULL);

Désormais, lorsque nous interrogerons la ligne que nous venons d'insérer, nous verrons que la colonne product_embedding est automatiquement mise à jour.

SELECT uniq_id, (product_embedding::real[])[1:5] as product_embedding  FROM cymbal_products WHERE uniq_id='fd604542e04b470f9e6348e640cff794';

Le résultat doit se présenter sous la forme suivante :

quickstart_db=> SELECT uniq_id,(product_embedding::real[])[1:5] as product_embedding  FROM cymbal_products WHERE uniq_id='fd604542e04b470f9e6348e640cff794';
             uniq_id              |                      product_embedding                       
----------------------------------+---------------------------------------------------------------
 fd604542e04b470f9e6348e640cff794 | {0.015003494,-0.005349732,-0.059790313,-0.0087091,-0.0271452}
(1 row)

Time: 3.295 ms

8. Créer un index vectoriel

Pour améliorer les performances de la recherche vectorielle, nous allons ajouter un index ScaNN.

Créer un index ScaNN

Pour créer l'index SCANN, nous devons activer une extension supplémentaire. L'extension alloydb_scann fournit une interface permettant d'utiliser l'index vectoriel de type ANN à l'aide de l'algorithme ScaNN de Google.

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=>

L'index peut être créé en mode MANUEL ou AUTO. Le mode MANUEL est activé par défaut. Vous pouvez créer un index et le gérer comme n'importe quel autre index. Toutefois, si vous activez le mode AUTO, vous pouvez créer l'index sans avoir à l'entretenir. Pour en savoir plus sur toutes les options, consultez la documentation. Dans notre cas, nous n'avons pas assez de lignes pour créer l'index en mode AUTO. Nous allons donc le créer en mode MANUAL et inclure des paramètres de réglage. Pour en savoir plus sur l'ajustement des paramètres d'index, consultez la documentation.

CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
  USING scann (product_embedding cosine)
  WITH (mode='MANUAL', num_leaves=31, max_num_levels = 2);

Résultat attendu :

quickstart_db=> CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
  USING scann (product_embedding cosine)
  WITH (num_leaves=31, max_num_levels = 2);
CREATE INDEX
quickstart_db=>

Inspecter l'utilisation de l'index

Nous pouvons maintenant exécuter la requête de recherche vectorielle en mode EXPLAIN et vérifier si l'index est 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.product_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 (masqué pour plus de clarté) :

...
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)
...

La sortie indique clairement que la requête utilisait "Index Scan using cymbal_products_embeddings_scann on cymbal_products".

9. Créer une instance Elastic

Elasticsearch est une marque d'Elastic NV et n'est pas affiliée à Google LLC. Nous utiliserons Elasticsearch pour la partie recherche en texte intégral (FTS) de la recherche hybride. Si vous disposez d'une instance Elasticsearch, vous pouvez ignorer les étapes suivantes et créer une clé API personnelle/utilisateur en lecture seule qu'AlloyDB pourra utiliser pour accéder à votre cluster Elasticsearch. Sinon, vous pouvez lancer une instance Elasticsearch dans la VM que vous avez créée précédemment.

Se connecter en SSH à la VM et installer Docker

sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Vous pouvez maintenant modifier la commande Docker à exécuter par votre utilisateur.

sudo usermod -aG docker $USER
newgrp docker

Dans le terminal de la VM, exécutez la commande suivante pour créer le conteneur élastique :

curl -fsSL https://elastic.co/start-local | sh

Résultat attendu (masqué)

🎉 Congrats, Elasticsearch and Kibana are installed and running in Docker!

🌐 Open your browser at http://localhost:5601

   Username: elastic
   Password: [password_value]

🔌 Elasticsearch API endpoint: http://localhost:9200
🔑 API key: [API Key]

Learn more at https://github.com/elastic/start-local

Copiez la sortie et collez-la dans le fichier suivant :

nano elastic-last-run.txt

Appuyez sur Ctrl+O, Entrée, Ctrl+X pour enregistrer et quitter.

Par défaut, le conteneur Docker écoute sur http://localhost:9200 et peut avoir du mal à recevoir la requête externe d'AlloyDB. Nous devons configurer docker-compose.yml pour qu'il écoute sur 9200:9200.

Après l'exécution du script, un répertoire elastic-start-local doit être créé. Accédez à ce répertoire et modifiez le fichier Dockerfile.

cd elastic-start-local/
nano docker-compose.yml

En haut de l'écran, vous trouverez

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:${ES_LOCAL_VERSION}
    container_name: ${ES_LOCAL_CONTAINER_NAME}
    volumes:
      - dev-elasticsearch:/usr/share/elasticsearch/data
    ports:
      - localhost:9200

Modifiez le champ ports pour qu'il soit

    ports:
      - 9200:9200

Enregistrez et quittez l'éditeur à l'aide des touches Ctrl+O, Entrée et Ctrl+X. Redémarrez maintenant la pile.

docker compose up -d

Nous allons maintenant remplir l'instance Elastic avec des descriptions et des noms de produits. Copiez le fichier CSV des produits depuis Cloud Storage vers la VM.

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

Résultat attendu

gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv .
Copying gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv to file://./cymbal_products.csv
  Completed files 1/1 | 1.4MiB/1.4MiB                                                                       

Average throughput: 147.9MiB/s

Créez maintenant un script Python pour extraire le fichier CSV et mettre en forme les données au format NDJSON pour l'importation groupée.

nano convert.py

Collez ce qui suit dans le fichier :

import csv
import json

# Configuration
input_file = 'cymbal_products.csv'
output_file = 'products.json'
index_name = 'elasticindexdemo'

def convert():
    try:
        with open(input_file, mode='r', encoding='utf-8') as f_in, \
             open(output_file, mode='w', encoding='utf-8') as f_out:
            
            reader = csv.DictReader(f_in)
            
            count = 0
            for row in reader:
                metadata = {
                    "index": {
                        "_index": index_name,
                        "_id": row['uniq_id'].strip()
                    }
                }
                
                # 2. Data/Source line
                document = {
                    "uniq_id": row['uniq_id'].strip(),
                    "product_name": row['product_name'].strip(),
                    "product_description": row['product_description'].strip()
                }
                
                # Write to file
                f_out.write(json.dumps(metadata) + '\n')
                f_out.write(json.dumps(document) + '\n')
                count += 1
                
            print(f"Success: Processed {count} products.")
            print(f"Output saved to: {output_file}")

    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == "__main__":
    convert()

Enregistrez le fichier et exécutez-le.

python3 convert.py

Résultat attendu

~$ python3 convert.py
Success: Processed 941 products.
Output saved to: products.json

Pour le chargement de données groupées, nous devons récupérer la clé API à partir de notre fichier d'exécution précédent et l'utiliser pour nous authentifier dans l'instance. Le fichier JSON créé précédemment est ensuite transmis. Pour les scénarios de production, il est préférable de définir l'index et les types de données dans Elasticsearch. Étant donné que l'ensemble de données de cet atelier de programmation est petit, nous laissons Elasticsearch gérer les données. Commencez par récupérer la clé API du fichier et enregistrez-la dans une variable.

AUTH_HDR=$(grep "API key" elastic-last-run.txt | sed -e "s/^.*API key:[[:space:]]*/ApiKey /g")

À l'aide de la variable que nous avons enregistrée, exécutez la commande curl suivante, qui importe les données du fichier JSON.

curl -s -X POST "localhost:9200/elasticindexdemo/_bulk?pretty" \
  -H "Content-Type: application/x-ndjson" \
  -H "Authorization: $AUTH_HDR" \
  --data-binary "@products.json"

Résultat attendu

~$ curl -s -X POST "localhost:9200/elasticindexdemo/_bulk?pretty" \
  -H "Content-Type: application/x-ndjson" \
  -H "Authorization: $AUTH_HDR" \
  --data-binary "@products.json"
{
  "errors" : false,
  "took" : 1003,
  "items" : [
    {
      "index" : {
        "_index" : "elasticindexdemo",
        "_id" : "a73d5f754f225ecb9fdc64232a57bc37",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 0,
        "_primary_term" : 1,
        "status" : 201
      }
    },
...]
}
Done

Enfin, nous devons récupérer la clé API de l'instance Elasticsearch afin de pouvoir l'enregistrer pour qu'AlloyDB puisse l'utiliser. Exécutez la commande suivante et copiez la valeur de la clé API.

cat elastic-last-run.txt

Avec la clé API, nous devons créer un secret dans Secret Manager. Dans Cloud Shell, exécutez la commande suivante avec votre clé API :

echo -n "[YOUR_API_KEY_VALUE]" | \
gcloud secrets create elasticsearch \
    --replication-policy="automatic" \
    --data-file=-

10. Créer un wrapper de données externes dans AlloyDB

Durée : 20:00

Pour interroger les données stockées dans Elasticsearch depuis AlloyDB, nous devons créer un wrapper de données externes (FDW) pour Elastic et une table externe. Auparavant, vous stockiez la clé API Elastic dans Secret Manager. Pour qu'AlloyDB puisse accéder au secret, accordez au compte de service l'autorisation requise.

Dans Cloud Shell, accordez au compte de service l'accès au secret elasticsearch.

gcloud secrets add-iam-policy-binding elasticsearch \
    --member="serviceAccount:service-$(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')@gcp-sa-alloydb.iam.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"

Résultat attendu

gcloud secrets add-iam-policy-binding elasticsearch \
    --member="serviceAccount:service-$(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')@gcp-sa-alloydb.iam.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"
Updated IAM policy for secret [elasticsearch].
bindings:
- members:
  - serviceAccount:service-257907437930@gcp-sa-alloydb.iam.gserviceaccount.com
  role: roles/secretmanager.secretAccessor
etag: BwZOghJiP5U=
version: 1

Accédez au cluster AlloyDB et ouvrez AlloyDB Studio (vous pouvez également utiliser psql pour vous connecter depuis la VM). Connectez-vous à quickstart_db en tant qu'utilisateur postgres.

Activer l'extension FDW

CREATE EXTENSION external_search_fdw;

Résultat attendu

Statement executed successfully

Pour accéder à Elasticsearch, créez un serveur de données étranger. L'adresse IP interne de la VM se trouve dans Compute Engine > Instances de VM. Pour le chemin d'accès au secret, accédez à Secret Manager et sélectionnez votre secret. Le chemin d'accès devrait se trouver en haut de la page. Assurez-vous d'inclure /versions/latest pour obtenir la version la plus récente du secret.

CREATE SERVER elastic_demo_server
FOREIGN DATA WRAPPER external_search_fdw
OPTIONS(
    server 'http://[VM INTERNAL IP ADDRESS]:9200',
    search_provider 'elastic',
    auth_method 'ApiKey',
    secret_path '[SECRET PATH]/versions/latest'
);

Définissez ensuite la table étrangère. Après les métadonnées, fournissez la définition du schéma de champ Elasticsearch pour qu'il corresponde aux données précédemment chargées. Dans la table distante, spécifiez le nom de l'index Elastic.

CREATE FOREIGN TABLE elasticindexdemo (
    metadata external_search_fdw_schema.OpaqueMetadata,
    uniq_id TEXT,
    product_name TEXT,
    product_description TEXT
)
SERVER elastic_demo_server
OPTIONS(
    remote_table_name 'elasticindexdemo'
);

Créer un mappage utilisateur pour le serveur

CREATE USER MAPPING FOR CURRENT_USER SERVER elastic_demo_server;

Vous pouvez maintenant tester la table externe.

SELECT uniq_id, product_name
FROM elasticindexdemo
ORDER BY metadata <@> 'product_description:lamp' DESC
limit 10;

Résultat attendu

"uniq_id","product_name"
"59c05332f09426c23d8d005528e3c12e","CVL Mini Vintage Metal Lamp Shade: Black Metal with Punched Pattern"
"c24dd78c0d570105256e1bf1cb2fea9d","Better Homes & Gardens Tapered Drum Shade, White Box Pleat"
"7ba20db2bcfab28f88fc714d73af1eb8","4 Pack E27 Wireless Remote Control Light Lamp Bulb Holder Cap Socket Switch 30m"
"0fad1469ea9dfa80b35cfe5266b8bfe7","Star Projector Lamp, 360 Degree Star Night Light Romantic Room Rotating Cosmos Star Projuctor With USB Cable, Light Lamp Starry Moon Sky Night Projector Kid Bedroom Lamp"
"70b37e483ef3678078236d36954525ce","Lucille 10.5\""h Duck Egg Blue Empire Stitched Lamp Shade 7x10x8"
"b7a4b9151598f4cae7707cbedabe3c1b","10x12x8\"" SLIP UNO FITTER Hardback Shallow Drum Lamp Shade Textured Slate"
"5962cf47b88186eed76d14f6376882df","E27 To E14 Lampshade Lamp Light Shades Socket Reducing Ring Adapter Washer"
"7c54fdebfe0b1dd3f649741b8928a95b","iMounTEK LED Projector Lamp Kids Night Light Star Moon Projection Night Lamp 360\u00b0 Rotation Timer for Children Bedroom"
"4531201095c2653530747e215fcc1435","Home Concept Inc 11 Classics Brass Empire Lamp Shade"
"350527adb4299a015bcce74dee97805e","6 Colors LED Star Projector Lamp 360 Degree Romantic Rotating Night Cosmos Star Sky Moon Projector Kids Sleep Night Light For Children Gift Bedroom Decor"

11. Utiliser la recherche hybride

Durée : 15:00

Maintenant que tout est configuré, nous pouvons utiliser la fonction ai.hybrid_search() pour combiner la recherche vectorielle et la recherche en texte intégral. Pour en savoir plus sur la recherche hybride, consultez la documentation. Lorsque vous utilisez la recherche hybride, les résultats de la requête utilisent par défaut l'algorithme Reciprocal Rank Fusion pour classer les résultats de plusieurs requêtes. Commençons par essayer la recherche vectorielle et la recherche hybride indépendamment pour analyser leurs différences.

La requête suivante effectue une recherche vectorielle pour trouver des produits similaires à la cerise. Le tableau fournit une liste des recherches à effectuer. Dans ce cas, nous n'utilisons que la recherche vectorielle, mais nous fournirons ultérieurement à la fois la recherche vectorielle et la recherche en texte intégral.

SELECT id, score, cymbal_products.product_name, cymbal_products.product_description
FROM ai.hybrid_search(
  ARRAY[
      '{
        "data_type": "vector",
        "table_name": "cymbal_products",
        "key_column": "uniq_id",
        "vec_column": "product_embedding",
        "distance_operator": "public.<=>",
        "limit": 3,
        "query_vector": "ai.embedding(''text-embedding-005'', ''cherry'')::vector"
      }'::JSONB
  ]
) JOIN cymbal_products ON id = cymbal_products.uniq_id;

Dans les résultats, le cerisier est le premier résultat, mais notez que les deux suivants sont également des arbres fruitiers. En effet, lorsque nous utilisons la recherche vectorielle dans la colonne product_description, nous trouvons des correspondances sémantiques à notre condition de recherche.

"id","score","product_name","product_description"
"d536e9e823296a2eba198e52dd23e712","0.01639344262295082","Cherry Tree","This is a beautiful cherry tree that will produce delicious cherries. It is an deciduous tree that grows to be about 15 feet tall. The leaves are dark green in the summer and turn a beautiful red in the fall. Cherry trees are known for their beauty and their ability to provide shade and privacy. Cherry trees prefer a cool, moist climate and sandy soil. They are best suited for USDA zones 4-9."
"b70c44b1a38c0a2329fa583c9109a80f","0.016129032258064516","Peach Tree","This is a beautiful peach tree that will produce delicious peaches. It is an evergreen tree that grows to be about 20 feet tall. The leaves are dark green in the summer and turn a beautiful yellow in the fall. Peach trees are known for their beauty and their ability to provide shade and privacy. Peach trees prefer a cool, moist climate and sandy soil. They are best suited for USDA zones 2-9."
"23e41a71d63d8bbc9bdfa1d118cfddc5","0.015873015873015872","Apple Tree","This is a beautiful apple tree that will produce delicious apples. It is a deciduous tree that grows to be about 30 feet tall. The leaves are dark green in the summer and turn a beautiful red, orange, and yellow in the fall. Apple trees are known for their strength and durability. They are also a popular choice for shade trees. Apple trees prefer a cool, moist climate and loamy soil. They are best suited for USDA zones 4-8."

Pour effectuer une recherche en texte intégral, exécutez la requête suivante :

SELECT id, score, cymbal_products.product_name, cymbal_products.product_description
FROM ai.hybrid_search(
  ARRAY[
      '{
        "limit": 3,
        "data_type": "external_search_fdw",
        "table_name": "elasticindexdemo",
        "key_column": "uniq_id",
        "query_text_input": "product_description:(cherry)"
      }'::JSONB
  ]
) JOIN cymbal_products ON id = cymbal_products.uniq_id;

Notez que, dans les résultats, la recherche en texte intégral utilise la correspondance exacte. Les résultats renvoient donc tout ce qui contient le mot "cerise" dans la description du produit.

"id","score","product_name","product_description"
"d536e9e823296a2eba198e52dd23e712","0.01639344262295082","Cherry Tree","This is a beautiful cherry tree that will produce delicious cherries. It is an deciduous tree that grows to be about 15 feet tall. The leaves are dark green in the summer and turn a beautiful red in the fall. Cherry trees are known for their beauty and their ability to provide shade and privacy. Cherry trees prefer a cool, moist climate and sandy soil. They are best suited for USDA zones 4-9."
"390cf08feac229e7b752709fd1f943b3","0.016129032258064516","Woven Round Placemat, Set of Twelve, Grass","...These placemats are great for special occasions and holidays, but are also perfect to accessorize your everyday place settings.|Measurements. 15-inch round diameter is the perfect size for most table sizes and shapes.|Pop Colors. Choose from 7 pop woven color placemats including: Black, Cherry, Grass, Taupe, Navy, Sun and Graphite."
"2c9aa7ac98c30abf78dd9c62a68a34e6","0.015873015873015872","48 Scented Wax Melts Wax Cubes: Jelly Belly Jelly Beans Candy Bulk Soy Wax Melts For Candle Warmer, Wax Warmers, Wax Melt Warmers In 8 Pack Set","...From These Flavors: Lemon Drop, Mixed Berry Smoothie, Sizzling Cinnamon, Crushed Pineapple, Juicy Pear, Cotton Candy, Toasted Marshmallow, French Vanilla, Watermelon, Red Apple, Very Cherry, Buttered Popcorn..."

Vous pouvez désormais combiner la recherche sémantique et la recherche en texte intégral pour obtenir des résultats plus pertinents. Imaginons que nous voulions rechercher un arbre qui peut atteindre une hauteur supérieure à celle d'une maison et qui provient de Californie. Nous avons divisé la requête pour exploiter l'intention sémantique par rapport à la mise en correspondance littérale. La recherche vectorielle gère la partie descriptive : "arbre qui peut devenir plus grand qu'une maison", car elle comprend le concept de hauteur et d'échelle sans avoir besoin de mots clés exacts. En parallèle, la recherche en texte intégral traite "Californie" comme un filtre strict pour s'assurer d'obtenir une correspondance géographique exacte plutôt qu'un résultat conceptuellement similaire.

SELECT id, score, cymbal_products.product_name, cymbal_products.product_description
FROM ai.hybrid_search(
  ARRAY[
    '{
        "data_type": "vector",
        "table_name": "cymbal_products",
        "key_column": "uniq_id",
        "vec_column": "product_embedding",
        "distance_operator": "public.<=>",
        "limit": 3,
        "query_vector": "ai.embedding(''text-embedding-005'', ''tree that can grow taller than a house'')::vector"
      }'::JSONB,
      '{
        "limit": 3,
        "data_type": "external_search_fdw",
        "table_name": "elasticindexdemo",
        "key_column": "uniq_id",
        "query_text_input": "product_description:(California)"
      }'::JSONB
  ]
) JOIN cymbal_products ON id = cymbal_products.uniq_id;

Résultats attendus :

"id","score","product_name","product_description"
"a589fd36a8a20fd9472d2403d6ed692a","0.00819672631147241","California Redwood","This is a beautiful redwood tree that can grow to be over 300 feet tall. It is an evergreen tree that grows in the coastal forests of California. Redwoods are known for their beauty and their strength. They are best suited for USDA zones 7-10."
"ef9432802da24041594c2cf368dfb4d2","0.008064521129029258","Madrone","This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an evergreen tree that grows in the coastal forests of California. Madronas are known for their beauty and their bark. They are best suited for USDA zones 7-10."
"1360d8642bc218e4ea28e9c32b2e1721","0.007936512936504936","California Sycamore","This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is an deciduous tree that grows in the valleys and foothills of California. California sycamores are known for their beauty and their shade. They are best suited for USDA zones 7-10."

12. Nettoyer l'environnement

Détruisez les instances et le cluster AlloyDB une fois l'atelier terminé.

Supprimer le cluster AlloyDB et toutes les instances

Si vous avez utilisé la version d'essai d'AlloyDB. Ne supprimez pas le cluster d'essai si vous prévoyez de tester d'autres ateliers et ressources à l'aide de ce cluster. Vous ne pourrez pas créer d'autre cluster d'essai dans le même projet.

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-hybrid-search
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

13. 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 AlloyDB Studio
  • Générer des embeddings avec Vertex AI
  • Créer un index vectoriel ScaNN pour améliorer la recherche vectorielle
  • Créer un wrapper de données étrangères (FDW) pour Elasticsearch
  • Effectuez une recherche hybride en combinant la recherche sémantique dans AlloyDB et la recherche en texte intégral dans Elastic.

Étapes suivantes

Vous trouverez d'autres ateliers de programmation AlloyDB sur le site officiel des ateliers de programmation.