1. Mục tiêu
Mục đích của hội thảo này là cung cấp thông tin giáo dục thực tế về Duet AI cho người dùng và chuyên gia.
Trong lớp học lập trình này, bạn sẽ tìm hiểu những nội dung sau:
- Kích hoạt Duet AI trong dự án GCP của bạn và định cấu hình để sử dụng trong một IDE và Cloud Console.
- Sử dụng Duet AI để tạo, hoàn thành và giải thích mã.
- Sử dụng Duet AI để giải thích và khắc phục vấn đề về ứng dụng.
- Các tính năng của Duet AI như trò chuyện trên IDE và trò chuyện nhiều lượt, so sánh tính năng trò chuyện với tính năng tạo mã nội tuyến, các thao tác thông minh như giải thích mã và xác nhận đọc thuộc lòng, v.v.
Narrative
Để minh hoạ cách sử dụng Duet AI cho nhà phát triển một cách chân thực trong quá trình phát triển hằng ngày, các hoạt động của hội thảo này diễn ra trong một bối cảnh tường thuật.
Một nhà phát triển mới gia nhập một công ty thương mại điện tử. Họ có nhiệm vụ thêm một dịch vụ mới vào ứng dụng thương mại điện tử hiện có (bao gồm nhiều dịch vụ). Dịch vụ mới này cung cấp thêm thông tin (kích thước, trọng lượng, v.v.) về các sản phẩm trong danh mục sản phẩm. Dịch vụ này sẽ giúp bạn có phí vận chuyển thấp hơn/hợp lý hơn dựa trên kích thước và trọng lượng của sản phẩm.
Vì là nhà phát triển mới của công ty, nên họ sẽ sử dụng Duet AI để tạo, giải thích và lập tài liệu về mã.
Sau khi dịch vụ được mã hoá, quản trị viên nền tảng sẽ sử dụng Duet AI (tính năng trò chuyện) để giúp tạo cấu phần phần mềm (vùng chứa Docker) và các tài nguyên cần thiết để triển khai cấu phần phần mềm đó vào GCP (ví dụ: Artifact Registry, quyền IAM, kho lưu trữ mã, cơ sở hạ tầng điện toán, tức là GKE hoặc CloudRun, v.v.)
Sau khi triển khai ứng dụng lên GCP, nhà điều hành ứng dụng/SRE sẽ sử dụng Duet AI (và Cloud Ops) để giúp khắc phục lỗi trong dịch vụ mới.
Vai trò
Hội thảo này đề cập đến những người dùng sau:
- Nhà phát triển ứng dụng – Cần có một số kiến thức về lập trình và phát triển phần mềm.
Phiên bản này của hội thảo Duet AI chỉ dành cho nhà phát triển. Bạn không cần có kiến thức về tài nguyên đám mây GCP. Bạn có thể tìm thấy các tập lệnh về cách tạo tài nguyên GCP cần thiết để chạy ứng dụng này tại đây. Bạn có thể làm theo hướng dẫn trong tài liệu này để triển khai các tài nguyên GCP cần thiết.
2. Chuẩn bị môi trường
Kích hoạt Duet AI
Bạn có thể kích hoạt Duet AI trong một dự án trên GCP thông qua API (gcloud hoặc các công cụ IaC như Terraform) hoặc thông qua giao diện người dùng Cloud Console.
Để kích hoạt Duet AI trong một dự án trên Google Cloud, bạn cần bật Cloud AI Companion API và cấp cho người dùng các vai trò Quản lý danh tính và quyền truy cập (IAM) của Người dùng Cloud AI Companion và Người xem mức sử dụng dịch vụ.
Qua gcloud
Kích hoạt Cloud Shell:
Định cấu hình PROJECT_ID, USER và bật 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}
Kết quả sẽ như sau:
Updated property [core/project]. Operation "operations/acat.p2-60565640195-f37dc7fe-b093-4451-9b12-934649e2a435" finished successfully.
Cấp vai trò Quản lý danh tính và quyền truy cập (IAM) cho Người dùng Cloud AI Companion và Người xem mức sử dụng dịch vụ cho tài khoản NGƯỜI DÙNG. Cloud Companion API nằm sau các tính năng trong cả IDE và bảng điều khiển mà chúng ta sẽ sử dụng. Quyền xem thông tin sử dụng dịch vụ được dùng để kiểm tra nhanh trước khi bật giao diện người dùng trong bảng điều khiển (để giao diện người dùng Duet chỉ xuất hiện trong những dự án đã bật 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
Kết quả sẽ như sau:
... - members: - user:<YOUR USER ACCOUNT> role: roles/cloudaicompanion.user ... - members: - user:<YOUR USER ACCOUNT> role: roles/serviceusage.serviceUsageViewer
Thông qua Cloud Console
Để bật API này, hãy chuyển đến trang Cloud AI Companion API trong bảng điều khiển Google Cloud.
Trong bộ chọn dự án, hãy chọn một dự án.
Nhấp vào Bật.
Trang này sẽ cập nhật và cho biết trạng thái Đã bật. Duet AI hiện đã có trong dự án trên đám mây của Google Cloud đã chọn cho tất cả người dùng có vai trò IAM bắt buộc.
Để cấp các vai trò IAM cần thiết để sử dụng Duet AI, hãy chuyển đến trang IAM.
Trong cột Chủ thể, hãy tìm NGƯỜI DÙNG mà bạn muốn cấp quyền truy cập vào Duet AI, sau đó nhấp vào biểu tượng bút chì ✏️ Chỉnh sửa chủ thể trong hàng đó.
Trong bảng Chỉnh sửa quyền truy cập, hãy nhấp vào Thêm vai trò khác.
Trong phần Chọn vai trò, hãy chọn Người dùng Cloud AI Companion.
Nhấp vào Thêm một vai trò khác rồi chọn Người xem mức sử dụng dịch vụ.
Nhấp vào Lưu.
Thiết lập IDE
Nhà phát triển có thể chọn trong số nhiều IDE phù hợp nhất với nhu cầu của họ. Tính năng hỗ trợ lập trình của Duet AI có trong nhiều IDE như Visual Studio Code, IDE của JetBrains (IntelliJ, PyCharm, GoLand, WebStorm và nhiều IDE khác), Cloud Workstations, Cloud Shell Editor.
Trong phòng thí nghiệm này, bạn có thể sử dụng Cloud Workstations hoặc Cloud Shell Editor.
Hội thảo này sử dụng Cloud Shell Editor.
Xin lưu ý rằng Cloud Workstations có thể mất từ 20 đến 30 phút để thiết lập.
Để sử dụng ngay, hãy dùng Cloud Shell Editor.
Mở Cloud Shell Editor bằng cách nhấp vào biểu tượng bút chì ✏️ trong thanh trình đơn trên cùng của Cloud Shell.
Cloud Shell Editor có giao diện người dùng và trải nghiệm người dùng rất giống với VSCode.

Nhấp vào CTRL (trong Windows)/CMD (trong Mac) + , (dấu phẩy) để chuyển đến ngăn Cài đặt.
Trong thanh Tìm kiếm, hãy nhập "duet ai".
Đảm bảo hoặc bật Cloudcode › Duet AI: Enable (Cloudcode › Duet AI: Bật) và Cloudcode › Duet AI › Inline Suggestions: Enable Auto (Cloudcode › Duet AI › Gợi ý nội tuyến: Bật tự động)

Trong Thanh trạng thái ở dưới cùng, hãy nhấp vào Cloud Code – Sign In (Cloud Code – Đăng nhập) rồi làm theo quy trình đăng nhập.
Nếu bạn đã đăng nhập, thanh trạng thái sẽ cho biết Cloud Code – No project (Cloud Code – Không có dự án).
Nhấp vào Cloud Code – No project (Cloud Code – Không có dự án) và một ngăn thả xuống hành động sẽ xuất hiện ở trên cùng. Nhấp vào Chọn một dự án trên đám mây của Google.

Bắt đầu nhập MÃ DỰ ÁN và dự án của bạn sẽ xuất hiện trong danh sách.

Chọn PROJECT_ID của bạn trong danh sách dự án.
Thanh trạng thái ở dưới cùng sẽ cập nhật để cho biết mã dự án của bạn. Nếu không, bạn có thể cần làm mới thẻ Cloud Shell Editor.
Nhấp vào biểu tượng AI
trong thanh trình đơn bên trái để mở cửa sổ trò chuyện của Duet AI. Nếu bạn thấy thông báo Chọn dự án GCP. Nhấp và chọn lại dự án.
Lúc này, bạn sẽ thấy cửa sổ trò chuyện của Duet AI

3. Thiết lập cơ sở hạ tầng

Để chạy dịch vụ vận chuyển mới trong GCP, bạn cần có các tài nguyên GCP sau:
- Một phiên bản Cloud SQL có cơ sở dữ liệu.
- Một cụm GKE để chạy dịch vụ được chứa trong vùng chứa.
- Một Artifact Registry để lưu trữ hình ảnh Docker.
- Một Cloud Source Repository cho mã.
Trong cửa sổ dòng lệnh Cloud Shell, hãy sao chép kho lưu trữ sau đây và chạy các lệnh sau để thiết lập cơ sở hạ tầng trong dự án GCP của bạn.
# 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. Phát triển dịch vụ Flask Python

Dịch vụ mà chúng ta sẽ tạo cuối cùng sẽ bao gồm các tệp sau. Bạn không cần tạo các tệp này ngay bây giờ và sẽ tạo từng tệp theo hướng dẫn bên dưới:
package-service.yaml– Một quy cách API mở cho dịch vụ gói hàng có dữ liệu như chiều cao, chiều rộng, trọng lượng và hướng dẫn xử lý đặc biệt.data_model.py– Mô hình dữ liệu cho thông số kỹ thuật API dịch vụ gói. Đồng thời, tạo bảngpackagestrong DB product_details.connect_connector.py– Kết nối CloudSQL (xác định công cụ, Phiên và ORM cơ sở)db_init.py– Tạo dữ liệu mẫu trong bảngpackages.main.py– Một dịch vụ Python Flask có điểm cuốiGETđể truy xuất thông tin chi tiết về gói từ dữ liệupackagesdựa trên product_id.test.py– Kiểm thử đơn vịrequirement.txt– Yêu cầu về PythonDockerfile– Để đóng gói ứng dụng này vào vùng chứa
Nếu bạn gặp phải vấn đề khó giải quyết trong các bài tập, thì tất cả các tệp cuối cùng đều nằm trong phần PHỤ LỤC của lớp học lập trình này để bạn tham khảo.
Ở bước trước, bạn đã tạo một Kho lưu trữ mã nguồn trên đám mây. Sao chép kho lưu trữ. Bạn sẽ tạo các tệp ứng dụng trong thư mục kho lưu trữ được sao chép.
Trong cửa sổ dòng lệnh Cloud Shell, hãy chạy lệnh sau để sao chép kho lưu trữ.
cd ~ gcloud source repos clone shipping shipping cd ~/shipping
Mở thanh bên trò chuyện của Duet AI trong trình đơn bên trái của Cloud Shell Editor. Biểu tượng này trông như
. Giờ đây, bạn có thể sử dụng Duet AI để được hỗ trợ về mã.
package-service.yaml
Khi không có tệp nào đang mở, hãy yêu cầu Duet tạo một quy cách Open API cho dịch vụ vận chuyển.
Câu lệnh 1: Tạo một quy cách OpenAPI yaml cho một dịch vụ cung cấp thông tin về việc vận chuyển và gói hàng dựa trên mã nhận dạng sản phẩm bằng số. Dịch vụ này phải có thông tin về chiều cao, chiều rộng, độ sâu, trọng lượng của gói hàng và mọi hướng dẫn đặc biệt về cách xử lý.

Có 3 lựa chọn được liệt kê ở trên cùng bên phải của cửa sổ mã được tạo.
Bạn có thể COPY
mã rồi DÁN mã đó vào một tệp.
Bạn có thể ADD
mã vào tệp hiện đang mở trong Trình chỉnh sửa.
Hoặc bạn có thể OPEN
mã này trong một tệp mới.
Nhấp vào OPEN
mã trong một tệp mới.
Nhấp vào CTRL/CMD + s để lưu tệp và lưu trữ tệp trong thư mục ứng dụng có tên tệp là package-service.yaml. Nhấp vào OK.

Tệp cuối cùng nằm trong phần PHỤ LỤC của lớp học lập trình này. Nếu không, hãy tự thực hiện các thay đổi thích hợp.
Bạn cũng có thể thử nhiều câu lệnh để xem câu trả lời của Duet AI.
Xoá nhật ký trò chuyện của Duet AI bằng cách nhấp vào biểu tượng thùng rác
ở đầu thanh bên của Duet AI.
data_model.py
Tiếp theo, bạn sẽ tạo tệp python mô hình dữ liệu cho dịch vụ dựa trên thông số kỹ thuật OpenAPI.
Khi mở tệp package-service.yaml, hãy nhập câu lệnh sau.
Câu lệnh 1: Sử dụng ORM sqlalchemy của python, hãy tạo một mô hình dữ liệu cho dịch vụ API này. Ngoài ra, hãy thêm một hàm riêng biệt và một điểm truy cập chính để tạo các bảng cơ sở dữ liệu.

Hãy xem từng phần được tạo. Duet AI vẫn là một trợ lý và mặc dù có thể giúp bạn viết mã nhanh chóng, nhưng bạn vẫn nên xem xét và hiểu rõ nội dung được tạo trong quá trình viết mã.
Trước tiên, có một Lớp có tên là Package thuộc loại Base xác định mô hình dữ liệu cho cơ sở dữ liệu packages như sau:
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))
Tiếp theo, bạn cần một hàm tạo bảng trong cơ sở dữ liệu như sau:
def create_tables(engine):
Base.metadata.create_all(engine)
Cuối cùng, bạn cần một hàm chính chạy hàm create_tables để thực sự tạo bảng trong cơ sở dữ liệu CloudSQL, chẳng hạn như sau:
if __name__ == '__main__':
from sqlalchemy import create_engine
engine = create_engine('sqlite:///shipping.db')
create_tables(engine)
print('Tables created successfully.')
Lưu ý rằng hàm main đang tạo một công cụ bằng cách sử dụng cơ sở dữ liệu sqlite cục bộ. Để sử dụng CloudSQL, bạn cần thay đổi giá trị này. Bạn sẽ làm việc đó sau.
Sử dụng OPEN
mã trong quy trình tạo tệp mới như trước. Lưu mã trong một tệp có tên là data_model.py (lưu ý dấu gạch dưới trong tên chứ không phải dấu gạch ngang).
Xoá nhật ký trò chuyện của Duet AI bằng cách nhấp vào biểu tượng thùng rác
ở đầu thanh bên của Duet AI.
connect-connector.py
Tạo trình kết nối CloudSQL.
Khi mở tệp data_model.py, hãy nhập các câu lệnh sau.
Câu lệnh 1: Sử dụng thư viện cloud-sql-python-connector, tạo một hàm khởi tạo một nhóm kết nối cho một phiên bản Cloud SQL của Postgres.

