1. الأهداف
الغرض من ورشة العمل هذه هو تقديم تدريب عملي على Duet AI للمستخدمين والممارسين.
في هذا الدرس التطبيقي حول الترميز، ستتعرّف على ما يلي:
- فعِّل Duet AI في مشروعك على Google Cloud Platform واضبطه لاستخدامه في بيئة تطوير متكاملة وCloud Console.
- استخدِم Duet AI لإنشاء الرموز البرمجية وإكمالها وشرحها.
- استخدام Duet AI لشرح مشكلة في أحد التطبيقات وتحديد أسبابها وحلّها
- ميزات Duet AI، مثل الدردشة في بيئة التطوير المتكاملة والدردشة المتعددة الأدوار، والدردشة مقابل إنشاء الرموز البرمجية المضمّنة، والإجراءات الذكية، مثل شرح الرموز البرمجية وتأكيد التلاوة وغير ذلك
Narrative
لإظهار كيفية استخدام "Duet AI للمطوّرين" بشكل واقعي في عملية التطوير اليومية، تجري أنشطة ورشة العمل هذه في سياق سردي.
انضمام مطوّر جديد إلى شركة للتجارة الإلكترونية مهمتهم هي إضافة خدمة جديدة إلى تطبيق التجارة الإلكترونية الحالي (الذي يتألف من خدمات متعددة). تقدّم الخدمة الجديدة معلومات إضافية (مثل الأبعاد والوزن وما إلى ذلك) عن المنتجات في كتالوج المنتجات. ستتيح هذه الخدمة تكاليف شحن أفضل/أرخص استنادًا إلى أبعاد المنتج وأوزانه.
بما أنّ المطوّر جديد في الشركة، سيستخدم Duet AI لإنشاء الرموز البرمجية وشرحها وتوثيقها.
بعد ترميز الخدمة، سيستخدم مشرف المنصة Duet AI (الدردشة) للمساعدة في إنشاء العنصر (حاوية Docker)، والموارد اللازمة لنشر العنصر على Google Cloud Platform (مثل Artifact Registry وأذونات "إدارة الهوية وإمكانية الوصول" ومستودع الرموز البرمجية والبنية الأساسية للحوسبة، أي GKE أو CloudRun وما إلى ذلك).
بعد نشر التطبيق على Google Cloud Platform، سيستخدم مشغّل التطبيق/مهندس موثوقية الموقع Duet AI (وCloud Ops) للمساعدة في تحديد المشاكل وحلّها في الخدمة الجديدة.
الدور الوظيفي
تتناول ورشة العمل الشخصية التالية:
- مطوّر التطبيقات: يجب أن تكون لديك بعض المعرفة بالبرمجة وتطوير البرامج.
هذه النسخة من ورشة عمل Duet AI مخصّصة للمطوّرين فقط. لا يلزم معرفة موارد السحابة الإلكترونية في Google Cloud. يمكنك العثور على النصوص البرمجية الخاصة بكيفية إنشاء موارد Google Cloud Platform المطلوبة لتشغيل هذا التطبيق هنا. يمكنك اتّباع التعليمات الواردة في هذا الدليل لنشر موارد Google Cloud Platform المطلوبة.
2. إعداد البيئة
تفعيل Duet AI
يمكنك تفعيل Duet AI في مشروع على "منصة Google Cloud" إما من خلال واجهة برمجة التطبيقات (gcloud أو أدوات البنية الأساسية كرمز برمجي مثل Terraform) أو من خلال واجهة مستخدم Cloud Console.
لتفعيل 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.
امنح حساب المستخدم أدوار "إدارة الهوية وإمكانية الوصول" (IAM) الخاصة بـ "مستخدم Cloud AI Companion" و"مشاهد استخدام الخدمة". تتوفّر Cloud Companion API خلف الميزات في كلّ من بيئة التطوير المتكاملة ووحدة التحكّم اللتين سنستخدمهما. يُستخدم إذن "عارض الاستخدام" للخدمة كفحص سريع قبل تفعيل واجهة المستخدم في وحدة التحكّم (حتى لا تظهر واجهة مستخدم Duet إلا في المشاريع التي تم تفعيل واجهة برمجة التطبيقات فيها).
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 Console
لتفعيل واجهة برمجة التطبيقات، انتقِل إلى صفحة Cloud AI Companion API في Google Cloud Console.
في أداة اختيار المشاريع، اختَر مشروعًا.
انقر على تفعيل.
يتم تعديل الصفحة وعرض الحالة مفعَّل. أصبحت ميزة Duet AI متاحة الآن في مشروع Google Cloud المحدّد لجميع المستخدمين الذين لديهم أدوار إدارة الهوية وإمكانية الوصول (IAM) المطلوبة.
لمنح أدوار "إدارة الهوية وإمكانية الوصول" المطلوبة لاستخدام Duet AI، انتقِل إلى صفحة إدارة الهوية وإمكانية الوصول.
في العمود الجهة الرئيسية، ابحث عن USER الذي تريد منح إذن الوصول إلى Duet AI له، ثم انقر على رمز القلم الرصاص ✏️ تعديل الجهة الرئيسية في هذا الصف.
في لوحة الوصول تعديل، انقر على إضافة دور آخر.
في "اختيار دور"، اختَر مستخدم Cloud AI Companion.
انقر على إضافة دور آخر واختَر عارض استخدام الخدمة.
انقر على حفظ.
إعداد بيئة التطوير المتكاملة
يمكن للمطوّرين الاختيار من بين مجموعة متنوعة من بيئات التطوير المتكاملة التي تناسب احتياجاتهم. تتوفّر ميزة المساعدة في كتابة الرموز البرمجية من Duet AI في العديد من بيئات التطوير المتكاملة، مثل Visual Studio Code وبيئات تطوير JetBrains المتكاملة (IntelliJ وPyCharm وGoLand وWebStorm وغيرها) وCloud Workstations ومحرِّر Cloud Shell.
في هذا الدرس التطبيقي، يمكنك استخدام محطات عمل Cloud أو Cloud Shell Editor.
تستخدم ورشة العمل هذه "محرّر Cloud Shell".
يُرجى العِلم أنّ إعداد Cloud Workstations قد يستغرق من 20 إلى 30 دقيقة.
لاستخدامها على الفور، استخدِم محرِّر Cloud Shell.
افتح "محرِّر Cloud Shell" من خلال النقر على رمز قلم الرصاص ✏️ في شريط القوائم العلوي في Cloud Shell.
يوفّر Cloud Shell Editor واجهة مستخدم وتجربة مستخدم مشابهتَين إلى حدّ كبير لتلك المتوفّرة في VSCode.

