دليل ورشة العمل حول الترميز الخاص بالمطوّرين في Duet AI

1. الأهداف

تهدف ورشة العمل هذه إلى توفير تعليم عملي بشأن Duet AI للمستخدمين والممارسين.

في هذا الدرس التطبيقي حول الترميز، ستتعرَّف على ما يلي:

  1. تفعيل Duet AI في مشروع Google Cloud Platform وإعداده للاستخدام في بيئة تطوير متكاملة (IDE) وCloud Console
  2. استخدام Duet AI لإنشاء الرموز البرمجية وإكمالها وشرحها
  3. يمكنك استخدام Duet AI لتوضيح مشكلة في التطبيق وحلّها.
  4. ميزات Duet AI، مثل المحادثة عبر بيئة تطوير متكاملة (IDE) والمحادثة المتعدّدة الأدوار والمحادثة وإنشاء الرموز المضمَّنة وإجراءات ذكية، مثل شرح الرموز البرمجية والإقرار بالتلاوات وغير ذلك

Narrative

إنّ أنشطة ورشة العمل هذه تتم في سياق سردي لشرح كيفية استخدام Duet AI for Developers بشكل أصيل في عمليات التطوير اليومية.

ينضم مطوِّر جديد إلى شركة تجارة إلكترونية. ويُكلف الفريق بإضافة خدمة جديدة إلى تطبيق التجارة الإلكترونية الحالي (تتألف من خدمات متعددة). توفّر الخدمة الجديدة معلومات إضافية (الأبعاد والوزن وما إلى ذلك) عن المنتجات في كتالوج المنتجات. تتيح هذه الخدمة توفير تكاليف شحن أفضل/أقل استنادًا إلى أبعاد المنتج وأوزانه.

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

بعد ترميز الخدمة، سيستخدم مشرف النظام الأساسي Duet AI (الدردشة) للمساعدة في إنشاء العنصر (حاوية التخزين)، والموارد اللازمة لنشر العناصر في Google Cloud Platform (مثل Artifact Registry وأذونات "إدارة الهوية وإمكانية الوصول" ومستودع الرموز والبنية الأساسية للحوسبة، مثل GKE أو CloudRun وما إلى ذلك).

بعد نشر التطبيق على Google Cloud Platform، سيستخدم مشغّل التطبيق/SRE Duet AI (وعمليات Cloud Ops) للمساعدة في تحديد خطأ ما في الخدمة الجديدة وحلّها.

الشخصية

تتناول ورشة العمل الشخصية التالية:

  1. مطوِّر التطبيقات: يلزم معرفة بعض الخبرة في مجال البرمجة وتطوير البرامج.

هذا الشكل من ورشة عمل Duet AI مخصّص للمطوّرين فقط. لست بحاجة إلى معرفة موارد السحابة الإلكترونية في Google Cloud Platform. يمكن العثور على النصوص البرمجية لكيفية إنشاء موارد GCP المطلوبة لتشغيل هذا التطبيق هنا. يمكنك اتّباع التعليمات الواردة في هذا الدليل لنشر موارد GCP المطلوبة.

2. تحضير البيئة

جارٍ تفعيل Duet AI

يمكنك تفعيل Duet AI في مشروع على Google Cloud Platform إما من خلال واجهة برمجة التطبيقات (gcloud أو أدوات IaC مثل Terraform) أو من خلال واجهة مستخدم Cloud Console.

لتفعيل Duet AI في مشروع على Google Cloud، عليك تفعيل Cloud AI Companion API ومنح "المستخدم المصاحب" في Cloud AI ودورَي "إدارة الهوية وإمكانية الوصول" (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 Companion API إلى الميزات المتوفّرة في كل من بيئة التطوير المتكاملة (IDE) ووحدة التحكّم التي سنستخدمها. يُستخدم إذن "عارِض استخدام الخدمة" كفحص سريع قبل تفعيل واجهة المستخدم في وحدة التحكّم (بحيث لا تظهر واجهة مستخدم 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 المحدّد لجميع المستخدمين الذين لديهم أدوار "إدارة الهوية وإمكانية الوصول" المطلوبة.

لمنح أدوار "إدارة الهوية وإمكانية الوصول" المطلوبة لاستخدام Duet AI، انتقِل إلى صفحة IAM.

في العمود مدير الحساب، ابحث عن المستخدم الذي تريد تفعيل إذن الوصول إلى Duet AI له، ثم انقر على رمز القلم الرصاص ✏️ تعديل المدير في ذلك الصف.

في لوحة تعديل إذن الوصول، انقر على إضافة دور آخر.

في "اختيار دور"، اختَر مستخدم مصاحب في Cloud AI.

انقر على إضافة دور آخر واختَر مُشاهد استخدام الخدمة.

انقر على حفظ.

إعداد بيئة التطوير المتكاملة

يمكن للمطوّرين الاختيار من بين مجموعة متنوّعة من حِزم تطوير البرامج (IDE) التي تناسب احتياجاتهم على أفضل وجه. تتوفّر ميزة المساعدة في رمز Duet AI في العديد من بيئات IDE، مثل Visual Studio Code وJetBrains IDE (IntelliJ وPyCharm وGoLand وWebStorm وغيرها) وCloud Workstations وCloud Shell Editor.

في هذا الدرس التطبيقي، يمكنك استخدام Cloud Workstations أو محرِّر Cloud Shell.

تستخدم ورشة العمل هذه محرِّر Cloud Shell.

يُرجى العلم أنّ إعداد Cloud Workstations قد يستغرق مدة تتراوح بين 20 و30 دقيقة.

لاستخدامها على الفور، استخدِم محرِّر Cloud Shell.

افتح تطبيق Cloud Shell Editor من خلال النقر على رمز القلم الرصاص ✏️ في شريط القائمة العلوي في Cloud Shell.

يحتوي محرِّر Cloud Shell على واجهة مستخدم وتجربة مستخدم متشابهة جدًا مع VSCode.

d6a6565f83576063.png

انقر على CTRL (في نظام التشغيل Windows)/CMD (في نظام التشغيل Mac) + , (فاصلة) للدخول إلى جزء الإعدادات.

في شريط البحث، اكتب "duet ai".

تأكَّد من Cloudcode أو فعِّله › Duet AI: تفعيل وCloudcode › Duet AI › الاقتراحات المضمّنة: تفعيل تلقائي

111b8d587330ec74.png

في شريط الحالة في أسفل الصفحة، انقر على رمز السحابة الإلكترونية - تسجيل الدخول واتّبِع خطوات تسجيل الدخول.

إذا سبق أن سجّلت الدخول، سيعرض شريط الحالة Cloud Code - ليس هناك مشروع.

انقر فوق "Cloud Code" (رمز السحابة) - لن يظهر أي مشروع وستظهر لوحة الإجراءات المنسدلة في الأعلى. انقر على اختيار مشروع على Google Cloud.

3241a59811e3c84a.png

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

c5358fc837588fe.png

حدد PROJECT_ID من قائمة المشروعات.

يتم تعديل شريط الحالة السفلي لعرض رقم تعريف مشروعك. وفي حال عدم حدوث ذلك، قد تحتاج إلى إعادة تحميل علامة التبويب "محرِّر Cloud Shell".

انقر على رمز Duet AI d97fc4e7b594c3af.png في شريط القوائم الأيمن، وستظهر نافذة المحادثة في Duet AI. إذا ظهرت رسالة تشير إلى اختيار مشروع Google Cloud Platform. انقر على المشروع وأعِد اختياره.

ستظهر الآن نافذة محادثة Duet AI.

781f888360229ca6.png

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

d3234d237f00fdbb.png

لاستخدام خدمة الشحن الجديدة في Google Cloud Platform، يجب أن تتوفّر لديك المَراجع التالية من Google Cloud Platform:

  1. مثيل Cloud SQL مع قاعدة بيانات.
  2. مجموعة GKE لتشغيل الخدمة المضمّنة في الحاوية.
  3. Artifact Registry لتخزين صورة Docker
  4. مستودع مصدر السحابة الإلكترونية للرمز البرمجي

في الوحدة الطرفية 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. تطوير خدمة python Flask

9745ba5c70782e76.png

ستتألف الخدمة التي سننشئها في النهاية من الملفات التالية. لا تحتاج إلى إنشاء هذه الملفات الآن وسيتم إنشاؤها واحدًا تلو الآخر من خلال اتّباع التعليمات أدناه:

  1. package-service.yaml - مواصفات واجهة برمجة التطبيقات المفتوحة لخدمة الحزمة التي تتضمن بيانات مثل الطول والعرض والوزن وتعليمات المناولة الخاصة.
  2. data_model.py - نموذج البيانات لمواصفات واجهة برمجة تطبيقات خدمة الحزمة. تنشئ أيضًا جدول packages في قاعدة بيانات product_details.
  3. connect_connector.py: اتصال CloudSQL (يعرّف المحرّك والجلسة وقاعدة ORM الأساسية)
  4. db_init.py: إنشاء عيّنات بيانات في جدول packages
  5. main.py: خدمة Python Flask مع نقطة نهاية GET لاسترداد تفاصيل الحزمة من بيانات packages استنادًا إلى product_id.
  6. test.py - اختبار الوحدة
  7. requirement.txt - متطلبات Python
  8. Dockerfile - لتضمين هذا التطبيق

إذا واجهت أي مشاكل ثابتة أثناء التمارين، يمكنك الاطّلاع على الملفات النهائية في ملحق هذا الدرس التطبيقي حول الترميز.

في الخطوة السابقة، أنشأت مستودع Cloud Source. استنساخ المستودع. ستنشئ ملفات التطبيق في مجلد المستودع المنسوخ.

في الوحدة الطرفية Cloud Shell، شغِّل الأمر التالي لانسخ المستودع.

cd ~
gcloud source repos clone shipping shipping
cd ~/shipping 

افتح الشريط الجانبي للمحادثة في Duet AI من القائمة اليمنى في "محرِّر Cloud Shell". يبدو الرمز مثل 8b135a000b259175.png. يمكنك الآن استخدام Duet AI للحصول على مساعدة بشأن الرمز البرمجي.

package-service.yaml

بدون فتح أي ملفات، اطلب من Duet إنشاء إحدى مواصفات واجهة برمجة التطبيقات المفتوحة لخدمة الشحن.

المطالبة 1: إنشاء مواصفات yaml في OpenAPI لخدمة تقدم معلومات الشحن والحزمة باستخدام معرّف رقمي للمنتج. ويجب أن تتضمّن الخدمة معلومات عن ارتفاع الطرود وعرضها وعمقها ووزنها وأي تعليمات خاصة حول المناولة.

ba12626f491a1204.png

هناك ثلاثة خيارات مدرجة في أعلى يسار نافذة الرمز التي تم إنشاؤها.

يمكنك COPY 71194556d8061dae.pngالرمز ولصقه في ملف.

يمكنك ADD df645de8c65607a.png إضافة الرمز إلى الملف المفتوح حاليًا في "محرّر إعلانات Google".

أو يمكنك OPEN a4c7ed6d845df343.png الرمز في ملف جديد.

انقر على الرمز OPEN a4c7ed6d845df343.png في ملف جديد.

انقر على CTRL/CMD + s لحفظ الملف وتخزين الملف في مجلد التطبيق باسم ملف باسم package-service.yaml. انقر على "موافق".

f6ebd5b836949366.png

الملف الأخير موجود في قسم APPENDIX من هذا الدرس التطبيقي حول الترميز. وإذا لم يحدث ذلك، يمكنك إجراء التغييرات المناسبة يدويًا.

يمكنك أيضًا تجربة طلبات مختلفة للاطّلاع على ردود Duet AI.

يمكنك إعادة ضبط سجلّ محادثات Duet AI من خلال النقر على رمز المهملات f574ca2c1e114856.png في أعلى الشريط الجانبي في Duet AI.

data_model.py

بعد ذلك، يمكنك إنشاء ملف نموذج البيانات بايثون للخدمة بناءً على مواصفات OpenAPI.

بعد فتح الملف package-service.yaml، أدخِل الطلب التالي.

المطالبة 1: باستخدام ORM بلغة python sqlalchemy، يمكنك إنشاء نموذج بيانات لخدمة واجهة برمجة التطبيقات هذه. عليك أيضًا تضمين دالة منفصلة ونقطة إدخال رئيسية لإنشاء جداول قاعدة البيانات.

b873a6a28bd28ca1.png

لنلقِ نظرة على كل جزء تم إنشاؤه. لا يزال 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 a4c7ed6d845df343.png في سير عمل جديد للملفات على النحو السابق. احفظ الرمز في ملف باسم data_model.py (يُرجى ملاحظة استخدام الشرطة السفلية في الاسم وليس شرطة).

يمكنك إعادة ضبط سجلّ محادثات Duet AI من خلال النقر على رمز المهملات f574ca2c1e114856.png في أعلى الشريط الجانبي في Duet AI.

connect-connector.py

أنشِئ موصِّل CloudSQL.

بعد فتح ملف data_model.py، أدخِل الطلبات التالية.

الطلب 1: باستخدام مكتبة cloud-sql-python-connector، إنشاء دالة تهيئ مجموعة اتصالات لمثيل Cloud SQL من Postgres

ed05cb6ff85d34c5.png

يُرجى العِلم أنّ الردّ لا يستخدم مكتبة "cloud-sql-python-connector". يمكنك تحسين الطلبات من خلال إضافة تذكير تلقائي إلى Duet AI، وذلك من خلال إضافة تفاصيل إلى سلسلة المحادثات نفسها.

لنستخدم طلبًا آخر.

المطالبة 2: يجب استخدام مكتبة cloud-sql-python-connector.

d09095b44dde35bf.png

تأكّد من أنّه يستخدم مكتبة cloud-sql-python-connector.

استخدام الرمز OPEN a4c7ed6d845df343.png في سير عمل جديد للملفات على النحو السابق. احفظ الرمز في ملف باسم connect_conector.py. قد تحتاج إلى استيراد مكتبة pg8000 يدويًا، ويُرجى الاطّلاع على الملف أدناه.

يمكنك محو سجلّ محادثات Duet AI، وفتح الملف connect_connector.py، يمكنك إنشاء عمليات ORM DB engine وsessionmaker وbase لاستخدامها في التطبيق.

المطالبة 1: إنشاء محرك وفئة صانع جلسات وقاعدة ORM باستخدام طريقة Connect_with_connector

6e4214b72ab13a63.png

قد يُلحق الرد engine وSession وBase في ملف connect_connector.py.

الملف الأخير موجود في قسم APPENDIX من هذا الدرس التطبيقي حول الترميز. وإذا لم يحدث ذلك، يمكنك إجراء التغييرات المناسبة يدويًا.

يمكنك أيضًا تجربة طلبات مختلفة للاطّلاع على الصيغة المحتملة لردود Duet AI.

يمكنك إعادة ضبط سجلّ محادثات Duet AI من خلال النقر على رمز المهملات f574ca2c1e114856.png في أعلى الشريط الجانبي في Duet AI.

جارٍ تحديث data_model.py

عليك استخدام المحرّك الذي أنشأته في الخطوة السابقة (في ملف connect_connector.py) لإنشاء جدول في قاعدة بيانات CloudSQL.

محو سجلّ محادثات Duet AI افتح ملف data_model.py. جرِّب الطلب التالي.

المطالبة 1: في الدالة الرئيسية، قم باستيراد واستخدام المحرك منconnect_connector.py

2e768c9b6c523b9a.png

من المفترض أن يظهر لك الرد الذي يستورد engine من connect_connector (بالنسبة إلى CloudSQL). وتستخدم create_table هذا المحرّك (بدلاً من قاعدة البيانات المحلية التلقائية sqlite).

يجب تعديل ملف data_model.py.

الملف الأخير موجود في قسم APPENDIX من هذا الدرس التطبيقي حول الترميز. وإذا لم يحدث ذلك، يمكنك إجراء التغييرات المناسبة يدويًا.

يمكنك أيضًا تجربة طلبات مختلفة للاطّلاع على ردود Duet AI المختلفة.

يمكنك إعادة ضبط سجلّ محادثات Duet AI من خلال النقر على رمز المهملات f574ca2c1e114856.png في أعلى الشريط الجانبي في Duet AI.

requirements.txt

أنشئ ملف requirements.txt للتطبيق.

افتح كلاً من connect_connector.py وملف data_model.py وأدخِل الطلب التالي.

الطلب 1: إنشاء ملف متطلبات pip لنموذج البيانات والخدمة هذا

الطلب 2: إنشاء ملف متطلبات pip لنموذج البيانات هذا وهذه الخدمة باستخدام أحدث الإصدارات

69fae373bc5c6a18.png

تأكَّد من صحة الأسماء والنُسخ. على سبيل المثال، في الردّ أعلاه، اسم 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 من خلال النقر على رمز المهملات f574ca2c1e114856.png في أعلى الشريط الجانبي في 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

اكتب \q للخروج من CloudSQL.

db_init.py

بعد ذلك، لنضيف بعض نماذج البيانات إلى جدول packages.

محو سجلّ محادثات Duet AI بعد فتح ملف data_model.py، جرِّب الطلبات التالية.

الطلب 1: إنشاء دالة تنشئ 10 نماذج لصفوف الحِزَم وتطبيقها في جدول الحِزم

المطالبة 2: باستخدام الجلسة منconnect_connector، إنشاء دالة تنشئ 10 صفوف لنماذج الحِزم وتطبيقها في جدول الحِزم

34a9afc5f04ba5.png

استخدام الرمز OPEN a4c7ed6d845df343.png في سير عمل جديد للملفات على النحو السابق. احفظ الرمز في ملف باسم db_init.py.

الملف الأخير موجود في قسم APPENDIX من هذا الدرس التطبيقي حول الترميز. وإذا لم يحدث ذلك، يمكنك إجراء التغييرات المناسبة يدويًا.

يمكنك أيضًا تجربة طلبات مختلفة للاطّلاع على ردود Duet AI المختلفة.

يمكنك إعادة ضبط سجلّ محادثات Duet AI من خلال النقر على رمز المهملات f574ca2c1e114856.png في أعلى الشريط الجانبي في 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)

اكتب \q للخروج من CloudSQL.

main.py

أثناء فتح الملفات data_model.py وpackage-service.yaml وconnect_connector.py، يمكنك إنشاء main.py للتطبيق.

الطلب 1: استخدام مكتبة Python flask - إنشاء عملية تنفيذ تستخدم نقاط نهاية http في هذه الخدمة

المطالبة 2: باستخدام مكتبة بايثون الميزات - إنشاء تنفيذ يستخدم نقاط نهاية استراحة http لهذه الخدمة. استخدام أداة SessionMaker منconnect_conector.py إلى بيانات الحزم واستخدامها.

المطالبة 3: باستخدام مكتبة بايثون flask - إنشاء تنفيذ يستخدم نقاط نهاية استراحة http لهذه الخدمة. استخدام الحزمة من data_model.py وsessionMaker منconnect_conector.py إلى بيانات الحزم.

الطلب 4: باستخدام مكتبة بايثون flask - إنشاء تنفيذ يستخدم نقاط نهاية http في هذه الخدمة. استيراد واستخدام الحزمة من data_model.py وsessionMaker منconnect_conector.py إلى بيانات الحزم. استخدام عنوان IP المضيف 0.0.0.0 للتطبيق app.run

6d794fc52a90e6ae.png

يُرجى تعديل متطلبات "main.py".

طلب: إنشاء ملف متطلبات لنظام التشغيلMain.py

1cc0b318d2d4ca2f.png

إلحاق هذا الإجراء بملف requirements.txt. تأكد من استخدام الإصدار 3.0.0 من Flask.

استخدام الرمز OPEN a4c7ed6d845df343.png في سير عمل جديد للملفات على النحو السابق. احفظ الرمز في ملف باسم main.py.

الملف الأخير موجود في قسم APPENDIX من هذا الدرس التطبيقي حول الترميز. وإذا لم يحدث ذلك، يمكنك إجراء التغييرات المناسبة يدويًا.

يمكنك إعادة ضبط سجلّ محادثات Duet AI من خلال النقر على رمز المهملات f574ca2c1e114856.png في أعلى الشريط الجانبي في 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: إنشاء اختبارات الوحدات

e861e5b63e1b2657.png

استخدام الرمز OPEN a4c7ed6d845df343.png في سير عمل جديد للملفات على النحو السابق. احفظ الرمز في ملف باسم test.py.

في الدالة test_get_package، يجب تحديد product_id. يمكنك إضافته يدويًا.

الملف الأخير موجود في قسم APPENDIX من هذا الدرس التطبيقي حول الترميز. وإذا لم يحدث ذلك، يمكنك إجراء التغييرات المناسبة يدويًا.

يمكنك إعادة ضبط سجلّ محادثات Duet AI من خلال النقر على رمز المهملات f574ca2c1e114856.png في أعلى الشريط الجانبي في Duet AI.

جارٍ إجراء اختبارات الوحدة

أجرِ اختبار الوحدة.

python test.py

تشبه النتيجة ما يلي:

.
----------------------------------------------------------------------
Ran 1 test in 1.061s

OK

أغلِق جميع الملفات في "محرِّر Cloud Shell" وامحُ سجلّ المحادثات من خلال النقر على رمز المهملات 1ecccfe10d6c540.png في شريط الحالة العلوي.

ملف شامل

إنشاء Dockerfile لهذا التطبيق.

افتح main.py وجرِّب الطلبات التالية.

الطلب 1: إنشاء ملف Dockerfile لهذا التطبيق

المطالبة 2: إنشاء ملف Dockerfile لهذا التطبيق. انسخ كل الملفات إلى الحاوية.

9c473caea437a5c3.png

يجب أيضًا ضبط السمة ENVARS لكل من INSTANCE_CONNECTION_NAME وDB_USER وDB_PASS وDB_NAME. يمكنك إجراء ذلك يدويًا. يجب أن يظهر الملف الشامل على النحو التالي:

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 a4c7ed6d845df343.png في سير عمل جديد للملفات على النحو السابق. احفظ التعليمة البرمجية في ملف يسمى Dockerfile.

الملف الأخير موجود في قسم APPENDIX من هذا الدرس التطبيقي حول الترميز. وإذا لم يحدث ذلك، يمكنك إجراء التغييرات المناسبة يدويًا.

تشغيل التطبيق محليًا

مع فتح "Dockerfile"، جرِّب الطلب التالي.

المطالبة 1: كيف أشغِّل حاوية على الجهاز باستخدام ملف Docker هذا

570fd5c296ca8c83.png

اتّبِع التعليمات.

# 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

انتظِر إلى أن تعمل مجموعات الأجهزة اللوحية ويتم تخصيص عنوان 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 من حساب خدمة "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

بعد إعادة تشغيل المجموعة، حاوِل الوصول إلى خدمة 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 >. أعباء العمل

d225b1916c829167.png

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

1d0459141483d6a7.png

انقر على رمز View in Log Explorer (مستكشف السجلّات) df8b9d19a9fe4c73.pngعلى يسار شريط الحالة. يؤدي ذلك إلى فتح نافذة مستكشف السجلّات جديدة.

e86d1c265e176bc4.png

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

d6af045cf03008bc.png

يمكنك قراءة شرح الخطأ.

بعد ذلك، لنطلب من Duet AI مساعدتك في تحديد الخطأ وحلّها.

جرِّب الطلب التالي.

المطالبة 1: مساعدتي في تحديد هذا الخطأ وحلّها

9288dd6045369167.png

أدخِل رسالة الخطأ في الطلب.

الطلب 2: محظور: يبدو أن العنصر الرئيسي المُصدَّق عليه لإدارة الهوية وإمكانية الوصول غير مُصرَّح له بتقديم طلب من واجهة برمجة التطبيقات. إثبات صحة "واجهة برمجة تطبيقات المشرف في Cloud SQL" يتم تفعيلها ضمن مشروع Google Cloud Platform و"عميل Cloud SQL". منح الدور إلى المسؤول الرئيسي عن "إدارة الهوية وإمكانية الوصول"

f1e64fbdc435d31c.png

وِبَعْدْ كِدَهْ.

الطلب 3: كيف يمكنني تعيين دور "عميل Cloud SQL" إلى حساب خدمة Google باستخدام gcloud؟

bb8926b995a8875c.png

أسنِد دور "عميل 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 بنجاح في تسجيل الدخول إلى السحابة الإلكترونية ومستكشف السجلّات وميزة شرح السجلّات لتحديد المشكلة وحلّها.

8. الخاتمة

تهانينا! لقد أكملت هذا الدرس التطبيقي حول الترميز بنجاح.

في هذا الدرس التطبيقي حول الترميز، تعلمت ما يلي:

  1. تفعيل Duet AI في مشروع Google Cloud Platform وإعداده للاستخدام في بيئة تطوير متكاملة (IDE) وCloud Console
  2. استخدام Duet AI لإنشاء الرموز البرمجية وإكمالها وشرحها
  3. يمكنك استخدام Duet AI لتوضيح مشكلة في التطبيق وحلّها.
  4. ميزات 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

ملف شامل

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"]