Duet AI Technical Hands On Workshop Manual for Developers Codelab

۱. اهداف

هدف از این کارگاه، ارائه آموزش عملی Duet AI به کاربران و متخصصان است.

در این آزمایشگاه کد، موارد زیر را یاد می‌گیرید:

  1. Duet AI را در پروژه GCP خود فعال کنید و آن را برای استفاده در IDE و Cloud Console پیکربندی کنید.
  2. از Duet AI برای تولید، تکمیل و توضیح کد استفاده کنید.
  3. از Duet AI برای توضیح و عیب‌یابی یک مشکل در برنامه استفاده کنید.
  4. ویژگی‌های هوش مصنوعی Duet مانند چت IDE و چت چند نوبتی، چت در مقابل تولید کد درون خطی، اقدامات هوشمند مانند توضیح کد و تأیید قرائت و موارد دیگر.

روایت

برای نشان دادن چگونگی استفاده‌ی واقعی از Duet AI برای توسعه‌دهندگان در توسعه‌ی روزمره، فعالیت‌های این کارگاه در یک بستر روایی انجام می‌شود.

یک توسعه‌دهنده جدید به یک شرکت تجارت الکترونیک می‌پیوندد. وظیفه آنها اضافه کردن یک سرویس جدید به برنامه تجارت الکترونیک موجود (که از چندین سرویس تشکیل شده است) است. این سرویس جدید اطلاعات اضافی (ابعاد، وزن و غیره) در مورد محصولات موجود در کاتالوگ محصول ارائه می‌دهد. این سرویس امکان هزینه‌های حمل و نقل بهتر/ارزان‌تر را بر اساس ابعاد و وزن محصول فراهم می‌کند.

از آنجایی که این توسعه‌دهنده تازه وارد شرکت است، از Duet AI برای تولید کد، توضیح و مستندسازی استفاده خواهد کرد.

پس از کدگذاری سرویس، مدیر پلتفرم از Duet AI (چت) برای کمک به ایجاد مصنوع (کانتینر داکر) و منابع مورد نیاز برای استقرار مصنوع در GCP (به عنوان مثال رجیستری مصنوع، مجوزهای IAM، مخزن کد، زیرساخت محاسباتی مانند GKE یا CloudRun و غیره) استفاده خواهد کرد.

پس از استقرار برنامه در GCP، یک اپراتور برنامه/SRE از Duet AI (و Cloud Ops) برای کمک به عیب‌یابی خطا در سرویس جدید استفاده خواهد کرد.

پرسونا

این کارگاه افراد زیر را پوشش می‌دهد:

  1. توسعه‌دهنده اپلیکیشن - آشنایی با برنامه‌نویسی و توسعه نرم‌افزار الزامی است.

این نسخه از کارگاه Duet AI فقط برای توسعه‌دهندگان است. هیچ دانشی در مورد منابع ابری GCP لازم نیست. اسکریپت‌های مربوط به نحوه ساخت منابع GCP مورد نیاز برای اجرای این برنامه را می‌توانید اینجا پیدا کنید. می‌توانید دستورالعمل‌های این راهنما را برای استقرار منابع GCP مورد نیاز دنبال کنید.

۲. آماده‌سازی محیط

فعال‌سازی هوش مصنوعی Duet

شما می‌توانید Duet AI را در یک پروژه GCP یا از طریق API (ابزارهای gcloud یا IaC مانند Terraform) یا از طریق رابط کاربری Cloud Console فعال کنید .

برای فعال کردن Duet AI در یک پروژه Google Cloud، شما API Cloud AI Companion را فعال می‌کنید و نقش‌های Cloud AI Companion User و Service Usage Viewer Identity and Access Management (IAM) را به کاربران اعطا می‌کنید.

از طریق جی‌کلاود

فعال کردن پوسته ابری:

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.

نقش‌های کاربر Cloud AI Companion و مدیریت هویت و دسترسی Service Usage Viewer (IAM) را به حساب کاربری USER اعطا کنید. API Cloud Companion پشت ویژگی‌های موجود در IDE و کنسولی که استفاده خواهیم کرد، قرار دارد. مجوز Service Usage Viewer به عنوان یک بررسی سریع قبل از فعال کردن رابط کاربری در کنسول استفاده می‌شود (به طوری که رابط کاربری Duet فقط در پروژه‌هایی که API در آنها فعال است، ظاهر می‌شود).

gcloud projects add-iam-policy-binding  ${PROJECT_ID} \
--member=user:${USER} --role=roles/cloudaicompanion.user

gcloud projects add-iam-policy-binding  ${PROJECT_ID} \
--member=user:${USER} --role=roles/serviceusage.serviceUsageViewer

خروجی مانند زیر است:

...
- members:
  - user:<YOUR USER ACCOUNT>
  role: roles/cloudaicompanion.user

...
- members:
  - user:<YOUR USER ACCOUNT>
  role: roles/serviceusage.serviceUsageViewer

از طریق کنسول ابری

برای فعال کردن API، به صفحه Cloud Companion API در کنسول Google Cloud بروید.

در انتخابگر پروژه، یک پروژه را انتخاب کنید.

روی فعال کردن کلیک کنید.

صفحه به‌روزرسانی می‌شود و وضعیت «فعال» را نشان می‌دهد. Duet AI اکنون در پروژه انتخاب‌شده Google Cloud برای همه کاربرانی که نقش‌های IAM مورد نیاز را دارند، در دسترس است.

برای اعطای نقش‌های که برای استفاده از Duet AI لازم است، به صفحه IAM بروید.

در ستون Principal ، کاربر (User) خود را که می‌خواهید دسترسی به Duet AI را برای او فعال کنید، پیدا کنید و سپس روی نماد مداد ✏️ ویرایش کاربر اصلی در آن ردیف کلیک کنید.

در پنل دسترسی ویرایش ، روی افزودن نقش دیگر کلیک کنید.

در بخش «انتخاب نقش»، گزینه «کاربر همراه هوش مصنوعی ابری» را انتخاب کنید.

روی «افزودن یک نقش دیگر» کلیک کنید و «نمایشگر میزان استفاده از خدمات» را انتخاب کنید.

روی ذخیره کلیک کنید.

راه‌اندازی IDE

توسعه‌دهندگان می‌توانند از بین IDEهای متنوعی که به بهترین وجه با نیازهایشان مطابقت دارد، انتخاب کنند. کمک کد Duet AI در IDEهای متعددی مانند Visual Studio Code ، IDEهای JetBrains (IntelliJ، PyCharm، GoLand، WebStorm و موارد دیگر)، Cloud Workstations و Cloud Shell Editor موجود است .

در این آزمایشگاه، می‌توانید از Cloud Workstations یا Cloud Shell Editor استفاده کنید.

این کارگاه از ویرایشگر Cloud Shell استفاده می‌کند.

توجه داشته باشید که راه‌اندازی Cloud Workstations می‌تواند ۲۰ تا ۳۰ دقیقه طول بکشد.

برای استفاده فوری، از ویرایشگر Cloud Shell استفاده کنید.

با کلیک روی آیکون مداد ✏️ در نوار منوی بالای پوسته ابری خود، ویرایشگر پوسته ابری را باز کنید.

ویرایشگر Cloud Shell رابط کاربری و تجربه کاربری بسیار مشابهی با VSCode دارد.

d6a6565f83576063.png

برای ورود به پنل تنظیمات ، کلیدهای CTRL (در ویندوز)/CMD (در مک) + , (ویرگول) را فشار دهید.

در نوار جستجو، عبارت «duet ai» را تایپ کنید.

اطمینان یا فعال کردن Cloudcode › Duet AI: فعال و Cloudcode › Duet AI › پیشنهادات درون خطی: فعال کردن خودکار

۱۱۱b8d587330ec74.png

در نوار وضعیت پایین، روی Cloud Code - Sign In کلیک کنید و مراحل ورود به سیستم را دنبال کنید.

اگر قبلاً وارد سیستم شده‌اید، نوار وضعیت عبارت Cloud Code - No project را نشان می‌دهد.

روی Cloud Code کلیک کنید - هیچ پروژه‌ای وجود ندارد و یک پنجره کشویی برای اقدامات در بالا ظاهر می‌شود. روی Select a Google Cloud project کلیک کنید.

3241a59811e3c84a.png

شروع به تایپ شناسه پروژه خود کنید، پروژه شما باید در لیست ظاهر شود.

c5358f837588fe.png

PROJECT_ID خود را از لیست پروژه‌ها انتخاب کنید.

نوار وضعیت پایین به‌روزرسانی می‌شود تا شناسه پروژه شما را نشان دهد. اگر این‌طور نشد، ممکن است لازم باشد برگه ویرایشگر پوسته ابری خود را به‌روزرسانی کنید.

روی آیکون Duet AI کلیک کنید d97fc4e7b594c3af.png در نوار منوی سمت چپ کلیک کنید تا پنجره چت Duet AI ظاهر شود. اگر پیامی مبنی بر انتخاب پروژه GCP دریافت کردید، روی آن کلیک کنید و دوباره پروژه را انتخاب کنید.

اکنون پنجره چت Duet AI را مشاهده می‌کنید.

781f888360229ca6.png

۳. راه‌اندازی زیرساخت

d3234d237f00fdbb.png

برای اجرای سرویس حمل و نقل جدید در GCP، به منابع GCP زیر نیاز دارید:

  1. یک نمونه SQL ابری، با یک پایگاه داده.
  2. یک کلاستر GKE برای اجرای سرویس کانتینری شده.
  3. یک رجیستری مصنوعات برای ذخیره تصویر داکر.
  4. یک مخزن منبع ابری برای کد.

در ترمینال Cloud Shell، مخزن زیر را کلون کنید و دستورات زیر را برای راه‌اندازی زیرساخت در پروژه GCP خود اجرا کنید.

# Set your project
export PROJECT_ID=<INSERT_YOUR_PROJECT_ID>
gcloud config set core/project ${PROJECT_ID}

# Enable Cloudbuild and grant Cloudbuild SA owner role 
export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format 'value(projectNumber)')
gcloud services enable cloudbuild.googleapis.com
gcloud projects add-iam-policy-binding ${PROJECT_ID} --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com --role roles/owner

# Clone the repo
git clone https://github.com/duetailabs/dev.git ~/duetaidev
cd ~/duetaidev

# Run Cloudbuild to create the necessary resources
gcloud builds submit --substitutions=_PROJECT_ID=${PROJECT_ID}

# To destroy all GCP resources, run the following
# gcloud builds submit --substitutions=_PROJECT_ID=${PROJECT_ID} --config=cloudbuild_destroy.yaml

۴. توسعه یک سرویس پایتون فلاسک

9745ba5c70782e76.png

سرویسی که ایجاد خواهیم کرد در نهایت شامل فایل‌های زیر خواهد بود. نیازی به ایجاد این فایل‌ها در حال حاضر نیست و می‌توانید آن‌ها را یکی‌یکی و با دنبال کردن دستورالعمل‌های زیر ایجاد کنید:

  1. package-service.yaml - یک مشخصات API باز برای سرویس بسته که دارای داده‌هایی مانند ارتفاع، عرض، وزن و دستورالعمل‌های ویژه مدیریت است.
  2. data_model.py - مدل داده برای مشخصات API مربوط به package-service. همچنین جدول packages را در پایگاه داده product_details ایجاد می‌کند.
  3. connect_connector.py - اتصال CloudSQL (موتور، جلسه و ORM پایه را تعریف می‌کند)
  4. db_init.py - داده‌های نمونه را در جدول packages تولید می‌کند.
  5. main.py - یک سرویس پایتون فلسک با نقطه پایانی GET برای بازیابی جزئیات بسته از داده‌های packages بر اساس product_id.
  6. test.py - تست واحد
  7. requirement.txt - پیش‌نیازهای پایتون
  8. Dockerfile - برای کانتینرایز کردن این برنامه

اگر در طول تمرین‌ها با هرگونه مشکل مواجه شدید، فایل‌های نهایی همگی در ضمیمه این آزمایشگاه کد برای مرجع قرار دارند.

در مرحله قبل، شما یک مخزن منبع ابری (Cloud Source Repository) ایجاد کردید. مخزن را کپی کنید. فایل‌های برنامه را در پوشه مخزن کپی شده خواهید ساخت.

در ترمینال Cloud Shell، دستور زیر را برای کلون کردن مخزن اجرا کنید.

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

نوار کناری چت Duet AI را از منوی سمت چپ Cloud Shell Editor باز کنید. آیکون آن شبیه به این است: 8b135a000b259175.png اکنون می‌توانید از Duet AI برای کمک در کدنویسی استفاده کنید.

بسته-سرویس.yaml

بدون باز کردن هیچ فایلی، از Duet بخواهید که یک مشخصات Open API برای سرویس حمل و نقل ایجاد کند.

سوال ۱: یک مشخصات OpenAPI yaml برای سرویسی ایجاد کنید که اطلاعات حمل و نقل و بسته‌بندی را با توجه به شناسه عددی محصول ارائه می‌دهد. این سرویس باید شامل اطلاعاتی در مورد ارتفاع، عرض، عمق، وزن و هرگونه دستورالعمل ویژه جابجایی بسته‌ها باشد.

ba12626f491a1204.png

سه گزینه در بالا سمت راست پنجره کد تولید شده وجود دارد.

شما می‌توانید COPY 71194556d8061dae.png کد را وارد کنید و آن را در یک فایل قرار دهید.

شما می‌توانید ADD df645de8c65607a.png کد مربوط به فایل باز شده فعلی در ویرایشگر.

یا می‌توانید OPEN a4c7ed6d845df343.png کد در یک فایل جدید.

روی OPEN کلیک کنید a4c7ed6d845df343.png کد در یک فایل جدید.

برای ذخیره فایل، CTRL/CMD + s را فشار دهید و فایل را در پوشه برنامه با نام فایل package-service.yaml ذخیره کنید. روی OK کلیک کنید.

f6ebd5b836949366.png

فایل نهایی در بخش پیوست این آزمایشگاه کد قرار دارد. اگر اینطور نیست، تغییرات مناسب را به صورت دستی اعمال کنید.

همچنین می‌توانید سوالات مختلفی را امتحان کنید تا پاسخ‌های Duet AI را ببینید.

با کلیک روی نماد سطل زباله، تاریخچه چت Duet AI را بازنشانی کنید f574ca2c1e114856.png در بالای نوار کناری Duet AI.

مدل_داده.py

در مرحله بعد، فایل پایتون مدل داده را برای سرویس بر اساس مشخصات OpenAPI ایجاد می‌کنید.

با باز کردن فایل package-service.yaml ، دستور زیر را وارد کنید.

نکته ۱: با استفاده از ORM پایتون sqlalchemy، یک مدل داده برای این سرویس API ایجاد کنید. همچنین یک تابع جداگانه و یک نقطه ورودی اصلی که جداول پایگاه داده را ایجاد می‌کند، اضافه کنید.

b873a6a28bd28ca1.png

بیایید به هر بخش تولید شده نگاهی بیندازیم. Duet AI هنوز یک دستیار است و اگرچه می‌تواند به سرعت در نوشتن کد کمک کند، اما شما همچنان باید محتوای تولید شده را بررسی کرده و در حین کار آن را درک کنید.

ابتدا، یک کلاس به نام Package of kind 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.

اتصال-اتصال.py

کانکتور CloudSQL را ایجاد کنید.

با باز کردن فایل data_model.py ، دستورات زیر را وارد کنید.

پیشنهاد ۱: با استفاده از کتابخانه cloud-sql-python-connector، تابعی ایجاد کنید که یک connection pool برای یک نمونه Cloud SQL از Postgres راه‌اندازی کند.

ed05cb6ff85d34c5.png

