בונה מדף ספרים: איך משתמשים ב-Gemini כדי ליצור פונקציה של Java Cloud Functions עבור אפליקציית Gemini

1. מבוא

אתם אוהבים לקרוא ספרים אבל מתקשים לבחור מתוך המגוון הרחב? תארו לעצמכם אפליקציה מבוססת-AI שממליצה על הספר המושלם בשבילכם, ומציעה גם סיכום תמציתי לפי הז'אנר שבחרתם, כדי שתוכלו להתרשם מהספר. ב-codelab הזה, אראה לכם איך לבנות אפליקציה כזו באמצעות BigQuery ו-Cloud Functions שמבוססים על Gemini.

סקירה כללית של הפרויקט

מקרה השימוש שלנו מתמקד ב-4 הרכיבים העיקריים האלה:

  • מסד נתונים של ספרים: מערך הנתונים הציבורי העצום של ספרים בארכיון האינטרנט ב-BigQuery ישמש כקטלוג מקיף של ספרים.
  • מנוע סיכום מבוסס-AI: Cloud Functions של Google, שמצוידות במודל השפה Gemini-Pro, ייצרו סיכומים מועילים בהתאם לבקשות המשתמשים.
  • שילוב BigQuery: פונקציה מרוחקת ב-BigQuery שקוראת לפונקציה של Cloud Functions שלנו כדי לספק סיכומים ונושאים של ספרים על פי דרישה.
  • ממשק משתמש: אפליקציית אינטרנט שמתארחת ב-Cloud Run ותציע למשתמשים אפליקציית אינטרנט לצפייה בתוצאות.

נחלק את ההטמעה ל-3 סדנאות קוד:

Codelab 1: Use Gemini to build a Java Cloud Function for a Gemini application.

‫Codelab 2: שימוש ב-Gemini ליצירת אפליקציות AI גנרטיביות שמבוססות על SQL בלבד באמצעות BigQuery.

Codelab 3: שימוש ב-Gemini ליצירת אפליקציית אינטרנט של Java Spring Boot שמתקשרת עם BigQuery.

2. שימוש ב-Gemini ליצירת אפליקציה של AI גנרטיבי ללא שרת ב-Java Cloud Function

מה תפַתחו

תצרו

  • אפליקציית Java Cloud Functions שמטמיעה את Gemini 1.0 Pro כדי לקבל הנחיה ספציפית כקלט בפורמט של מערך JSON ולהחזיר תגובה (ערך JSON עם התווית replies).
  • תבצעו את שלבי הבנייה והפריסה בעזרת Gemini

3. דרישות

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

אלה הדרישות המוקדמות:

יצירת הפרויקט

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

הפעלת Cloud Shell

  1. תשתמשו ב-Cloud Shell, סביבת שורת פקודה שפועלת ב-Google Cloud וכוללת את bq שנטען מראש:

בפינה הימנית העליונה של Cloud Console, לוחצים על 'הפעלת Cloud Shell': 6757b2fb50ddcc2d.png

  1. אחרי שמתחברים ל-Cloud Shell, אמור להופיע אימות שכבר בוצע ושהפרויקט כבר הוגדר לפי מזהה הפרויקט. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שעברתם אימות:
gcloud auth list
  1. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שפקודת gcloud מכירה את הפרויקט.
gcloud config list project
  1. אם הפרויקט לא מוגדר, משתמשים בפקודה הבאה כדי להגדיר אותו:
gcloud config set project <YOUR_PROJECT_ID>

אפשר לעיין במאמרי העזרה בנושא פקודות gcloud ושימוש בהן.

4. הפעלת Gemini for Google Cloud וממשקי ה-API הנדרשים

הפעלת Gemini

  1. כדי להפעיל את ה-API, עוברים אל Gemini for Google Cloud ב-Marketplace. אפשר גם להשתמש בפקודה הבאה:
gcloud services enable cloudaicompanion.googleapis.com --project PROJECT_ID
  1. נכנסים לדף Gemini ולוחצים על 'התחלת שיחה'.

חשוב: כדי להתחיל להשתמש ב-Gemini ולהפעיל את Gemini ב-Cloud Shell IDE, צריך לפעול לפי שלבים 1 ו-2 ב-codelab הזה.

הפעלה של ממשקי API נדרשים אחרים

איך עושים את זה? יש לך שאלה ל-Gemini? אבל לפני כן, חשוב לזכור:

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

כדי לעבור למסוף של Gemini, לוחצים על הסמל 'פתיחת Gemini' בפינה השמאלית העליונה, ליד סרגל החיפוש במסוף Google Cloud.

26e1491322855614.png

מקלידים את השאלה הבאה בקטע "כאן כותבים הנחיה":

How do I enable the cloud functions api using a gcloud command? 

אמורה להתקבל תגובה שדומה לזו:

gcloud services enable cloudfunctions.googleapis.com

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

gcloud services enable \
  cloudfunctions.googleapis.com \
  aiplatform.googleapis.com \
  run.googleapis.com \
  cloudbuild.googleapis.com

5. הכנת תבנית של Cloud Functions באמצעות Gemini

בשלב הזה, אני מניח ש-Gemini כבר מופעל ב-Cloud Shell IDE.

לוחצים על סמל Open Editor (פתיחת העורך) בפינה הימנית העליונה של Cloud Shell Terminal (אני בדרך כלל מעדיף לפתוח את הטרמינל ואת העורך בכרטיסיות נפרדות במקביל, כדי שאוכל לכתוב קוד בכרטיסייה אחת ולבצע בנייה בכרטיסייה אחרת).

edd258384bc74f1f.png

אחרי שפותחים את Editor, מוודאים שהלוגו של Gemini בפינה השמאלית התחתונה של מסוף Editor פעיל (ולא מבוטל). בנוסף, מוודאים שהפרויקט ב-Google Cloud בפינה הימנית התחתונה מצביע על הפרויקט הפעיל הנוכחי שרוצים לעבוד איתו. אם הם לא פעילים, לוחצים עליהם, מאשרים, בוחרים את פרויקט Google Cloud שאליו רוצים שהם יצביעו ומפעילים אותם.

אחרי ששתי האפשרויות פעילות, לוחצים על שם הפרויקט בפינה הימנית התחתונה, ובחלון הקופץ שנפתח עם הכותרת Cloud Code, גוללים למטה אל New Application (אפליקציה חדשה).

ca08602b576ebd57.png

ברשימה הזו, בוחרים באפשרות 'אפליקציית Cloud Functions'. מהרשימה שקופצת, בוחרים באפשרות Java:

ac2b44245949da68.png

ברשימה שמופיעה, מקלידים את שם הפרויקט duetai-gemini-calling במקום helloworld ולוחצים על OK.

bf9cfe86e35cdced.png

מעולה! השתמשת ב-Gemini כדי ליצור אפליקציה פשוטה של Java Cloud Functions, ולא עשית הרבה מעבר להפעלת ההגדרות, נכון?

זה מבנה הפרויקט שאתם אמורים לראות:

d56e410fb76f183f.png

עכשיו אפשר לפרוס את הפונקציה. אבל זו לא הסיבה שבגללה התחלנו את התהליך הזה. בואו נבנה את ההטמעה של Gemini Pro API בפונקציה של Cloud Functions הזו באמצעות Java SDK.

עכשיו ניצור את הפונקציונליות לתרחיש השימוש שלנו, שהוא הפעלת מודל Gemini Pro בפונקציית Cloud Functions הזו. כדי לעשות את זה, אתם יכולים להוסיף עוד הנחיות ולפתח את הקוד בהדרגה באמצעות Gemini, או לכתוב את הלוגיקה בעצמכם. אני אעשה גם וגם.

6. הוספת יחסי תלות

במסוף הצ'אט של Gemini (זה שבתוך עורך Cloud Code בחלונית הימנית), מקלידים את ההנחיה הבאה:

what is the maven dependency for com.google.cloud.vertexai library

הסיבה שבגללה אני מבקש ספציפית את החבילה com.google.cloud.vertexai היא שבה אני משתמש בקוד המקור שלי, שבו אני מטמיע את קוד ההפעלה של Gemini.

קיבלתי את התוצאה הבאה:

62c4295b9b4654e9.png

 <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-vertexai</artifactId>
      <version>0.1.0</version>
    </dependency>

מעתיקים את הקוד הזה ומדביקים אותו בקובץ pom.xml, לפני התג </dependencies>. מחליפים את הגרסה ב-0.1.0 (אפשר להסיר את התג <version> אם משתמשים ב-Spring Cloud GCP BOM כדי לנהל את מספרי הגרסאות של spring-cloud-gcp).

המקטע dependency אמור להיראות כך:

1800f10af9331210.png

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

    <dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.10</version>
    </dependency>

7. שינוי נקודת הכניסה של הפונקציה ושם הכיתה

  1. עוברים לקובץ launch.json בתיקייה ‎.vscode. עורכים את שם הפונקציה מ-function-hello-world ל-function-gemini-calling.
  2. מעדכנים את הערך של entryPoint מ-cloudcode.helloworld.HelloWorld ל-cloudcode.bookshelf.Bookshelf.
  3. עכשיו עוברים לקובץ המחלקה Java‏ HelloWorld.java. משנים את שם החבילה ל-package cloudcode.bookshelf; בחלון השגיאה שקופץ, לוחצים על הנורה הצהובה ואז על האפשרות Move HelloWorld.java to package cloudcode.bookshelf;‎ (העברת HelloWorld.java לחבילה cloudcode.bookshelf).

38d721978bddc8a8.png

  1. מעדכנים את שם הכיתה ל-Bookshelf, ובשגיאה שמופיעה לוחצים על הנורה הצהובה הקטנה ובוחרים באפשרות 'שינוי שם הקובץ ל-Bookshelf.java'. בוחרים באפשרות הזו.

8. יצירת השיטה שקוראת ל-Gemini Pro

בואו נטמיע את הפונקציונליות הזו במחלקה Bookshelf.java. מחליפים את הקובץ Bookshelf.java בקוד הבא:

package cloudcode.bookshelf;
import java.io.BufferedWriter;
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.cloud.vertexai.VertexAI;
import com.google.cloud.vertexai.api.GenerateContentResponse;
import com.google.cloud.vertexai.api.GenerationConfig;
import com.google.cloud.vertexai.generativeai.preview.GenerativeModel;
import com.google.cloud.vertexai.generativeai.preview.ResponseHandler;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.util.Map;
import java.util.LinkedHashMap;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;

public class Bookshelf implements HttpFunction {
  private static final Gson gson = new Gson();

 @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    BufferedWriter writer = response.getWriter();

 // Get the request body as a JSON object.
 JsonObject requestJson = new Gson().fromJson(request.getReader(), JsonObject.class);
 JsonArray calls_array = requestJson.getAsJsonArray("calls");
 JsonArray calls = (JsonArray) calls_array.get(0);
 String context = calls.get(0).toString().replace("\"", "");

 //Invoke Gemini model
  String raw_result = callGemini(context);
  raw_result = raw_result.replace("\n","");
  String trimmed = raw_result.trim();
  List<String> result_list = Arrays.asList(trimmed);
  Map<String, List<String>> stringMap = new LinkedHashMap<>();
  stringMap.put("replies", result_list);
 
  // Serialization
  String return_value = gson.toJson(stringMap);
  writer.write(return_value);
    }
  public String callGemini(String context) throws IOException{
      String res = "";
        try (VertexAI vertexAi = new VertexAI("REPLACE_WITH_YOUR_PROJECT_ID", "us-central1"); ) {
          GenerationConfig generationConfig =
              GenerationConfig.newBuilder()
                  .setMaxOutputTokens(2048)
                  .setTemperature(0.4F)
                  .setTopK(32)
                  .setTopP(1)
                  .build();  
        GenerativeModel model = new GenerativeModel("gemini-pro", generationConfig, vertexAi);
        GenerateContentResponse response = model.generateContent(context);
        res = ResponseHandler.getText(response);
      }catch(Exception e){
        System.out.println(e);
        }
        return res;
    }
}

הקלט של המחלקה הזו צריך להיות במבנה JSON כמו בדוגמה הבאה:

