1. מבוא

ב-codelab הזה נראה איך Gemini Code Assist יכול לעזור לכם בשלבים מרכזיים במחזור החיים של פיתוח תוכנה (SDLC), כמו תכנון, בנייה, בדיקה ופריסה. אנחנו נעצב ונפתח אפליקציה שלמה ונפרוס אותה ב-Google Cloud.
אנחנו ניצור API ואפליקציה לחיפוש בסשנים באירוע טכני. לכל סשן יהיו כותרת, סיכום, משך, קטגוריות ודובר אחד או יותר.
מה תעשו
- תכנון, בנייה, בדיקה ופריסה של אפליקציית אינטרנט על סמך מפרט OpenAPI מאפס
מה תלמדו
- איך משתמשים ב-Gemini Code Assist כדי ליצור מפרט OpenAPI
- איך משתמשים בתכונות של Gemini Code Assist ליצירת קוד כדי לפתח אפליקציית Python Flask למפרט OpenAPI
- איך משתמשים ב-Gemini Code Assist כדי ליצור קצה קדמי לאפליקציית Python Flask
- איך משתמשים ב-Gemini Code Assist כדי לקבל עזרה בהטמעה של האפליקציה ב-Google Cloud Run
- שימוש בתכונות של Gemini Code Assist כמו הסבר על קוד ויצירת תרחישי בדיקה, במהלך הפיתוח והבדיקה של האפליקציה
מה תצטרכו
- דפדפן האינטרנט Chrome
- חשבון Gmail
- פרויקט ב-Cloud עם חיוב מופעל
- Gemini Code Assist מופעל בפרויקט שלכם ב-Cloud
שיעור ה-Lab הזה מיועד למפתחים בכל הרמות, כולל מתחילים. אף על פי שאפליקציית הדוגמה כתובה בשפת Python, לא צריך להכיר את התכנות ב-Python כדי להבין מה קורה. ההתמקדות שלנו תהיה בהכרת היכולות של Gemini Code Assist.
2. הגדרה של Gemini Code Assist
בקטע הזה מפורט כל מה שצריך לעשות כדי להתחיל את שיעור ה-Lab.
הפעלת Gemini Code Assist ב-Cloud Shell IDE
נשתמש ב-Cloud Shell IDE, סביבת פיתוח מנוהלת מלאה שמבוססת על Code OSS, בשאר שלבי ה-codelab. צריך להפעיל ולהגדיר את Code Assist בסביבת הפיתוח המשולבת (IDE) של Cloud Shell. השלבים מפורטים בהמשך:
- נכנסים לכתובת ide.cloud.google.com. יכול להיות שיעבור זמן עד שה-IDE יופיע, אז צריך להתאזר בסבלנות ולאשר את ברירות המחדל של ההגדרה. אם מופיעות הוראות להגדרת סביבת הפיתוח המשולבת, צריך לפעול לפיהן ולהשלים את ההגדרה עם הגדרות ברירת המחדל.
- לוחצים על הלחצן Cloud Code - Sign in (קוד בענן – כניסה) בשורת הסטטוס התחתונה, כמו שמוצג. נותנים הרשאה לפלאגין לפי ההוראות. אם בשורת המצב מופיע הכיתוב Cloud Code - no project, בוחרים באפשרות הזו ואז בוחרים את הפרויקט הספציפי ב-Google Cloud שרוצים לעבוד איתו.

- לוחצים על הלחצן Code Assist בפינה השמאלית התחתונה כמו שמוצג, ובוחרים בפעם האחרונה את הפרויקט הנכון ב-Google Cloud. אם תתבקשו להפעיל את Cloud AI Companion API, תצטרכו לעשות זאת כדי להמשיך.
- אחרי שבוחרים את פרויקט Google Cloud, מוודאים שהוא מופיע בהודעת הסטטוס של Cloud Code בסרגל הסטטוס, וגם ש-Code Assist מופעל בצד ימין בסרגל הסטטוס, כמו שמוצג כאן:

Gemini Code Assist מוכן לשימוש!
3. הגדרת Firestore
Cloud Firestore הוא מסד נתונים מנוהל למסמכים, שניתן להתאמה ללא שרת (serverless), שישמש כקצה עורפי לנתוני האפליקציה. הנתונים ב-Cloud Firestore מובנים באוספים של מסמכים.
אנחנו צריכים ליצור אוסף בשם sessions במסד הנתונים של Firestore שמוגדר כברירת מחדל. האוסף הזה יכיל נתונים לדוגמה (מסמכים) שנשתמש בהם אחר כך באפליקציה שלנו.
פותחים את הטרמינל מתוך סביבת הפיתוח המשולבת (IDE) של Cloud Shell דרך התפריט הראשי, כמו שמוצג בהמשך:

אנחנו צריכים ליצור אוסף בשם sessions. כאן תופיע רשימה של מסמכים לדוגמה של סשנים. לכל מסמך יהיו המאפיינים הבאים:
- title: מחרוזת
- categories: מערך של מחרוזות
- speakers: מערך של מחרוזות
- duration: מחרוזת
- סיכום: מחרוזת
כדי לאכלס את האוסף הזה בנתוני דוגמה, מעתיקים קובץ שמכיל את נתוני הדוגמה לדלי בפרויקט שלכם, ומשם אפשר לייבא את האוסף באמצעות הפקודה gcloud firestore import.
הפעלה של מסד נתונים ב-Firestore
נכנסים לדף Firestore במסוף Cloud.
אם לא הפעלתם מסד נתונים של Firestore בפרויקט, אתם צריכים ליצור את מסד הנתונים default. במהלך יצירת מסד הנתונים, משתמשים בערכים הבאים:
- מצב Firestore:
Native - מיקום: בוחרים את סוג המיקום
Regionובוחרים את האזור שמתאים לבקשה. חשוב לרשום את המיקום הזה, כי תצטרכו אותו בשלב הבא כדי להגדיר את מיקום הדלי. - יוצרים את מסד הנתונים.

עכשיו ניצור את אוסף sessions לפי השלבים הבאים:
- יוצרים קטגוריה בפרויקט באמצעות הפקודה
gsutilשמופיעה בהמשך. מחליפים את המשתנה<PROJECT_ID>בפקודה שלמטה במזהה הפרויקט ב-Google Cloud. מחליפים את<BUCKET_LOCATION>בשם אזור שמתאים לאזור הגיאוגרפי של מסד הנתונים של Firestore שמוגדר כברירת מחדל (כפי שצוין בשלב הקודם). האפשרויות הן US-WEST1, EUROPE-WEST1, ASIA-EAST1 :
gsutil mb -l <BUCKET-LOCATION> gs://<PROJECT_ID>-my-bucket
- אחרי שיוצרים את הדלי, צריך להעתיק אליו את קובץ הייצוא של מסד הנתונים שהכנו, כדי שנוכל לייבא אותו למסד הנתונים של Firebase. משתמשים בפקודה שמופיעה בהמשך:
gsutil cp -r gs://sessions-master-database-bucket/2024-03-26T09:28:15_95256 gs://<PROJECT_ID>-my-bucket
עכשיו שיש לנו את הנתונים לייבוא, אפשר לעבור לשלב האחרון של ייבוא הנתונים למסד הנתונים של Firebase (default) שיצרנו.
- משתמשים בפקודה הבאה של gcloud:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2024-03-26T09:28:15_95256
הייבוא יימשך כמה שניות. כשהוא יסתיים, תוכלו לאמת את מסד הנתונים של Firestore ואת האוסף. לשם כך, עוברים אל https://console.cloud.google.com/firestore/databases, בוחרים במסד הנתונים default ובאוסף sessions כמו שמוצג בהמשך:

כך מסיימים ליצור את האוסף של Firestore שבו נשתמש באפליקציה שלנו.
4. יצירת תבנית האפליקציה
ניצור אפליקציה לדוגמה (אפליקציית Python Flask) שבה נשתמש בהמשך ה-codelab. האפליקציה הזו תחפש בין הסשנים שמוצעים בכנס טכני.
כך עושים את זה:
- לוחצים על שם הפרויקט ב-Google Cloud בסרגל הסטטוס שבתחתית המסך.

- תוצג רשימה של אפשרויות. לוחצים על New Application (אפליקציה חדשה) מהרשימה שלמטה.

- בוחרים באפשרות Cloud Run application (זו תהיה סביבת זמן הריצה של האפליקציה).
- בוחרים את תבנית האפליקציה Python (Flask): Cloud Run.
- נותנים לאפליקציה שם ושומרים אותה במיקום הרצוי.
- תוצג הודעה שמאשרת שהבקשה נוצרה, וייפתח חלון חדש עם הבקשה שנטענה, כמו שמוצג בהמשך. קובץ
README.mdייפתח. אפשר לסגור את התצוגה הזו עכשיו.

5. איך משתמשים ב-Gemini Code Assist
לצורך שיעור ה-Lab הזה, נשתמש ב-Gemini Code Assist Chat שזמין ב-Cloud Shell IDE כחלק מהתוסף Cloud Code ב-VS Code. כדי להציג אותו, לוחצים על הלחצן Code Assist (עזרה בכתיבת קוד) בסרגל הניווט הימני. חפשו את סמל העזרה בכתיבת קוד
בסרגל הניווט הימני ולוחצים עליו.
תיפתח חלונית הצ'אט של Code Assist בסביבת הפיתוח המשולבת (IDE) של Cloud Shell, ותוכלו להתכתב עם Code Assist.

