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

1. الأهداف

الغرض من ورشة العمل هذه هو تقديم تدريب عملي على Duet AI للمستخدمين والممارسين.

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

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

Narrative

لإظهار كيفية استخدام "Duet AI للمطوّرين" بشكل واقعي في عملية التطوير اليومية، تجري أنشطة ورشة العمل هذه في سياق سردي.

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

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

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

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

الدور الوظيفي

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

  1. مطوّر التطبيقات: يجب أن تكون لديك بعض المعرفة بالبرمجة وتطوير البرامج.

هذه النسخة من ورشة عمل 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.

d6a6565f83576063.png

اضغط على CTRL (في نظام التشغيل Windows)/CMD (في نظام التشغيل Mac) + , (فاصلة) لفتح لوحة "الإعدادات".

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

تأكَّد من تفعيل Cloudcode › Duet AI: Enable وCloudcode › Duet AI › Inline Suggestions: Enable Auto أو فعِّلهما.

111b8d587330ec74.png

في "شريط الحالة" في أسفل الشاشة، انقر على Cloud Code - Sign In واتّبِع خطوات تسجيل الدخول.

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

انقر على Cloud Code - No project (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

لتشغيل خدمة الشحن الجديدة في GCP، تحتاج إلى موارد GCP التالية:

  1. مثيل Cloud SQL يتضمّن قاعدة بيانات
  2. مجموعة GKE لتشغيل الخدمة المستندة إلى الحاويات
  3. مستودع Artifact Registry لتخزين صورة Docker
  4. مستودع 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

9745ba5c70782e76.png

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

  1. package-service.yaml: مواصفات Open API لخدمة الحِزم التي تتضمّن بيانات مثل الارتفاع والعرض والوزن وتعليمات المناولة الخاصة
  2. data_model.py: نموذج بيانات لمواصفات واجهة برمجة التطبيقات الخاصة بحزمة الخدمات، ويتم أيضًا إنشاء جدول packages في قاعدة بيانات product_details.
  3. connect_connector.py - اتصال CloudSQL (يحدّد المحرّك والجلسة وBase 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 Repository. أنشئ نسخة طبق الأصل من المستودع. ستنشئ ملفات التطبيق في مجلد المستودع الذي تم استنساخه.

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

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

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

package-service.yaml

بدون فتح أي ملفات، اطلب من Duet إنشاء مواصفات Open API لخدمة الشحن.

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

ba12626f491a1204.png

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

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

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

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

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

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

f6ebd5b836949366.png

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

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

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

data_model.py

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

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

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

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 بشكل أفضل.

لنجرّب طلبًا آخر.

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

d09095b44dde35bf.png

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

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

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

الطلب 1: إنشاء محرك وفئة sessionmaker وBase ORM باستخدام طريقة connect_with_connector

6e4214b72ab13a63.png

قد يضيف الردّ engine وSession وBase إلى ملف connect_connector.py.

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

يمكنك أيضًا تجربة طلبات مختلفة للاطّلاع على الاختلافات المحتملة في ردود 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

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

يمكنك أيضًا تجربة طلبات مختلفة للاطّلاع على ردود متنوعة من 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

بعد إدخال كلمة المرور (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 صفوف حِزم نموذجية وتثبّتها في جدول الحِزم

34a9afc5f04ba5.png

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

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

يمكنك أيضًا تجربة طلبات مختلفة للاطّلاع على ردود متنوعة من 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

بعد إدخال كلمة المرور (المعروفة أيضًا باسم 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

6d794fc52a90e6ae.png

تعديل متطلبات main.py

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

1cc0b318d2d4ca2f.png

أضِف هذا إلى ملف requirements.txt. تأكَّد من استخدام الإصدار 3.0.0 من Flask.

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

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

أعِد ضبط سجلّ محادثات 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. يمكنك إضافته يدويًا.

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

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

تشغيل اختبارات الوحدات

نفِّذ اختبار الوحدة.

python test.py

يكون الناتج مشابهًا لما يلي:

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

OK

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

ملف شامل

أنشئ Dockerfile لهذا التطبيق.

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

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

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

9c473caea437a5c3.png

عليك أيضًا ضبط 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 a4c7ed6d845df343.png الرمز في سير عمل ملف جديد كما كان من قبل. احفظ الرمز في ملف باسم Dockerfile.

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

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

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

السؤال 1: كيف يمكنني تشغيل حاوية محليًا باستخدام ملف Dockerfile هذا؟

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

انتظِر إلى أن يتم تشغيل وحدات 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 > أحمال العمل

d225b1916c829167.png

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

1d0459141483d6a7.png

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

e86d1c265e176bc4.png

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

d6af045cf03008bc.png

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

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

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

الطلب 1: ساعدني في تحديد المشاكل وحلّها

9288dd6045369167.png

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

الرسالة 2: محظور: يبدو أنّ كيان IAM الذي تمت مصادقته ليس لديه إذن بتقديم طلب بيانات من واجهة برمجة التطبيقات. تأكَّد من تفعيل Cloud SQL Admin API في مشروعك على 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 بنجاح في Cloud Logging ومستكشف السجلات وميزة شرح السجلات لتحديد المشكلة وحلّها.

8. الخاتمة

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

في هذا الدرس العملي، تعرّفت على ما يلي:

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