1. מבוא
בשיעור ה-Lab הזה תבנו שירות אינטרנט ליצירת חידונים של טריוויה ותשלבו אותו באפליקציה כיפית ופעילה. תשתמשו בשפת תכנות שונה מזו שאולי השתמשתם בה בעבר: אנגלית!
מה עושים...
- תנסחו הנחיה ליצירת חידון טריוויה לפי קבוצת קריטריונים.
- תבנו אפליקציית אינטרנט פשוטה ותוודאו שהיא פועלת כמו שצריך בסביבת הפיתוח.
- תוסיפו בהדרגה לוגיקה לאפליקציית האינטרנט כדי להפוך אותה לשרת API שיוצר חידונים בהתאם לקבוצה של פרמטרים לקלט.
- תראו כמה קל לפרוס את שירות יצירת החידונים בענן באמצעות Google Cloud Run.
- לבסוף, תגדירו אפליקציה אמיתית ( quizaic.com) לשימוש בשירות ליצירת חידונים שפרסתם, ותוכלו לשחק בחידונים בזמן אמת על סמך הפלט.
מה תלמדו...
- איך יוצרים הנחיה מבוססת-תבנית למודל שפה גדול (LLM).
- איך יוצרים אפליקציית שרת אינטרנט פשוטה ב-Python.
- איך מוסיפים תמיכה ב-LLM של Google לאפליקציית האינטרנט.
- איך פורסים את האפליקציה בענן כדי שכל אחד יוכל לנסות את היצירה החדשה.
- איך משלבים את מחולל החידונים באפליקציה גדולה יותר.
מה צריך...
- דפדפן האינטרנט Chrome
- חשבון Google
- פרויקט ב-Cloud עם חיוב מופעל
שיעור ה-Lab הזה מיועד למפתחים בכל הרמות, כולל מתחילים. למרות שתשתמשו ב-Python, לא צריך להכיר את התכנות ב-Python כדי להבין מה קורה, כי נסביר את כל הקוד שיוצג.
2. הגדרה

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



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

הפעלת Cloud Shell
- ב-Cloud Console, לוחצים על Activate Cloud Shell
.

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

הקצאת המשאבים והחיבור ל-Cloud Shell נמשכים רק כמה רגעים.