שימו לב לסמל פח האשפה בחלק העליון – כך מאפסים את ההקשר של היסטוריית הצ'אט של Code Assist. חשוב גם לציין שההתכתבות בצ'אט הזו היא בהקשר של הקבצים שאתם עובדים עליהם בסביבת הפיתוח המשולבת.
6. עיצוב API
השלב הראשון יהיה להיעזר ב-Gemini Code Assist בשלב העיצוב. בשלב הזה ניצור מפרט OpenAPI לישויות (סשנים טכניים באירוע) שאנחנו רוצים לחפש בהן.
מזינים את ההנחיה הבאה:
Generate an Open API spec that will allow me to retrieve all sessions, sessions by category, session by id. Each session has the following attributes: id, title, list of speakers, list of categories, summary and duration.
הפעולה הזו אמורה ליצור מפרט OpenAPI לחיפוש בין סשנים באמצעות פרמטרים שונים של שאילתה. דוגמה למפרט:
openapi: 3.0.0
info:
title: Sessions API
description: This API allows you to retrieve all sessions, sessions by category, and session by id.
version: 1.0.0
servers:
- url: https://sessions.example.com
paths:
/sessions:
get:
summary: Get all sessions
operationId: getSessions
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Session'
/sessions/{id}:
get:
summary: Get session by id
operationId: getSessionById
parameters:
- name: id
in: path
required: true
description: The id of the session
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Session'
/sessions/categories/{category}:
get:
summary: Get sessions by category
operationId: getSessionsByCategory
parameters:
- name: category
in: path
required: true
description: The category of the sessions
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Session'
components:
schemas:
Session:
type: object
properties:
id:
type: string
description: The id of the session
title:
type: string
description: The title of the session
speakers:
type: array
items:
type: string
description: The list of speakers for the session
categories:
type: array
items:
type: string
description: The list of categories for the session
summary:
type: string
description: The summary of the session
duration:
type: string
description: The duration of the session
אפשר לראות שבמפרט מופיעים הרכיבים הבאים:
- סכימה שמוגדרת עבור סוג הסשן.
- הוגדרו כמה נתיבי API:
/sessions/sessions/{id}/sessions/categories/{category}
יוצרים קובץ בשם sessionsapi.yaml בתיקייה העליונה ומעתיקים את התוכן מחלון הצ'אט של Code Assist באמצעות האפשרות 'הוספה לקובץ הנוכחי' (הלחצן +). משאירים את הקובץ פתוח בסביבת הפיתוח המשולבת של Cloud Shell.
בשלב הזה, כדאי לשים לב לתכונה מעניינת של Gemini Code Assist: ציטוט. המידע הזה מוצג למפתח כשהקוד שנוצר מצטט ישירות ובאופן נרחב ממקור אחר, כמו קוד קיים ממקור פתוח. היא מציעה למפתח את המקור ואת הרישיון, והוא מחליט מה לעשות איתם.
אם אנחנו מרוצים מהתוכן שנוצר, אנחנו יכולים להשתמש במסמך המפרט הזה כדי ליצור אפליקציית Python Flask.
7. יצירת האפליקציה
עכשיו נבקש מ-Code Assist ליצור את האפליקציה. נותנים את ההנחיה הבאה כשהקובץ sessionsapi.yaml פתוח.
Generate a Python Application using the Flask framework, based on the sessionsapi.yaml file. This application uses a local in memory list of sessions. Do not use any Flask extensions.
הפעולה הזו אמורה לספק לכם שלד לאפליקציית Python Flask שמבוססת על הפונקציונליות והנתיבים שצוינו בקובץ מפרט OpenAPI.
קוד האפליקציה Python Flask שמופיע צריך להיות דומה לקוד הבא:
from flask import Flask, jsonify, request
app = Flask(__name__)
sessions = [
{
"id": "1",
"title": "Session 1",
"speakers": ["Speaker 1", "Speaker 2"],
"categories": ["Category 1", "Category 2"],
"summary": "This is a summary of session 1.",
"duration": "1 hour",
},
{
"id": "2",
"title": "Session 2",
"speakers": ["Speaker 3", "Speaker 4"],
"categories": ["Category 3", "Category 4"],
"summary": "This is a summary of session 2.",
"duration": "1 hour 30 minutes",
},
]
@app.route('/sessions', methods=['GET'])
def get_sessions():
return jsonify(sessions)
@app.route('/sessions/<id>', methods=['GET'])
def get_session_by_id(id):
session = next((session for session in sessions if session['id'] == id), None)
if session is None:
return jsonify({}), 404
return jsonify(session)
@app.route('/sessions/categories/<category>', methods=['GET'])
def get_sessions_by_category(category):
sessions_by_category = [session for session in sessions if category in session['categories']]
return jsonify(sessions_by_category)
if __name__ == '__main__':
app.run()
קיים קובץ app.py שנוצר כחלק מהשלב הקודם. פשוט מחליפים את התוכן שלו בקוד שנוצר על ידי Code Assist ושומרים את הקובץ.
אנחנו רוצים לשנות את השורה app.run() כך שתשתמש ביציאה 8080, בכתובת המארח 0.0.0.0, וגם תפעל במצב ניפוי באגים במהלך הביצוע המקומי.הנה דרך לעשות זאת. קודם כל, נדגיש או נבחר את השורה:
app.run()
בממשק הצ'אט של Code Assist, מקלידים את ההנחיה: Explain this.
יוצג הסבר מפורט על השורה הספציפית הזו, כמו בדוגמה הבאה:

