פיתוח מחולל בוחן באמצעות GenAI ו-Cloud Run

1. מבוא

בשיעור ה-Lab הזה תפתחו שירות אינטרנט כדי ליצור חידוני טריוויה ולשלב אותו באפליקציה כיפית ופעילה. עליך להשתמש בשפת תכנות שונה מזו שבה השתמשת בעבר: אנגלית!

מה עושים...

  • תיצרו הנחיה שיוצרת בוחן טריוויה בהתאם לקבוצת קריטריונים.
  • אתם תלמדו לפתח אפליקציית אינטרנט פשוטה ותוודאו שהיא פועלת כצפוי בסביבת הפיתוח שלכם.
  • תצטרכו להוסיף לוגיקה בהדרגה לאפליקציית האינטרנט כדי להפוך אותה לשרת API שיוצר חידונים בהתאם לקבוצה של פרמטרים לקלט.
  • תראו כמה קל לפרוס את שירות יצירת החידונים בענן באמצעות Google Cloud Run.
  • בשלב האחרון מגדירים אפליקציה אמיתית ( quizaic.com) לשימוש בשירות ליצירת בחנים שנפרסו, ואפשר לשחק בבחנים בזמן אמת על סמך הפלט שמתקבל.

מה תלמדו...

  • איך ליצור הנחיה בתבנית בשביל מודל שפה גדול (LLM).
  • איך יוצרים אפליקציית שרת אינטרנט פשוטה ב-Python.
  • איך מוסיפים לאפליקציית האינטרנט תמיכה ב-LLM של Google.
  • איך לפרוס את האפליקציה בענן כדי שכולם יוכלו לנסות את היצירה החדשה שיצרתם.
  • איך לשלב את מחולל החידונים באפליקציה גדולה יותר.

מה צריך...

  • דפדפן האינטרנט Chrome
  • חשבון Google
  • פרויקט בענן שהופעל בו חיוב

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

2. הגדרה

a08aa5878e36b60c.png

בחלק הזה נסביר את כל מה שצריך לעשות כדי להתחיל את שיעור ה-Lab הזה.

הגדרת סביבה בקצב עצמאי

  1. נכנסים למסוף Google Cloud ויוצרים פרויקט חדש או עושים שימוש חוזר בפרויקט קיים. אם אין לכם עדיין חשבון Gmail או חשבון Google Workspace, עליכם ליצור חשבון.

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • Project name הוא השם המוצג של המשתתפים בפרויקט. זו מחרוזת תווים שלא משמשת את Google APIs. תמיד אפשר לעדכן.
  • Project ID הוא ייחודי בכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו (אי אפשר לשנות אותו אחרי שמגדירים אותו). מסוף Cloud יוצר מחרוזת ייחודית באופן אוטומטי; בדרך כלל לא מעניין אותך מה זה. ברוב ה-codelabs תצטרכו להפנות למזהה הפרויקט שלכם (בדרך כלל מזוהה כ-PROJECT_ID). אם המזהה שנוצר לא מוצא חן בעיניכם, אתם יכולים ליצור מזהה אקראי אחר. לחלופין, אפשר לנסות שם משלך ולראות אם הוא זמין. לא ניתן לשנות אותו אחרי השלב הזה, והוא נשאר למשך הפרויקט.
  • לידיעתך, יש ערך שלישי, Project Number, שבו משתמשים בחלק מממשקי ה-API. מידע נוסף על כל שלושת הערכים האלה זמין במסמכי התיעוד.
  1. בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים או בממשקי API של Cloud. מעבר ב-Codelab הזה לא יעלה הרבה כסף, אם בכלל. כדי להשבית משאבים ולא לצבור חיובים מעבר למדריך הזה, אתם יכולים למחוק את המשאבים שיצרתם או למחוק את הפרויקט. משתמשים חדשים ב-Google Cloud זכאים להצטרף לתוכנית תקופת ניסיון בחינם בשווי 1,200 ש"ח.

הפעלת Cloud Shell

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

4a95152439f0159b.png

הפעלת Cloud Shell

  1. במסוף Cloud, לוחצים על Activate Cloud Shell 853e55310c205094.png.

3c1dabeca90e44e5.png

אם זו הפעם הראשונה שאתם מפעילים את Cloud Shell, יוצג לכם מסך ביניים שמתאר מהו. אם הוצג לכם מסך ביניים, לוחצים על המשך.