اضغط على CTRL (في نظام التشغيل Windows)/CMD (في نظام التشغيل Mac) + , (فاصلة) لفتح لوحة "الإعدادات".
في شريط البحث، اكتب "duet ai".
تأكَّد من تفعيل Cloudcode › Duet AI: Enable وCloudcode › Duet AI › Inline Suggestions: Enable Auto أو فعِّلهما.

في "شريط الحالة" في أسفل الشاشة، انقر على Cloud Code - Sign In واتّبِع خطوات تسجيل الدخول.
إذا كنت قد سجّلت الدخول، سيعرض شريط الحالة Cloud Code - No project.
انقر على Cloud Code - No project (Cloud Code - بدون مشروع)، وسيظهر جزء من القائمة المنسدلة للإجراء في أعلى الصفحة. انقر على اختيار مشروع Google Cloud.

ابدأ بكتابة رقم تعريف مشروعك، وسيظهر مشروعك في القائمة.

اختَر PROJECT_ID من قائمة المشاريع.
يتم تعديل شريط الحالة في أسفل الصفحة لعرض رقم تعريف مشروعك. إذا لم يظهر، قد تحتاج إلى إعادة تحميل علامة التبويب "محرّر Cloud Shell".
انقر على رمز من إنشاء الذكاء الاصطناعي Duet AI
في شريط القوائم الأيمن، وستظهر نافذة محادثة Duet AI. إذا تلقّيت رسالة تفيد بأنّه عليك اختيار مشروع Google Cloud Platform انقر على المشروع وأعِد اختياره.
تظهر الآن نافذة محادثة Duet AI