עכשיו, משתמשים בהנחיה הבאה:
update the code to run the application on port 8080, host address 0.0.0.0, and in debug mode
הקוד המוצע שנוצר צריך להיות: :
app.run(host='0.0.0.0', port=8080, debug=True)
חשוב לזכור לעדכן את הקובץ app.py באמצעות קטע הקוד הזה.
הרצת האפליקציה באופן מקומי
עכשיו נריץ את האפליקציה באופן מקומי כדי לאמת את דרישות האפליקציה בהתאם למה שהתחלנו איתו.
השלב הראשון הוא ליצור סביבה וירטואלית של Python עם רכיבי Python תלויים בחבילה ב-requirements.txt להתקנה בסביבה הווירטואלית. כדי לעשות את זה, עוברים אל לוח הפקודות (Ctrl+Shift+P) בסביבת הפיתוח המשולבת (IDE) של Cloud Shell ומקלידים יצירת סביבת Python. פועלים לפי השלבים הבאים כדי לבחור סביבה וירטואלית (venv), רכיב תרגום Python 3.x ואת הקובץ requirements.txt.
אחרי שיוצרים את הסביבה, מפעילים חלון טרמינל חדש (Ctrl+Shift+`) ומזינים את הפקודה הבאה:
python app.py
דוגמה להרצה:
(.venv) romin@cloudshell: $ python app.py
* Serving Flask app 'app'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:8080
* Running on http://10.88.0.3:8080
Press CTRL+C to quit
* Restarting with stat
* Debugger is active!
* Debugger PIN: 132-247-368
עכשיו אפשר לראות תצוגה מקדימה של ה-API בכתובות ה-URL הבאות. אנחנו מניחים ששרת הפיתוח שלכם פועל ביציאה 8080. אם לא, צריך לשנות אותו למספר היציאה המתאים.
https://<host-name>:8080/sessionshttps://<host-name>:8080/sessions/{id}https://<host-name>:8080/sessions/categories/{category}
כדי לוודא שתוכלו לאחזר באמצעות כתובות ה-URL האלה את נתוני ה-JSON שמופיעים בקובץ app.py, פועלים לפי השלבים הבאים:
פותחים חלון טרמינל חדש ומנסים להריץ אחת מהפקודות הבאות:
curl -X GET http://127.0.0.1:8080/sessions
curl -X GET http://127.0.0.1:8080/sessions/<ID>
curl -X GET http://127.0.0.1:8080/sessions/categories/<CATEGORY_NAME>
8. ארגון הקוד מחדש (Refactoring)
במקום ש-app.py יכיל את נתוני ה-JSON לדוגמה שמוגדרים בקוד, כדאי להפריד או לחלץ אותם למודול אחר, כדי לשמור על הפרדה ברורה בין הקוד לבין הנתונים. קדימה!
משאירים את הקובץ app.py פתוח ומזינים את ההנחיה הבאה:
Can I improve this code and separate out the sessions data from this app.py file?
אמורות להופיע הצעות שיעזרו לכם לעשות את זה. למטה מוצגת דוגמה להצעה שקיבלנו, ואתם אמורים לקבל הצעה דומה:

נפעל לפי ההצעה ונפריד את הנתונים לקובץ sessions.py כמו שמוצע ב-Code Assist.
יוצרים קובץ חדש בשם sessions.py
, שהתוכן שלו הוא רשימת ה-JSON, כמו שמופיע בהמשך לפי הנתונים שנוצרו:
sessions = [
{
"id": "1",
"title": "Session 1",
"speakers": ["Speaker 1", "Speaker 2"],
"categories": ["Category 1", "Category 2"],
"summary": "This is a summary of session 1.",
"duration": "1 hour",
},
{
"id": "2",
"title": "Session 2",
"speakers": ["Speaker 3", "Speaker 4"],
"categories": ["Category 3", "Category 4"],
"summary": "This is a summary of session 2.",
"duration": "1 hour 30 minutes",
},
]
קובץ app.py עכשיו פשוט הרבה יותר, והוא מוצג בהמשך:
from flask import Flask, jsonify, request
from sessions import sessions
app = Flask(__name__)
@app.route('/sessions', methods=['GET'])
def get_sessions():
return jsonify(sessions.sessions)
@app.route('/sessions/<id>', methods=['GET'])
def get_session_by_id(id):
session = next((session for session in sessions.sessions if session['id'] == id), None)
if session is None:
return jsonify({}), 404
return jsonify(session)
@app.route('/sessions/categories/<category>', methods=['GET'])
def get_sessions_by_category(category):
sessions_by_category = [session for session in sessions.sessions if category in session['categories']]
return jsonify(sessions_by_category)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080, debug=True)
חשוב לוודא שעדיין אפשר להפעיל את האפליקציה באופן מקומי ולהשתמש ב-API עם השינויים שבוצעו. סביר להניח ששרת הפיתוח של Python עדיין פועל, לכן צריך רק להריץ שוב את הפקודות curl מהשלב הקודם.
9. שילוב עם אוסף Firestore
השלב הבא הוא להפסיק להשתמש ברשימת ה-JSON המקומית שנשמרת בזיכרון של הסשנים שלנו, ולחבר את האפליקציה לאוסף הסשנים במסד הנתונים של Firestore שיצרנו בתחילת ה-codelab.
משאירים את הקובץ sessions.py פתוח ומזינים את ההנחיה הבאה:
Can you further refactor the sessions.py code to read from a Firestore database that has a collection named sessions. The collection has the same attributes as the session object that we have defined. Use the Python module google-cloud-firestore.
קיבלנו את ההצעה הבאה לקרוא את כל הסשנים מהאוסף של Firestore:
import google.cloud.firestore
# Create a Firestore client
db = google.cloud.firestore.Client()
# Get the sessions collection
sessions_collection = db.collection("sessions")
# Create a list of sessions
sessions = []
# Iterate over the documents and add them to the list
for doc in sessions_collection.stream():
session = doc.to_dict()
session["id"] = doc.id
sessions.append(session)
אפשר להוסיף את הקוד ל-sessions.py.
אם שרת הפיתוח של Flask פועל באופן מקומי, יכול להיות שהאפליקציה נסגרה עם הודעה על כך שלא נמצא מודול Python.
לדוגמה, אפשר לשאול את Code Assist איזה מודול Python צריך להוסיף לקובץ requirements.txt, באופן הבא:
Which Python package needs to be installed to make the firestore code work?
הפעולה הזו תספק לכם את השם של מודול Python (לדוגמה, google-cloud-firestore). מוסיפים את השם הזה לקובץ requirements.txt.
תצטרכו ליצור מחדש את סביבת Python עם המודול החדש שנוסף (google-cloud-firestore). כדי לעשות זאת, מריצים את הפקודה הבאה בחלון הקיים של Terminal:
pip install -r requirements.txt
מריצים את האפליקציה שוב (מפעילים אותה מחדש באמצעות python app.py) ועוברים לכתובת ה-URL /sessions. עכשיו אמורים להופיע מסמכי הדוגמה שהוספנו לאוסף sessions.

אתם יכולים לשלוח שאילתות לגבי כתובות URI אחרות כדי לאחזר סשנים ספציפיים או את כל הסשנים בקטגוריה מסוימת, כמו שמתואר בשלבים הקודמים.
10. הסבר על הקוד
עכשיו זה זמן טוב להשתמש בתכונה "Explain this" של Gemini Code Assist כדי להבין את הקוד. אתם יכולים להיכנס לכל אחד מהקבצים או לבחור קטעי קוד ספציפיים ולשאול את Code Assist את ההנחיה הבאה: Explain this.
כדי לתרגל, אפשר להיכנס לקובץ sessions.py, לסמן את הקוד הספציפי ל-Firestore ולקבל הסבר על הקוד. כדאי לנסות להשתמש בתכונה הזו גם בקבצים אחרים בפרויקט, ולא רק בקוד Python.
11. יצירת אפליקציית האינטרנט
אחרי שיצרנו את ה-API ושילבנו אותו עם אוסף Firestore פעיל, ניצור חזיתית מבוססת-אינטרנט לאפליקציה. בשלב הזה, הפונקציונליות של ממשק הקצה האינטרנטי שלנו תהיה מינימלית, כלומר תהיה אפשרות לחפש סשנים ששייכים לקטגוריה מסוימת. חשוב לזכור שיש לנו נתיב API בשביל זה, כלומר /sessions/categories/{category}, ולכן אפליקציית האינטרנט שלנו צריכה להפעיל אותו ולאחזר את התוצאות.
קדימה, מתחילים. נותנים את ההנחיה הבאה ל-Code Assist:
Generate a web application that allows me to search for sessions by category and uses the Flask application that we created. Please use basic HTML, CSS and JS. Embed all the Javascript and CSS code into a single HTML file only.
המערכת תיצור את קוד ה-HTML של אפליקציית האינטרנט עם JavaScript ו-CSS מוטמעים. בנוסף, תתבקשו להוסיף נתיב חדש לקובץ app.py, כדי שכל משתמש שיבקר בכתובת ה-URL הבסיסית או בכתובת ה-URL של שורש האתר יועבר לדף הבית. אם המידע הזה לא מוזכר, כדאי לשאול על כך או להשתמש בקטע הטקסט שמופיע בהמשך:
@app.route('/')
def index():
return render_template('index.html')
אפשר לשמור את הקובץ הזה בשם index.html, אבל יכול להיות שיהיו לכם שאלות לגבי המיקום שבו צריך לשמור את הקובץ (למשל, באיזו תיקייה). אנחנו יכולים לשאול שאלת המשך את Code Assist.
Given that I am using the flask framework, where should I put the index.html file?
המידע שמוצג צריך להיות ברור ולהסביר שהאפליקציה משתמשת ב-framework render_template, ולכן צריך למקם את הקובץ index.html בתיקייה templates. התיקייה הזו תהיה זמינה כי יצרנו אפליקציה על סמך תבנית Flask בתחילת ה-codelab הזה. כתוצאה מכך, קיים קובץ index.html, ופשוט צריך להחליף את התוכן שלו בתוכן החדש שנוצר כאן. בנוסף, Code Assist מציין שצריך לייבא את render_template בקובץ app.py.
שומרים את קוד אפליקציית האינטרנט בקובץ index.html וזוכרים למקם את הקובץ בתיקייה templates.
הרצת האפליקציה באופן מקומי
עכשיו נריץ את האפליקציה באופן מקומי כדי לאמת את דרישות האפליקציה בהתאם למה שהתחלנו איתו.
מוודאים ששרת Flask המקומי עדיין פועל ולא מוצגות בו שגיאות. במקרה של שגיאות, צריך לטפל בהן ולהפעיל את השרת.
אחרי שהאפליקציה תפעל, נכנסים לכתובת ה-URL של דף הבית שלה. הוא אמור להציג את הקובץ index.html שמוצג כמו שמופיע בהמשך:

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

תרגיל אופציונלי: הצגת מטא-נתונים נוספים כמו משך, קטגוריות, דוברים וסיכום לכל אחד מהסשנים.
12. יצירת מקרי בדיקה
יצרנו את ה-API של הסשנים, ועכשיו הגיע הזמן להשתמש ב-Gemini Code Assist כדי ליצור תרחישי בדיקה ליחידות שונות של נתיבי API.
משאירים את הקובץ app.py פתוח ומזינים את ההנחיה הבאה:
Generate unit test cases for app routes. Use unittest module.
קיבלנו את התשובה הבאה:
import unittest
from app import app
class FlaskAppTestCase(unittest.TestCase):
def test_index(self):
tester = app.test_client()
response = tester.get('/')
self.assertEqual(response.status_code, 200)
def test_get_sessions(self):
tester = app.test_client()
response = tester.get('/sessions')
self.assertEqual(response.status_code, 200)
def test_get_session_by_id(self):
tester = app.test_client()
response = tester.get('/sessions/1')
self.assertEqual(response.status_code, 200)
def test_get_sessions_by_category(self):
tester = app.test_client()
response = tester.get('/sessions/categories/category1')
self.assertEqual(response.status_code, 200)
if __name__ == '__main__':
unittest.main()
יוצרים קובץ בשם tests.py עם הקוד שלמעלה.
הערה לגבי יצירת תרחישי בדיקה
יכול להיות שתראו רשימת קודים שונה מזו שמופיעה למעלה, וזה עלול לגרום לבעיות בהרצת תרחישי הבדיקה. לדוגמה, ראינו שבחלק מההרצות שלנו, חסרו חלקי הקוד העיקריים הבאים:
from app import app
הקוד שלמעלה נדרש כדי לייבא את אפליקציית Flask הקיימת, שנגדה נפעיל את מקרי הבדיקה.
if __name__ == '__main__':
`unittest.main()`
הקוד שלמעלה נדרש להרצת תרחישי הבדיקה.
מומלץ לבדוק כל אחד ממקרי הבדיקה, את assertEqual ותנאים אחרים בקוד שנוצר כדי לוודא שהוא יפעל. הנתונים נמצאים מחוץ לאוסף Firestore, ולכן יכול להיות שלא תהיה לו גישה אליהם והוא ישתמש בנתוני דמה. כתוצאה מכך, יכול להיות שהבדיקות ייכשלו. לכן, צריך לשנות את תרחישי הבדיקה בהתאם או להוסיף הערות לחלק מתרחישי הבדיקה שאולי לא תצטרכו באופן מיידי.
כדי להדגים את התהליך, הפעלנו את מקרי הבדיקה באמצעות הפקודה הבאה (חשוב להפעיל את שרת הפיתוח המקומי כי הקריאות יבוצעו לנקודות הקצה המקומיות של ה-API):
python tests.py
קיבלנו את סיכום התוצאות הבא:
Ran 4 tests in 0.274s
FAILED (failures=2)
זה אכן נכון, כי מזהה הסשן לא היה נכון בבדיקה השלישית ואין קטגוריה בשם category1
.
לכן, כדאי להתאים את המקרים לבדיקה ולבדוק אותם.
13. Test Driven Development
עכשיו נראה איך מוסיפים שיטת חיפוש חדשה ב-API של הסשנים שלנו באמצעות המתודולוגיה של פיתוח מונחה-בדיקות (TDD). המתודולוגיה הזו מתבססת על כתיבת תרחישי בדיקה קודם, גורמת להם להיכשל בגלל חוסר הטמעה ומשתמשת ב-Gemini Code Assist כדי ליצור את ההטמעה החסרה כך שהבדיקה תעבור.
עוברים לקובץ tests.py (בהנחה שתיקנתם את הקובץ tests.py כך שיכלול את כל הבדיקות שעוברות). מזינים את ההנחיה הבאה ל-Code Assist:
Generate a new test case to search for sessions by speaker
כך קיבלנו את ההטמעה הבאה של תרחיש הבדיקה, שהוספנו לקובץ tests.py.
def test_get_sessions_by_speaker(self):
tester = app.test_client()
response = tester.get('/sessions/speakers/speaker1')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json, [sessions.sessions[0], sessions.sessions[1]])
אם מריצים את הבדיקות, אמורה להופיע השגיאה הבאה:
$ python tests.py
.F.
======================================================================
FAIL: test_get_sessions_by_speaker (__main__.FlaskAppTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/romin/hello-world-5/tests.py", line 21, in test_get_sessions_by_speaker
self.assertEqual(response.status_code, 200)
AssertionError: 404 != 200
----------------------------------------------------------------------
Ran 3 tests in 0.010s
FAILED (failures=1)
הסיבה לכך היא שתסריט הבדיקה הפעיל את הנתיב הבא (/sessions/speakers/) ואין הטמעה של הנתיב הזה ב-app.py.
נבקש מ-Code Assist לספק לנו הטמעה. עוברים לקובץ app.py ומזינים את ההנחיה הבאה ל-Code Assist:
Add a new route to search for sessions by a specific speaker
קיבלנו את ההטמעה הבאה שהוצעה על ידי Code Assist, והוספנו אותה לקובץ app.py:
@app.route('/sessions/speakers/<speaker>', methods=['GET'])
def get_sessions_by_speaker(speaker):
sessions_by_speaker = [session for session in sessions.sessions if speaker in session['speakers']]
return jsonify(sessions_by_speaker)
בדקנו שוב את הקובץ tests.py ושינינו את תרחיש הבדיקה שלנו באופן הבא כדי לבצע בדיקה מהירה:
def test_get_sessions_by_speaker(self):
tester = app.test_client()
response = tester.get('/sessions/speakers/Romin Irani')
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json), 1)
הבדיקה פעלה בצורה תקינה. מומלץ לעיין בתרחישי הבדיקה שנוצרו, לבצע בהם שינויים קלים בהתאם לנתונים שיש לכם ב-Firestore ולהשתמש בשיטות המתאימות של assert* בתרחישי הבדיקה של יחידות Python.
14. פריסה ב-Google Cloud Run
עכשיו, אחרי שסיימנו לפתח את האפליקציה, השלב האחרון הוא לפרוס אותה ב-Google Cloud Run. אבל אולי, כדי להיות בטוחים, כדאי לשאול את Code Assist אם שכחנו משהו. פותחים את app.py ושולחים את ההנחיה הבאה :
Is there something here I should change before I deploy to production?
טוב ששאלת, כי שכחנו להגדיר את דגל הניפוי באגים למצב 'מושבת':

כמו שצוין, משביתים את הניפוי באגים וממשיכים לבקש מ-Gemini Code Assist עזרה בפקודה gcloud שאפשר להשתמש בה כדי לפרוס את האפליקציה ב-Cloud Run ישירות ממקור (בלי לבנות קודם קונטיינר).
מזינים את ההנחיה הבאה:
I would like to deploy the application to Cloud Run directly from source. What is the gcloud command to do that?
נסו כמה וריאציות של ההנחיה שלמעלה. ניסינו גם את הפקודה:
I would like to deploy this application to Cloud Run. I don't want to build a container image locally but deploy directly from source to Cloud Run. What is the gcloud command for that?
במצב אידאלי, הפקודה gcloud הבאה אמורה להתקבל:
gcloud run deploy sessions --source .
יכול להיות שתקבלו גם:
gcloud run deploy <service-name> --source . \
—-platform managed \
—-allow-unauthenticated
מריצים את הפקודה שלמעלה מתיקיית הבסיס של האפליקציה. כשמתבקשים לבחור region, בוחרים באפשרות us-central1, וכשמתבקשים לאשר את unauthenticated invocations, בוחרים באפשרות Y. יכול להיות שתתבקשו גם להפעיל ממשקי Google Cloud API כמו Artifact Registry, Cloud Build ו-Cloud Run, ולקבל הרשאה ליצור מאגר Artifact Registry. אם תתבקשו, תנו את ההרשאה.
תהליך הפריסה יימשך כ-2 דקות, אז כדאי לחכות בסבלנות.
אחרי הפריסה המוצלחת, תוכלו לראות את כתובת ה-URL של שירות Cloud Run. אם תיכנסו לכתובת ה-URL הציבורית הזו, תוכלו לראות את אפליקציית האינטרנט שפרסתם, והיא תפעל בצורה תקינה.

כל הכבוד!
15. (אופציונלי) שימוש ב-Cloud Logging
אנחנו יכולים להוסיף רישום ביומן לאפליקציה שלנו, כך שיומני האפליקציה ירוכזו באחד משירותי Google Cloud (Cloud Logging). לאחר מכן, אפשר להשתמש בתכונת Gemini Observability כדי להבין גם את רשומות היומן.
כדי לעשות זאת, נצטרך קודם להשתמש בספריית Python Cloud Logging קיימת מ-Google Cloud, ולהשתמש בה כדי לרשום ביומן הודעות מידע, אזהרה או שגיאה (בהתאם ליומן או לרמת החומרה).
בואו ננסה לשאול את Code Assist את השאלה הזו קודם. נסו את ההנחיה הבאה:
How do I use the google-cloud-logging package in Python?
אמורה להתקבל תגובה עם מידע על הנושא, כמו בדוגמה הבאה:

נוסיף הצהרות רישום ביומן לפונקציה שמחפשת סשנים לפי קטגוריה.
קודם כול, מוסיפים את חבילת Python google-cloud-logging לקובץ requirements.txt.
בהמשך מופיע קטע קוד שמראה איך שילבנו את הקוד כדי להטמיע רישום ביומן:
...
from google.cloud import logging
...
app = Flask(__name__)
# Create a logger
logger = logging.Client().logger('my-log')
@app.route('/sessions/categories/<category>', methods=['GET'])
def get_sessions_by_category(category):
logger.log_text(f"Fetching sessions with category {category}")
sessions_by_category = [session for session in sessions.sessions if category in session['categories']]
logger.log_text(f'Found {len(sessions_by_category)} sessions with category {category}')
return jsonify(sessions_by_category)
# # Other App Routes
פורסים את השירות ב-Cloud Run שוב באמצעות אותה פקודה כמו בקטע הקודם, ואחרי הפריסה מריצים כמה קריאות לנקודת הקצה /sessions/categories/<category>.
עוברים אל Cloud Console → Logs Explorer

...ואז תוכלו לסנן את ההצהרות האלה ביומן כמו שמוצג בהמשך:

אפשר ללחוץ על כל אחת מההצהרות ביומן, להרחיב אותה ואז ללחוץ על Explain this log entry כדי להשתמש ב-Gemini להסבר של הרשומה ביומן. שימו לב: אם לא הפעלתם את Gemini for Google Cloud, תתבקשו להפעיל את Cloud AI Companion API. אפשר להמשיך ולבצע את הפעולות הנדרשות.
דוגמה לתשובה:

16. מזל טוב
כל הכבוד, יצרתם בהצלחה אפליקציה מאפס והשתמשתם ב-Gemini Code Assist בהיבטים שונים של מחזור החיים של פיתוח תוכנה (SDLC), כולל עיצוב, בנייה, בדיקה ופריסה.
מה השלב הבא?
כדאי לעיין ב-Codelabs הבאים…
- סיור ב-Duet AI למפתחים
- שימוש ב-Duet AI לאורך מחזור החיים של פיתוח תוכנה
- איך משתמשים ב-Duet AI for Developers כדי ליצור סגנונות