Xin lưu ý rằng phản hồi này không sử dụng thư viện cloud-sql-python-connector. Bạn có thể tinh chỉnh câu lệnh để hướng dẫn Duet bằng cách thêm thông tin cụ thể vào cùng một chuỗi trò chuyện.
Hãy dùng một câu lệnh khác.
Lời nhắc 2: Phải sử dụng thư viện cloud-sql-python-connector.

Đảm bảo rằng ứng dụng sử dụng thư viện cloud-sql-python-connector.
Sử dụng OPEN
mã trong quy trình tạo tệp mới như trước. Lưu mã trong một tệp có tên là connect_conector.py. Bạn có thể cần nhập thư viện pg8000 theo cách thủ công, vui lòng xem tệp bên dưới.
Xoá nhật ký trò chuyện của Duet AI và khi mở tệp connect_connector.py, hãy tạo ORM DB engine, sessionmaker và base để dùng trong ứng dụng.
Câu lệnh 1: Tạo một công cụ, lớp sessionmaker và Base ORM bằng phương thức connect_with_connector

Phản hồi có thể nối engine, Session và Base vào tệp connect_connector.py.
Tệp cuối cùng nằm trong phần PHỤ LỤC của lớp học lập trình này. Nếu không, hãy tự thực hiện các thay đổi thích hợp.
Bạn cũng có thể thử nhiều câu lệnh để xem các biến thể tiềm năng của câu trả lời từ Duet AI.
Xoá nhật ký trò chuyện của Duet AI bằng cách nhấp vào biểu tượng thùng rác
ở đầu thanh bên của Duet AI.
Cập nhật data_model.py
Bạn cần sử dụng công cụ mà bạn đã tạo ở bước trước (trong tệp connect_connector.py) để tạo một bảng trong cơ sở dữ liệu CloudSQL.
Xoá nhật ký trò chuyện của Duet AI. Mở tệp data_model.py. Hãy thử câu lệnh sau.
Câu lệnh 1: Trong hàm chính, hãy nhập và sử dụng công cụ từ connect_connector.py

