1. מבוא
ב-codelab הזה מוסבר איך פורסים את AlloyDB ואיך משתמשים בשילוב AI לחיפוש סמנטי באמצעות הטמעות מרובות מצבים. ה-Lab הזה הוא חלק מאוסף של Labs שמוקדשים לתכונות של AlloyDB AI. מידע נוסף זמין בדף AlloyDB AI בתיעוד.
דרישות מוקדמות
- הבנה בסיסית של Google Cloud ושל המסוף
- מיומנויות בסיסיות בממשק שורת הפקודה וב-Cloud Shell
מה תלמדו
- איך פורסים את AlloyDB ל-Postgres
- איך משתמשים בחיפוש וקטורי מרובה מצבים
- איך מפעילים אופרטורים של AlloyDB AI
- איך משתמשים באופרטורים שונים של AlloyDB AI לחיפוש מרובה מצבים
- איך משתמשים ב-AlloyDB AI כדי לשלב תוצאות חיפוש של טקסט ותמונות
מה צריך
- חשבון Google Cloud ופרויקט Google Cloud
- דפדפן אינטרנט כמו Chrome שתומך במסוף Google Cloud וב-Cloud Shell
2. הגדרה ודרישות
הגדרת סביבה בקצב אישי
- נכנסים ל-Google Cloud Console ויוצרים פרויקט חדש או משתמשים בפרויקט קיים. אם עדיין אין לכם חשבון Gmail או חשבון Google Workspace, אתם צריכים ליצור חשבון.
- שם הפרויקט הוא השם המוצג למשתתפים בפרויקט. זו מחרוזת תווים שלא נמצאת בשימוש ב-Google APIs. תמיד אפשר לעדכן את המיקום.
- מזהה הפרויקט הוא ייחודי לכל הפרויקטים ב-Google Cloud, והוא קבוע (אי אפשר לשנות אותו אחרי שהוא מוגדר). מסוף Cloud יוצר באופן אוטומטי מחרוזת ייחודית. בדרך כלל לא צריך לדעת מה היא. ברוב ה-Codelabs, תצטרכו להפנות למזהה הפרויקט (בדרך כלל מסומן כ-
PROJECT_ID
). אם אתם לא אוהבים את המזהה שנוצר, אתם יכולים ליצור מזהה אקראי אחר. אפשר גם לנסות שם משתמש משלכם ולבדוק אם הוא זמין. אי אפשר לשנות את ההגדרה הזו אחרי השלב הזה, והיא נשארת לאורך הפרויקט. - לידיעתכם, יש ערך שלישי, מספר פרויקט, שחלק מממשקי ה-API משתמשים בו. במאמרי העזרה מפורט מידע נוסף על שלושת הערכים האלה.
- בשלב הבא, תצטרכו להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבי Cloud או בממשקי API של Cloud. השלמת ה-codelab הזה לא תעלה לכם הרבה, אם בכלל. כדי להשבית את המשאבים ולמנוע חיובים נוספים אחרי שתסיימו את המדריך הזה, תוכלו למחוק את המשאבים שיצרתם או למחוק את הפרויקט. משתמשים חדשים ב-Google Cloud זכאים לתוכנית תקופת ניסיון בחינם בשווי 300$.
הפעלת Cloud Shell
אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-codelab הזה תשתמשו ב-Google Cloud Shell, סביבת שורת פקודה שפועלת בענן.
ב-Google Cloud Console, לוחצים על סמל Cloud Shell בסרגל הכלים שבפינה הימנית העליונה:
יחלפו כמה רגעים עד שההקצאה והחיבור לסביבת העבודה יושלמו. בסיום התהליך, אמור להופיע משהו כזה:
המכונה הווירטואלית הזו כוללת את כל הכלים הדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר מאוד את הביצועים והאימות של הרשת. אפשר לבצע את כל העבודה ב-codelab הזה בדפדפן. לא צריך להתקין שום דבר.
3. לפני שמתחילים
הפעלת ה-API
ב-Cloud Shell, מוודאים שמזהה הפרויקט מוגדר:
gcloud config set project [YOUR-PROJECT-ID]
מגדירים את משתנה הסביבה PROJECT_ID:
PROJECT_ID=$(gcloud config get-value project)
מפעילים את כל השירותים הנדרשים:
gcloud services enable alloydb.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
servicenetworking.googleapis.com \
aiplatform.googleapis.com \
discoveryengine.googleapis.com \
secretmanager.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.
4. פריסת AlloyDB
יצירת אשכול AlloyDB ומכונה ראשית. בקטע הבא מוסבר איך ליצור אשכול ומופע של AlloyDB באמצעות Google Cloud SDK. אם אתם מעדיפים להשתמש במסוף, תוכלו לפעול לפי ההוראות במאמר הזה.
לפני שיוצרים אשכול AlloyDB, צריך להגדיר ב-VPC טווח כתובות IP פרטיות שיהיה זמין לשימוש על ידי מכונת 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-aip-01 כשם האשכול:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
מריצים את הפקודה ליצירת האשכול:
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION \
--subscription-type=TRIAL
הפלט הצפוי במסוף:
export REGION=us-central1 export ADBCLUSTER=alloydb-aip-01 gcloud alloydb clusters create $ADBCLUSTER \ --password=$PGPASSWORD \ --network=default \ --region=$REGION \ --subscription-type=TRIAL Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4 Creating cluster...done.
יוצרים מכונת AlloyDB ראשית לאשכול באותו סשן של Cloud Shell. אם החיבור ינותק, תצטרכו להגדיר מחדש את משתני הסביבה של שם האזור והאשכול.
gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=8 \
--region=$REGION \
--cluster=$ADBCLUSTER
הפלט הצפוי במסוף:
student@cloudshell:~ (test-project-402417)$ gcloud alloydb instances create $ADBCLUSTER-pr \ --instance-type=PRIMARY \ --cpu-count=8 \ --region=$REGION \ --availability-type ZONAL \ --cluster=$ADBCLUSTER Operation ID: operation-1697659203545-6080315c6e8ee-391805db-25852721 Creating instance...done.
יצירת אשכול AlloyDB Standard
אם זה לא אשכול ה-AlloyDB הראשון שלכם בפרויקט, ממשיכים ליצירה של אשכול רגיל.
מגדירים את האזור ואת שם אשכול AlloyDB. אנחנו נשתמש באזור us-central1 וב-alloydb-aip-01 כשם האשכול:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
מריצים את הפקודה ליצירת האשכול:
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION
הפלט הצפוי במסוף:
export REGION=us-central1 export ADBCLUSTER=alloydb-aip-01 gcloud alloydb clusters create $ADBCLUSTER \ --password=$PGPASSWORD \ --network=default \ --region=$REGION Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4 Creating cluster...done.
יוצרים מכונת AlloyDB ראשית לאשכול באותו סשן של Cloud Shell. אם החיבור ינותק, תצטרכו להגדיר מחדש את משתני הסביבה של שם האזור והאשכול.
gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=2 \
--region=$REGION \
--cluster=$ADBCLUSTER
הפלט הצפוי במסוף:
student@cloudshell:~ (test-project-402417)$ gcloud alloydb instances create $ADBCLUSTER-pr \ --instance-type=PRIMARY \ --cpu-count=2 \ --region=$REGION \ --availability-type ZONAL \ --cluster=$ADBCLUSTER Operation ID: operation-1697659203545-6080315c6e8ee-391805db-25852721 Creating instance...done.
5. הכנת מסד נתונים
צריך ליצור מסד נתונים, להפעיל את השילוב עם Vertex AI, ליצור אובייקטים של מסד נתונים ולייבא את הנתונים.
מתן ההרשאות הנדרשות ל-AlloyDB
מוסיפים הרשאות Vertex AI לסוכן השירות של AlloyDB.
פותחים כרטיסייה נוספת ב-Cloud Shell באמצעות הסימן '+' בחלק העליון.
בכרטיסייה החדשה של 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
התחברות ל-AlloyDB Studio
בפרקים הבאים, אפשר להריץ ב-AlloyDB Studio את כל פקודות ה-SQL שדורשות חיבור למסד הנתונים. כדי להריץ את הפקודה, צריך לפתוח את ממשק מסוף האינטרנט של אשכול AlloyDB על ידי לחיצה על המופע הראשי.
אחר כך לוחצים על AlloyDB Studio בצד ימין:
בוחרים את מסד הנתונים של postgres, את המשתמש postgres ומזינים את הסיסמה שרשמתם כשיצרתם את האשכול. לאחר מכן לוחצים על הלחצן 'אימות'.
ממשק AlloyDB Studio ייפתח. כדי להריץ את הפקודות במסד הנתונים, לוחצים על הכרטיסייה Editor 1 (עורך 1) בצד שמאל.
ייפתח ממשק שבו אפשר להריץ פקודות SQL
יצירת מסד נתונים
מדריך להתחלה מהירה ליצירת מסד נתונים
בעורך של AlloyDB Studio, מריצים את הפקודה הבאה.
יצירת מסד נתונים:
CREATE DATABASE quickstart_db
הפלט אמור להיראות כך:
Statement executed successfully
התחברות ל-quickstart_db
מתחברים מחדש ל-Studio באמצעות הלחצן להחלפת משתמש או מסד נתונים.
בוחרים מהרשימה הנפתחת את מסד הנתונים החדש quickstart_db ומשתמשים באותו משתמש ובאותה סיסמה כמו קודם.
תיפתח לכם חיבור חדש שבו תוכלו לעבוד עם אובייקטים ממסד הנתונים quickstart_db.
6. נתונים לדוגמה
עכשיו צריך ליצור אובייקטים במסד הנתונים ולטעון נתונים. נשתמש בחנות בדיונית בשם Cymbal עם נתונים בדיוניים.
לפני שמייבאים את הנתונים, צריך להפעיל תוספים שתומכים בסוגי נתונים ובאינדקסים. אנחנו צריכים שתי תוספים: אחד שתומך בסוג הנתונים של הווקטור, והשני שתומך באינדקס AlloyDB ScaNN.
ב-AlloyDB Studio, מתחברים ל-quickstart_db ומריצים את הפקודה.
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
מערך הנתונים מוכן ומוצב כקובץ SQL שאפשר לטעון למסד הנתונים באמצעות ממשק הייבוא. ב-Cloud Shell, מריצים את הפקודות הבאות:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
gcloud alloydb clusters import $ADBCLUSTER --region=$REGION --database=quickstart_db --gcs-uri='gs://sample-data-and-media/ecomm-retail/ecom_generic_vectors.sql' --user=postgres --sql
הפקודה משתמשת ב-AlloyDB SDK ויוצרת משתמש בשם agentspace_user, ואז מייבאת נתונים לדוגמה ישירות ממאגר GCS למסד הנתונים, יוצרת את כל האובייקטים הנדרשים ומכניסה נתונים.
אחרי הייבוא, אפשר לבדוק את הטבלאות ב-AlloyDB Studio. הטבלאות נמצאות בסכימת ecomm:
ולאמת את מספר השורות באחת מהטבלאות.
ייבאנו בהצלחה את הנתונים לדוגמה ואפשר להמשיך לשלבים הבאים.
7. חיפוש סמנטי באמצעות הטמעות טקסט
בפרק הזה ננסה להשתמש בחיפוש סמנטי באמצעות הטמעות טקסט, ונשווה אותו לחיפוש טקסט מסורתי ולחיפוש טקסט מלא ב-Postgres.
קודם ננסה את החיפוש הקלאסי באמצעות SQL סטנדרטי של PostgreSQL עם האופרטור LIKE.
אם ננסה לחפש מעיל גשם באמצעות השאילתה הבאה:
SET session.my_search_var='%wet%conditions%jacket%';
SELECT
name,
product_description,
retail_price, replace(product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url
FROM
ecomm.products
WHERE
name ILIKE current_setting('session.my_search_var')
OR product_description ILIKE current_setting('session.my_search_var')
LIMIT
10;
השאילתה לא מחזירה שורות כי היא צריכה מילים מדויקות כמו wet conditions ו-jacket שיופיעו בשם המוצר או בתיאור שלו. המונח 'מעיל לתנאים רטובים' לא זהה למונח 'מעיל לתנאי גשם'.
אנחנו יכולים לנסות לכלול את כל הווריאציות האפשריות של החיפוש. ננסה לכלול רק שתי מילים. לדוגמה:
SELECT
name,
product_description,
retail_price,
replace(product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url
FROM
ecomm.products
WHERE
name ILIKE '%wet%jacket%'
OR name ILIKE '%jacket%wet%'
OR name ILIKE '%jacket%'
OR name ILIKE '%%wet%'
OR product_description ILIKE '%wet%jacket%'
OR product_description ILIKE '%jacket%wet%'
OR product_description ILIKE '%jacket%'
OR product_description ILIKE '%wet%'
LIMIT
10;
הפעולה הזו תחזיר כמה שורות, אבל לא כולן יתאימו באופן מושלם לבקשה שלנו לגבי מעילים, וקשה למיין אותן לפי הרלוונטיות. לדוגמה, אם נוסיף עוד תנאים כמו 'לגברים' ואחרים, מורכבות השאילתה תגדל באופן משמעותי. לחלופין, אפשר לנסות חיפוש טקסט מלא, אבל גם כאן יש מגבלות שקשורות למילים מדויקות פחות או יותר ולרלוונטיות של התשובה.
עכשיו אפשר לבצע חיפוש דומה באמצעות הטמעות. כבר חישבנו מראש את ההטמעות של המוצרים שלנו באמצעות מודלים שונים. נשתמש במודל gemini-embedding-001 העדכני של Google. שמרנו אותם בעמודה product_embedding בטבלה ecomm.products. אם מריצים שאילתה לתנאי החיפוש 'מעיל גשם לגברים' באמצעות השאילתה הבאה:
SELECT
name,
product_description,
retail_price,
replace(product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url,
product_embedding <=> embedding ('gemini-embedding-001','wet conditions jacket for men')::vector AS distance
FROM
ecomm.products
ORDER BY distance
LIMIT
10;
היא תחזיר לא רק את המעילים לתנאים רטובים, אלא גם תמיין את כל התוצאות כך שהתוצאות הרלוונטיות ביותר יוצגו בחלק העליון.
השאילתה עם ההטמעות מחזירה תוצאות תוך 90-150 אלפיות השנייה, כאשר חלק מהזמן מושקע בהשגת הנתונים ממודל ההטמעה בענן. אם בודקים את תוכנית הביצוע, רואים שהבקשה למודל כלולה בזמן התכנון. החלק בשאילתה שמבצע את החיפוש עצמו הוא קצר למדי. החיפוש ב-29,000 רשומות באמצעות אינדקס AlloyDB ScaNN נמשך פחות מ-7 אלפיות השנייה.
Limit (cost=2709.20..2718.82 rows=10 width=490) (actual time=6.966..7.049 rows=10 loops=1)
-> Index Scan using embedding_scann on products (cost=2709.20..30736.40 rows=29120 width=490) (actual time=6.964..7.046 rows=10 loops=1)
Order By: (product_embedding <=> '[-0.0020264734,-0.016582033,0.027258193
...
-0.0051468653,-0.012440448]'::vector)
Limit: 10
Planning Time: 136.579 ms
Execution Time: 6.791 ms
(6 rows)
זה היה חיפוש הטמעה של טקסט באמצעות מודל ההטמעה של טקסט בלבד. אבל יש לנו גם תמונות של המוצרים ואנחנו יכולים להשתמש בהן בחיפוש. בפרק הבא נסביר איך המודל הרב-אופני משתמש בתמונות לחיפוש.
8. שימוש בחיפוש מרובה מצבים
חיפוש סמנטי מבוסס-טקסט הוא שימושי, אבל יכול להיות קשה לתאר פרטים מורכבים. החיפוש ב-AlloyDB באמצעות multimodal מאפשר ללקוחות לגלות מוצרים באמצעות הזנת תמונות. האפשרות הזו שימושית במיוחד כשייצוג חזותי מסביר את כוונת החיפוש בצורה יעילה יותר מאשר תיאורים מילוליים בלבד. לדוגמה: "תמצא לי מעיל כמו זה שבתמונה".
נחזור לדוגמה של המעיל. אם יש לי תמונה של מעיל שדומה למה שאני רוצה למצוא, אני יכול להעביר אותה למודל ההטמעה הרב-אופני של Google ולהשוות אותה להטמעות של תמונות המוצרים שלי. בטבלה שלנו כבר חישבנו את ההטמעות של תמונות המוצרים בעמודה product_image_embedding, ואפשר לראות את המודל שבו השתמשנו בעמודה product_image_embedding_model.
בחיפוש שלנו, אנחנו יכולים להשתמש בפונקציה image_embedding כדי לקבל הטמעה של התמונה שלנו ולהשוות אותה להטמעות שחושבו מראש. כדי להפעיל את הפונקציה, צריך לוודא שמשתמשים בגרסה הנכונה של התוסף google_ml_integration.
בואו נאמת את הגרסה הנוכחית של התוסף. ב-AlloyDB Studio, מריצים את הפקודה.
SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';
אם הגרסה נמוכה מ-1.4.4, מריצים את התהליך הבא.
CALL google_ml.upgrade_to_preview_version();
ואז בודקים שוב את גרסת התוסף. הגרסה צריכה להיות 1.4.4.
זו תמונה לדוגמה לחיפוש, אבל אפשר להשתמש בכל תמונה בהתאמה אישית. פשוט מעלים אותו לאחסון של Google או למשאב אחר שזמין לכולם, ומזינים את ה-URI בשאילתה.
והוא מועלה אל gs://pr-public-demo-data/alloydb-retail-demo/user_photos/4.png
חיפוש תמונות באמצעות תמונות
קודם כל, אנחנו מנסים לחפש רק לפי התמונה:
SELECT
name,
product_description,
retail_price,
replace(product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url,
product_image_embedding <=> google_ml.image_embedding (model_id => 'multimodalembedding@001',image => 'gs://pr-public-demo-data/alloydb-retail-demo/user_photos/4.png', mimetype => 'image/png')::vector AS distance
FROM
ecomm.products
ORDER BY distance
LIMIT
4;
ומצאנו במלאי כמה מעילים מחממים.
חיפוש התמונות מחזיר פריטים שדומים לתמונה שסיפקנו להשוואה. כמו שכבר ציינתי, אפשר לנסות להעלות תמונות משלכם למאגר ציבורי ולראות אם הוא יכול למצוא סוגים שונים של בגדים.
השתמשנו במודל 'multimodalembedding@001' של Google לחיפוש התמונות שלנו. הפונקציה image_embedding שולחת את התמונה אל Vertex AI, ממירה אותה לווקטור ומחזירה אותה כדי להשוות אותה לווקטורים של תמונות שמאוחסנים במסד הנתונים שלנו.
אנחנו יכולים גם לבדוק באמצעות EXPLAIN ANALYZE כמה מהר הוא פועל עם אינדקס AlloyDB ScaNN שלנו.
Limit (cost=971.70..975.55 rows=4 width=490) (actual time=2.453..2.477 rows=4 loops=1)
-> Index Scan using product_image_embedding_scann on products (cost=971.70..28998.90 rows=29120 width=490) (actual time=2.451..2.475 rows=4 loops=1)
Order By: (product_image_embedding <=> '[0.02119865,0.034206174,0.030682731,
...
,-0.010307034,-0.010053742]'::vector)
Limit: 4
Planning Time: 913.322 ms
Execution Time: 2.517 ms
(6 rows)
ושוב, כמו בדוגמה הקודמת, אפשר לראות שרוב הזמן הושקע בהמרת התמונה להטבעות באמצעות נקודת הקצה בענן, והחיפוש הווקטורי עצמו נמשך רק 2.5 אלפיות השנייה.
חיפוש תמונות לפי טקסט
בנוסף, באמצעות multimodal אפשר להעביר למודל תיאור טקסט של הז'קט שאנחנו מנסים לחפש באמצעות google_ml.text_embedding לאותו מודל, ולהשוות אותו להטמעות של תמונות כדי לראות אילו תמונות המודל מחזיר.
SELECT
name,
product_description,
retail_price,
replace(product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url,
product_image_embedding <=> google_ml.text_embedding (model_id => 'multimodalembedding@001',content => 'puffy jacket for men, grey or dark colour')::vector AS distance
FROM
ecomm.products
ORDER BY distance
LIMIT
4;
קיבלנו גם סט של מעילי פוך בצבעים אפורים או כהים.
קיבלנו קבוצה קצת שונה של מעילים, אבל המערכת בחרה נכון את המעילים על סמך התיאור שלנו וחיפוש בהטמעות של התמונות.
ננסה דרך אחרת לחפש בין התיאורים באמצעות ההטמעה שלנו לתמונת החיפוש.
חיפוש טקסט בתמונות
ניסינו לחפש תמונות על ידי העברת ההטמעה של התמונה שלנו והשוואה להטמעות של תמונות שחושבו מראש עבור המוצרים שלנו. ניסינו גם לחפש תמונות באמצעות הטמעה של בקשת הטקסט שלנו, ולחפש בין אותן הטמעות את תמונות המוצרים. עכשיו ננסה להשתמש בהטמעה בשביל התמונה שלנו ונשווה אותה להטמעות טקסט של תיאורי המוצרים. ההטמעה מאוחסנת בעמודה product_description_embedding ומשתמשת באותו מודל multimodalembedding@001.
זו השאילתה שלנו:
SELECT
name,
product_description,
retail_price,
replace(product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url,
product_description_embedding <=> google_ml.image_embedding (model_id => 'multimodalembedding@001',image => 'gs://pr-public-demo-data/alloydb-retail-demo/user_photos/4.png', mimetype => 'image/png')::vector AS distance
FROM
ecomm.products
ORDER BY distance
LIMIT
4;
והנה קיבלנו קבוצה קצת שונה של מעילים בצבעים אפורים או כהים, שחלק מהם זהים או דומים מאוד לאלה שנבחרו בדרך חיפוש אחרת.
הפונקציה מחזירה את אותם מעילים כמו בדוגמה שלמעלה, אבל בסדר שונה. על סמך ההטמעה של התמונות, המודל יכול להשוות אותן להטמעות מחושבות של תיאור הטקסט ולהחזיר את קבוצת המוצרים הנכונה.
חיפוש משולב של טקסט ותמונות
אפשר גם להתנסות בשילוב של הטמעות טקסט והטמעות תמונות, למשל באמצעות שילוב של דירוג הדדי. זו דוגמה לשאילתה כזו שבה שילבנו שני חיפושים, הקצנו ניקוד לכל דירוג וסידרנו את התוצאות לפי הניקוד המשולב.
WITH image_search AS (
SELECT id,
RANK () OVER (ORDER BY product_image_embedding <=>google_ml.image_embedding(model_id => 'multimodalembedding@001',image => 'gs://pr-public-demo-data/alloydb-retail-demo/user_photos/4.png', mimetype => 'image/png')::vector) AS rank
FROM ecomm.products
ORDER BY product_image_embedding <=>google_ml.image_embedding(model_id => 'multimodalembedding@001',image => 'gs://pr-public-demo-data/alloydb-retail-demo/user_photos/4.png', mimetype => 'image/png')::vector LIMIT 5
),
text_search AS (
SELECT id,
RANK () OVER (ORDER BY product_description_embedding <=>google_ml.text_embedding(model_id => 'multimodalembedding@001',content => 'puffy jacket for men, grey or dark colour'
)::vector) AS rank
FROM ecomm.products
ORDER BY product_description_embedding <=>google_ml.text_embedding(model_id => 'multimodalembedding@001',content => 'puffy jacket for men, grey or dark colour'
)::vector LIMIT 5
),
rrf_score AS (
SELECT
COALESCE(image_search.id, text_search.id) AS id,
COALESCE(1.0 / (60 + image_search.rank), 0.0) + COALESCE(1.0 / (60 + text_search.rank), 0.0) AS rrf_score
FROM image_search FULL OUTER JOIN text_search ON image_search.id = text_search.id
ORDER BY rrf_score DESC
)
SELECT
ep.name,
ep.product_description,
ep.retail_price,
replace(ep.product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url
FROM ecomm.products ep, rrf_score
WHERE
ep.id=rrf_score.id
ORDER by rrf_score DESC
LIMIT 4;
אפשר לנסות לשחק עם פרמטרים שונים בשאילתה ולראות אם זה משפר את תוצאות החיפוש.
בשלב הזה המעבדה תסתיים, וכדי למנוע חיובים לא צפויים מומלץ למחוק משאבים שלא נעשה בהם שימוש.
בנוסף, אפשר להשתמש באופרטורים אחרים של AI כדי לדרג את התוצאות, כמו שמתואר במסמכי התיעוד.
9. ניקוי הסביבה
השמדת המכונות והאשכול של AlloyDB כשמסיימים את שיעור ה-Lab
מחיקת אשכול AlloyDB וכל המכונות
האשכול נהרס עם האפשרות force, שמוחקת גם את כל המופעים ששייכים לאשכול.
ב-Cloud Shell, מגדירים את משתני הפרויקט והסביבה אם התנתקתם וכל ההגדרות הקודמות אבדו:
gcloud config set project <your project id>
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
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.
10. מזל טוב
כל הכבוד, סיימתם את ה-Codelab. למדתם איך להשתמש בחיפוש מולטי-מודאלי ב-AlloyDB באמצעות פונקציות הטמעה של טקסטים ותמונות. אפשר לנסות לבדוק את החיפוש המולטימודאלי ולשפר אותו באמצעות הפונקציה google_ml.rank באמצעות codelab לאופרטורים של AlloyDB AI.
מה למדנו
- איך פורסים את AlloyDB ל-Postgres
- איך משתמשים בחיפוש וקטורי מרובה מצבים
- איך מפעילים אופרטורים של AlloyDB AI
- איך משתמשים באופרטורים שונים של AlloyDB AI לחיפוש מרובה מצבים
- איך משתמשים ב-AlloyDB AI כדי לשלב תוצאות חיפוש של טקסט ותמונות
11. סקר
פלט: