תחילת העבודה עם חיפוש היברידי ב-AlloyDB

1. מבוא

בשיעור Codelab הזה נלמד איך לבצע חיפוש היברידי ב-AlloyDB באמצעות התוסף RUM (שיטת עדכון הדירוג) והאינדקס ScaNN (חיפוש שכן קרוב מדרגי). שיעור ה-Lab הזה הוא חלק מאוסף שיעורי Lab שמוקדשים לתכונות של AlloyDB AI. מידע נוסף זמין בדף AlloyDB AI בתיעוד.

דרישות מוקדמות

  • הבנה בסיסית של Google Cloud Console
  • מיומנויות בסיסיות בממשק שורת הפקודה (CLI) וב-Google Shell

מה תלמדו

  • איך פורסים אשכול AlloyDB ומופע ראשי
  • איך מתחברים ל-AlloyDB ממכונה וירטואלית של Google Compute Engine
  • איך יוצרים מסד נתונים ומפעילים את AlloyDB AI
  • איך טוענים נתונים למסד הנתונים
  • איך משתמשים ב-AlloyDB Studio
  • יצירת הטמעות באמצעות Vertex AI
  • איך ליצור אינדקס וקטורי של ScaNN כדי לשפר את החיפוש הווקטורי
  • איך מפעילים את תוסף ה-RUM ומשתמשים בו לחיפוש טקסט מלא
  • ביצוע חיפוש היברידי על ידי שילוב של חיפוש טקסט מלא, חיפוש וקטורי ו-Reciprocal Rank Fusion (RRF)

מה תצטרכו

  • חשבון Google Cloud ופרויקט Google Cloud
  • דפדפן אינטרנט כמו Chrome

2. הגדרה ודרישות

הגדרת פרויקט

נכנסים ל-מסוף Google Cloud. אם עדיין אין לכם חשבון Gmail או Google Workspace, אתם צריכים ליצור חשבון.

משתמשים בחשבון לשימוש אישי במקום בחשבון לצורכי עבודה או בחשבון בית ספרי.

יצירת פרויקט ב-Google Cloud

  1. במסוף Google Cloud, בדף לבחירת הפרויקט, בוחרים פרויקט ב-Google Cloud או יוצרים פרויקט.
  2. הקפידו לוודא שהחיוב מופעל בפרויקט שלכם ב-Cloud. כך בודקים אם החיוב מופעל בפרויקט

הפעלת החיוב

יש שתי דרכים להפעיל את החיוב. אתם יכולים להשתמש בחשבון החיוב האישי שלכם או לממש את הקרדיטים באמצעות השלבים הבאים.

הגדרה של חשבון לחיוב לשימוש אישי

אם הגדרתם חיוב באמצעות קרדיטים ב-Google Cloud, אתם יכולים לדלג על השלב הזה.

כדי להגדיר חשבון לחיוב לשימוש אישי, עוברים לכאן כדי להפעיל את החיוב ב-Cloud Console.

הערות:

  • העלות של השלמת ה-Lab הזה במשאבי Cloud צריכה להיות פחות מ-3 דולר ארה"ב.
  • כדי להימנע מחיובים נוספים, אפשר למחוק את המשאבים בסיום ה-Lab.
  • משתמשים חדשים זכאים לתקופת ניסיון בחינם בשווי 300$.

מפעילים את Cloud Shell

אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-Codelab הזה נשתמש ב-Google Cloud Shell, סביבת שורת פקודה שפועלת בענן.

Cloud Shell היא סביבת שורת פקודה שפועלת ב-Google Cloud וכוללת מראש את הכלים הנדרשים.

  1. לוחצים על Activate Cloud Shell בחלק העליון של מסוף Google Cloud.
  2. אחרי שמתחברים ל-Cloud Shell, מאמתים את האימות:
    gcloud auth list
    
  3. מוודאים שהפרויקט מוגדר:
    gcloud config get project
    
  4. אם הפרויקט לא מוגדר כמו שציפיתם, מגדירים אותו:
    export PROJECT_ID=<YOUR_PROJECT_ID>
    gcloud config set project $PROJECT_ID
    

