איך יוצרים אפליקציית המלצות לפי הקשר של תנוחות יוגה באמצעות Firestore, ‏ Vector Search ו-Gemini 2.0

1. סקירה כללית

בעולם של אפליקציות בריאות וכושר, חשוב מאוד לספק למשתמשים חוויה עשירה ומרתקת. באפליקציית יוגה, המשמעות היא שצריך להציע מידע מקיף, תוכן מולטימדיה ויכולות חיפוש חכמות, ולא רק תיאורים פשוטים של תנוחות. בפוסט הזה נסביר איך ליצור מסד נתונים חזק של תנוחות יוגה באמצעות Firestore של Google Cloud, להשתמש בתוסף Vector Search כדי לבצע התאמה לפי הקשר ולשלב את העוצמה של Gemini 2.0 Flash (Experimental) לעבודה עם תוכן רב-מודלי.

למה כדאי להשתמש ב-Firestore?

Firestore הוא מסד נתונים ללא שרת (serverless) לאחסון מסמכים מסוג NoSQL ב-Google Cloud, והוא בחירה מצוינת לפיתוח אפליקציות דינמיות וניתנות להתאמה לעומס. הסיבה לכך היא שהיא מתאימה במיוחד לאפליקציית היוגה שלנו:

  • יכולת התאמה לעומס וביצועים: Firestore מתאים את עצמו באופן אוטומטי כדי לטפל במיליונים של משתמשים ובמערכי נתונים עצומים, וכך מבטיח שהאפליקציה תמשיך להגיב במהירות גם כשהיא תגדל.
  • עדכונים בזמן אמת: סנכרון מובנה בזמן אמת שומר על עקביות הנתונים בכל הלקוחות המחוברים, והוא מושלם לתכונות כמו שיעורים בשידור חי או תרגול משותף.
  • מודל נתונים גמיש: המבנה מבוסס-המסמכים של Firestore מאפשר לאחסן סוגים שונים של נתונים, כולל טקסט, תמונות ואפילו הטמעות (embeds), ולכן הוא אידיאלי לייצוג מידע מורכב על תנוחות יוגה.
  • שאילתות מתקדמות: Firestore תומך בשאילתות מורכבות, כולל שאילתות של שוויון, אי-שוויון, ועכשיו, עם התוסף החדש, גם חיפושים של דמיון בין וקטורים.
  • תמיכה במצב אופליין: נתונים נשמרים במטמון של Firestore באופן מקומי, כך שהאפליקציה יכולה לפעול גם כשהמשתמשים במצב אופליין.

שיפור החיפוש באמצעות תוסף החיפוש לפי וקטור של Firestore

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

בעזרת Vector Search ב-Firestore אפשר:

  • יצירת הטמעות (embeddings): טרנספורמציה של תיאורי טקסט, ובעתיד אולי גם של תמונות ואודיו, לייצוגים של וקטורים מספריים (embeddings) שמתעדים את המשמעות הסמנטית שלהם באמצעות מודלים כמו אלה שזמינים ב-Vertex AI או מודלים מותאמים אישית.
  • שמירת הטמעות: שמירת הטמעות אלה ישירות במסמכים של Firestore.
  • ביצוע חיפושים לפי דמיון: שאילתות במסד הנתונים כדי למצוא מסמכים שדומים מבחינה סמנטית לווקטור שאילתה נתון, וכך לאפשר התאמה לפי הקשר.

שילוב של Gemini 2.0 Flash (ניסיוני)