توجه داشته باشید که این پاسخ از کتابخانه cloud-sql-python-connector استفاده نمی‌کند. می‌توانید با اضافه کردن جزئیات به همان رشته چت، پیام‌ها را اصلاح کنید تا Duet کمی مورد توجه قرار گیرد.

بیایید از یک دستور دیگر استفاده کنیم.

نکته ۲: باید از کتابخانه 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 و ORM base را برای استفاده در برنامه تولید کنید.

نکته ۱: ایجاد یک موتور، کلاس 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

برای ایجاد جدول در پایگاه داده CloudSQL، باید از موتوری که در مرحله قبل (در فایل connect_connector.py ) ایجاد کردید، استفاده کنید.

تاریخچه چت Duet AI را پاک کنید. فایل data_model.py را باز کنید. دستور زیر را امتحان کنید.

اعلان ۱: در تابع اصلی، موتور را از connect_connector.py وارد کرده و استفاده کنید.

2e768c9b6c523b9a.png

شما باید engine واردکننده‌ی پاسخ را از connect_connector (برای CloudSQL) ببینید. create_table از آن موتور استفاده می‌کند (به جای پایگاه داده‌ی محلی پیش‌فرض sqlite ).

فایل data_model.py را به‌روزرسانی کنید.

فایل نهایی در بخش پیوست این آزمایشگاه کد قرار دارد. اگر اینطور نیست، تغییرات مناسب را به صورت دستی اعمال کنید.

همچنین می‌توانید سوالات مختلفی را امتحان کنید تا پاسخ‌های مختلف Duet AI را ببینید.

با کلیک روی نماد سطل زباله، تاریخچه چت Duet AI را بازنشانی کنید f574ca2c1e114856.png در بالای نوار کناری Duet AI.

الزامات.txt

یک فایل requirements.txt برای برنامه ایجاد کنید.

هر دو فایل connect_connector.py و data_model.py را باز کنید و عبارت زیر را وارد کنید.

نکته ۱: یک فایل الزامات pip برای این مدل داده و سرویس ایجاد کنید

نکته ۲: با استفاده از آخرین نسخه‌ها، یک فایل الزامات 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

برای خروج از CloudSQL \q را تایپ کنید.

db_init.py

در مرحله بعد، بیایید چند داده نمونه به جدول packages اضافه کنیم.

تاریخچه چت Duet AI را پاک کنید. با باز کردن فایل data_model.py ، دستورالعمل‌های زیر را امتحان کنید.

دستور ۱: تابعی ایجاد کنید که ۱۰ ردیف بسته نمونه ایجاد کند و آنها را در جدول بسته‌ها ثبت کند.

اعلان ۲: با استفاده از جلسه connect_connector، تابعی ایجاد کنید که ۱۰ ردیف بسته نمونه ایجاد کرده و آنها را به جدول بسته‌ها ارسال کند.

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 )، تمام داده‌ها را از جدول packages دریافت کنید.

product_details=> SELECT * FROM packages;

خروجی مشابه زیر است:

 id | product_id | height | width | depth | weight |   special_handling_instructions   
----+------------+--------+-------+-------+--------+-----------------------------------
  1 |          0 |     10 |    10 |    10 |     10 | No special handling instructions.
  2 |          1 |     10 |    10 |    10 |     10 | No special handling instructions.
  3 |          2 |     10 |    10 |    10 |     10 | No special handling instructions.
  4 |          3 |     10 |    10 |    10 |     10 | No special handling instructions.
  5 |          4 |     10 |    10 |    10 |     10 | No special handling instructions.
  6 |          5 |     10 |    10 |    10 |     10 | No special handling instructions.
  7 |          6 |     10 |    10 |    10 |     10 | No special handling instructions.
  8 |          7 |     10 |    10 |    10 |     10 | No special handling instructions.
  9 |          8 |     10 |    10 |    10 |     10 | No special handling instructions.
 10 |          9 |     10 |    10 |    10 |     10 | No special handling instructions.
(10 rows)

برای خروج از CloudSQL \q را تایپ کنید.

فایل اصلی.py

با باز کردن فایل‌های data_model.py ، package-service.yaml و connect_connector.py ، یک main.py برای برنامه ایجاد کنید.