Bạn sẽ thấy phản hồi nhập engine từ connect_connector (đối với CloudSQL). create_table sử dụng công cụ đó (thay vì DB cục bộ sqlite mặc định).
Cập nhật tệp data_model.py.
Tệp cuối cùng nằm trong phần PHỤ LỤC của lớp học lập trình này. Nếu không, hãy tự thực hiện các thay đổi thích hợp.
Bạn cũng có thể thử nhiều câu lệnh để xem các câu trả lời của Duet AI.
Xoá nhật ký trò chuyện của Duet AI bằng cách nhấp vào biểu tượng thùng rác
ở đầu thanh bên của Duet AI.
requirements.txt
Tạo tệp requirements.txt cho ứng dụng.
Mở cả connect_connector.py và tệp data_model.py rồi nhập câu lệnh sau.
Câu lệnh 1: Tạo tệp yêu cầu pip cho mô hình dữ liệu và dịch vụ này
Câu lệnh 2: Tạo tệp yêu cầu pip cho mô hình dữ liệu và dịch vụ này bằng các phiên bản mới nhất

Xác minh rằng tên và phiên bản là chính xác. Ví dụ: trong phản hồi ở trên, cả tên và phiên bản google-cloud-sql-connecter đều không chính xác. Khắc phục các phiên bản theo cách thủ công và tạo một tệp requirements.txt có dạng như sau:
cloud-sql-python-connector==1.2.4
sqlalchemy==1.4.36
pg8000==1.22.0
Trong cửa sổ dòng lệnh, hãy chạy lệnh sau:
pip3 install -r requirements.txt
Xoá nhật ký trò chuyện của Duet AI bằng cách nhấp vào biểu tượng thùng rác
ở đầu thanh bên của Duet AI.
Tạo bảng gói trong CloudSQL
Đặt các biến môi trường cho trình kết nối cơ sở dữ liệu 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
Bây giờ, hãy chạy data_model.py.
python data_model.py
Kết quả sẽ tương tự như sau (hãy kiểm tra mã để xem kết quả thực tế):
Tables created successfully.
Kết nối với phiên bản CloudSQL và kiểm tra xem cơ sở dữ liệu đã được tạo hay chưa.
gcloud sql connect ${INSTANCE_NAME} --user=evolution --database=product_details
Sau khi nhập mật khẩu (cũng là evolution), hãy lấy các bảng.
product_details=> \dt
Kết quả sẽ tương tự như sau:
List of relations Schema | Name | Type | Owner --------+----------+-------+----------- public | packages | table | evolution (1 row)
Bạn cũng có thể kiểm tra mô hình dữ liệu và thông tin chi tiết về bảng.
product_details=> \d+ packages
Kết quả sẽ tương tự như sau:
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
Nhập \q để thoát CloudSQL.
db_init.py
Tiếp theo, hãy thêm một số dữ liệu mẫu vào bảng packages.
Xoá nhật ký trò chuyện của Duet AI. Khi mở tệp data_model.py, hãy thử các câu lệnh sau.
Câu lệnh 1: Tạo một hàm tạo 10 hàng gói mẫu và xác nhận các hàng đó vào bảng gói
Câu lệnh 2: Sử dụng phiên từ connect_connector, tạo một hàm tạo 10 hàng gói mẫu và xác nhận các hàng đó vào bảng packages