Gemini 2.0 Flash הוא מודל ה-AI המתקדם ביותר של Google שמשתמש במגוון מודלים. התכונה הזו עדיין נמצאת בשלבי ניסוי, אבל היא מציעה אפשרויות מעניינות להעשרת אפליקציית היוגה שלנו:

  • יצירת טקסט: אפשר להשתמש ב-Gemini 2.0 Flash כדי ליצור תיאורים מפורטים של תנוחות יוגה, כולל יתרונות, שינויים והתוויות נגד.
  • יצירת תמונות (חיקוי): יצירת תמונות ישירות באמצעות Gemini עדיין לא זמינה לציבור, אבל הדגמתי את התהליך הזה באמצעות Imagen של Google, ויצרתי תמונות שמייצגות באופן חזותי את תנוחות הישיבה.
  • יצירת אודיו (חיקוי): באופן דומה, אפשר להשתמש בשירות המרה של טקסט לדיבור (TTS) כדי ליצור הוראות אודיו לכל תנוחה, ולהנחות את המשתמשים בתרגול.

יכול להיות שאציע את השילוב כדי לשפר את האפליקציה כך שתשתמש בתכונות הבאות של המודל:

  • Multimodal Live API: ממשק ה-API החדש הזה עוזר לכם ליצור אפליקציות של סטרימינג של אודיו ותמונות בזמן אמת באמצעות שימוש בכלים.
  • מהירות וביצועים: ב-Gemini 2.0 Flash זמן הקבלה של האסימון הראשון (TTFT) קצר בהרבה בהשוואה ל-Gemini 1.5 Flash.
  • שיפורים בחוויית השימוש ב-Agent: ב-Gemini 2.0 יש שיפורים בהבנה של מידע ממקורות שונים, בתכנות, במילוי הוראות מורכבות ובקריאה לפונקציות. השיפורים האלה פועלים יחד כדי לשפר את חוויית השימוש של הסוכנות.

למידע נוסף, אפשר לעיין בדף הזה%20over%20Gemini%201.5%20Flash).

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

  • חיפוש לפי הקשר: כשמשתמש עם הרשאת אדמין מזין את הפרטים של תנוחה, אנחנו יכולים להשתמש בשם התנועה כדי לבצע חיפוש ב-Google.
  • חילוץ כתובות URL: אנחנו יכולים לחלץ מתוצאות החיפוש כתובות URL רלוונטיות, כמו מאמרים, סרטונים או אתרי יוגה מהימנים, ולהציג אותן באפליקציה.

מה תפַתחו

במסגרת שיעור ה-Lab הזה תלמדו:

  1. יצירת אוסף ב-Firestore וטעינה של מסמכי יוגה
  2. איך יוצרים אפליקציות CRUD באמצעות Firestore
  3. יצירת תיאור של תנוחת יוגה באמצעות Gemini 2.0 Flash
  4. הפעלת Firebase Vector Search בשילוב עם Firestore
  5. יצירת הטמעות (embeddings) מהתיאור של יוגה
  6. ביצוע חיפוש הדמיון לטקסט החיפוש של המשתמש

דרישות

  • דפדפן, כמו Chrome או Firefox
  • פרויקט ב-Google Cloud שבו החיוב מופעל.

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

יצירת פרויקט

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

תמונה של לחצן הפעלת Cloud Shell

  1. אחרי שמתחברים ל-Cloud Shell, בודקים שכבר בוצע אימות ושהמזהה של הפרויקט מוגדר כפרויקט באמצעות הפקודה הבאה:
gcloud auth list
  1. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שהפקודה gcloud מכירה את הפרויקט.
gcloud config list project
  1. אם הפרויקט לא מוגדר, משתמשים בפקודה הבאה כדי להגדיר אותו:
gcloud config set project <YOUR_PROJECT_ID>
  1. מפעילים את ממשקי ה-API הנדרשים.
gcloud services enable firestore.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       run.googleapis.com \
                       cloudbuild.googleapis.com \
                       cloudfunctions.googleapis.com \
                       aiplatform.googleapis.com \
                       storage.googleapis.com \ 
                       secretmanager.googleapis.com \ 
                       texttospeech.googleapis.com

האפשרות החלופית לפקודה gcloud היא דרך מסוף, על ידי חיפוש של כל מוצר או באמצעות הקישור הזה.

אם חסר ממשק API כלשהו, תמיד תוכלו להפעיל אותו במהלך ההטמעה.