پیشنهاد اول: استفاده از کتابخانه پایتون فلاسک - پیاده‌سازی‌ای ایجاد کنید که از نقاط انتهایی http rest برای این سرویس استفاده کند

نکته ۲: استفاده از کتابخانه پایتون فلاسک - پیاده‌سازی‌ای ایجاد کنید که از نقاط انتهایی http rest برای این سرویس استفاده کند. SessionMaker را از connect_conector.py برای داده‌های بسته‌ها وارد و استفاده کنید.

اعلان ۳: استفاده از کتابخانه flask پایتون - پیاده‌سازی‌ای ایجاد کنید که از نقاط انتهایی http rest برای این سرویس استفاده کند. برای داده‌های packages، Package را از data_model.py و SessionMaker را از connect_conector.py وارد و استفاده کنید.

اعلان ۴: استفاده از کتابخانه flask پایتون - پیاده‌سازی‌ای ایجاد کنید که از نقاط انتهایی http rest برای این سرویس استفاده کند. برای داده‌های packages، Package را از data_model.py و SessionMaker را از connect_conector.py وارد و استفاده کنید. برای app.run از host IP 0.0.0.0 استفاده کنید.

6d794fc52a90e6ae.png

الزامات مربوط به main.py را به‌روزرسانی کنید.

درخواست: ایجاد فایل نیازمندی‌ها برای main.py

۱cc0b318d2d4ca2f.png

این را به فایل requirements.txt اضافه کنید. مطمئن شوید که از نسخه ۳.۰.۰ فلسک استفاده می‌کنید.

با استفاده از OPEN a4c7ed6d845df343.png کد را در یک فایل جدید مانند قبل ذخیره کنید. کد را در فایلی به نام main.py ذخیره کنید.

فایل نهایی در بخش پیوست این آزمایشگاه کد قرار دارد. اگر اینطور نیست، تغییرات مناسب را به صورت دستی اعمال کنید.

با کلیک روی نماد سطل زباله، تاریخچه چت Duet AI را بازنشانی کنید f574ca2c1e114856.png در بالای نوار کناری Duet AI.

۵. تست و اجرای برنامه

الزامات را نصب کنید.

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 را وارد کنید.

تولید تست‌های واحد

با باز کردن فایل main.py ، تست‌های واحد را ایجاد کنید.

دستور شماره ۱: تولید تست‌های واحد.

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 را ببندید و با کلیک روی نماد سطل زباله، تاریخچه چت را پاک کنید. 1ecccfe10d6c540.png در نوار وضعیت بالا.

داکرفایل

برای این برنامه یک Dockerfile ایجاد کنید.

main.py را باز کنید و دستورات زیر را امتحان کنید.

نکته ۱: یک فایل داکر برای این برنامه ایجاد کنید.

مرحله ۲: یک فایل Dockerfile برای این برنامه ایجاد کنید. تمام فایل‌ها را در کانتینر کپی کنید.

9c473caea437a5c3.png

همچنین باید ENVARS برای INSTANCE_CONNECTION_NAME ، DB_USER ، DB_PASS و DB_NAME تنظیم کنید. می‌توانید این کار را به صورت دستی انجام دهید. فایل Docker شما باید به شکل زیر باشد:

FROM python:3.10-slim

WORKDIR /app

COPY . ./

RUN pip install -r requirements.txt

# Add these manually for your project
ENV INSTANCE_CONNECTION_NAME=YOUR_INSTANCE_CONNECTION_NAME
ENV DB_USER=evolution
ENV DB_PASS=evolution
ENV DB_NAME=product_details

CMD ["python", "main.py"]

با استفاده از OPEN a4c7ed6d845df343.png کد را در یک فایل جدید مانند قبل ذخیره کنید. کد را در فایلی به نام Dockerfile ذخیره کنید.

فایل نهایی در بخش پیوست این آزمایشگاه کد قرار دارد. اگر اینطور نیست، تغییرات مناسب را به صورت دستی اعمال کنید.

اجرای محلی برنامه