9c92662c6a846a5c.png

ההקצאה וההתחברות ל-Cloud Shell נמשכת כמה דקות.

9f0e51b578fecce5.png

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

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

  1. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שהאימות בוצע:
gcloud auth list

פלט הפקודה

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שהפקודה ב-gcloud יודעת על הפרויקט שלכם:
gcloud config list project

פלט הפקודה

[core]
project = <PROJECT_ID>

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

gcloud config set project <PROJECT_ID>

פלט הפקודה

Updated property [core/project].

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

בשלבים הבאים תראו איפה השירותים האלה נחוצים (ולמה), אבל בינתיים, מריצים את הפקודה הזו כדי לתת לפרויקט גישה ל-Cloud Build, Artifact Registry, Vertex AI ו-Cloud Run:

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

אמורה ליצור מסר מוצלח שדומה לזה:

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

3. הנחיות – תכנות בשפה טבעית

92f630373224ead8.png

נתחיל בהדרכה איך לפתח הנחיה למודל שפה גדול (LLM). נכנסים למסוף Google Cloud > Vertex AI Vertex AI Studio (שפה). אתם אמורים לראות דף כזה:

bfe5706041ae6454.png

בקטע Generate Text, לוחצים על הלחצן Text Prompt. בתיבת הדו-שיח הבאה, מזינים הנחיה שלדעתכם יכולה להיות יעילה ליצירת בוחן טריוויה בהתאם לדרישות הבאות:

  • נושא: היסטוריה עולמית
  • מספר שאלות: 5
  • רמת קושי: בינונית
  • שפה: אנגלית

כדי לראות את הפלט, צריך ללחוץ על הלחצן 'שליחה'.

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

8aa89a1970ea9335.png

ההגדרות הבאות זמינות:

  • 'אזור' הוא המקום שבו בקשת הגנרציה צריכה לפעול.
  • המודל בוחר במודל שפה גדול (LLM) שרוצים להשתמש בו. ב-Codelab הזה, נשארים עם 'gemini-1.0-pro-001'.
  • הטמפרטורה קובעת את רמת הרנדומיזציה בבחירת האסימון. טמפרטורות נמוכות טובות להנחיות עם ציפייה לתשובה נכונה או מדויקת, ואילו טמפרטורות גבוהות יכולות להוביל לתוצאות יותר מגוונות או לא צפויות.
  • מגבלת האסימון קובעת את הכמות המקסימלית של פלט טקסט מהנחיה אחת. אסימון באורך של כארבעה תווים. ערך ברירת המחדל הוא 1,024.
  • Top-k משנה את האופן שבו המודל בוחר אסימונים לפלט. המשמעות של k-1 היא שהאסימון הנבחר הוא ההסתברות הגבוהה ביותר מבין כל האסימונים באוצר המילים של המודל (נקרא גם פענוח greedy). המספר הגבוה ביותר (k) של 3 פירושו שהאסימון הבא נבחר מתוך 3 האסימונים בעלי הסבירות הגבוהה ביותר (באמצעות טמפרטורה). ערך ברירת המחדל של הערכים העליונים הוא 40.
  • לחיצה על 'ראש הדף' משנה את האופן שבו המודל בוחר אסימונים לפלט. האסימונים נבחרים מהגבוה לנמוך עד שסכום ההסתברויות שלהם שווה לערך p העליון.
  • 'מקסימום תגובות' הוא המספר המקסימלי של תשובות שהמודל יצר לכל הנחיה.
  • רצף עצירה הוא סדרה של תווים (כולל רווחים) שמפסיקים את יצירת התגובה אם המודל נתקל בו.
  • ההגדרה הזו קובעת אם התשובות יודפסו כשהן נוצרות או נשמרות כשהן מוצגות כשהן מוכנות.
  • הסף של מסנן הבטיחות משנה את הסבירות לקבלת תגובות שעלולות להזיק.

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

החידונים בשיעור ה-Lab הזה מבוטאים כמערך אובייקטים, כאשר כל אובייקט מכיל שאלה, מערך של תשובות אפשריות לשאלה הזו ותשובה נכונה. זהו קידוד JSON לחידונים בשיעור ה-Lab הזה:

[
    {
        "question": "Who was the first person to walk on the moon?",
          "responses": [
              "Neil Armstrong",
              "Buzz Aldrin",
              "Michael Collins",
              "Yuri Gagarin"
           ],
           "correct": "Neil Armstrong"
    },
    {
        "question": "What was the name of the war that took place between the British and the French in North America from 1754 to 1763??",
          "responses": [
              "The French and Indian War",
              "The Seven Years' War",
              "The War of the Austrian Succession",
              "The Great War"
           ],
           "correct": "The French and Indian War"
    },

    ...
]

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

  1. מציינים במילים את הפורמט המדויק שרוצים לחפש (למשל, המשפט הנטוי שלמעלה).
  2. כוללים בהנחיה דוגמה לפורמט ה-JSON הרצוי.

אחרי שיוצרים הנחיה ליצירת בחנים בהתאם למפרט הרצוי, לוחצים על הלחצן GET CODE בפינה השמאלית העליונה של הדף כדי לראות קוד Python שאפשר להשתמש בו כדי לשלוח באופן פרוגרמטי את ההנחיה ל-Vertex AI LLM. אם אתם רוצים להשתמש בשפת תכנות שהיא לא Python, מומלץ להיכנס אל https://cloud.google.com/vertex-ai/docs/samples?text=generative.

4. בניית שרת אינטרנט פשוט

c73008bb8a72b57b.png

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

כדי להתחיל, לוחצים על הלחצן Open Editor בחלק העליון של החלונית של Cloud Shell. כך הוא נראה:

e2a06b5304079efc.png

לאחר מכן תופיע סביבת פיתוח משולבת (IDE) שדומה ל-Visual Studio Code, שבה אפשר ליצור פרויקטים, לערוך את קוד המקור, להריץ תוכנות וכו'.

אם המסך דחוס מדי, אפשר להרחיב או לכווץ את הקו המפריד בין המסוף לבין חלון העריכה/הסיום על ידי גרירת הסרגל האופקי בין שני האזורים האלה, המודגש כאן:

8dea35450851af53.png

אפשר לעבור בין Editor לבין הטרמינל בלחיצה על הלחצנים Open Editor ו-Open Terminal, בהתאמה. נסו לעבור בין שתי הסביבות האלה עכשיו.

בשלב הבא יוצרים תיקייה שבה תשמרו את העבודה בשיעור ה-Lab הזה. לשם כך, לוחצים על הלחצן להוספת תיקייה 5f4e64909bc15e30.png, כותבים quiz-generator ומקישים על Enter. כל הקבצים שתיצרו בשיעור ה-Lab הזה וכל העבודה שתבצעו ב-Cloud Shell יועברו לתיקייה הזו.

בשלב הזה יוצרים קובץ requirements.txt. הקוד הזה מורה ל-Python אילו ספריות האפליקציה תלויה. באפליקציית האינטרנט הפשוטה הזו משתמשים במודול Python פופולרי לבניית שרתי אינטרנט שנקרא Flask, ספריית הלקוח google-cloud-aiplatform, ו-framework של שרת אינטרנט שנקרא gunicorn. בחלונית הניווט של הקבצים, לוחצים לחיצה ימנית על התיקייה quiz-generator ובוחרים באפשרות New file בתפריט, כך:

613eb3de4b9b750a.png

כשמוצגת הנחיה לתת שם לקובץ החדש, כותבים requirements.txt ומקישים על Enter. מוודאים שהקובץ החדש מסתיים בתיקיית הפרויקט quiz-generator.

מדביקים את השורות הבאות בקובץ החדש כדי לציין שהאפליקציה תלויה בחבילת flask של Python, בשרת האינטרנט gunicorn ובספריית הלקוח google-cloud-aiplatform, ובגרסאות שמשויכות לכל אחת מהן.

flask==3.0.0
gunicorn==21.2.0
google-cloud-aiplatform==1.47.0

אין צורך לשמור באופן מפורש את הקובץ הזה כי Cloud Editor ישמור את השינויים באופן אוטומטי.

באותה שיטה, יוצרים קובץ חדש נוסף בשם main.py. זה יהיה קובץ המקור הראשי (והיחיד) של האפליקציה ב-Python. שוב, מוודאים שהקובץ החדש נמצא בתיקייה quiz-generator.

מזינים את הקוד הבא בקובץ הזה:

from flask import Flask
import os

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.
if not PORT:
    PORT = 8080

# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
@app.route("/", methods=["GET"])
def say_hello():
    html = "<h1>Hello world!</h1>"
    return html

# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

חוזרים לטרמינל ומחליפים לתיקיית הפרויקט באמצעות הפקודה הבאה:

cd quiz-generator

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

pip3 install -r requirements.txt

אחרי יחסי התלות של ההתקנה, אמור להופיע פלט שמסתיים כך:

Successfully installed flask-3.0.0

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

flask --app main.py --debug run --port 8080

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

לוחצים על הלחצן web preview ואז על האפשרות Preview on Port 8080 בתפריט:

7f938c0bc1b4154c.png

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

aaaf366f9bf74a28.png

5. הוספה של שיטת יצירה עם ניתוח פרמטרים

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

from flask import Flask
from flask import request                       #<-CHANGED
import os

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.
if not PORT:
    PORT = 8080

# The app.route decorator routes any GET requests sent to the /generate
# path to this function, which responds with "Generating:" followed by
# the body of the request.
@app.route("/", methods=["GET"])                #<-CHANGED
def generate():                                 #<-CHANGED
    params = request.args.to_dict()             #<-CHANGED
    html = f"<h1>Quiz Generator</h1>"           #<-CHANGED
    for param in params:                        #<-CHANGED
        html += f"<br>{param}={params[param]}"  #<-CHANGED
    return html                                 #<-CHANGED

# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

עכשיו צריך לטעון מחדש את הכרטיסייה הקיימת בדפדפן האינטרנט כדי לראות את התוצאות. הפעם אמור להופיע הכלי 'מחולל חידונים', לצד פרמטר של שאילתה שיתווסף באופן אוטומטי לכתובת ה-URL (authuser). כדי לנסות להוסיף עוד שני פרמטרים, צריך להוסיף את המחרוזת ''&param1=val1&param2=val2'" בסוף כתובת ה-URL שמוצגת בסרגל הכתובות של הדפדפן, טוענים מחדש את הדף. אתם אמורים לראות משהו כזה:

6e223ca358e4e009.png

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

  • topic – הנושא הרצוי בבוחן
  • num_q – מספר השאלות הרצויות
  • diff – רמת הקושי הרצויה (קלה, בינונית, קשה)
  • lang – שפת הבוחן הרצויה
from flask import Flask
from flask import request
import os

# Default quiz settings  #<-CHANGED
TOPIC = "History"        #<-CHANGED
NUM_Q = "5"              #<-CHANGED
DIFF = "intermediate"    #<-CHANGED
LANG = "English"         #<-CHANGED

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.
if not PORT:
    PORT = 8080

# This function takes a dictionary, a name, and a default value.
# If the name exists as a key in the dictionary, the corresponding
# value is returned. Otherwise, the default value is returned.
def check(args, name, default):  #<-CHANGED
    if name in args:             #<-CHANGED
        return args[name]        #<-CHANGED
    return default               #<-CHANGED

# The app.route decorator routes any GET requests sent to the /generate
# path to this function, which responds with "Generating:" followed by
# the body of the request.
@app.route("/", methods=["GET"])
# This function generates a quiz using Vertex AI.
def generate():
    args = request.args.to_dict()        #<-CHANGED
    topic = check(args, "topic", TOPIC)  #<-CHANGED
    num_q = check(args, "num_q", NUM_Q)  #<-CHANGED
    diff = check(args, "diff", DIFF)     #<-CHANGED
    lang = check(args, "lang", LANG)     #<-CHANGED
    html = f"""
        <h1>Quiz Generator</h1><br>
        {topic=}<br>
        {num_q=}<br>
        {diff=}<br>
        {lang=}"""                       #<-CHANGED
    return html

# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

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

15eed60f6a805212.png

כדאי לנסות לשנות את כתובת ה-URL ולהגדיר ערכים לפרמטרים שונים. לדוגמה, אפשר לנסות להשתמש בסיומת "?authuser=0&topic=Literature&num_q=10&diff=easy&lang=French" בסוף כתובת ה-URL בסרגל הכתובות:

f629dba5fa207cef.png

6. מוסיפים עיצוב של הנחיה

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

  • topic – הנושא הרצוי בבוחן
  • num_q – מספר השאלות הרצויות
  • diff – רמת הקושי הרצויה (קלה, בינונית, קשה)
  • lang – שפת הבוחן הרצויה

מעתיקים את ההנחיה שפיתחתם ב-Vertex Generative AI Studio בשלב מוקדם יותר, אבל משנים את הערכים בתוך הקוד של הנושא, מספר השאלות ורמת הקושי באמצעות המחרוזות הבאות:

  • {topic}
  • {num_q}
  • {diff}
  • {lang}
from flask import Flask
from flask import request
import os

# Default quiz settings
TOPIC = "History"
NUM_Q = 5
DIFF = "intermediate"
LANG = "English"

PROMPT = """
Generate a quiz according to the following specifications:

- topic: {topic}
- num_q: {num_q}
- diff:  {diff}
- lang:  {lang}

Output should be (only) an unquoted json array of objects with keys:
"Question", "responses", and "correct".

"""  #<-CHANGED

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.
if not PORT:
    PORT = 8080

# This function takes a dictionary, a name, and a default value.
# If the name exists as a key in the dictionary, the corresponding
# value is returned. Otherwise, the default value is returned.
def check(args, name, default):
    if name in args:
        return args[name]
    return default

# The app.route decorator routes any GET requests sent to the /generate
# path to this function, which responds with "Generating:" followed by
# the body of the request.
@app.route("/", methods=["GET"])
# This function generates a quiz using Vertex AI.
def generate():
    args = request.args.to_dict()
    topic = check(args, "topic", TOPIC)
    num_q = check(args, "num_q", NUM_Q)
    diff = check(args, "diff", DIFF)
    lang = check(args, "lang", LANG)
    prompt = PROMPT.format(topic=topic, num_q=num_q, diff=diff, lang=lang)  #<-CHANGED 
    html = f"<h1>Prompt:</h1><br><pre>{prompt}</pre>"                       #<-CHANGED
    return html

# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

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

3c2b9dfcfba86b7a.png

נסו לשנות את כתובת ה-URL כדי לשנות את ארבעת הפרמטרים האלה.

7. הוספה של ספריית הלקוח של Vertex AI

עכשיו אנחנו מוכנים להשתמש בספריית הלקוח של Vertex AI Python כדי ליצור את הבוחן. הפעולה הזו תהפוך את ההנחיות האינטראקטיביות לאוטומטיות בשלב 3 ותעניק לשירות הגנרטור גישה פרוגרמטית ליכולות ה-LLM של Google. מעדכנים את קובץ main.py באופן הבא:

חשוב להחליף את "YOUR_PROJECT" במזהה הפרויקט בפועל.

from flask import Flask
from flask import request
from flask import Response                                          #<-CHANGED
import os

import vertexai    
from vertexai.generative_models import GenerativeModel  #<-CHANGED

# Default quiz settings
TOPIC = "History"
NUM_Q = 5
DIFF = "intermediate"
LANG = "English"
MODEL = "gemini-1.0-pro"  #<-CHANGED

PROMPT = """
Generate a quiz according to the following specifications:

- topic: {topic}
- num_q: {num_q}
- diff:  {diff}
- lang:  {lang}

Output should be (only) an unquoted json array of objects with keys "question", "responses", and "correct".

"""

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.
if not PORT:
    PORT = 8080

# Initialize Vertex AI access.
vertexai.init(project="YOUR_PROJECT", location="us-central1")  #<-CHANGED
parameters = {                                                 #<-CHANGED
    "candidate_count": 1,                                      #<-CHANGED
    "max_output_tokens": 1024,                                 #<-CHANGED
    "temperature": 0.5,                                        #<-CHANGED
    "top_p": 0.8,                                              #<-CHANGED
    "top_k": 40,                                               #<-CHANGED
}                                                              #<-CHANGED
model = GenerativeModel(MODEL)             #<-CHANGED

# This function takes a dictionary, a name, and a default value.
# If the name exists as a key in the dictionary, the corresponding
# value is returned. Otherwise, the default value is returned.
def check(args, name, default):
    if name in args:
        return args[name]
    return default

# The app.route decorator routes any GET requests sent to the /generate
# path to this function, which responds with "Generating:" followed by
# the body of the request.
@app.route("/", methods=["GET"])
# This function generates a quiz using Vertex AI.
def generate():
    args = request.args.to_dict()
    topic = check(args, "topic", TOPIC)
    num_q = check(args, "num_q", NUM_Q)
    diff = check(args, "diff", DIFF)
    lang = check(args, "lang", LANG)
    prompt = PROMPT.format(topic=topic, num_q=num_q, diff=diff, lang=lang)
    response = model.generate_content(prompt, generation_config=parameters)  #<-CHANGED
    print(f"Response from Model: {response.text}")           #<-CHANGED
    html = f"{response.text}"                                #<-CHANGED
    return Response(html, mimetype="application/json")       #<-CHANGED

# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

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

f43d3ba5102857b8.png

כדאי לנסות לשנות את כתובת ה-URL כך שיבקשו נושא אחר בבוחן, מספר השאלות ורמת הקושי.

זהו, סיימנו את המיקרו-שירות (microservice) – כל הכבוד! בשלב הבא תלמדו איך לפרוס את השירות שלכם בענן כדי שכל אחד יוכל לגשת אליו מכל מקום.

8. לענן!

67c99bf45a7b7805.png

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

  • פועל באופן מהימן – מקבלים אוטומטית הגנה מפני כשלים במקרה שמחשב מריץ את האפליקציה
  • מותאמות לעומס (scaling) באופן אוטומטי – האפליקציה מתעדכנת בנפחים גדולים של תנועה ותצמצם את טביעת הרגל הפחמנית באופן אוטומטי כשהיא לא בשימוש
  • יפחית את העלויות שלך, בכך שלא תחייב אותך עבור משאבים שבהם אינך משתמש – תחויב רק עבור המשאבים שנעשה בהם שימוש בזמן התגובה לתנועה
  • ניתן לגשת אליו באמצעות שם דומיין מותאם אישית - יש לך גישה לפתרון בלחיצה אחת להקצאת שם דומיין מותאם אישית לשירות שלך
  • מציע זמן תגובה מצוין – הפעלות במצב התחלתי (cold start) מגיבות באופן סביר, אבל אפשר לכוונן זאת באמצעות ציון הגדרה של מופע מינימלי.
  • תמיכה בהצפנה מקצה לקצה באמצעות אבטחת אינטרנט סטנדרטית של SSL או TLS. כשפורסים שירות, מקבלים הצפנת אינטרנט סטנדרטית ואת האישורים הנדרשים התואמים, בחינם ובאופן אוטומטי.

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

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

לקבלת מידע נוסף על קונטיינרים ועל אופן הפעולה שלהם ב-Google Cloud Run, אתם מוזמנים לעבור אל Dev to Prod in 3 Easy שלבים עם Cloud Run.

פריסת האפליקציה ל-Cloud Run

Cloud Run הוא שירות אזורי. כלומר, התשתית שמפעילה את שירותי Cloud Run ממוקמת באזור מסוים ומנוהלת על ידי Google כך שהיא תהיה זמינה באופן יתירות בכל התחומים (zones) באותו אזור. כדי לפשט את הנושא, בשיעור ה-Lab הזה נשתמש באזור שכתוב בתוך הקוד us-central1.

נשתמש במשהו שנקרא buildpack כדי ליצור את הקונטיינר באופן אוטומטי. יוצרים קובץ חדש בשם Procfile ב-Cloud Editor ומוסיפים את שורת הטקסט הבאה:

web: gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

הפקודה הזו מנחה את מערכת ה-buildpack איך להריץ את האפליקציה בקונטיינר שנוצר באופן אוטומטי. לאחר מכן, מריצים את הפקודה הבאה בטרמינל של Cloud Shell (מאותה ספריית quiz-generator) :

gcloud run deploy quiz-generator  \
    --source .                    \
    --region us-central1          \
    --allow-unauthenticated

הפקודה הזו מנחה את הפקודה gcloud שאתם רוצים שתשתמש ב-buildpacks כדי ליצור קובץ אימג' בקונטיינר, על סמך קובצי המקור שהוא מוצא בספרייה הנוכחית (ה-dot ב---source . הוא קיצור של הספרייה הנוכחית). מכיוון שהשירות מטפל באופן מרומז בקובץ האימג' של הקונטיינר, אין צורך לציין תמונה בפקודה gcloud הזו.

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