במסמכי העזרה מפורטות הפקודות של gcloud והשימוש בהן.

3. הגדרת מסד נתונים

במסמכי התיעוד מפורטים שלבים מלאים יותר להגדרת מכונה של Firestore. באופן כללי, כדי להתחיל, אעשה את הפעולות הבאות:

1 עוברים אל Firestore Viewer ובמסך Select a database service בוחרים ב-Firestore במצב Native.

  1. בחירת מיקום ל-Firestore
  2. לוחצים על 'יצירת מסד נתונים' (אם זו הפעם הראשונה, משאירים את מסד הנתונים כ'(default)')

כשיוצרים פרויקט Firestore, המערכת מפעילה גם את ה-API במנהל Cloud API.

  1. חשוב: בוחרים את הגרסה לבדיקה (לא גרסת הייצור) של כללי האבטחה כדי שאפשר יהיה לגשת לנתונים.
  2. אחרי ההגדרה, תראו את תצוגת מסד הנתונים, האוסף והמסמך של Firestore במצב מקורי, כפי שמוצג בתמונה הבאה:

f7136d53253c59a.png

  1. לא צריך לבצע את השלב הזה עדיין, אבל לידיעתך, אפשר ללחוץ על 'התחלת אוסף' וליצור אוסף חדש. מגדירים את מזהה האוסף בתור 'poses'. לוחצים על הלחצן שמירה.

a26eb470aa9bfda9.png

טיפים למומחים לשימוש באפליקציה בסביבת הייצור:

  1. אחרי שתסיימו את בניית מודל הנתונים ותזהו למי צריכה להיות גישה למסמכים מסוגים שונים, תוכלו ליצור, לערוך ולפקח על כללי אבטחה בממשק של Firebase. אפשר לגשת לכללי האבטחה דרך הקישור הזה: https://console.firebase.google.com/u/0/project/<<your_project_id>>/firestore/rules
  2. חשוב לערוך, לעקוב ולבדוק את כללי האבטחה לפני הפריסה או ההשקה של הפרויקט משלב הפיתוח, כי לרוב הם הגורם השקט לכך שהאפליקציה פועלת בצורה שונה :)

בדגמה הזו נשתמש בו במצב TEST.

4. Firestore REST API

  1. ה-API ל-REST יכול להיות שימושי בתרחישי השימוש הבאים:א. גישה ל-Firestore מסביבה עם מחסור במשאבים שבה אי אפשר להריץ ספריית לקוח מלאה. אוטומציה של ניהול מסדי נתונים או אחזור של מטא-נתונים מפורטים של מסדי נתונים
  2. הדרך הקלה ביותר להשתמש ב-Firestore היא להשתמש באחת מספריות הלקוח המקומיות. עם זאת, יש מצבים שבהם כדאי לבצע קריאה ישירה ל-API ל-REST.
  3. במסגרת הפוסט הזה, נסביר איך משתמשים ב-API ל-REST של Firestore ומציגים הדגמה שלו, ולא ספריות לקוח מקומיות.
  4. לצורך אימות, ה-API ל-REST של Firestore מקבל אסימון מזהה של אימות ב-Firebase או אסימון OAuth 2.0 של Google Identity. מידע נוסף בנושא אימות והרשאה זמין במסמכי העזרה.
  5. כל נקודות הקצה של ה-API ל-REST נמצאות בכתובת ה-URL הבסיסית https://firestore.googleapis.com/v1/.

Spring Boot ו-Firestore API

הפתרון הזה ב-Spring Boot Framework מיועד להדגמה של אפליקציית לקוח שמשתמשת בממשקי ה-API של Firestore כדי לאסוף ולשנות פרטים של תנוחות יוגה ונשימות, עם חוויית משתמש אינטראקטיבית.

בקישור הבלוג מוסבר בפירוט שלב אחרי שלב על הפתרון של CRUD ב-Firestore, שמופיע באפליקציית תנוחות היוגה.