המכונה הווירטואלית הזו כוללת את כל הכלים שדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר מאוד את הביצועים והאימות ברשת. אפשר לבצע את כל העבודה ב-codelab הזה בדפדפן. לא צריך להתקין שום דבר.

3. לפני שמתחילים

הפעלת ה-API

פלט:

כדי להשתמש ב-AlloyDB, ב-Compute Engine, ב-Networking services וב-Vertex AI, צריך להפעיל את ממשקי ה-API שלהם בפרויקט בענן של Google Cloud.

הפעלת ממשקי ה-API

בטרמינל של Cloud Shell, מוודאים שמזהה הפרויקט מוגדר:

gcloud config set project [YOUR-PROJECT-ID]

מגדירים את משתנה הסביבה PROJECT_ID:

PROJECT_ID=$(gcloud config get-value project)

מפעילים את כל ממשקי ה-API הנדרשים:

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

הפלט הצפוי

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.

מבוא לממשקי ה-API

  • AlloyDB API‏ (alloydb.googleapis.com) מאפשר לכם ליצור ולנהל אשכולות של AlloyDB ל-PostgreSQL, ולשנות את גודלם. הוא מספק שירות מנוהל של מסד נתונים שתואם ל-PostgreSQL ומיועד לעומסי עבודה כבדים בטרנזקציות ובניתוחים בארגונים.
  • Compute Engine API‏ (compute.googleapis.com) מאפשר לכם ליצור ולנהל מכונות וירטואליות (VM), דיסקים לאחסון מתמיד והגדרות רשת. היא מספקת את הבסיס של תשתית כשירות (IaaS) שנדרש להפעלת עומסי העבודה ולאירוח התשתית הבסיסית של שירותים מנוהלים רבים.
  • Cloud Resource Manager API‏ (cloudresourcemanager.googleapis.com) מאפשר לכם לנהל באופן פרוגרמטי את המטא-נתונים וההגדרות של פרויקט Google Cloud. היא מאפשרת לכם לארגן משאבים, לטפל במדיניות של ניהול זהויות והרשאות גישה (IAM) ולאמת הרשאות בהיררכיית הפרויקט.
  • Service Networking API ‏ (servicenetworking.googleapis.com) מאפשר לכם להגדיר באופן אוטומטי קישוריות פרטית בין הרשת של הענן הווירטואלי הפרטי (VPC) שלכם לבין השירותים המנוהלים של Google. הוא נדרש במיוחד כדי ליצור גישה לכתובות IP פרטיות לשירותים כמו AlloyDB, כדי שהם יוכלו לתקשר בצורה מאובטחת עם המשאבים האחרים שלכם.
  • Vertex AI API‏ (aiplatform.googleapis.com) מאפשר לאפליקציות שלכם ליצור מודלים של למידת מכונה, לפרוס אותם ולבצע להם התאמה לעומס (scaling). הוא מספק ממשק מאוחד לכל שירותי ה-AI של Google Cloud, כולל גישה למודלים של AI גנרטיבי (כמו Gemini) ואימון מודלים בהתאמה אישית.

אפשר גם להגדיר את אזור ברירת המחדל לשימוש במודלים להטמעה של Vertex AI. מידע נוסף על המיקומים שבהם Vertex AI זמין בדוגמה אנחנו משתמשים באזור us-central1.

gcloud config set compute/region us-central1

4. פריסת AlloyDB

לפני שיוצרים אשכול AlloyDB, צריך להגדיר טווח כתובות IP פרטיות שיהיה זמין ב-VPC, כדי שמכונת AlloyDB תוכל להשתמש בו בעתיד. אם אין לנו את המזהה, אנחנו צריכים ליצור אותו, להקצות אותו לשימוש בשירותים פנימיים של Google, ואז נוכל ליצור את האשכול ואת המופע.

יצירת טווח כתובות IP פרטיות

אנחנו צריכים להגדיר גישה לשירותים פרטיים ב-VPC שלנו ל-AlloyDB. ההנחה כאן היא שיש לנו רשת VPC 'ברירת מחדל' בפרויקט, והיא תשמש לכל הפעולות.