Building using Buildpacks and deploying container to Cloud Run service [quiz-generator] in project [YOUR_PROJECT] region [YOUR_REGION]
OK Building and deploying new service... Done.                                                                          
  OK Creating Container Repository...                                                                                   
  OK Uploading sources...                                                                                               
  OK Building Container... Logs are available at [https://console.cloud.google.com/cloud-build/builds/0cf1383f-35db-412d
  -a973-557d5e2cd4a4?project=780573810218].                                                                             
  OK Creating Revision...                                                                                               
  OK Routing traffic...                                                                                                 
  OK Setting IAM Policy...                                                                                              
Done.                                                                                                                   
Service [quiz-generator] revision [quiz-generator-00001-xnr] has been deployed and is serving 100 percent of traffic.
Service URL: https://quiz-generator-co24gukjmq-uc.a.run.app

אפשר גם לאחזר את כתובת ה-URL של השירות באמצעות הפקודה הבאה:

gcloud run services describe quiz-generator  \
  --region us-central1                       \
  --format "value(status.url)"

זה אמור להראות משהו כמו:

https://quiz-generator-co24gukjmq-uc.a.run.app

הקישור הזה הוא כתובת URL ייעודית, עם אבטחת TLS, לשירות Cloud Run שלך. הקישור הזה הוא קבוע (כל עוד לא משביתים את השירות) ואפשר להשתמש בו בכל מקום באינטרנט. היא לא משתמשת במנגנון שרת ה-proxy של Cloud Shell שצוין קודם, שתלוי במכונה וירטואלית זמנית.

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

מעולה! האפליקציה שלך פועלת עכשיו בענן של Google. האפליקציה שלכם זמינה לכולם, עם הצפנת TLS (HTTPS) והתאמה אוטומטית לעומס (auto-scaling) לרמות תנועה מדהימות.

9. מחברים את כל החלקים

9927db1725bcd5d6.png

בשלב האחרון, אנחנו מוכנים להפעיל את מחולל החידונים שלכם כחלק מאפליקציית החידונים. נכנסים אל כתובת ה-URL של החידון, מתחברים לחשבון Google ועוברים לכרטיסייה Create Quiz. בוחרים את סוג המחולל Custom, מדביקים את כתובת ה-URL של Cloud Run בשדה של כתובת ה-URL, ממלאים את שאר שדות החובה ושולחים את הטופס.

328ee05579ea05f9.png

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

1719169140978b63.png

10. ניקוי

c1592d590c563428.png

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

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

gcloud config set artifacts/repository cloud-run-source-deploy
gcloud config set artifacts/location us-central1
gcloud artifacts docker images list

# Note image tag for resulting list

gcloud artifacts docker images delete <IMAGE-TAG>

כדי למחוק את השירות Cloud Run, משתמשים בפקודה הבאה:

gcloud run services delete quiz-generator --region us-central1 --quiet

11. עשית את זה!

910162be58c0f6d6.png

כל הכבוד – יצרתם בהצלחה הנחיה ל-LLM ופרסתם מיקרו-שירות (microservice) של Cloud Run באמצעות ההנחיה הזו. עכשיו אפשר לתכנת בשפה טבעית ולשתף את היצירות שלך עם העולם!

אני רוצה להשאיר אותך עם שאלה חשובה אחת:

לאחר שהפעלתם את האפליקציה בסביבת הפיתוח, כמה שורות קוד צריך לשנות כדי לפרוס אותה בענן, עם כל המאפיינים ברמת הייצור שמוצעים על ידי Cloud Run?

התשובה היא כמובן אפס. :)

Codelabs נוספים שכדאי לנסות...

מסמכי עזר...

12. קריאה לפעולה

אם נהניתם מה-Codelab הזה ויש סיכוי גבוה שתקדישו יותר זמן להתנסות ב-Google Cloud, כדאי לכם להצטרף ל-Google Cloud Innovators כבר היום.

498cab7d87ec12d3.png

שירות Google Cloud Innovators זמין בחינם וכולל:

  • דיונים, AMA ומפגשי מפת דרכים בשידור חי כדי ללמוד מה מה שחדש ישירות מהגוגלרים
  • החדשות האחרונות על Google Cloud ישירות לתיבת הדואר הנכנס
  • תג דיגיטלי ורקע של שיחת ועידה בווידאו
  • 500 קרדיטים של שיעורי Lab ולמידה ב-Skills Boost

אפשר ללחוץ כאן כדי להירשם.