Sử dụng OPEN
mã trong quy trình tạo tệp mới như trước. Lưu mã trong một tệp có tên là db_init.py.
Tệp cuối cùng nằm trong phần PHỤ LỤC của lớp học lập trình này. Nếu không, hãy tự thực hiện các thay đổi thích hợp.
Bạn cũng có thể thử nhiều câu lệnh để xem các câu trả lời của Duet AI.
Xoá nhật ký trò chuyện của Duet AI bằng cách nhấp vào biểu tượng thùng rác
ở đầu thanh bên của Duet AI.
Tạo dữ liệu mẫu về gói
Chạy db_init.py từ dòng lệnh.
python db_init.py
Kết quả sẽ tương tự như sau:
Packages created successfully.
Kết nối lại với phiên bản CloudSQL và xác minh rằng dữ liệu mẫu đã được thêm vào bảng gói.
Kết nối với phiên bản CloudSQL và kiểm tra xem cơ sở dữ liệu đã được tạo hay chưa.
gcloud sql connect ${INSTANCE_NAME} --user=evolution --database=product_details
Sau khi nhập mật khẩu (cũng là evolution), hãy lấy tất cả dữ liệu từ bảng packages.
product_details=> SELECT * FROM packages;
Kết quả sẽ tương tự như sau:
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)
Nhập \q để thoát CloudSQL.
main.py
Khi mở các tệp data_model.py, package-service.yaml và connect_connector.py, hãy tạo một main.py cho ứng dụng.
Câu lệnh 1: Sử dụng thư viện python flask – tạo một phương thức triển khai sử dụng các điểm cuối http rest cho dịch vụ này
Câu lệnh 2: Sử dụng thư viện python flask – tạo một quy trình triển khai sử dụng các điểm cuối http rest cho dịch vụ này. nhập và sử dụng SessionMaker từ connect_conector.py để lấy dữ liệu gói.
Câu lệnh 3: Sử dụng thư viện python flask – tạo một phương thức triển khai sử dụng các điểm cuối http rest cho dịch vụ này. Nhập và sử dụng Gói từ data_model.py và SessionMaker từ connect_conector.py cho dữ liệu gói.
Câu lệnh 4: Sử dụng thư viện python flask – tạo một phương thức triển khai sử dụng các điểm cuối http rest cho dịch vụ này. nhập và sử dụng Gói từ data_model.py và SessionMaker từ connect_conector.py cho dữ liệu gói. Sử dụng IP máy chủ lưu trữ 0.0.0.0 cho app.run