כדי להתמקד בפתרון הנוכחי וללמוד את החלק של CRUD בזמן אמת, אפשר לשכפל את הפתרון כולו שמתמקד בבלוג הזה מהמאגר שבהמשך בטרמינל של Cloud Shell ולקבל עותק של קוד הבסיס.

git clone https://github.com/AbiramiSukumaran/firestore-poserecommender

לתשומת ליבך:

  1. אחרי שתיצרו עותק מקודד של המאגר הזה, תצטרכו לבצע רק כמה שינויים במזהה הפרויקט, בממשקי ה-API וכו'. לא נדרשים שינויים נוספים כדי להפעיל את האפליקציה. כל אחד מהרכיבים של האפליקציה מוסבר בקטעים הבאים. ריכזנו כאן את השינויים:
  2. בקובץ src/main/java/com/example/demo/GenerateImageSample.java, מחליפים את "<<YOUR_PROJECT_ID>>" במזהה הפרויקט.
  3. בקובץ src/main/java/com/example/demo/GenerateEmbeddings.java, מחליפים את "<<YOUR_PROJECT_ID>>" במזהה הפרויקט
  4. בקובץ src/main/java/com/example/demo/PoseController.java, מחליפים את כל המופעים של '<<YOUR_PROJECT_ID>>" ואת שם מסד הנתונים,, במקרה הזה "(default)",, בערכים המתאימים מההגדרה:
  5. ב-src/main/java/com/example/demo/PoseController.java, מחליפים את '[YOUR_API_KEY]' במפתח ה-API שלכם ל-Gemini 2.0 Flash. אפשר לקבל את הקוד הזה מ-AI Studio.
  6. כדי לבדוק באופן מקומי, מריצים את הפקודות הבאות מתוך תיקיית הפרויקט ב-Cloud Shell Terminal:
mvn package

mvn spring-boot:run

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

  1. אופציונלי: אם רוצים לפרוס את האפליקציה ב-Cloud Run, צריך ליצור מאפס אפליקציית Java Cloud Run חדשה ב-Cloud Shell Editor ולהוסיף את קובצי ה-src ואת קובצי התבניות מ-repo לפרויקט החדש בתיקיות המתאימות (כי הפרויקט הנוכחי במאגר GitHub לא מוגדר כברירת מחדל להגדרות הפריסה של Cloud Run). במקרה כזה, צריך לבצע את השלבים הבאים (במקום לשכפל את המאגר הקיים):
  2. עוברים אל Cloud Shell Editor (מוודאים שעורך הקוד פתוח ולא הטרמינל), לוחצים על סמל שם הפרויקט ב-Google Cloud בצד ימין של סרגל הסטטוס (החלק החסום בצילום המסך שבהמשך)

d3f0de417094237d.png

  1. בוחרים באפשרות New application (אפליקציה חדשה) -> Cloud Run Application (אפליקציית Cloud Run) -> Java: Cloud Run (Java:‏ Cloud Run) מרשימת האפשרויות, ומעניקים לה את השם firestore-poserecommender.

d5ef8b4ca8bf3f85.png

  1. עכשיו אמורה להופיע תבנית של סטאק מלא לאפליקציית Java Cloud Run, שמוגדרת מראש ומוכנה לשימוש.
  2. מסירים את הכיתה הקיימת Controller ומעתיקים את הקבצים הבאים לתיקיות המתאימות שלהם במבנה הפרויקט:

firestore-poserecommender/src/main/java/com/example/demo/

  1. FirestoreSampleApplication.java
  2. GenerateEmbeddings.java
  3. GenerateImageSample.java
  4. Pose.java
  5. PoseController.java
  6. ServletInitializer.java
             firestore-poserecommender/src/main/resources/static/
    
  7. Index.html

firestore-poserecommender/src/main/resources/templates/

  1. contextsearch.html
  2. createpose.html
  3. errmessage.html
  4. pose.html
  5. ryoq.html
  6. searchpose.html
  7. showmessage.html