המכונה הווירטואלית הזו כוללת את כל הכלים הדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר מאוד את הביצועים והאימות ברשת. אפשר לבצע את רוב העבודה ב-codelab הזה, אם לא את כולה, באמצעות דפדפן.
אחרי שמתחברים ל-Cloud Shell, אמור להופיע אימות ושהפרויקט מוגדר לפי מזהה הפרויקט.
- מריצים את הפקודה הבאה ב-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`
- מריצים את הפקודה הבאה ב-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. כתיבת הנחיות – תכנות בשפה טבעית

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

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

ההגדרות הבאות זמינות:
- האזור הוא המקום שבו צריך להריץ את בקשת היצירה.
- מודל – בוחרים את מודל השפה הגדול (LLM) שבו רוצים להשתמש. ב-codelab הזה, כדאי להשתמש ב-gemini-1.0-pro-001.
- הטמפרטורה שולטת במידת האקראיות בבחירת האסימון. טמפרטורות נמוכות טובות להנחיות עם ציפייה לתשובה נכונה או מדויקת, ואילו טמפרטורות גבוהות יכולות להוביל לתוצאות יותר מגוונות או לא צפויות.
- מגבלת הטוקנים קובעת את כמות הטקסט המקסימלית שמתקבלת מהנחיה אחת. טוקן הוא בערך ארבעה תווים. ערך ברירת המחדל הוא 1024.
- ההגדרה Top-k משנה את האופן שבו המודל בוחר אסימונים לפלט. ערך של 1 בפרמטר Top-K אומר שהאסימון שנבחר הוא האסימון הסביר ביותר מבין כל האסימונים באוצר המילים של המודל (נקרא גם פענוח חמדן), בעוד שערך של 3 בפרמטר Top-K אומר שהאסימון הבא נבחר מבין 3 האסימונים הסבירים ביותר (באמצעות רמת אקראיות). ערך ברירת המחדל של top-k הוא 40.
- הפרמטר Top-p משנה את האופן שבו המודל בוחר אסימונים לפלט. האסימונים נבחרים מהסבירים ביותר לסבירים פחות עד שסכום ההסתברויות שלהם שווה לערך של top-p.
- מספר התשובות המקסימלי הוא מספר התשובות המקסימלי של המודל שנוצרות לכל הנחיה.
- רצף עצירה הוא סדרה של תווים (כולל רווחים) שמפסיקה את יצירת התשובה אם המודל נתקל בה.
- ההגדרה 'הצגת התשובות באופן שוטף' קובעת אם התשובות יוצגו כשהן מוכנות או כשהן נוצרות.
- הסף של מסנן הבטיחות קובע את הסבירות שתראו תשובות שעלולות להיות מזיקות.
אחרי שיש לכם הנחיה שנראה שמייצרת חידון סביר בהתאם לדרישות שצוינו למעלה, אפשר לנתח את החידון הזה באמצעות קוד מותאם אישית. אבל לא יהיה נחמד יותר אם ה-LLM ייצור את החידון בפורמט מובנה שנוכל לטעון ישירות לתוכנית שלנו? התוכנית שבה נשתמש בהמשך המעבדה הזו כדי לקרוא לגנרטור מצפה שהחידונים ייוצגו בפורמט JSON, שהוא פורמט פופולרי חוצה-שפות לייצוג נתונים מובְנים.
החידונים במעבדה הזו מוגדרים כמערך של אובייקטים, שכל אובייקט מכיל שאלה, מערך של תשובות אפשריות לשאלה ותשובה נכונה. זוהי קידוד ה-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 הנדרש.
- צריך לציין במילים את הפורמט המדויק שאתם מחפשים (לדוגמה, המשפט המודגש שלמעלה).
- בהנחיה, כדאי לכלול דוגמה לפורמט JSON הרצוי.
אחרי שיוצרים הנחיה שמפיקה חידונים לפי המפרט הרצוי, לוחצים על הלחצן GET CODE בפינה השמאלית העליונה של הדף כדי לראות קוד Python שאפשר להשתמש בו כדי לשלוח את ההנחיה באופן אוטומטי למודל LLM של Vertex AI. אם אתם רוצים להשתמש בשפת תכנות אחרת מלבד Python, תוכלו לעיין בכתובת https://cloud.google.com/vertex-ai/docs/samples?text=generative.
4. בניית שרת אינטרנט פשוט

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

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

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

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

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

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). מנסים להוסיף עוד שני פרמטרים על ידי הוספת המחרוזת '`¶m1=val1¶m2=val2`' לסוף כתובת ה-URL בסרגל הכתובות של הדפדפן, טוענים מחדש את הדף ואמורה להופיע תוצאה כמו זו:

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

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

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

אפשר לנסות לשנות את כתובת ה-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. אתם אמורים לראות דף אינטרנט שדומה לזה:

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

אחרי שבניתם מחולל חידונים משלכם, כדאי לשתף את הכלי המדהים הזה עם שאר העולם. הגיע הזמן לפרוס אותו בענן. אבל אתם רוצים לעשות איתו יותר מאשר רק לשתף אותו. אתם רוצים לוודא שהיא:
- פועל בצורה מהימנה – אתם מקבלים סבילות אוטומטית לתקלות במקרה של קריסת מחשב שבו האפליקציה פועלת
- התאמה אוטומטית של קנה המידה – האפליקציה תעמוד בקצב של רמות תנועה גבוהות, ותצמצם אוטומטית את טביעת הרגל שלה כשהיא לא בשימוש
- מצמצם את העלויות, כי לא מחייבים אתכם על משאבים שאתם לא משתמשים בהם – אתם מחויבים רק על משאבים שנצרכים בזמן התגובה לתנועה
- אפשר לגשת אליו דרך שם דומיין מותאם אישית – יש לכם גישה לפתרון בלחיצה אחת להקצאת שם דומיין מותאם אישית לשירות
- זמן התגובה מצוין – התגובה במצב התחלתי (cold start) סבירה, אבל אפשר לשפר אותה על ידי הגדרת מופע מינימלי
- תומך בהצפנה מקצה לקצה באמצעות אבטחת אינטרנט רגילה של SSL/TLS – כשפורסים שירות, מקבלים הצפנה רגילה של האינטרנט ואת האישורים הנדרשים המתאימים, בחינם ובאופן אוטומטי
אם פורסים את האפליקציה ב-Google Cloud Run, מקבלים את כל היתרונות שצוינו למעלה ועוד. אבן הבניין הבסיסית לשיתוף האפליקציה עם Cloud Run היא קונטיינר.
קונטיינרים מאפשרים לנו ליצור תיבה מודולרית שבה אפשר להריץ אפליקציה עם כל התלות שלה. אפשר להשתמש בקונטיינרים כמעט בכל שרת וירטואלי או פיזי, ולכן הם מאפשרים לנו לפרוס את האפליקציה שלכם בכל מקום שתרצו, החל משרתים מקומיים ועד ל-Cloud, ואפילו להעביר את האפליקציה מספק שירותים אחד לאחר.
כדי לקבל מידע נוסף על קונטיינרים ועל אופן הפעולה שלהם ב-Google Cloud Run, אפשר לעיין ב-codelab Dev to Prod in Three Easy Steps with 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 שרוצים שהיא תשתמש ב-Buildpack כדי ליצור את קובץ אימג' של קונטיינר, על סמך קובצי המקור שהיא מוצאת בספרייה הנוכחית (הסימן dot ב---source . הוא קיצור של הספרייה הנוכחית). מכיוון שהשירות מטפל בקובץ האימג' בקונטיינר באופן מרומז, לא צריך לציין קובץ אימג' בפקודה gcloud הזו.
מחכים כמה רגעים עד שהפריסה תושלם. אם הפקודה מסתיימת ללא שגיאות, היא מציגה את כתובת ה-URL של השירות החדש:gcloud
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 Cloud. האפליקציה שלכם זמינה לציבור, עם הצפנת TLS (HTTPS) והתאמה אוטומטית לעומס לרמות תנועה מדהימות, בלי שתצטרכו לחשוב על זה.
9. חיבור כל החלקים
בשלב האחרון הזה, אנחנו מוכנים להריץ את מחולל החידונים כחלק מאפליקציית quizaic. נכנסים לכתובת ה-URL של quizaic, מתחברים לחשבון Google ועוברים לכרטיסייה Create Quiz. בוחרים את סוג הגנרטור Custom, מדביקים את כתובת ה-URL של Cloud Run בשדה כתובת ה-URL, ממלאים את שאר שדות החובה ושולחים את הטופס.

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

10. ניקוי

ב-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. כל הכבוד!

כל הכבוד – יצרתם בהצלחה הנחיה ל-LLM ופרסתם מיקרו-שירות ב-Cloud Run באמצעות ההנחיה הזו. עכשיו אפשר לתכנת בשפה טבעית ולשתף את היצירות עם העולם!
אני רוצה להשאיר אותך עם שאלה חשובה אחת:
אחרי שהאפליקציה התחילה לפעול בסביבת הפיתוח, כמה שורות קוד היית צריך לשנות כדי לפרוס אותה בענן, עם כל המאפיינים ברמת הייצור שמוצעים על ידי Cloud Run?
התשובה היא אפס. :)
עוד codelabs שכדאי לעיין בהם…
- מעבר מפיתוח לייצור בשלושה שלבים פשוטים באמצעות Cloud Run
- אפליקציית סיכום טקסט באמצעות Vertex AI ו-Svelte Kit
- אפליקציית צ'אט עם PaLM API ב-Cloud Run
- פונקציית Cloud Functions שעוטפת את מודלי הטקסט של PaLM Bison
- נתונים ל-AI גנרטיבי באמצעות Spanner ו-Vertex AI Imagen API
מסמכי עזר...
12. קריאה לפעולה
אם נהניתם מה-codelab הזה ואתם מתכננים להשקיע עוד זמן בהתנסות מעשית עם Google Cloud, כדאי לכם להצטרף ל-Google Cloud Innovators עוד היום!

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