Cập nhật các yêu cầu đối với main.py.
Câu lệnh: Tạo tệp requirements cho main.py

Thêm nội dung này vào tệp requirements.txt. Đảm bảo bạn sử dụng Flask phiên bản 3.0.0.
Sử dụng OPEN
mã trong quy trình tạo tệp mới như trước. Lưu mã trong một tệp có tên là main.py.
Tệp cuối cùng nằm trong phần PHỤ LỤC của lớp học lập trình này. Nếu không, hãy tự thực hiện các thay đổi thích hợp.
Xoá nhật ký trò chuyện của Duet AI bằng cách nhấp vào biểu tượng thùng rác
ở đầu thanh bên của Duet AI.
5. Kiểm thử và chạy ứng dụng
Cài đặt các yêu cầu.
pip3 install -r requirements.txt
Chạy main.py.
python main.py
Kết quả sẽ tương tự như sau:
* 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
Từ thiết bị đầu cuối thứ hai, hãy kiểm thử điểm cuối /packages/<product_id>.
curl localhost:5000/packages/1
Kết quả sẽ tương tự như sau:
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
Bạn cũng có thể kiểm thử mọi mã sản phẩm khác trong dữ liệu mẫu.
Nhập CTRL_C để thoát khỏi vùng chứa docker đang chạy trong thiết bị đầu cuối.
Tạo các kiểm thử đơn vị
Khi mở tệp main.py, hãy tạo các kiểm thử đơn vị.
Câu lệnh 1: Tạo các kiểm thử đơn vị.

