1. מטרות
מטרת הסדנה הזאת היא לספק הדרכה מעשית בנושא Duet AI למשתמשים ולמומחים.
ב-Codelab הזה תלמדו:
- צריך להפעיל את Duet AI בפרויקט ב-GCP ולהגדיר אותו לשימוש בסביבת פיתוח משולבת (IDE) ובמסוף Cloud.
- שימוש ב-Duet AI ליצירת קוד, להשלמה ולהסבר.
- אפשר להשתמש ב-Duet AI כדי להסביר בעיה באפליקציה ולפתור אותה.
- תכונות של Duet AI כמו צ'אט בסביבת פיתוח משולבת (IDE) וצ'אט מרובה פניות, צ'אט לעומת יצירת קוד בגוף ההודעה, פעולות חכמות כמו הסבר על הקוד, הכרת הקוד ועוד.
הסיפור
כדי להראות איך השימוש ב-Duet AI למפתחים בפיתוח היומיומי שלו, הפעילויות בסדנה מתקיימות בהקשר של סיפור.
מפתח חדש מצטרף לחברת מסחר אלקטרוני. המשימה שלהם היא להוסיף שירות חדש לאפליקציה הקיימת של המסחר האלקטרוני (שמורכבת מכמה שירותים). השירות החדש מספק מידע נוסף (מידות, משקל וכו') על המוצרים בקטלוג המוצרים. השירות הזה מאפשר עלויות משלוח טובות או זולות יותר על סמך המידות והמשקל של המוצר.
המפתח הוא חדש בחברה, לכן הוא ישתמש ב-Duet AI ליצירת קוד, להסבר ולתיעוד.
לאחר הקידוד של השירות, אדמין של הפלטפורמה ישתמש ב-Duet AI (צ'אט) כדי ליצור את הארטיפקט (קונטיינר Docker) ובמשאבים הדרושים לפריסת הארטיפקט ב-GCP (לדוגמה Artifact Registry, הרשאות IAM, מאגר קוד, תשתית מחשוב, כלומר GKE או CloudRun וכו').
לאחר פריסת האפליקציה ב-GCP, מפעילי אפליקציות/SRE ישתמשו ב-Duet AI (וב-Cloud Ops) כדי לפתור שגיאה בשירות החדש.
פרסונה
הסדנה עוסקת בפרסונה הבאה:
- מפתח אפליקציות – נדרש ידע מסוים בתכנות ובפיתוח תוכנות.
הווריאציה הזו של סדנת Duet AI מיועדת למפתחים בלבד. לא נדרש ידע על משאבי הענן של GCP. הסקריפטים הדרושים לפיתוח משאבי ה-GCP הנדרשים להפעלת האפליקציה הזו זמינים כאן. תוכלו לפעול לפי ההוראות שבמדריך הזה כדי לפרוס את המשאבים הנדרשים של GCP.
2. הכנת הסביבה
הפעלה של Duet AI
אפשר להפעיל את Duet AI בפרויקט GCP באמצעות API (כלים של gcloud או IaC כמו Terraform) או דרך ממשק המשתמש של מסוף Cloud.
כדי להפעיל את Duet AI בפרויקט ב-Google Cloud, מפעילים את Cloud AI Companion API ומקצים למשתמשים את התפקידים 'משתמש נלווה ב-Cloud AI Companion' ו'ניהול זהויות והרשאות גישה (IAM)' של השימוש בשירות.
מ-gcloud
מפעילים את Cloud Shell:
צריך להגדיר את PROJECT_ID
והUSER
ולהפעיל את Cloud AI Companion API.
export PROJECT_ID=<YOUR PROJECT ID> export USER=<YOUR USERNAME> # Use your full LDAP, e.g. name@example.com gcloud config set project ${PROJECT_ID} gcloud services enable cloudaicompanion.googleapis.com --project ${PROJECT_ID}
הפלט אמור להיראות כך:
Updated property [core/project]. Operation "operations/acat.p2-60565640195-f37dc7fe-b093-4451-9b12-934649e2a435" finished successfully.
מקצים לחשבון המשתמש את התפקיד 'משתמש Companion ב-Cloud AI' ואת התפקידים 'ניהול זהויות והרשאות גישה (IAM)' של השימוש בשירות. ה-Cloud Companion API נמצא מאחורי התכונות בסביבת הפיתוח המשולבת (IDE) ובמסוף, שבהן נשתמש. ההרשאה 'צפייה בשימוש בשירות' משמשת כבדיקה מהירה לפני הפעלת ממשק המשתמש במסוף (כך שממשק המשתמש של Duet יופיע רק בפרויקטים שבהם ה-API מופעל).
gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member=user:${USER} --role=roles/cloudaicompanion.user gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member=user:${USER} --role=roles/serviceusage.serviceUsageViewer
הפלט אמור להיראות כך:
... - members: - user:<YOUR USER ACCOUNT> role: roles/cloudaicompanion.user ... - members: - user:<YOUR USER ACCOUNT> role: roles/serviceusage.serviceUsageViewer
ממסוף Cloud
כדי להפעיל את ה-API, נכנסים לדף Cloud AI Companion API במסוף Google Cloud.
בבורר הפרויקטים, בוחרים את הפרויקט.
לוחצים על Enable.
הדף יתעדכן ויציג את הסטטוס מופעל. Duet AI זמין עכשיו בפרויקט Google Cloud שנבחר לכל המשתמשים שיש להם את תפקידי ה-IAM הנדרשים.
בדף IAM אפשר להקצות את תפקידי ה-IAM שנדרשים לשימוש ב-Duet AI.
בעמודה Principal, מחפשים את המשתמש שעבורו רוצים להפעיל את הגישה ל-Duet AI ואז לוחצים על סמל העיפרון ✏️ Edit principal בשורה הזו.
בחלונית הגישה Edit, לוחצים על Add Add another role.
בקטע 'בחירת תפקיד', בוחרים באפשרות Cloud AI Companion User.
לוחצים על Add another role ובוחרים באפשרות Service Usage Viewer.
לוחצים על שמירה.
הגדרת סביבת הפיתוח המשולבת (IDE)
המפתחים יכולים לבחור מתוך מגוון סביבות פיתוח משולבות (IDE) שהכי מתאימות לצרכים שלהם. אפשר לקבל עזרה בכתיבת קוד באמצעות Duet AI בכמה סביבות פיתוח משולבות (IDE), כמו Visual Studio Code, JetBrains IDEs (IntelliJ, PyCharm, GoLand, WebStorm ועוד), Cloud Workstations ו-Cloud Shell Editor.
בשיעור ה-Lab הזה תוכלו להשתמש ב-Cloud Workstations או ב-Cloud Shell Editor.
בסדנה הזאת אנחנו משתמשים ב-Cloud Shell Editor.
הערה: תהליך ההגדרה של Cloud Workstations עשוי להימשך 20-30 דקות.
כדי להתחיל מיד, משתמשים ב-Cloud Shell Editor.
פותחים את Cloud Shell Editor בלחיצה על סמל העיפרון ✏️ בסרגל התפריטים העליון ב-Cloud Shell.
ממשק המשתמש וחוויית המשתמש של Cloud Shell Editor דומים מאוד ל-VSCode.
לוחצים על CTRL (ב-Windows)/CMD (ב-Mac) + , (פסיק) כדי להיכנס לחלונית ההגדרות.
בסרגל החיפוש, מקלידים 'duet AI'.
צריך לוודא או להפעיל את Cloudcode › Duet AI: הפעלה ו-Cloudcode › Duet AI › הצעות מוטבעות: הפעלה אוטומטית
בשורת הסטטוס התחתונה, לוחצים על Cloud Code – כניסה ופועלים לפי תהליך הכניסה לחשבון.
אם כבר נכנסתם לחשבון, בשורת הסטטוס יופיע Cloud Code – אין פרויקט.
לוחצים על Cloud Code – No project (אין פרויקט) וחלונית נפתחת של פעולות תופיע בחלק העליון של המסך. לוחצים על Select a Google Cloud project.
מתחילים להקליד את מזהה הפרויקט, והפרויקט אמור להופיע ברשימה.
בוחרים את PROJECT_ID מרשימת הפרויקטים.
שורת הסטטוס התחתונה תתעדכן ותוכלו לראות את מזהה הפרויקט. אם הוא לא חוזר, יכול להיות שתצטרכו לרענן את הכרטיסייה של Cloud Shell Editor.
לוחצים על הסמל של Duet AI בסרגל התפריטים השמאלי, וחלון הצ'אט של Duet AI מופיע. אם מוצגת ההודעה Select GCP Project. לוחצים על הפרויקט ובוחרים אותו מחדש.
עכשיו מוצג חלון הצ'אט של Duet AI
3. הגדרת התשתית
כדי להפעיל את שירות המשלוחים החדש ב-GCP, צריך להשתמש במקורות המידע הבאים של GCP:
- מכונה של Cloud SQL, עם מסד נתונים.
- אשכול GKE להרצת השירות בקונטיינרים.
- Artifact Registry לאחסון קובץ אימג' של Docker.
- Cloud Source Repository של הקוד.
בטרמינל של Cloud Shell, משכפלים את המאגר הבא ומריצים את הפקודות הבאות כדי להגדיר את התשתית בפרויקט ב-GCP.
# Set your project export PROJECT_ID=<INSERT_YOUR_PROJECT_ID> gcloud config set core/project ${PROJECT_ID} # Enable Cloudbuild and grant Cloudbuild SA owner role export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format 'value(projectNumber)') gcloud services enable cloudbuild.googleapis.com gcloud projects add-iam-policy-binding ${PROJECT_ID} --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com --role roles/owner # Clone the repo git clone https://github.com/duetailabs/dev.git ~/duetaidev cd ~/duetaidev # Run Cloudbuild to create the necessary resources gcloud builds submit --substitutions=_PROJECT_ID=${PROJECT_ID} # To destroy all GCP resources, run the following # gcloud builds submit --substitutions=_PROJECT_ID=${PROJECT_ID} --config=cloudbuild_destroy.yaml
4. פיתוח שירות Fithon Flask
השירות שניצור יכלול בסופו של דבר את הקבצים הבאים. אין צורך ליצור את הקבצים האלה עכשיו. את הקבצים האלה אפשר ליצור בכל פעם בהתאם להוראות הבאות:
package-service.yaml
– מפרט API פתוח לשירות החבילה, שכולל נתונים כמו גובה, רוחב, משקל והוראות לטיפול מיוחד.data_model.py
– מודל הנתונים למפרט ה-API של שירות החבילות. יוצרת גם את הטבלהpackages
ב-product_details DB.connect_connector.py
– חיבור ל-CloudSQL (מגדירים את המנוע, הסשן ו-Base ORM)db_init.py
– יצירת נתונים לדוגמה לטבלהpackages
.main.py
– שירות Python Flask עם נקודת קצה (endpoint)GET
שמאחזר את פרטי החבילה מנתוניpackages
על סמך product_id.test.py
– בדיקת יחידהrequirement.txt
– דרישות PythonDockerfile
– כדי ליצור קונטיינרים של האפליקציה הזו
אם נתקלים בבעיות במיקום קבוע במהלך התרגילים, הקבצים הסופיים מופיעים בנספח ב-Codelab הזה.
בשלב הקודם יצרתם מאגר Cloud Source Repository. משכפלים את המאגר. אתם תיצרו את קובצי האפליקציה בתיקיית המאגר המשוכפל.
בטרמינל של Cloud Shell, מריצים את הפקודה הבאה כדי לשכפל את המאגר.
cd ~ gcloud source repos clone shipping shipping cd ~/shipping
פותחים את סרגל הצד של הצ'אט ב-Duet AI בתפריט השמאלי של Cloud Shell Editor. הסמל נראה כמו . עכשיו יש לך אפשרות להיעזר ב-Duet AI לקבלת עזרה בתכנות.
package-service.yaml
אם אין קבצים פתוחים, צריך לבקש מ-Duet ליצור מפרט Open API לשירות המשלוחים.
הנחיה 1: יצירת מפרט OpenAPI yaml לשירות שמספק פרטי משלוח וחבילה לפי מזהה מוצר מספרי. השירות צריך לכלול מידע על הגובה, הרוחב, העומק, המשקל של האריזה וכן הוראות לטיפול מיוחד.
מופיעות שלוש אפשרויות בפינה השמאלית העליונה של חלון הקוד שנוצר.
אפשר COPY
את הקוד ולהדביק אותו בקובץ.
אפשר ADD
את הקוד לקובץ שפתוח עכשיו ב-Editor.
לחלופין, אפשר OPEN
את הקוד בקובץ חדש.
לוחצים על הסמל OPEN
על הקוד בקובץ חדש.
לוחצים על CTRL/CMD + s
כדי לשמור את הקובץ ומאחסנים אותו בתיקיית האפליקציות עם שם הקובץ package-service.yaml
. לחץ על 'אישור'.
הקובץ הסופי נמצא בקטע 'נספח' ב-Codelab הזה. אם הוא לא מתרחש, צריך לבצע את השינויים הנדרשים באופן ידני.
אפשר גם לנסות כמה הנחיות כדי לראות את התשובות של Duet AI.
כדי לאפס את היסטוריית הצ'אט של Duet AI, לוחצים על סמל האשפה בחלק העליון של סרגל הצד של Duet AI.
data_model.py
בשלב הבא יוצרים את קובץ python של מודל הנתונים עבור השירות, על סמך מפרט OpenAPI.
כשהקובץ package-service.yaml
פתוח, מזינים את ההנחיה הבאה.
הנחיה 1: באמצעות python sqlalchemy ORM, יוצרים מודל נתונים לשירות ה-API הזה. צריך לכלול גם פונקציה נפרדת ונקודת כניסה ראשית שיוצרת את הטבלאות של מסדי הנתונים.
בואו נסתכל על כל חלק שנוצר. Duet AI הוא עדיין העוזר הדיגיטלי, ולמרות שהוא יכול לעזור בכתיבה מהירה של קוד, עדיין כדאי לבדוק את התוכן שנוצר ולהבין אותו תוך כדי כתיבה.
ראשית, יש מחלקה בשם Package
מסוג Base
, שמגדירה את מודל הנתונים למסד הנתונים packages
באופן הבא:
class Package(Base):
__tablename__ = 'packages'
id = Column(Integer, primary_key=True)
product_id = Column(String(255))
height = Column(Float)
width = Column(Float)
depth = Column(Float)
weight = Column(Float)
special_handling_instructions = Column(String(255))
בשלב הבא צריך פונקציה שיוצרת את הטבלה במסד הנתונים, למשל:
def create_tables(engine):
Base.metadata.create_all(engine)
לבסוף, צריך פונקציה ראשית שמריצה את הפונקציה create_tables
כדי ליצור בפועל את הטבלה במסד הנתונים של CloudSQL, למשל:
if __name__ == '__main__':
from sqlalchemy import create_engine
engine = create_engine('sqlite:///shipping.db')
create_tables(engine)
print('Tables created successfully.')
חשוב לשים לב שהפונקציה main
יוצרת מנוע באמצעות מסד נתונים מקומי sqlite
. כדי להשתמש ב-CloudSQL, צריך לשנות אותו. אפשר לעשות את זה קצת מאוחר יותר.
שימוש בקוד OPEN
בתהליך עבודה חדש של קבצים כמו קודם. שומרים את הקוד בקובץ בשם
data_model.py
(שימו לב לקו תחתון בשם ולא במקף).
כדי לאפס את היסטוריית הצ'אט של Duet AI, לוחצים על סמל האשפה בחלק העליון של סרגל הצד של Duet AI.
connect-connector.py
יוצרים את המחבר של CloudSQL.
כשהקובץ data_model.py
פתוח, מזינים את ההנחיות הבאות.
הנחיה ראשונה: באמצעות הספרייה cloud-sql-python-connector, יוצרים פונקציה שמפעילה מאגר חיבור למופע של Cloud SQL של Postgres.
שימו לב שהתשובה לא משתמשת בספרייה cloud-sql-python-connector
. אתם יכולים להוסיף פרטים ספציפיים לאותו שרשור בצ'אט כדי לתת ל-Duet נדנוד אחד ולחדד את ההנחיות.
נשתמש בהנחיה אחרת.
הנחיה 2: חובה להשתמש בספריית cloud-sql-python-connector.
חשוב לוודא שהוא משתמש בספרייה cloud-sql-python-connector
.
שימוש בקוד OPEN
בתהליך עבודה חדש של קבצים כמו קודם. שומרים את הקוד בקובץ בשם
connect_conector.py
. יכול להיות שיהיה עליך לייבא באופן ידני את הספרייה pg8000
. כדאי לעיין בקובץ שבהמשך.
מוחקים את היסטוריית הצ'אט של Duet AI, וכשהקובץ connect_connector.py
פתוח, יוצרים את ה-ORM DB engine
, sessionmaker
ו-base
לשימוש באפליקציה.
הנחיה 1: יצירת מנוע, מחלקה של יוצרי סשן ו-Base ORM באמצעות שיטת connect_with_connector
התגובה עשויה לצרף את engine
, Session
ואת Base
לקובץ connect_connector.py
.
הקובץ הסופי נמצא בקטע 'נספח' ב-Codelab הזה. אם הוא לא מתרחש, צריך לבצע את השינויים הנדרשים באופן ידני.
אפשר גם לנסות הנחיות שונות כדי לראות את הווריאציה הפוטנציאלית בתשובות של Duet AI.
כדי לאפס את היסטוריית הצ'אט של Duet AI, לוחצים על סמל האשפה בחלק העליון של סרגל הצד של Duet AI.
עדכון data_model.py
כדי ליצור טבלה במסד הנתונים של CloudSQL, עליכם להשתמש במנוע שיצרתם בשלב הקודם (בקובץ connect_connector.py
).
מחיקת היסטוריית הצ'אט של Duet AI. פותחים את הקובץ data_model.py
. אפשר לנסות להזין את ההנחיה הבאה.
הנחיה 1: בפונקציה הראשית, מייבאים את המנוע מ-connect_connector.py ומשתמשים בו
אמורה להופיע התשובה שמייבאת את engine
מ-connect_connector
(ל-CloudSQL). ה-create_table
משתמש במנוע הזה (במקום בברירת המחדל של דציבלים מקומיים מסוג sqlite
).
עדכון קובץ data_model.py
.
הקובץ הסופי נמצא בקטע 'נספח' ב-Codelab הזה. אם הוא לא מתרחש, צריך לבצע את השינויים הנדרשים באופן ידני.
אפשר גם לנסות הנחיות שונות כדי לראות את התשובות השונות של Duet AI.
כדי לאפס את היסטוריית הצ'אט של Duet AI, לוחצים על סמל האשפה בחלק העליון של סרגל הצד של Duet AI.
requirements.txt
יוצרים קובץ requirements.txt
לאפליקציה.
פותחים גם את connect_connector.py
וגם את הקובץ data_model.py
ומזינים את ההנחיה הבאה.
הנחיה 1: יצירת קובץ דרישות של PIP למודל הנתונים ולשירות הזה
הנחיה 2: יצירת קובץ דרישות של PIP למודל הנתונים ולשירות הזה באמצעות הגרסאות האחרונות
יש לוודא שהשמות והגרסאות נכונים. לדוגמה, בתשובה שלמעלה, השם והגרסה של google-cloud-sql-connecter
שגויים. מתקנים את הגרסאות באופן ידני ויוצרים קובץ requirements.txt
שנראה כך:
cloud-sql-python-connector==1.2.4
sqlalchemy==1.4.36
pg8000==1.22.0
בטרמינל של הפקודה, מריצים את הפקודה הבאה:
pip3 install -r requirements.txt
כדי לאפס את היסטוריית הצ'אט של Duet AI, לוחצים על סמל האשפה בחלק העליון של סרגל הצד של Duet AI.
יצירת טבלת חבילות ב-CloudSQL
הגדרת משתני הסביבה של מחבר מסד הנתונים ב-CloudSQL.
export INSTANCE_NAME=$(gcloud sql instances list --format='value(name)') export INSTANCE_CONNECTION_NAME=$(gcloud sql instances describe ${INSTANCE_NAME} --format="value(connectionName)") export DB_USER=evolution export DB_PASS=evolution export DB_NAME=product_details
עכשיו מריצים את data_model.py.
python data_model.py
הפלט אמור להיראות כך (יש לבדוק את הקוד כדי לראות מה צפוי בפועל):
Tables created successfully.
מתחברים למכונה של CloudSQL ובודקים שמסד הנתונים נוצר.
gcloud sql connect ${INSTANCE_NAME} --user=evolution --database=product_details
אחרי שמזינים את הסיסמה (גם אבולוציה), מקבלים את הטבלאות.
product_details=> \dt
הפלט אמור להיראות כך:
List of relations Schema | Name | Type | Owner --------+----------+-------+----------- public | packages | table | evolution (1 row)
אפשר גם לבדוק את מודל הנתונים ואת פרטי הטבלה.
product_details=> \d+ packages
הפלט אמור להיראות כך:
Table "public.packages" Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description -------------------------------+-------------------+-----------+----------+--------------------------------------+----------+-------------+--------------+------------- id | integer | | not null | nextval('packages_id_seq'::regclass) | plain | | | product_id | integer | | not null | | plain | | | height | double precision | | not null | | plain | | | width | double precision | | not null | | plain | | | depth | double precision | | not null | | plain | | | weight | double precision | | not null | | plain | | | special_handling_instructions | character varying | | | | extended | | | Indexes: "packages_pkey" PRIMARY KEY, btree (id) Access method: heap
כדי לצאת מ-CloudSQL, מקלידים \q
.
db_init.py
בשלב הבא נוסיף נתונים לדוגמה לטבלה packages
.
מחיקת היסטוריית הצ'אט של Duet AI. כשהקובץ data_model.py
פתוח, אפשר לנסות את ההנחיות הבאות.
הנחיה 1: יצירת פונקציה שיוצרת 10 שורות של חבילות לדוגמה ומשייכת אותן לטבלת החבילות
הנחיה 2: באמצעות הסשן מ-connect_connector, יוצרים פונקציה שיוצרת 10 שורות של חבילות לדוגמה ומציבה אותן בטבלת החבילות
שימוש בקוד OPEN
בתהליך עבודה חדש של קבצים כמו קודם. שומרים את הקוד בקובץ בשם
db_init.py
.
הקובץ הסופי נמצא בקטע 'נספח' ב-Codelab הזה. אם הוא לא מתרחש, צריך לבצע את השינויים הנדרשים באופן ידני.
אפשר גם לנסות הנחיות שונות כדי לראות את התשובות השונות של Duet AI.
כדי לאפס את היסטוריית הצ'אט של Duet AI, לוחצים על סמל האשפה בחלק העליון של סרגל הצד של Duet AI.
יצירת נתונים של חבילות לדוגמה
מריצים את הפקודה db_init.py
משורת הפקודה.
python db_init.py
הפלט אמור להיראות כך:
Packages created successfully.
מתחברים שוב למכונה של CloudSQL ומוודאים שהנתונים לדוגמה נוספו לטבלת החבילות.
מתחברים למכונה של CloudSQL ובודקים שמסד הנתונים נוצר.
gcloud sql connect ${INSTANCE_NAME} --user=evolution --database=product_details
אחרי הזנת הסיסמה (גם אבולוציה), צריך לאחזר את כל הנתונים מטבלת החבילות.
product_details=> SELECT * FROM packages;
הפלט אמור להיראות כך:
id | product_id | height | width | depth | weight | special_handling_instructions ----+------------+--------+-------+-------+--------+----------------------------------- 1 | 0 | 10 | 10 | 10 | 10 | No special handling instructions. 2 | 1 | 10 | 10 | 10 | 10 | No special handling instructions. 3 | 2 | 10 | 10 | 10 | 10 | No special handling instructions. 4 | 3 | 10 | 10 | 10 | 10 | No special handling instructions. 5 | 4 | 10 | 10 | 10 | 10 | No special handling instructions. 6 | 5 | 10 | 10 | 10 | 10 | No special handling instructions. 7 | 6 | 10 | 10 | 10 | 10 | No special handling instructions. 8 | 7 | 10 | 10 | 10 | 10 | No special handling instructions. 9 | 8 | 10 | 10 | 10 | 10 | No special handling instructions. 10 | 9 | 10 | 10 | 10 | 10 | No special handling instructions. (10 rows)
כדי לצאת מ-CloudSQL, מקלידים \q
.
main.py
כשהקבצים data_model.py
, package-service.yaml
ו-connect_connector.py
פתוחים, צריך ליצור main.py
לאפליקציה.
הנחיה 1: שימוש בספריית בקבוקי python – יצירת הטמעה שמשתמשת בנקודות קצה של מנוחה ב-http לשירות הזה
הנחיה 2: שימוש בספריית בקבוקי python – יצירת הטמעה שמשתמשת בנקודות קצה של מנוחה ב-http לשירות הזה. לייבא ולהשתמש ב-sessionMaker מ-connect_conector.py אל לנתוני חבילות.
הנחיה 3: שימוש בספריית בקבוקי python – יצירת הטמעה שמשתמשת בנקודות קצה של מנוחה ב-http לשירות הזה. לייבא ולהשתמש ב-Package מ-data_model.py ומ-SessionMaker מ-connect_conector.py אל נתוני חבילות.
הנחיה 4: שימוש בספריית בקבוקי python – יצירת הטמעה שמשתמשת בנקודות קצה של מנוחה ב-http לשירות הזה. לייבא ולהשתמש ב-Package מ-data_model.py ומ-SessionMaker מ-connect_conector.py אל נתוני חבילות. שימוש בכתובת ה-IP של המארח 0.0.0.0 ל-app.run
עליך לעדכן את הדרישות לגבי main.py
.
הנחיה: יצירת קובץ דרישות ל-main.py
צירוף לקובץ requirements.txt
. עליכם לוודא שאתם משתמשים ב-Flask גרסה 3.0.0.
שימוש בקוד OPEN
בתהליך עבודה חדש של קבצים כמו קודם. שומרים את הקוד בקובץ בשם
main.py
.
הקובץ הסופי נמצא בקטע 'נספח' ב-Codelab הזה. אם הוא לא מתרחש, צריך לבצע את השינויים הנדרשים באופן ידני.
כדי לאפס את היסטוריית הצ'אט של Duet AI, לוחצים על סמל האשפה בחלק העליון של סרגל הצד של Duet AI.
5. בדיקה והפעלה של האפליקציה
מתקינים את הדרישות.
pip3 install -r requirements.txt
מריצים את main.py
.
python main.py
הפלט אמור להיראות כך:
* Serving Flask app 'main' * Debug mode: off 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:5000 * Running on http://10.88.0.3:5000 Press CTRL+C to quit
בטרמינל שני, בודקים את נקודת הקצה /packages/<product_id>
.
curl localhost:5000/packages/1
הפלט אמור להיראות כך:
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
תוכלו גם לבדוק כל מזהה מוצר אחר בנתונים לדוגמה.
כדי לצאת ממאגר ה-Docker הפעיל בטרמינל, מזינים CTRL_C
.
יצירת בדיקות יחידה
כשהקובץ main.py
פתוח, יוצרים בדיקות יחידה (unit testing).
הנחיה 1: יצירת בדיקות יחידה.
שימוש בקוד OPEN
בתהליך עבודה חדש של קבצים כמו קודם. שומרים את הקוד בקובץ בשם
test.py
.
בפונקציה test_get_package
, צריך להגדיר product_id
. אפשר להוסיף אותו באופן ידני.
הקובץ הסופי נמצא בקטע 'נספח' ב-Codelab הזה. אם הוא לא מתרחש, צריך לבצע את השינויים הנדרשים באופן ידני.
כדי לאפס את היסטוריית הצ'אט של Duet AI, לוחצים על סמל האשפה בחלק העליון של סרגל הצד של Duet AI.
מתבצעות בדיקות יחידה (unit testing)
מריצים את בדיקת היחידה.
python test.py
הפלט אמור להיראות כך:
. ---------------------------------------------------------------------- Ran 1 test in 1.061s OK
סוגרים את כל הקבצים ב-Cloud Shell Editor ומנקים את היסטוריית הצ'אט בלחיצה על סמל האשפה בשורת הסטטוס העליונה.
קובץ Docker
יצירת Dockerfile
לאפליקציה הזו.
אפשר לפתוח את main.py
ולנסות את ההנחיות הבאות.
הנחיה 1: יצירת קובץ Docker לאפליקציה הזו.
הנחיה 2: יצירת קובץ Docker לאפליקציה הזו. מעתיקים את כל הקבצים למאגר התגים.
צריך גם להגדיר את ENVARS
עבור INSTANCE_CONNECTION_NAME
, DB_USER
, DB_PASS
וגם DB_NAME
. אפשר לעשות זאת באופן ידני. קובץ ה-Docker אמור להיראות כך:
FROM python:3.10-slim
WORKDIR /app
COPY . ./
RUN pip install -r requirements.txt
# Add these manually for your project
ENV INSTANCE_CONNECTION_NAME=YOUR_INSTANCE_CONNECTION_NAME
ENV DB_USER=evolution
ENV DB_PASS=evolution
ENV DB_NAME=product_details
CMD ["python", "main.py"]
שימוש בקוד OPEN
בתהליך עבודה חדש של קבצים כמו קודם. שומרים את הקוד בקובץ בשם Docker.
הקובץ הסופי נמצא בקטע 'נספח' ב-Codelab הזה. אם הוא לא מתרחש, צריך לבצע את השינויים הנדרשים באופן ידני.
הרצה מקומית של האפליקציה
כשהDockerfile
פתוח, אפשר לנסות את ההנחיה הבאה.
הנחיה 1: איך מריצים קונטיינר באופן מקומי באמצעות קובץ ה-Docker הזה
פועלים לפי ההוראות.
# Build docker build -t shipping . # And run docker run -p 5000:5000 -it shipping
הפלט אמור להיראות כך:
* Serving Flask app 'main' * Debug mode: off 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:5000 * Running on http://172.17.0.2:5000 Press CTRL+C to quit
ניגשים למאגר התגים מחלון שני של טרמינל.
curl localhost:5000/packages/1
הפלט אמור להיראות כך:
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
האפליקציה בקונטיינרים פועלת.
כדי לצאת ממאגר ה-Docker הפעיל בטרמינל, מזינים CTRL_C
.
פיתוח קובץ אימג' של קונטיינר ב-Artifact Registry
יוצרים את קובץ האימג' של הקונטיינר ומעבירים אותו ל-Artifact Registry.
cd ~/shipping gcloud auth configure-docker us-central1-docker.pkg.dev docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping . docker push us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping
קונטיינר האפליקציות נמצא עכשיו ב-us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping
וניתן לפרוס אותו ב-GKE.
6. פריסת אפליקציה לאשכול GKE
אשכול GKE Autopilot נוצר כשיצרתם את משאבי GCP לסדנה הזאת. התחברות לאשכול GKE.
gcloud container clusters get-credentials gke1 \ --region=us-central1
הוספת הערות לחשבון השירות שמשמש כברירת מחדל ב-Kubernetes עם חשבון השירות של Google.
kubectl annotate serviceaccount default iam.gke.io/gcp-service-account=cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com
הפלט אמור להיראות כך:
serviceaccount/default annotated
מכינים ומחילים את קובץ k8s.yaml.
cp ~/duetaidev/k8s.yaml_tmpl ~/shipping/. export INSTANCE_NAME=$(gcloud sql instances list --format='value(name)') export INSTANCE_CONNECTION_NAME=$(gcloud sql instances describe ${INSTANCE_NAME} --format="value(connectionName)") export IMAGE_REPO=us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping envsubst < ~/shipping/k8s.yaml_tmpl > k8s.yaml kubectl apply -f k8s.yaml
הפלט אמור להיראות כך:
deployment.apps/shipping created service/shipping created
ממתינים עד שה-Pods יתחיל לפעול ולשירות תוקצה כתובת IP חיצונית למאזן עומסים חיצוני.
kubectl get pods kubectl get service shipping
הפלט אמור להיראות כך:
# kubectl get pods NAME READY STATUS RESTARTS AGE shipping-f5d6f8d5-56cvk 1/1 Running 0 4m47s shipping-f5d6f8d5-cj4vv 1/1 Running 0 4m48s shipping-f5d6f8d5-rrdj2 1/1 Running 0 4m47s # kubectl get service shipping NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE shipping LoadBalancer 34.118.225.125 34.16.39.182 80:30076/TCP 5m41s
לאשכולות GKE Autopilot, צריך להמתין כמה דקות עד שהמשאבים יהיו מוכנים.
ניגשים לשירות דרך הכתובת EXTERNAL-IP
.
export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://${EXTERNAL_IP}/packages/1
הפלט אמור להיראות כך:
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
7. Extra Credit: פתרון בעיות באפליקציה
הסרת תפקיד ה-IAM של לקוח Cloud SQL מחשבון השירות של cloudsqlsa
. הדבר גורם לשגיאה בהתחברות למסד הנתונים של CloudSQL.
gcloud projects remove-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/cloudsql.client"
צריך להפעיל מחדש את ה-Pod של משלוחים.
kubectl rollout restart deployment shipping
אחרי שה-Pod יופעל מחדש, אפשר לנסות לגשת שוב לשירות shipping
.
export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://${EXTERNAL_IP}/packages/1
הפלט אמור להיראות כך:
... <title>500 Internal Server Error</title> <h1>Internal Server Error</h1> <p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>
כדי לבדוק את היומנים, עוברים אל Kubernetes Engine > עומסי עבודה (workloads)
לוחצים על הפריסה shipping
ואז על הכרטיסייה יומנים.
לוחצים על הסמל הצגה ב-Log Explorer בצד שמאל של שורת הסטטוס. נפתח חלון חדש של Log Explorer.
לוחצים על אחת מרשומות השגיאה Traceback
, ולאחר מכן לוחצים על הסבר על ערך היומן הזה.
אפשר לקרוא את הסבר לשגיאה.
בשלב הבא צריך להיעזר ב-Duet AI כדי לפתור את השגיאה.
אפשר לנסות להזין את ההנחיה הבאה.
הנחיה 1: עזרה בפתרון השגיאה הזו
מזינים את הודעת השגיאה שמופיעה בהנחיה.
הנחיה 2: אסור: נראה שלחשבון משתמש מאומת ב-IAM אין הרשאה לשלוח בקשת API. אימות של Cloud SQL Admin API מופעלת בפרויקט GCP ובחשבון לקוח Cloud SQL. הוקצה לחשבון המשתמש ב-IAM
ואז.
הנחיה 3: איך מקצים את התפקיד 'לקוח Cloud SQL' לחשבון שירות של Google באמצעות gcloud?
מקצים את התפקיד 'לקוח Cloud SQL' ל-cloudsqlsa
.
gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/cloudsql.client"
המתינו מספר דקות ונסו שוב לגשת לאפליקציה.
export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://${EXTERNAL_IP}/packages/1
הפלט אמור להיראות כך:
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
השתמשתם ב-Duet AI ב-Cloud Logging, ב-Log Explorer ובתכונה Log Explainer כדי לפתור את הבעיה.
8. סיכום
מעולה! השלמת בהצלחה את ה-Codelab הזה.
ב-Codelab הזה למדנו את הדברים הבאים:
- צריך להפעיל את Duet AI בפרויקט ב-GCP ולהגדיר אותו לשימוש בסביבת פיתוח משולבת (IDE) ובמסוף Cloud.
- שימוש ב-Duet AI ליצירת קוד, להשלמה ולהסבר.
- אפשר להשתמש ב-Duet AI כדי להסביר בעיה באפליקציה ולפתור אותה.
- תכונות של Duet AI כמו צ'אט בסביבת פיתוח משולבת (IDE) וצ'אט מרובה פניות, צ'אט לעומת יצירת קוד בגוף ההודעה, פעולות חכמות כמו הסבר על הקוד, הכרת הקוד ועוד.
9. נספח
package-service.yaml
swagger: "2.0"
info:
title: Shipping and Package Information API
description: This API provides information about shipping and packages.
version: 1.0.0
host: shipping.googleapis.com
schemes:
- https
produces:
- application/json
paths:
/packages/{product_id}:
get:
summary: Get information about a package
description: This method returns information about a package, including its height, width, depth, weight, and any special handling instructions.
parameters:
- name: product_id
in: path
required: true
type: integer
format: int64
responses:
"200":
description: A successful response
schema:
type: object
properties:
height:
type: integer
format: int64
width:
type: integer
format: int64
depth:
type: integer
format: int64
weight:
type: integer
format: int64
special_handling_instructions:
type: string
"404":
description: The product_id was not found
data_model.py
from sqlalchemy import Column, Integer, String, Float
from sqlalchemy.ext.declarative import declarative_base
from connect_connector import engine
Base = declarative_base()
class Package(Base):
__tablename__ = 'packages'
id = Column(Integer, primary_key=True)
product_id = Column(Integer, nullable=False)
height = Column(Float, nullable=False)
width = Column(Float, nullable=False)
depth = Column(Float, nullable=False)
weight = Column(Float, nullable=False)
special_handling_instructions = Column(String, nullable=True)
def create_tables():
Base.metadata.create_all(engine)
if __name__ == '__main__':
create_tables()
print('Tables created successfully.')
connect_connector.py
import os
from google.cloud.sql.connector import Connector, IPTypes
import sqlalchemy
# You may need to manually import pg8000 and Base as follows
import pg8000
from sqlalchemy.ext.declarative import declarative_base
def connect_with_connector() -> sqlalchemy.engine.base.Engine:
"""Initializes a connection pool for a Cloud SQL instance of Postgres."""
# Note: Saving credentials in environment variables is convenient, but not
# secure - consider a more secure solution such as
# Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
# keep secrets safe.
instance_connection_name = os.environ[
"INSTANCE_CONNECTION_NAME"
] # e.g. 'project:region:instance'
db_user = os.environ["DB_USER"] # e.g. 'my-database-user'
db_pass = os.environ["DB_PASS"] # e.g. 'my-database-password'
db_name = os.environ["DB_NAME"] # e.g. 'my-database'
ip_type = IPTypes.PRIVATE if os.environ.get("PRIVATE_IP") else IPTypes.PUBLIC
connector = Connector()
def getconn() -> sqlalchemy.engine.base.Engine:
conn: sqlalchemy.engine.base.Engine = connector.connect(
instance_connection_name,
"pg8000",
user=db_user,
password=db_pass,
db=db_name,
ip_type=ip_type,
)
return conn
pool = sqlalchemy.create_engine(
"postgresql+pg8000://",
creator=getconn,
# ...
)
return pool
# Create a connection pool
engine = connect_with_connector()
# Create a sessionmaker class to create new sessions
SessionMaker = sqlalchemy.orm.sessionmaker(bind=engine)
# Create a Base class for ORM
# You may need to manually fix the following
Base = declarative_base()
db_init.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from connect_connector import engine
from data_model import Package
def create_packages():
# Create a session
session = sessionmaker(bind=engine)()
# Create 10 sample packages
for i in range(10):
package = Package(
product_id=i,
height=10.0,
width=10.0,
depth=10.0,
weight=10.0,
special_handling_instructions="No special handling instructions."
)
# Add the package to the session
session.add(package)
# Commit the changes
session.commit()
if __name__ == '__main__':
create_packages()
print('Packages created successfully.')
main.py
from flask import Flask, request, jsonify
from data_model import Package
from connect_connector import SessionMaker
app = Flask(__name__)
session_maker = SessionMaker()
@app.route("/packages/<int:product_id>", methods=["GET"])
def get_package(product_id):
"""Get information about a package."""
session = session_maker
package = session.query(Package).filter(Package.product_id == product_id).first()
if package is None:
return jsonify({"message": "Package not found."}), 404
return jsonify(
{
"height": package.height,
"width": package.width,
"depth": package.depth,
"weight": package.weight,
"special_handling_instructions": package.special_handling_instructions,
}
), 200
if __name__ == "__main__":
app.run(host="0.0.0.0")
test.py
import unittest
from data_model import Package
from connect_connector import SessionMaker
from main import app
class TestPackage(unittest.TestCase):
def setUp(self):
self.session_maker = SessionMaker()
def tearDown(self):
self.session_maker.close()
def test_get_package(self):
"""Test the `get_package()` function."""
package = Package(
product_id=11, # Ensure that the product_id different from the sample data
height=10,
width=10,
depth=10,
weight=10,
special_handling_instructions="Fragile",
)
session = self.session_maker
session.add(package)
session.commit()
response = app.test_client().get("/packages/11")
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.json,
{
"height": 10,
"width": 10,
"depth": 10,
"weight": 10,
"special_handling_instructions": "Fragile",
},
)
if __name__ == "__main__":
unittest.main()
requirements.txt
cloud-sql-python-connector==1.2.4
sqlalchemy==1.4.36
pg8000==1.22.0
Flask==3.0.0
gunicorn==20.1.0
psycopg2-binary==2.9.3
קובץ Docker
FROM python:3.10-slim
WORKDIR /app
COPY . ./
RUN pip install -r requirements.txt
# Add these manually for your project
ENV INSTANCE_CONNECTION_NAME=YOUR_INSTANCE_CONNECTION_NAME
ENV DB_USER=evolution
ENV DB_PASS=evolution
ENV DB_NAME=product_details
CMD ["python", "main.py"]