firestore-poserecommender/‎

  1. קובץ Docker
  2. צריך לבצע את השינויים בקובצים המתאימים כדי להחליף את PROJECT ID ואת API KEY בערכים המתאימים. (שלבים 1 א', ב', ג' ו-ד' שלמעלה).

5. הטמעת נתונים

הנתונים של האפליקציה זמינים בקובץ data.json: https://github.com/AbiramiSukumaran/firestore-poserecommender/blob/main/data.json

אם רוצים להתחיל עם נתונים מוגדרים מראש, אפשר להעתיק את ה-JSON ולהחליף את כל המופעים של "<<YOUR_PROJECT_ID>>" בערך הרצוי.

  • עוברים אל Firestore Studio.
  • מוודאים שיצרתם אוסף בשם 'תנוחות'.
  • הוספה ידנית של מסמכים מקובץ המאגר שצוין למעלה, אחד אחרי השני

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

  1. נכנסים ל-Cloud Shell Terminal ומוודאים שהפרויקט הפעיל ב-Google Cloud מוגדר ושיש לכם הרשאה. יוצרים קטגוריה בפרויקט באמצעות הפקודה gsutil שמופיעה בהמשך. מחליפים את המשתנה <PROJECT_ID> בפקודה הבאה במזהה הפרויקט ב-Google Cloud:

gsutil mb -l us gs://<PROJECT_ID>-yoga-poses-bucket

  1. עכשיו, אחרי שיצרנו את הקטגוריה, אנחנו צריכים להעתיק אליה את הייצוא של מסד הנתונים שהכינו, כדי שנוכל לייבא אותו למסד הנתונים של Firebase. משתמשים בפקודה הבאה:

gsutil cp -r gs://demo-bq-gemini-public/yoga_poses gs://<PROJECT_ID>-yoga-poses-bucket

עכשיו שיש לנו את הנתונים לייבוא, אנחנו יכולים לעבור לשלב האחרון של ייבוא הנתונים למסד הנתונים של Firebase (ברירת המחדל) שיצרנו.

  1. עכשיו עוברים למסוף Firestore ולוחצים על ייבוא/ייצוא בתפריט הניווט שמימין.

בוחרים באפשרות 'ייבוא', בוחרים את הנתיב ב-Cloud Storage שיצרתם זה עתה ומנווטים עד שמוצאים את הקובץ yoga_poses.overall_export_metadata:

f5c1d16df7d5a64a.png

  1. לחץ על 'ייבא'.

הייבוא יימשך כמה שניות. בסיום, תוכלו לאמת את מסד הנתונים ואת האוסף ב-Firestore בכתובת https://console.cloud.google.com/firestore/databases. בוחרים את מסד הנתונים default ואת האוסף poses כפי שמתואר בהמשך:

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

6. חיפוש וקטור

הפעלת התוסף Firestore Vector Search

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

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

בואו נעבור על השלבים:

מתקינים את התוסף:

לוחצים על 'התקנה במסוף Firebase' כדי להתקין את התוסף 'חיפוש וקטורים באמצעות Firestore' מ-Firebase Extensions Marketplace.

חשוב:

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

715426b97c732649.png

אם הפרויקט לא מופיע ברשימה, מוסיפים אותו ל-Firebase (בוחרים את הפרויקט הקיים ב-Google Cloud מהרשימה).

הגדרת התוסף:

מציינים את האוסף ("poses"), את השדה שמכיל את הטקסט להטמעה ("posture") ופרממטרים אחרים כמו המאפיינים של ההטמעה.

אם יש ממשקי API שצריך להפעיל, הם יופיעו בשלב הזה. תוכלו להפעיל אותם בדף ההגדרות.

אם הדף לא מגיב לאחר הפעלת ממשקי ה-API במשך זמן מה, פשוט מרעננים אותו ואמורים לראות את ממשקי ה-API מופעלים.

5ba59b45710c567b.png