יוצרים את טווח כתובות ה-IP הפרטיות:

gcloud compute addresses create psa-range \
    --global \
    --purpose=VPC_PEERING \
    --prefix-length=24 \
    --description="VPC private service access" \
    --network=default

יוצרים חיבור פרטי באמצעות טווח כתובות ה-IP שהוקצה:

gcloud services vpc-peerings connect \
    --service=servicenetworking.googleapis.com \
    --ranges=psa-range \
    --network=default

הפלט הצפוי במסוף:

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

יצירת אשכול AlloyDB

בקטע הזה אנחנו יוצרים אשכול AlloyDB באזור us-central1.

מגדירים סיסמה למשתמש postgres. אתם יכולים להגדיר סיסמה משלכם או להשתמש בפונקציה אקראית כדי ליצור סיסמה

export PGPASSWORD=`openssl rand -hex 12`

הפלט הצפוי במסוף:

student@cloudshell:~ (test-project-402417)$ export PGPASSWORD=`openssl rand -hex 12`

חשוב לשמור את הסיסמה של PostgreSQL לשימוש עתידי.

echo $PGPASSWORD

תצטרכו את הסיסמה הזו בעתיד כדי להתחבר למופע בתור משתמש postgres. מומלץ לרשום את הסיסמה או להעתיק אותה למקום כלשהו כדי שתוכלו להשתמש בה בהמשך.

הפלט הצפוי במסוף:

student@cloudshell:~ (test-project-402417)$ echo $PGPASSWORD
bbefbfde7601985b0dee5723

יצירת אשכול AlloyDB

מגדירים את האזור ואת שם האשכול של AlloyDB. אנחנו נשתמש באזור us-central1 וב-alloydb-hybrid-search כשם האשכול:

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

מריצים את הפקודה ליצירת האשכול:

gcloud alloydb clusters create $ADBCLUSTER \
    --password=$PGPASSWORD \
    --network=default \
    --region=$REGION

הפלט הצפוי במסוף:

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.                                                                                                                                                                                                                                                           

יוצרים מכונת AlloyDB ראשית לאשכול באותו סשן של Cloud Shell. אם החיבור ינותק, תצטרכו להגדיר מחדש את משתני הסביבה של שם האזור ושם האשכול.

gcloud alloydb instances create $ADBCLUSTER-pr \
    --instance-type=PRIMARY \
    --cpu-count=2 \
    --region=$REGION \
    --cluster=$ADBCLUSTER

הפלט הצפוי במסוף:

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. חיבור ל-AlloyDB

‫AlloyDB נפרס באמצעות חיבור פרטי בלבד, ולכן אנחנו צריכים מכונה וירטואלית עם לקוח PostgreSQL מותקן כדי לעבוד עם מסד הנתונים.

פריסת מכונה וירטואלית ב-GCE

יוצרים מכונת GCE וירטואלית באותו אזור ובאותו VPC כמו אשכול AlloyDB.

ב-Cloud Shell, מריצים את הפקודה:

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

הפלט הצפוי במסוף:

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

התקנת לקוח Postgres

התקנת תוכנת הלקוח של PostgreSQL במכונה הווירטואלית שנפרסה

מתחברים ל-VM:

gcloud compute ssh instance-1 --zone=us-central1-a

הפלט הצפוי במסוף:

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

מריצים את פקודת התוכנה בתוך ה-VM:

sudo apt-get update
sudo apt-get install --yes postgresql-client

הפלט הצפוי במסוף:

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

התחברות למופע

מתחברים למופע הראשי מהמכונה הווירטואלית באמצעות psql.

בכרטיסייה של Cloud Shell שבה פתוח סשן SSH למכונה הווירטואלית instance-1.

משתמשים בערך הסיסמה (PGPASSWORD) של AlloyDB שרשמתם ובמזהה האשכול של AlloyDB כדי להתחבר ל-AlloyDB מהמכונה הווירטואלית של 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"

הפלט הצפוי במסוף:

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

סוגרים את סשן ה-psql:

exit

6. הכנת מסד הנתונים

צריך ליצור מסד נתונים, להפעיל את השילוב עם Vertex AI, ליצור אובייקטים של מסד נתונים ולייבא את הנתונים.