Sử dụng OPEN
mã trong quy trình tạo tệp mới như trước. Lưu mã trong một tệp có tên là test.py.
Trong hàm test_get_package, bạn phải xác định một product_id. Bạn có thể thêm thẻ này theo cách thủ công.
Tệp cuối cùng nằm trong phần PHỤ LỤC của lớp học lập trình này. Nếu không, hãy tự thực hiện các thay đổi thích hợp.
Xoá nhật ký trò chuyện của Duet AI bằng cách nhấp vào biểu tượng thùng rác
ở đầu thanh bên của Duet AI.
Chạy kiểm thử đơn vị
Chạy kiểm thử đơn vị.
python test.py
Kết quả sẽ tương tự như sau:
. ---------------------------------------------------------------------- Ran 1 test in 1.061s OK
Đóng tất cả các tệp trong Cloud Shell Editor và xoá nhật ký trò chuyện bằng cách nhấp vào biểu tượng thùng rác
trong thanh trạng thái trên cùng.
tệp Docker
Tạo một Dockerfile cho ứng dụng này.
Mở main.py và thử các câu lệnh sau.
Câu lệnh 1: Tạo một Dockerfile cho ứng dụng này.
Câu lệnh 2: Tạo một Dockerfile cho ứng dụng này. Sao chép tất cả các tệp vào vùng chứa.