באחד מהשלבים הבאים, הוא מאפשר לכם להשתמש ב-LLM שבחרתם ליצירת הטמעות (embeddings). בוחרים באפשרות Vertex AI.

bb528a04ebb5f976.png

ההגדרות הבאות קשורות לאוסף ולשדה שרוצים להטמיע:

LLM: ‏ Vertex AI

נתיב האוסף: poses

מגבלת השאילתות שמוגדר כברירת מחדל: 3

מדד המרחק: קוסינוס

שם שדה הקלט: posture

שם שדה הפלט: embedding

שם שדה הסטטוס: status

הטמעת מסמכים קיימים: כן

עדכון של הטמעות קיימות: כן

מיקום Cloud Functions: us-central1

Enable Events (הפעלת אירועים): לא מסומן

fb8cdf1163fac7cb.png

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

יצירת הטמעות:

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

יצירת אינדקס

הוא ידרוש ליצור אינדקס בשדה ההטמעה בזמן השימוש בהטמעה באפליקציה.

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

  1. מעבר לטרמינל Cloud Shell
  2. מריצים את הפקודה הבאה:
gcloud firestore indexes composite create --collection-group="poses" --query-scope=COLLECTION --database="(default)" --field-config vector-config='{"dimension":"768", "flat": "{}"}',field-path="embedding"

מידע נוסף זמין כאן.

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

הערה חשובה:

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

נבחן איך האפליקציה החדשה שלכם מתקרבת לחיפוש וקטורים. אחרי שמטמיעים את הנתונים, אפשר להשתמש בכיתה VectorQuery של Firestore Java SDK כדי לבצע חיפוש וקטורים ולקבל תוצאות של השכן הקרוב ביותר:

CollectionReference coll = firestore.collection("poses");
    VectorQuery vectorQuery = coll.findNearest(
        "embedding",
        userSearchTextEmbedding, 
        /* limit */ 3,
        VectorQuery.DistanceMeasure.EUCLIDEAN,
        VectorQueryOptions.newBuilder().setDistanceResultField("vector_distance")
         .setDistanceThreshold(2.0)
          .build());
ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();
List<Pose> posesList = new ArrayList<Pose>();
// Get the ID of the closest document (assuming results are sorted by distance)
String closestDocumentId = vectorQuerySnapshot.getDocuments().get(0).getId();

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

7. Gemini 2.0 Flash

שילוב של Gemini 2.0 Flash (לצורך יצירת תיאורים)

נראה איך האפליקציה החדשה שלכם מטפלת בשילוב של Gemini 2.0 Flash ליצירת תיאורים.

נניח שמשתמש עם הרשאת אדמין או מורה ליוגה רוצה להזין את פרטי תנוחות היוגה בעזרת Gemini 2.0 Flash, ואז לבצע חיפוש כדי לראות את התוצאות הכי דומות. התוצאה היא חילוץ הפרטים של תנוחות תואמות יחד עם אובייקטים מרובת-מודלים שתומכים בתוצאות.

String apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key=[YOUR_API_KEY]";
Map<String, Object> requestBody = new HashMap<>();
List<Map<String, Object>> contents = new ArrayList<>();
List<Map<String, Object>> tools = new ArrayList<>();
Map<String, Object> content = new HashMap<>();
List<Map<String, Object>> parts = new ArrayList<>();
Map<String, Object> part = new HashMap<>();
part.put("text", prompt);
parts.add(part);
content.put("parts", parts);
contents.add(content);
requestBody.put("contents", contents);
/**Setting up Grounding*/
Map<String, Object> googleSearchTool = new HashMap<>();
googleSearchTool.put("googleSearch", new HashMap<>());
tools.add(googleSearchTool);
requestBody.put("tools", tools);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(apiUrl, HttpMethod.POST, requestEntity, String.class);
System.out.println("Generated response: " + response);
String responseBody = response.getBody();
JSONObject jsonObject = new JSONObject(responseBody);
JSONArray candidates = jsonObject.getJSONArray("candidates");
JSONObject candidate = candidates.getJSONObject(0);
JSONObject contentResponse = candidate.getJSONObject("content");
JSONArray partsResponse = contentResponse.getJSONArray("parts");
JSONObject partResponse = partsResponse.getJSONObject(0);
String generatedText = partResponse.getString("text");
System.out.println("Generated Text: " + generatedText);