מתן ההרשאות הנדרשות ל-AlloyDB

מוסיפים הרשאות ל-Vertex AI לסוכן השירות של AlloyDB.

פותחים כרטיסייה נוספת ב-Cloud Shell באמצעות הסימן '+' בחלק העליון.

abc505ac4d41f24e.png

בכרטיסייה החדשה של Cloud Shell, מריצים את הפקודה:

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"

הפלט הצפוי במסוף:

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
 

סוגרים את הכרטיסייה באמצעות הפקודה 'exit' בכרטיסייה:

exit

יצירת מסד נתונים

יוצרים מסד נתונים בשם quickstart.

בסשן של המכונה הווירטואלית ב-GCE, מריצים את הפקודה:

יצירת מסד נתונים:

psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db"

הפלט הצפוי במסוף:

student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db"
CREATE DATABASE
student@instance-1:~$  

הפעלת השילוב של Vertex AI

מפעילים את האינטגרציה של Vertex AI ואת התוספים pgvector במסד הנתונים.

במכונה הווירטואלית של GCE מריצים את הפקודה:

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"

הפלט הצפוי במסוף:

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

ייבוא נתונים

מורידים את הנתונים המוכנים ומייבאים אותם למסד הנתונים החדש.

במכונה הווירטואלית של GCE מריצים את הפקודה:

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"

הפלט הצפוי במסוף:

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

7. יצירת הטמעות וקטוריות

אחרי ייבוא הנתונים, יש לנו את הטבלאות הבאות: cymbal_products שבה מאוחסן מידע על מוצרים, cymbal_inventory שבה מתבצע מעקב אחר מלאי הפריטים בכל חנות, ו-cymbal_stores שהיא רשימה של חנויות. כדי לבצע חיפוש סמנטי במוצרים שלנו, אנחנו צריכים ליצור הטבעות וקטוריות של תיאורי המוצרים באמצעות הפונקציה initialize_embeddings. אנחנו נשתמש באינטגרציה של Vertex AI כדי לחשב נתוני וקטורים על סמך תיאורי המוצרים שלנו, ונוסיף אותם לטבלה. ניתן לקרוא מידע נוסף על הטכנולוגיה שבה נעשה שימוש במאמרי העזרה.

כדי להשתמש בשילוב, מתחברים למסד הנתונים באמצעות psql מהמכונה הווירטואלית באמצעות כתובת ה-IP של מכונת AlloyDB והסיסמה של postgres:

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

בודקים את הגרסה של התוסף google_ml_integration.

SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';

הגרסה צריכה להיות 1.5.2 ומעלה. דוגמה לפלט:

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

גרסת ברירת המחדל צריכה להיות 1.5.2 ומעלה, אבל אם במופע שלכם מופיעה גרסה ישנה יותר, כנראה שצריך לעדכן אותה. בודקים אם התחזוקה הושבתה במופע.

נשתמש ביצירת הטמעה של קבוצות כדי לשפר את היעילות. במדריך אפשר לקרוא מידע נוסף על אפשרויות וטכניקות שונות ליצירת הטמעה. כדי להשתמש בהטמעה של קבוצות, צריך להפעיל את goole_ml_integration.enable_faster_embedding_generation

show google_ml_integration.enable_faster_embedding_generation;

אם הדגל נמצא במיקום הנכון, הפלט הצפוי ייראה כך:

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

אבל אם מופיעה האפשרות 'כבוי', צריך לעדכן את המופע. אפשר לעשות את זה באמצעות מסוף האינטרנט או פקודת gcloud, כמו שמתואר בתיעוד. כאן מוסבר איך לעשות את זה באמצעות פקודת gcloud:

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 \
   --region=$REGION \
   --cluster=$ADBCLUSTER \
   --project=$PROJECT_ID \
   --update-mode=FORCE_APPLY

יכול להיות שיעברו כמה דקות, אבל בסופו של דבר הערך של הדגל ישתנה ל'מופעל'. אחרי זה אפשר להמשיך לשלבים הבאים.

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