Bạn cũng cần đặt ENVARS cho INSTANCE_CONNECTION_NAME, DB_USER, DB_PASS và DB_NAME. Bạn có thể làm việc đó theo cách thủ công. Dockerfile của bạn sẽ có dạng như sau:
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"]
Sử dụng OPEN
mã trong quy trình tạo tệp mới như trước. Lưu mã trong một tệp có tên là Dockerfile.
Tệp cuối cùng nằm trong phần PHỤ LỤC của lớp học lập trình này. Nếu không, hãy tự thực hiện các thay đổi thích hợp.
Chạy ứng dụng cục bộ
Khi Dockerfile mở, hãy thử câu lệnh sau.
Câu lệnh 1: Làm cách nào để chạy một vùng chứa cục bộ bằng Dockerfile này

Làm theo hướng dẫn.
# Build docker build -t shipping . # And run docker run -p 5000:5000 -it shipping
Kết quả sẽ tương tự như sau:
* 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
Từ cửa sổ dòng lệnh thứ hai, hãy truy cập vào vùng chứa.
curl localhost:5000/packages/1
Kết quả sẽ tương tự như sau:
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
Ứng dụng trong vùng chứa đang hoạt động.
Nhập CTRL_C để thoát khỏi vùng chứa docker đang chạy trong thiết bị đầu cuối.
Tạo hình ảnh vùng chứa trong Artifact Registry
Tạo hình ảnh vùng chứa và đẩy vào 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
Giờ đây, vùng chứa ứng dụng nằm tại us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping và có thể được triển khai đến GKE.
6. Triển khai ứng dụng vào cụm GKE
Một cụm GKE Autopilot đã được tạo khi bạn tạo các tài nguyên GCP cho hội thảo này. Kết nối với cụm GKE.
gcloud container clusters get-credentials gke1 \
--region=us-central1
Chú thích tài khoản dịch vụ mặc định của Kubernetes bằng tài khoản dịch vụ của Google.
kubectl annotate serviceaccount default iam.gke.io/gcp-service-account=cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com
Kết quả sẽ tương tự như sau:
serviceaccount/default annotated
Chuẩn bị và áp dụng tệp 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
Kết quả sẽ tương tự như sau:
deployment.apps/shipping created service/shipping created
Chờ cho đến khi các Pod đang chạy và Dịch vụ đã được chỉ định địa chỉ IP của trình cân bằng tải bên ngoài.
kubectl get pods kubectl get service shipping
Kết quả sẽ tương tự như sau:
# 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
Đối với các cụm GKE Autopilot, hãy đợi vài phút cho đến khi các tài nguyên sẵn sàng.
Truy cập dịch vụ thông qua địa chỉ EXTERNAL-IP.
export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl http://${EXTERNAL_IP}/packages/1
Kết quả sẽ tương tự như sau:
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
7. Tín chỉ bổ sung: Khắc phục sự cố cho ứng dụng
Xoá vai trò IAM của CloudSQL Client khỏi tài khoản dịch vụ cloudsqlsa. Điều này gây ra lỗi khi kết nối với cơ sở dữ liệu CloudSQL.
gcloud projects remove-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"
Khởi động lại Pod vận chuyển.
kubectl rollout restart deployment shipping
Sau khi Pod khởi động lại, hãy thử truy cập lại dịch vụ shipping.
export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl http://${EXTERNAL_IP}/packages/1
Kết quả sẽ tương tự như sau:
... <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>
Kiểm tra nhật ký bằng cách chuyển đến phần Kubernetes Engine > Workloads (Kubernetes Engine > Tải công việc)