{ "calls": [["YOUR_PROMPT_HERE"]] }

התגובה שמתקבלת היא:

‫(Json) Map<String, List<String>> {"replies": ["response"]}

כדי לקבל הסבר על הקוד, אפשר לנסות את האפשרות של Gemini Chat בחלונית הימנית של Cloud Shell Editor. אפשר גם לבחור את כל הקוד, ללחוץ על סמל הנורה הצהובה בפינה הימנית העליונה של הבחירה ולבחור באפשרות 'הסבר על הקוד'.

66fb67507793e368.png

9. פריסת הפונקציה ב-Cloud Functions

עכשיו, אחרי שהפונקציה של Cloud Functions מוכנה, נשאל את Gemini איך לפרוס אותה. עוברים לצ'אט עם Gemini בעורך Cloud Code ומזינים את הטקסט הבא:

   How to deploy this Cloud Function with a gcloud command?

קיבלתי את התשובה הבאה:

9f9db98933841864.png

עכשיו רציתי לבדוק את זה יותר לעומק. לכן ביקשתי מ-Gemini לתת לי את הפקודה המלאה לפריסת פונקציות gcloud. התגובה תהיה כפי שמוצג בהמשך:

b77701c00dc3eaf1.png

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

פורמט גוף הבקשה:

82bf20304143a374.png

וגם

פורמט התגובה:

ade55b3de5d823a6.png

עכשיו נריץ את פקודת gcloud ש-Gemini נתן לנו כדי לפרוס את הפונקציה. לשם כך, צריך לפתוח את הטרמינל של Cloud Shell. אפשר לפתוח אותו בכרטיסייה חדשה בכתובת https://console.cloud.google.com ולוודא שהפרויקט הנכון נבחר. לוחצים על סמל ההפעלה של Cloud Shell בפינה הימנית העליונה של המסוף כדי לפתוח את מסוף Cloud Shell, ומוודאים שאתם בתיקיית הפרויקט הנכונה באמצעות הפקודה הבאה:

cd duetai-gemini-calling

ואז מריצים את הפקודה הבאה:

gcloud functions deploy bookshelf --runtime java17 --trigger-http --entry-point cloudcode.bookshelf.Bookshelf --allow-unauthenticated

תוצג השאלה 'האם לאפשר הפעלות לא מאומתות של פונקציה חדשה [bookshelf]?'. אומרים "y" ולוחצים על Enter. לאחר מכן, אם רלוונטי, תופיענה כמה שאלות, והפונקציה של Cloud Functions ללא שרת תיפרס עם כתובת ה-URL שנפרסה: https://us-central1-*******.cloudfunctions.net/bookshelf.

עכשיו נפעיל את הפונקציה של Cloud Functions שפרסנו ונבדוק אותה.

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

10. הפעלת הפונקציה של Cloud Functions שנפרסה

יש לך שאלה ל-Gemini? הזנתי את ההנחיה

How to call the deployed cloud function?

קיבלתי את התוצאה הבאה: (יכול להיות שתקבלו תשובה שונה, אתם מוזמנים לשחק עם ההנחיה ולראות את ההבדלים בתשובות).

1d2242715571fe6f.png

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

how to call the deployed cloud function using gcloud

קיבלתי את התשובה הבאה: e7b29b2cfb57782c.png

אפשר להשתמש בתגובה הזו (הפקודה gcloud functions call) מהטרמינל עם שינויים כדי שהיא תפעל בתרחיש שלנו (לחלופין, אפשר לנסות להעביר את הפרמטרים בהנחיה עצמה ולראות אם אפשר לקבל את התגובה המפורטת של gcloud functions call):

gcloud functions call bookshelf --region=us-central1 --gen2 --data '{"calls":[["Hello! This is my test prompt."]]}'

הנה התוצאה שלי:

6f396d915251db78.png

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

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

12. מזל טוב

יצרתם, פרסתם ובדקתם בהצלחה פונקציות Java Cloud Functions כדי לבצע קריאה ל-Gemini 1.0 Pro באמצעות Gemini. האפליקציה הזו מקבלת את ההנחיה שקשורה להמלצה על ספר עם סיכום ונושאים של ספרים.