3- إعداد البنية الأساسية

لتشغيل خدمة الشحن الجديدة في GCP، تحتاج إلى موارد GCP التالية:
- مثيل Cloud SQL يتضمّن قاعدة بيانات
- مجموعة GKE لتشغيل الخدمة المستندة إلى الحاويات
- مستودع Artifact Registry لتخزين صورة Docker
- مستودع Cloud Source Repository للرمز
في نافذة Cloud Shell الطرفية، استنسِخ المستودع التالي ونفِّذ الأوامر التالية لإعداد البنية الأساسية في مشروعك على Google Cloud Platform.
# 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. تطوير خدمة Flask بلغة Python

ستتألف الخدمة التي سننشئها في النهاية من الملفات التالية. لست بحاجة إلى إنشاء هذه الملفات الآن، بل ستنشئها واحدًا تلو الآخر باتّباع التعليمات أدناه:
-
package-service.yaml: مواصفات Open API لخدمة الحِزم التي تتضمّن بيانات مثل الارتفاع والعرض والوزن وتعليمات المناولة الخاصة data_model.py: نموذج بيانات لمواصفات واجهة برمجة التطبيقات الخاصة بحزمة الخدمات، ويتم أيضًا إنشاء جدولpackagesفي قاعدة بيانات product_details.connect_connector.py- اتصال CloudSQL (يحدّد المحرّك والجلسة وBase ORM)db_init.py: لإنشاء بيانات نموذجية في جدولpackages.main.py: خدمة Python Flask تتضمّن نقطة نهايةGETلاسترداد تفاصيل الحزمة من بياناتpackagesاستنادًا إلى product_id.test.py- اختبار الوحدةrequirement.txt- متطلبات PythonDockerfile: لتضمين هذا التطبيق في حاوية
إذا واجهت أي مشاكل صعبة أثناء التمارين، ستجد جميع الملفات النهائية في الملحق من هذا الدرس العملي كمرجع.
في الخطوة السابقة، أنشأت مستودع Cloud Source Repository. أنشئ نسخة طبق الأصل من المستودع. ستنشئ ملفات التطبيق في مجلد المستودع الذي تم استنساخه.
في وحدة Cloud Shell الطرفية، نفِّذ الأمر التالي لاستنساخ المستودع.
cd ~ gcloud source repos clone shipping shipping cd ~/shipping
افتح الشريط الجانبي لمحادثة Duet AI من القائمة اليمنى في "محرّر Cloud Shell". يبدو الرمز على النحو التالي:
. يمكنك الآن استخدام Duet AI للحصول على مساعدة في كتابة الرموز البرمجية.
package-service.yaml
بدون فتح أي ملفات، اطلب من Duet إنشاء مواصفات Open API لخدمة الشحن.
الطلب 1: إنشاء مواصفات OpenAPI yaml لخدمة تقدّم معلومات عن الشحن والطرود استنادًا إلى معرّف منتج رقمي يجب أن تتضمّن الخدمة معلومات حول ارتفاع الحِزم وعرضها وعمقها ووزنها وأي تعليمات خاصة بشأن التعامل معها.

تتوفّر ثلاثة خيارات في أعلى يسار نافذة الرمز البرمجي الذي تم إنشاؤه.
يمكنك إما COPY
الرمز ولصقه في ملف.
يمكنك ADD
الرمز إلى الملف المفتوح حاليًا في "المحرّر".
أو يمكنك OPEN
الرمز في ملف جديد.
انقر على OPEN
الرمز في ملف جديد.
انقر على CTRL/CMD + s لحفظ الملف، وخزِّنه في مجلد التطبيق باسم الملف package-service.yaml. انقر على "موافق".

يمكنك العثور على الملف النهائي في قسم "الملحق" من هذا الدرس التطبيقي. إذا لم يكن الأمر كذلك، عليك إجراء التغييرات المناسبة يدويًا.
يمكنك أيضًا تجربة طلبات مختلفة للاطّلاع على ردود Duet AI.
أعِد ضبط سجلّ محادثات Duet AI من خلال النقر على رمز سلة المهملات
في أعلى الشريط الجانبي لـ Duet AI.
data_model.py
بعد ذلك، يمكنك إنشاء ملف Python لنموذج البيانات الخاص بالخدمة استنادًا إلى مواصفات OpenAPI.
بعد فتح ملف package-service.yaml، أدخِل الطلب التالي.
الطلب 1: باستخدام python sqlalchemy ORM، أنشئ نموذج بيانات لخدمة واجهة برمجة التطبيقات هذه. يجب أيضًا تضمين دالة منفصلة ونقطة دخول رئيسية تنشئ جداول قاعدة البيانات.

لنلقِ نظرة على كل جزء تم إنشاؤه. لا يزال 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، أدخِل الطلبات التالية.
الطلب 1: باستخدام مكتبة 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، إنشاء DB engine وsessionmaker وbase ORM لاستخدامها في التطبيق
الطلب 1: إنشاء محرك وفئة sessionmaker وBase ORM باستخدام طريقة connect_with_connector

قد يضيف الردّ engine وSession وBase إلى ملف connect_connector.py.
يمكنك العثور على الملف النهائي في قسم "الملحق" من هذا الدرس التطبيقي. إذا لم يكن الأمر كذلك، عليك إجراء التغييرات المناسبة يدويًا.
يمكنك أيضًا تجربة طلبات مختلفة للاطّلاع على الاختلافات المحتملة في ردود Duet AI.
أعِد ضبط سجلّ محادثات Duet AI من خلال النقر على رمز سلة المهملات
في أعلى الشريط الجانبي لـ Duet AI.
تعديل ملف data_model.py
عليك استخدام المحرّك الذي أنشأته في الخطوة السابقة (في الملف connect_connector.py) من أجل إنشاء جدول في قاعدة بيانات CloudSQL.
محو سجلّ محادثات Duet AI افتح ملف data_model.py. جرِّب الطلب التالي.
الطلب 1: في الدالة الرئيسية، استورِد المحرك واستخدِمه من connect_connector.py

من المفترض أن تظهر عملية استيراد الردود engine من connect_connector (بالنسبة إلى CloudSQL). يستخدم create_table هذا المحرّك (بدلاً من قاعدة البيانات المحلية التلقائية sqlite).
تعديل ملف data_model.py
يمكنك العثور على الملف النهائي في قسم "الملحق" من هذا الدرس التطبيقي. إذا لم يكن الأمر كذلك، عليك إجراء التغييرات المناسبة يدويًا.
يمكنك أيضًا تجربة طلبات مختلفة للاطّلاع على ردود متنوعة من 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
بعد إدخال كلمة المرور (evolution أيضًا)، احصل على الجداول.
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
اكتب \q للخروج من CloudSQL.
db_init.py
بعد ذلك، لنضِف بعض البيانات النموذجية إلى جدول packages.
محو سجلّ محادثات Duet AI بعد فتح ملف data_model.py، جرِّب الطلبات التالية.
الطلب 1: إنشاء دالة تنشئ 10 صفوف حِزم نموذجية وتُدرجها في جدول الحِزم
الطلب 2: باستخدام الجلسة من connect_connector، أنشئ دالة تنشئ 10 صفوف حِزم نموذجية وتثبّتها في جدول الحِزم

استخدِم OPEN
الرمز في سير عمل ملف جديد كما كان من قبل. احفظ الرمز في ملف باسم db_init.py.
يمكنك العثور على الملف النهائي في قسم "الملحق" من هذا الدرس التطبيقي. إذا لم يكن الأمر كذلك، عليك إجراء التغييرات المناسبة يدويًا.
يمكنك أيضًا تجربة طلبات مختلفة للاطّلاع على ردود متنوعة من 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
بعد إدخال كلمة المرور (المعروفة أيضًا باسم evolution)، احصل على جميع البيانات من جدول الحِزم.
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)
اكتب \q للخروج من CloudSQL.
main.py
بعد فتح ملفات data_model.py وpackage-service.yaml وconnect_connector.py، أنشئ main.py للتطبيق.
الطلب 1: باستخدام مكتبة python flask، أنشئ عملية تنفيذ تستخدم نقاط نهاية http rest لهذه الخدمة
الطلب 2: باستخدام مكتبة python flask، أنشئ عملية تنفيذ تستخدم نقاط نهاية http rest لهذه الخدمة. استورِد SessionMaker واستخدِمه من connect_conector.py للحصول على بيانات الحِزم.
الطلب 3: باستخدام مكتبة python flask، أنشئ عملية تنفيذ تستخدم نقاط نهاية http rest لهذه الخدمة. استورِد الحزمة واستخدِمها من data_model.py وSessionMaker من connect_conector.py لبيانات الحزم.
الطلب 4: باستخدام مكتبة python flask، أنشئ عملية تنفيذ تستخدم نقاط نهاية http rest لهذه الخدمة. استورِد الحزمة واستخدِمها من data_model.py وSessionMaker من connect_conector.py لبيانات الحِزم. استخدام عنوان IP للمضيف 0.0.0.0 في app.run

تعديل متطلبات main.py
الطلب: إنشاء ملف متطلبات لملف main.py

أضِف هذا إلى ملف requirements.txt. تأكَّد من استخدام الإصدار 3.0.0 من Flask.
استخدِم OPEN
الرمز في سير عمل ملف جديد كما كان من قبل. احفظ الرمز في ملف باسم main.py.
يمكنك العثور على الملف النهائي في قسم "الملحق" من هذا الدرس التطبيقي. إذا لم يكن الأمر كذلك، عليك إجراء التغييرات المناسبة يدويًا.
أعِد ضبط سجلّ محادثات 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}
يمكنك أيضًا اختبار أيّ رقم تعريف منتج آخر في بياناتك النموذجية.
أدخِل CTRL_C للخروج من حاوية Docker قيد التشغيل في الوحدة الطرفية.
إنشاء اختبارات الوحدة
بعد فتح الملف main.py، أنشئ اختبارات الوحدة.
الطلب 1: إنشاء اختبارات الوحدة

استخدِم OPEN
الرمز في سير عمل ملف جديد كما كان من قبل. احفظ الرمز في ملف باسم test.py.
في الدالة test_get_package، يجب تحديد product_id. يمكنك إضافته يدويًا.
يمكنك العثور على الملف النهائي في قسم "الملحق" من هذا الدرس التطبيقي. إذا لم يكن الأمر كذلك، عليك إجراء التغييرات المناسبة يدويًا.
أعِد ضبط سجلّ محادثات Duet AI من خلال النقر على رمز سلة المهملات
في أعلى الشريط الجانبي لـ Duet AI.
تشغيل اختبارات الوحدات
نفِّذ اختبار الوحدة.
python test.py
يكون الناتج مشابهًا لما يلي:
. ---------------------------------------------------------------------- Ran 1 test in 1.061s OK
أغلِق جميع الملفات في Cloud Shell Editor وامحُ سجلّ المحادثات بالنقر على رمز سلة المهملات
في شريط الحالة العلوي.
ملف شامل
أنشئ Dockerfile لهذا التطبيق.
افتح main.py وجرِّب الطلبات التالية.
الطلب 1: إنشاء Dockerfile لهذا التطبيق
الطلب 2: إنشاء Dockerfile لهذا التطبيق انسخ جميع الملفات إلى الحاوية.