א. חיקוי של יצירת תמונות ואודיו

המודל Gemini 2.0 Flash Experimental מסוגל ליצור תוצאות מרובות-מודולים, אבל עדיין לא נרשמתי לתוכנית הגישה המוקדמת שלו, ולכן חיקיתי את הפלט של התמונה והאודיו באמצעות ממשקי ה-API של Imagen ו-TTS, בהתאמה. איזה כיף שאפשר ליצור את כל זה באמצעות קריאה אחת ל-API של Gemini 2.0 Flash!

try (PredictionServiceClient predictionServiceClient =
          PredictionServiceClient.create(predictionServiceSettings)) {
  
        final EndpointName endpointName =
            EndpointName.ofProjectLocationPublisherModelName(
                projectId, location, "google", "imagen-3.0-generate-001");
  
        Map<String, Object> instancesMap = new HashMap<>();
        instancesMap.put("prompt", prompt);
        Value instances = mapToValue(instancesMap);
  
        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("sampleCount", 1);
        paramsMap.put("aspectRatio", "1:1");
        paramsMap.put("safetyFilterLevel", "block_few");
        paramsMap.put("personGeneration", "allow_adult");
        Value parameters = mapToValue(paramsMap);
  
        PredictResponse predictResponse =
            predictionServiceClient.predict(
                endpointName, Collections.singletonList(instances), parameters);
  
        for (Value prediction : predictResponse.getPredictionsList()) {
          Map<String, Value> fieldsMap = prediction.getStructValue().getFieldsMap();
          if (fieldsMap.containsKey("bytesBase64Encoded")) {
            bytesBase64Encoded = fieldsMap.get("bytesBase64Encoded").getStringValue();
       }
      }
      return bytesBase64Encoded;
    }
 try {
            // Create a Text-to-Speech client
            try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create()) {
                // Set the text input to be synthesized
                SynthesisInput input = SynthesisInput.newBuilder().setText(postureString).build();

                // Build the voice request, select the language code ("en-US") and the ssml
                // voice gender
                // ("neutral")
                VoiceSelectionParams voice =
                        VoiceSelectionParams.newBuilder()
                                .setLanguageCode("en-US")
                                .setSsmlGender(SsmlVoiceGender.NEUTRAL)
                                .build();

                // Select the type of audio file you want returned
                AudioConfig audioConfig =
                        AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build();

                // Perform the text-to-speech request on the text input with the selected voice
                // parameters and audio file type
                SynthesizeSpeechResponse response =
                        textToSpeechClient.synthesizeSpeech(input, voice, audioConfig);

                // Get the audio contents from the response
                ByteString audioContents = response.getAudioContent();

                // Convert to Base64 string
                String base64Audio = Base64.getEncoder().encodeToString(audioContents.toByteArray());

                // Add the Base64 encoded audio to the Pose object
               return base64Audio;
            }

        } catch (Exception e) {
            e.printStackTrace(); // Handle exceptions appropriately. For a real app, log and provide user feedback.
            return "Error in Audio Generation";
        }
}

ב. חיפוש Google:

אם בודקים את קוד ההפעלה של Gemini בשלב 6, רואים את קטע הקוד הבא שמאפשר את הטעינה של חיפוש Google בתגובה ל-LLM:

 /**Setting up Grounding*/
Map<String, Object> googleSearchTool = new HashMap<>();
googleSearchTool.put("googleSearch", new HashMap<>());
tools.add(googleSearchTool);
requestBody.put("tools", tools);