בסשן psql שמחובר למסד הנתונים, יוצרים עמודה חדשה לאחסון הטמעות ב-cymbal_products

ALTER TABLE cymbal_products ADD COLUMN product_embedding vector(768);

הפלט הצפוי במסוף:

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

בנוסף, אנחנו רוצים שההטמעות יתעדכנו כשהערכים בעמודה משתנים, ולכן אנחנו כוללים את הארגומנט incremental_refresh_mode בבקשה להפעלת פונקציה. הפעולה הזו מוסיפה עומס למסד הנתונים שלנו, אבל אנחנו מוכנים לשלם את המחיר הזה כדי לשמור על סנכרון אוטומטי בין ההטמעות לתוכן. אם רוצים לעדכן את ההטמעות באופן ידני, אפשר למצוא את ההוראות במסמכי התיעוד.

עכשיו נחבר את הכול וניצור הטמעות. נשתמש בפונקציה initialize_embeddings, נעביר את batch_size של 50 כרמז לגבי גודל האצווה ונגדיר את incremental_refresh_mode ל-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'
);

ועכשיו, אם נוסיף שורה חדשה לטבלה עם הערך NULL בעמודה 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);

עכשיו, כשנריץ שאילתה על השורה שהוספנו, נראה שהעמודה product_embedding מתעדכנת באופן אוטומטי.

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

הפלט אמור להיראות כך:

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. יצירת אינדקס וקטורי

כדי לשפר את הביצועים של חיפוש וקטורי, נוסיף אינדקס ScaNN.

יצירת אינדקס ScaNN

כדי ליצור את אינדקס SCANN, צריך להפעיל עוד תוסף. התוסף alloydb_scann מספק ממשק לעבודה עם אינדקס וקטורי מסוג ANN באמצעות אלגוריתם ScaNN של Google.

CREATE EXTENSION IF NOT EXISTS alloydb_scann;

הפלט אמור להיראות כך:

quickstart_db=> CREATE EXTENSION IF NOT EXISTS alloydb_scann;
CREATE EXTENSION
Time: 27.468 ms
quickstart_db=> 

אפשר ליצור את האינדקס במצב ידני או במצב אוטומטי. המצב 'ידני' מופעל כברירת מחדל, ואפשר ליצור אינדקס ולתחזק אותו כמו כל אינדקס אחר. אבל אם מפעילים את מצב AUTO, אפשר ליצור את האינדקס בלי שיהיה צורך לבצע תחזוקה מצדכם. במאמרי העזרה אפשר לקרוא פרטים על כל האפשרויות. במקרה שלנו, אין לנו מספיק שורות כדי ליצור את האינדקס במצב AUTO, ולכן ניצור אותו במצב MANUAL ונכלול פרמטרים של כוונון. במסמכי התיעוד מוסבר איך לשנות את הפרמטרים של האינדקס.

צריך להפעיל את הדגל scann.enable_preview_features כדי שנוכל לשנות את פרמטרים ההתאמה. ב-Cloud Shell

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 scann.enable_preview_features=on \
   --region=$REGION \
   --cluster=$ADBCLUSTER \
   --project=$PROJECT_ID \
   --update-mode=FORCE_APPLY

יכול להיות שיעברו כמה דקות, אבל בסופו של דבר הערך של הדגל ישתנה ל'מופעל'. אחרי שמגדירים את הדגל, אפשר לחזור לpsql הסשן במכונה הווירטואלית וליצור את האינדקס עם פרמטרים של כוונון.

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

הפלט אמור להיראות כך:

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

בדיקת השימוש באינדקס

עכשיו אפשר להריץ את שאילתת החיפוש הווקטורי במצב EXPLAIN ולאמת אם נעשה שימוש באינדקס.

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;

הפלט הצפוי (הושמטו פרטים לשם הבהרה):

...
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 באמצעות cymbal_products_embeddings_scann ב-cymbal_products.

9. אינדקס חיפוש טקסט מלא