عليك أيضًا ضبط ENVARS لكل من INSTANCE_CONNECTION_NAME وDB_USER وDB_PASS وDB_NAME. يمكنك إجراء ذلك يدويًا. يجب أن يبدو ملف Dockerfile على النحو التالي:
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
الرمز في سير عمل ملف جديد كما كان من قبل. احفظ الرمز في ملف باسم Dockerfile.
يمكنك العثور على الملف النهائي في قسم "الملحق" من هذا الدرس التطبيقي. إذا لم يكن الأمر كذلك، عليك إجراء التغييرات المناسبة يدويًا.
تشغيل التطبيق محليًا
مع فتح Dockerfile، جرِّب الطلب التالي.
السؤال 1: كيف يمكنني تشغيل حاوية محليًا باستخدام ملف Dockerfile هذا؟

اتّبِع التعليمات.
# 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}
يعمل التطبيق المحفوظ في حاوية.
أدخِل CTRL_C للخروج من حاوية Docker قيد التشغيل في الوحدة الطرفية.
إنشاء صورة حاوية في 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 عند إنشاء موارد Google Cloud Platform لورشة العمل هذه. اتّصِل بمجموعة 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
انتظِر إلى أن يتم تشغيل وحدات Pod وتعيين عنوان 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. مكافأة إضافية: تحديد المشاكل في التطبيق وحلّها
أزِل دور CloudSQL Client IAM من حساب الخدمة cloudsqlsa. يؤدي ذلك إلى حدوث خطأ أثناء الاتصال بقاعدة بيانات CloudSQL.
gcloud projects remove-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"
أعِد تشغيل وحدة الشحن.
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 > أحمال العمل

انقر على عملية النشر shipping ثم على علامة التبويب السجلات.

انقر على رمز عرض في "مستكشف السجلّ"
على يسار شريط الحالة. سيؤدي ذلك إلى فتح نافذة مستكشف السجلّ جديدة.

انقر على أحد إدخالات الخطأ Traceback، ثم انقر على شرح إدخال السجلّ هذا.

يمكنك قراءة شرح الخطأ.
بعد ذلك، لنطلب من Duet AI المساعدة في تحديد المشاكل وحلّها.
جرِّب الطلب التالي.
الطلب 1: ساعدني في تحديد المشاكل وحلّها

أدخِل رسالة الخطأ في الطلب.
الرسالة 2: محظور: يبدو أنّ كيان IAM الذي تمت مصادقته ليس لديه إذن بتقديم طلب بيانات من واجهة برمجة التطبيقات. تأكَّد من تفعيل Cloud SQL Admin API في مشروعك على Google Cloud Platform ومن منح دور "عميل Cloud SQL" إلى مدير الهوية وإمكانية الوصول

ثم
السؤال 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 ومستكشف السجلات وميزة شرح السجلات لتحديد المشكلة وحلّها.
8. الخاتمة
تهانينا! لقد أكملت هذا الدرس التطبيقي حول الترميز بنجاح.
في هذا الدرس العملي، تعرّفت على ما يلي:
- فعِّل Duet AI في مشروعك على Google Cloud Platform واضبطه لاستخدامه في بيئة تطوير متكاملة وCloud Console.
- استخدِم Duet AI لإنشاء الرموز البرمجية وإكمالها وشرحها.
- استخدام Duet AI لشرح مشكلة في أحد التطبيقات وتحديد أسبابها وحلّها
- ميزات Duet AI، مثل الدردشة في بيئة التطوير المتكاملة والدردشة المتعددة الأدوار، والدردشة مقابل إنشاء الرموز البرمجية المضمّنة، والإجراءات الذكية، مثل شرح الرموز البرمجية وتأكيد التلاوة وغير ذلك
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
ملف شامل
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"]