כך אנחנו יכולים לוודא שאנחנו:

  • התבססות המודל על תוצאות חיפוש בפועל
  • חילוץ כתובות URL רלוונטיות שצוינו בחיפוש

8. הרצת האפליקציה

נבחן את כל היכולות של אפליקציית Java Spring Boot החדשה שיצרתם עם ממשק אינטרנט פשוט של Thymeleaf:

  1. פעולות CRUD ב-Firestore (יצירה, קריאה, עדכון, מחיקה)
  2. חיפוש באמצעות מילת מפתח
  3. יצירת הקשר על סמך AI גנרטיבי
  4. חיפוש לפי הקשר (חיפוש וקטור)
  5. פלט מרובה מצבים שקשור לחיפוש
  6. הרצת שאילתה משלכם (שאילתות בפורמט structuredQuery)

דוגמה: {"structuredQuery":{"select":{"fields":[{"fieldPath":"name"}]},"from":[{"collectionId":"fitness_poses"}]}}

כל התכונות שצוינו עד כה הן חלק מהאפליקציה שיצרתם עכשיו מהמאגר: https://github.com/AbiramiSukumaran/firestore-poserecommender

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

mvn package

mvn spring-boot:run

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

המלצות לתנוחות עם Firestore, ‏ Vector Search ו-Gemini 2.0 Flash

שלב אופציונלי:

כדי לפרוס אותה ב-Cloud Run (בהנחה שיצרתם אפליקציה חדשה לגמרי באמצעות Dockerfile והעתקתם את הקבצים לפי הצורך), מריצים את הפקודה הבאה מטרמינל Cloud Shell בתוך ספריית הפרויקט:

gcloud run deploy --source .

נותנים את שם האפליקציה, קוד האזור (בוחרים את הקוד של us-central1) ובוחרים באפשרות 'Y' להפעלה ללא אימות כפי שמופיע בהודעה. לאחר השלמת הפריסה, נקודת הקצה של האפליקציה אמורה להופיע במסוף.

9. הסרת המשאבים

כדי להימנע מצבירת חיובים בחשבון Google Cloud על המשאבים שבהם השתמשתם בפוסט הזה, פועלים לפי השלבים הבאים:

  1. נכנסים לדף Manage resources במסוף Google Cloud.
  2. ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete.
  3. כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.

10. מזל טוב

מעולה! השתמשתם ב-Firestore כדי ליצור אפליקציה חזקה וחכמה לניהול תנוחות יוגה. על ידי שילוב של העוצמה של Firestore, התוסף לחיפוש וקטורים והיכולות של Gemini 2.0 Flash (עם יצירת תמונות ואודיו מדומים), יצרנו אפליקציית יוגה מעניינת ומועילה במיוחד, שמאפשרת להטמיע את פעולות ה-CRUD, לבצע חיפוש מבוסס מילות מפתח, חיפוש וקטורי לפי הקשר וליצור תוכן מולטימדיה.

הגישה הזו לא מוגבלת לאפליקציות יוגה. ככל שמודלים של AI כמו Gemini ימשיכו להתפתח, כך האפשרויות ליצור חוויות משתמש immersive ומותאמות אישית יותר רק יגדלו. חשוב להתעדכן בהתפתחויות האחרונות ובמסמכי העזרה של Google Cloud ו-Firebase כדי לנצל את מלוא הפוטנציאל של הטכנולוגיות האלה.

אם הייתי מרחיב את האפליקציה הזו, הייתי מנסה לעשות שני דברים באמצעות Gemini 2.0 Flash:

  1. כדי להשתמש ב-API של Multimodal Live, יוצרים שידור וידאו ואודיו בזמן אמת לתרחיש לדוגמה.
  2. אתם יכולים להפעיל את מצב החשיבה כדי ליצור את המחשבות שמאחורי התשובות לאינטראקציה עם נתונים בזמן אמת, וכך לשפר את חוויית השימוש.

אפשר לנסות ולשלוח בקשת משיכה :>D!!!