‫AlloyDB תומך בכל סוגי האינדקסים לחיפוש טקסט מלא שנתמכים ב-PostgreSQL מקורי. הבחירה באינדקס תלויה באיזון בין מהירות החיפוש, משך זמן של תהליך build של האינדקס, מהירות העדכון והפונקציות הספציפיות של החיפוש שנדרשות, כמו חיפוש של צירופי מילים או דירוג לפי רלוונטיות.

בדוגמה שלנו נשתמש בתוסף RUM כדי לבצע פעולות חיפוש טקסט מלא בצורה יעילה יותר. השימוש ב-RUM משפר את האינדקסים הרגילים של GIN כי הוא מאחסן מידע על מיקום ישירות באינדקס, וכך מאפשר לבצע חיפושים מהירים יותר של צירופי מילים ודירוג רלוונטיות בלי לגשת לנתוני הטבלה.

אפשר להשתמש ב-AlloyDB Studio או להמשיך להשתמש בלקוח psql כדי להפעיל את התוסף rum.

יצירת אינדקס RUM

CREATE EXTENSION IF NOT EXISTS rum;

כדי לחפש בתיאורי המוצרים בטבלה cymbal_products, צריך ליצור עמודה שבה מאוחסן תיאור המוצר כ-tsvector. בעמודה הזו מאוחסן באופן אוטומטי הטקסט שעבר עיבוד, והיא משפרת את ביצועי השאילתות.

ALTER TABLE cymbal_products
ADD COLUMN product_search_vector tsvector
GENERATED ALWAYS AS (to_tsvector('english', product_description)) STORED;

עכשיו אפשר ליצור אינדקס RUM חדש לעמודה product_search_vector.

CREATE INDEX cymbal_products_rum
ON cymbal_products
USING rum (product_search_vector rum_tsvector_ops);

כדי לשלוח שאילתה לטבלה באמצעות האינדקס, מריצים את השאילתה הבאה שמחפשת התאמות ל'עץ דובדבן'. האופרטור <=> מחשב את ציון הרלוונטיות, או המרחק, בין המסמך לבין השאילתה ישירות מהאינדקס.

SELECT product_name, product_description
FROM cymbal_products
WHERE product_search_vector @@ to_tsquery('english', 'cherry <-> tree')
ORDER BY product_search_vector <=> to_tsquery('english', 'cherry <-> tree');

10. ביצוע חיפוש היברידי

הפונקציה google_vector_utils.hybrid_search() מאפשרת לשלב תוצאות מכמה סוגי חיפוש, כמו חיפוש וקטורי וחיפוש טקסט מלא. הפונקציה ממזגת את התוצאות המדורגות מכל רכיב חיפוש לרשימה מאוחדת אחת באמצעות האלגוריתם Reciprocal Rank Fusion (מיזוג דירוג הפוך, RRF). הגישה הזו מספקת תוצאות רלוונטיות יותר מאשר סוג חיפוש יחיד.

הפונקציה hybrid_search() יוצרת ומריצה באופן דינמי שאילתת SQL אחת. הוא יוצר ביטוי טבלה נפוץ (CTE) לכל רכיב חיפוש שאתם מגדירים. הפונקציה מצטרפת לתוצאות מכל ה-CTE ומחשבת ציון RRF סופי לכל מסמך כדי ליצור רשימה מאוחדת ומדורגת.

כדי להשתמש בפונקציה, צריך להפעיל את enable_preview_ai_functions במופע הראשי. מריצים את הפקודה הבאה ב-Cloud Shell

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_preview_ai_functions=on \
   --region=$REGION \
   --cluster=$ADBCLUSTER \
   --project=$PROJECT_ID \
   --update-mode=FORCE_APPLY

השאילתה הבאה משלבת בין השאלה הקודמת שלנו לגבי חיפוש וקטורי לבין השאלה שלנו לגבי חיפוש טקסט מלא. זו שאילתת חיפוש היברידית פשוטה מאוד. אפשר לנסות משהו מורכב יותר, כמו שימוש ב'עצים שגובהם גדול יותר מגובה של בית' ברכיב החיפוש הווקטורי וב'קליפורניה' ברכיב FTS.

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

הפלט הצפוי