Nhấp vào chế độ triển khai shipping rồi nhấp vào thẻ Nhật ký.

Nhấp vào biểu tượng Xem trong Trình khám phá nhật ký
ở bên phải thanh trạng thái. Thao tác này sẽ mở một cửa sổ Log Explorer (Trình khám phá nhật ký) mới.

Nhấp vào một trong các mục lỗi Traceback, rồi nhấp vào Giải thích mục nhật ký này.

Bạn có thể đọc phần giải thích về lỗi này.
Tiếp theo, hãy để Duet AI giúp bạn khắc phục lỗi.
Hãy thử câu lệnh sau.
Câu lệnh 1: Giúp tôi khắc phục lỗi này

Nhập thông báo lỗi vào câu lệnh.
Lời nhắc 2: Bị cấm: Có vẻ như đối tượng chính IAM đã xác thực không được phép đưa ra yêu cầu API. Xác minh rằng "API Quản trị của Cloud SQL" đã được bật trong dự án GCP của bạn và vai trò "Cloud SQL Client" đã được cấp cho IAM principal

Và sau đó.
Câu hỏi 3: Làm cách nào để chỉ định vai trò ứng dụng Cloud SQL cho một tài khoản dịch vụ của Google bằng gcloud?

Chỉ định vai trò Ứng dụng Cloud SQL cho cloudsqlsa.
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"
Vui lòng đợi một lát rồi thử truy cập lại ứng dụng.
export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl http://${EXTERNAL_IP}/packages/1
Kết quả sẽ tương tự như sau:
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
Bạn đã sử dụng thành công Duet AI trong Cloud Logging, Log Explorer và tính năng Log Explainer để khắc phục vấn đề.
8. Kết luận
Xin chúc mừng! Bạn đã hoàn tất thành công lớp học lập trình này.
Trong lớp học lập trình này, bạn đã tìm hiểu những nội dung sau:
- Kích hoạt Duet AI trong dự án GCP của bạn và định cấu hình để sử dụng trong một IDE và Cloud Console.
- Sử dụng Duet AI để tạo, hoàn thành và giải thích mã.
- Sử dụng Duet AI để giải thích và khắc phục vấn đề về ứng dụng.
- Các tính năng của Duet AI như trò chuyện trên IDE và trò chuyện nhiều lượt, so sánh tính năng trò chuyện với tính năng tạo mã nội tuyến, các thao tác thông minh như giải thích mã và xác nhận đọc thuộc lòng, v.v.
9. Phụ lục
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
tệp 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"]