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

1. מבוא

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

מה עושים...

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

מה תלמדו...

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

מה צריך…

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

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

2. הגדרה

a08aa5878e36b60c.png

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

הגדרת סביבה בקצב אישי

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

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

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

הפעלת Cloud Shell

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

4a95152439f0159b.png

הפעלת Cloud Shell

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

3c1dabeca90e44e5.png

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

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

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

bfe5706041ae6454.png

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

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

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

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

8aa89a1970ea9335.png

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

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

אחרי שתקבלו הנחיה שנראה שהיא יוצרת חידון סביר בהתאם לדרישות שצוינו למעלה, נוכל לנתח את החידון הזה באמצעות קוד מותאם אישית, אבל לא יהיה נחמד יותר לאפשר ל-LLM ליצור את החידון בפורמט מובנה שאפשר לטעון ישירות לתוכנית שלנו? התוכנית שבה נשתמש בהמשך הסדנה הזו כדי לקרוא לגנרטור מצפה שהחידונים יפורסמו בפורמט 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 שאפשר להשתמש בו כדי לשלוח את ההנחיה באופן פרוגרמטי ל-LLM של Vertex AI. אם אתם רוצים להשתמש בשפת תכנות אחרת מלבד Python, תוכלו לבדוק את הדוגמאות ב-https://cloud.google.com/vertex-ai/docs/samples?text=generative.

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

c73008bb8a72b57b.png

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

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

e2a06b5304079efc.png

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

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

8dea35450851af53.png

כדי לעבור בין ה-Editor ל-Terminal, לוחצים על הלחצנים 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.

מדביקים את השורות הבאות בקובץ החדש כדי לציין שהאפליקציה תלויה בחבילת Python‏ flask, בשרת האינטרנט 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)

עכשיו צריך לטעון מחדש את הכרטיסייה הקיימת בדפדפן האינטרנט כדי לראות את התוצאות. הפעם אמור להופיע "Quiz Generator", יחד עם פרמטר של שאילתה שיתווסף באופן אוטומטי לכתובת ה-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 כדי לבקש נושא אחר של חידון, מספר שאלות אחר ורמת קושי אחרת.

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

8. לענן!

67c99bf45a7b7805.png

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

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

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

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

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

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

Cloud Run הוא שירות אזורי, כלומר התשתית שמפעילה את שירותי Cloud Run ממוקמת באזור ספציפי ומנוהלת על ידי Google כדי להיות זמינה באופן יתיר בכל האזורים באותו אזור. כדי לפשט את העניין, בשיעור ה-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.

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

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

9927db1725bcd5d6.png

בשלב האחרון הזה, אנחנו מוכנים להריץ את הכלי ליצירת השאלות כחלק מאפליקציית Quizaic. נכנסים אל כתובת ה-URL של Quizaic, נכנסים לחשבון 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 ופרסמתם מיקרו-שירות ב-Cloud Run באמצעות ההנחיה הזו. עכשיו אפשר לתכנת בשפה טבעית ולשתף את היצירות שלכם עם העולם!

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

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

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

סדנאות Codelab נוספות שכדאי לבדוק...

מסמכי עזר...

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

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

498cab7d87ec12d3.png

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

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

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