"score","id","product_name"
"0.00819672631147241","d536e9e823296a2eba198e52dd23e712","Cherry Tree"
"0.015873015873015872","23e41a71d63d8bbc9bdfa1d118cfddc5","Apple Tree"
"0.00819672631147241","dc789a2f87b142e94e6e325689482af9","Oak Tree"
"0.008064521129029258","f5c70d62ccf3118d73863bf3b17edcbe","Cypress Tree"
"0.008064521129029258","b70c44b1a38c0a2329fa583c9109a80f","Peach Tree"

בתוצאות יופיע id שהוא key_column שצוין, ו-score הוא הערך הסופי שמחושב על ידי RRF. האלגוריתם Reciprocal Rank Fusion ‏ (RRF) מבוסס על דירוג, והוא משלב כמה רשימות מדורגות של תוצאות חיפוש לרשימה מדורגת אחת על ידי הקצאת ניקוד לכל מסמך. הציון הזה מבוסס על הדירוג ההדדי של RRF בכל הרשימות התורמות, כאשר מסמכים עם דירוג גבוה יותר מקבלים תרומה גדולה יותר. באמצעות include_json_output => true בפרמטר, תוחזר עמודה detail_json שמכילה פירוט של חישוב הניקוד לכל רכיב.

חיפוש טקסט מלא הוא הכי טוב למציאת מונחים ספציפיים או התאמות מדויקות, אבל חיפוש וקטורי מצטיין במציאת מילים נרדפות וכוונות, גם כשאין התאמה בין המילים. המיזוג של שתי השיטות האלה מאפשר לחיפוש ההיברידי לספק למשתמשים קבוצה חזקה של תוצאות שהן גם מדויקות מבחינה מילולית וגם רלוונטיות מבחינה סמנטית.

11. ניקוי הסביבה

בסיום שיעור ה-Lab, משמידים את המופעים ואת האשכול של AlloyDB.

מחיקת אשכול AlloyDB וכל המכונות

אם השתמשתם בגרסת הניסיון של AlloyDB. אל תמחקו את אשכול הניסיון אם אתם מתכננים לבדוק מעבדות ומשאבים אחרים באמצעות אשכול הניסיון. לא תוכלו ליצור אשכול ניסיון נוסף באותו פרויקט.

האשכול נהרס עם האפשרות force, שמוחקת גם את כל המופעים ששייכים לאשכול.

אם התנתקתם וכל ההגדרות הקודמות אבדו, מגדירים את משתני הפרויקט והסביבה ב-Cloud Shell:

gcloud config set project <your project id>
export REGION=us-central1
export ADBCLUSTER=alloydb-hybrid-search
export PROJECT_ID=$(gcloud config get-value project)

מחיקת האשכול:

gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force

הפלט הצפוי במסוף:

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.   

מחיקת גיבויים של AlloyDB

מחיקת כל הגיבויים של AlloyDB באשכול:

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

הפלט הצפוי במסוף:

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.                                                                                                                                                                                                                                                            

עכשיו אפשר להרוס את המכונה הווירטואלית

מחיקת מכונה וירטואלית של GCE

ב-Cloud Shell, מריצים את הפקודה:

export GCEVM=instance-1
export ZONE=us-central1-a
gcloud compute instances delete $GCEVM \
    --zone=$ZONE \
    --quiet

הפלט הצפוי במסוף:

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. מזל טוב

כל הכבוד, סיימתם את ה-Codelab.

מה נכלל

  • איך פורסים אשכול AlloyDB ומופע ראשי
  • איך מתחברים ל-AlloyDB ממכונה וירטואלית של Google Compute Engine
  • איך יוצרים מסד נתונים ומפעילים את AlloyDB AI
  • איך טוענים נתונים למסד הנתונים
  • איך משתמשים ב-AlloyDB Studio
  • יצירת הטמעות באמצעות Vertex AI
  • איך ליצור אינדקס וקטורי של ScaNN כדי לשפר את החיפוש הווקטורי
  • איך מפעילים את תוסף ה-RUM ומשתמשים בו לחיפוש טקסט מלא
  • ביצוע חיפוש היברידי על ידי שילוב של חיפוש טקסט מלא, חיפוש וקטורי ו-Reciprocal Rank Fusion (RRF)