با باز شدن Dockerfile ، دستور زیر را امتحان کنید.

سوال اول: چگونه می‌توانم با استفاده از این 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 را وارد کنید.

ساخت تصویر کانتینر در رجیستری مصنوعات

تصویر کانتینر را بسازید و آن را به رجیستری مصنوعات (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 مستقر شود.

۶. استقرار برنامه در کلاستر GKE

یک کلاستر GKE Autopilot هنگام ساخت منابع GCP برای این کارگاه ایجاد شد. به کلاستر GKE متصل شوید.

gcloud container clusters get-credentials gke1 \
    --region=us-central1

حساب سرویس پیش‌فرض Kubernetes را با حساب سرویس گوگل حاشیه‌نویسی کنید.

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}

۷. امتیاز اضافی: عیب‌یابی برنامه

نقش 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

پس از راه‌اندازی مجدد پاد، دوباره سعی کنید به سرویس shipping دسترسی پیدا کنید.

export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl http://${EXTERNAL_IP}/packages/1 

خروجی مشابه زیر است:

...
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>

با رفتن به Kubernetes Engine > Workloads ، لاگ‌ها را بررسی کنید.

d225b1916c829167.png

روی گزینه استقرار shipping و سپس تب گزارش‌ها کلیک کنید.

۱d0459141483d6a7.png

روی View در Log Explorer کلیک کنید df8b9d19a9fe4c73.png نماد در سمت راست نوار وضعیت. این یک پنجره جدید Log Explorer باز می‌کند.

e86d1c265e176bc4.png

روی یکی از ورودی‌های خطای Traceback کلیک کنید و سپس روی Explain this Log Entry کلیک کنید.

d6af045cf03008bc.png

می‌توانید توضیح خطا را بخوانید.

در مرحله بعد، بیایید از Duet AI برای عیب‌یابی خطا کمک بگیریم.

دستور زیر را امتحان کنید.

نکته ۱: برای رفع این خطا به من کمک کنید

9288dd6045369167.png

پیام خطا را در قسمت اعلان وارد کنید.

درخواست شماره ۲: ممنوع: به نظر نمی‌رسد مدیر اصلی IAM که احراز هویت شده است، مجاز به درخواست API باشد. تأیید کنید که «Cloud SQL Admin API» در پروژه GCP شما فعال شده باشد و نقش «Cloud SQL Client» به مدیر اصلی IAM اعطا شده باشد.

f1e64fbdc435d31c.png

و سپس.

نکته ۳: چگونه می‌توانم نقش Cloud SQL Client را با استفاده از gcloud به یک حساب سرویس گوگل اختصاص دهم؟

bb8926b995a8875c.png

نقش Cloud SQL Client را به cloudsqlsa اختصاص دهید.

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/cloudsql.client"

چند لحظه صبر کنید و دوباره سعی کنید به برنامه دسترسی پیدا کنید.

export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl http://${EXTERNAL_IP}/packages/1

خروجی مشابه زیر است:

{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}

شما با موفقیت از Duet AI در Cloud Logging ، Log Explorer و ویژگی Log Explainer برای عیب‌یابی مشکل استفاده کردید.

۸. نتیجه‌گیری

تبریک می‌گویم! شما با موفقیت این آزمایشگاه کد را به پایان رساندید.

در این آزمایشگاه کد، موارد زیر را یاد گرفتید:

  1. Duet AI را در پروژه GCP خود فعال کنید و آن را برای استفاده در IDE و Cloud Console پیکربندی کنید.
  2. از Duet AI برای تولید، تکمیل و توضیح کد استفاده کنید.
  3. از Duet AI برای توضیح و عیب‌یابی یک مشکل در برنامه استفاده کنید.
  4. ویژگی‌های هوش مصنوعی Duet مانند چت IDE و چت چند نوبتی، چت در مقابل تولید کد درون خطی، اقدامات هوشمند مانند توضیح کد و تأیید قرائت و موارد دیگر.

۹. پیوست

بسته-سرویس.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

مدل_داده.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.')

فایل اصلی.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()

الزامات.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"]