Codelab Workshop Interaktif Duet AI untuk Developer

1. Tujuan

Tujuan workshop ini adalah memberikan pendidikan Duet AI secara langsung kepada pengguna dan praktisi.

Dalam codelab ini, Anda akan mempelajari hal-hal berikut:

  1. Aktifkan Duet AI di project GCP Anda dan konfigurasikan untuk digunakan di IDE dan Konsol Cloud.
  2. Gunakan Duet AI untuk pembuatan, penyelesaian, dan penjelasan kode.
  3. Menggunakan Duet AI untuk menjelaskan dan memecahkan masalah aplikasi.
  4. Fitur Duet AI seperti chat IDE dan chat multi-giliran, pembuatan kode inline vs. chat, tindakan cerdas seperti penjelasan kode dan pengakuan pembacaan, dan banyak lagi.

Naratif

Untuk menunjukkan cara penggunaan Duet AI untuk Developer secara autentik dalam pengembangan sehari-hari, aktivitas workshop ini berlangsung dalam konteks naratif.

Seorang developer baru bergabung dengan perusahaan e-commerce. Mereka bertugas menambahkan layanan baru ke aplikasi e-commerce yang sudah ada (yang terdiri dari beberapa layanan). Layanan baru ini memberikan informasi tambahan (dimensi, berat, dll.) tentang produk dalam katalog produk. Layanan ini akan memungkinkan biaya pengiriman yang lebih baik/murah berdasarkan dimensi dan berat produk.

Karena developer baru bergabung dengan perusahaan, dia akan menggunakan Duet AI untuk pembuatan, penjelasan, dan dokumentasi Kode.

Setelah layanan dikodekan, administrator platform akan menggunakan Duet AI (chat) untuk membantu membuat artefak (container Docker), dan resource yang diperlukan untuk men-deploy artefak ke GCP (misalnya, Artifact Registry, izin IAM, repositori kode, infrastruktur komputasi, yaitu GKE atau CloudRun, dll.)

Setelah aplikasi di-deploy ke GCP, operator aplikasi/SRE akan menggunakan Duet AI (dan Cloud Ops) untuk membantu memecahkan masalah error di layanan baru.

Persona

Workshop ini mencakup persona berikut:

  1. Developer Aplikasi - Diperlukan pengetahuan tentang pemrograman dan pengembangan software.

Variasi workshop Duet AI ini hanya ditujukan bagi developer. Tidak diperlukan pengetahuan tentang resource cloud GCP. Skrip tentang cara membangun resource GCP yang diperlukan untuk menjalankan aplikasi ini dapat ditemukan di sini. Anda dapat mengikuti petunjuk dalam panduan ini untuk men-deploy resource GCP yang diperlukan.

2. Mempersiapkan lingkungan

Mengaktifkan Duet AI

Anda dapat mengaktifkan Duet AI di project GCP melalui API (gcloud atau alat IaC seperti Terraform) atau melalui UI Konsol Cloud.

Untuk mengaktifkan Duet AI di project Google Cloud, Anda harus mengaktifkan Cloud AI Companion API dan memberikan peran Identity and Access Management (IAM) Cloud AI Companion User dan Service Usage Viewer kepada pengguna.

Melalui gcloud

Aktifkan Cloud Shell:

Konfigurasi PROJECT_ID, USER, dan aktifkan 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}

Outputnya seperti berikut:

Updated property [core/project].
Operation "operations/acat.p2-60565640195-f37dc7fe-b093-4451-9b12-934649e2a435" finished successfully.

Berikan peran Identity and Access Management (IAM) Cloud AI Companion User dan Service Usage Viewer ke akun USER. Cloud Companion API berada di balik fitur di IDE dan konsol yang akan kita gunakan. Izin Usage Viewer layanan digunakan sebagai pemeriksaan cepat sebelum mengaktifkan UI di konsol (sehingga UI Duet hanya muncul di project yang API-nya diaktifkan).

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

Outputnya seperti berikut:

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

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

Melalui Konsol Cloud

Untuk mengaktifkan API, buka halaman Cloud AI Companion API di konsol Google Cloud.

Di pemilih project, pilih project.

Klik Enable.

Halaman diperbarui dan menampilkan status Diaktifkan. Duet AI kini tersedia di project Google Cloud yang dipilih untuk semua pengguna yang memiliki peran IAM yang diperlukan.

Untuk memberikan peran IAM yang diperlukan untuk menggunakan Duet AI, buka halaman IAM.

Di kolom Principal, temukan USER Anda yang ingin Anda beri akses ke Duet AI, lalu klik ikon pensil ✏️ Edit principal di baris tersebut.

Di panel akses Edit, klik Tambahkan peran lain.

Di Pilih peran, pilih Cloud AI Companion User.

Klik Add another role, lalu pilih Service Usage Viewer.

Klik Simpan.

Menyiapkan IDE

Developer dapat memilih dari berbagai IDE yang paling sesuai dengan kebutuhan mereka. Bantuan kode Duet AI tersedia di beberapa IDE seperti Visual Studio Code, JetBrains IDEs (IntelliJ, PyCharm, GoLand, WebStorm, dan lainnya), Cloud Workstations, Cloud Shell Editor.

Dalam lab ini, Anda dapat menggunakan Cloud Workstations atau Cloud Shell Editor.

Workshop ini menggunakan Editor Cloud Shell.

Perhatikan bahwa penyiapan Cloud Workstations dapat memerlukan waktu 20-30 menit.

Untuk segera menggunakannya, gunakan Cloud Shell Editor.

Buka Cloud Shell Editor dengan mengklik ikon pensil ✏️ di panel menu atas Cloud Shell Anda.

Cloud Shell Editor memiliki UI dan UX yang sangat mirip dengan VSCode.

d6a6565f83576063.png

Klik CTRL (di Windows)/CMD (di Mac) + , (koma) untuk membuka panel Setelan.

Di Kotak penelusuran, ketik "duet ai".

Pastikan atau aktifkan Cloudcode › Duet AI: Enable dan Cloudcode › Duet AI › Inline Suggestions: Enable Auto

111b8d587330ec74.png

Di Status Bar bawah, klik Cloud Code - Sign In dan ikuti alur kerja login.

Jika Anda sudah login, status bar akan menampilkan Cloud Code - No project.

Klik Cloud Code - No project dan panel drop-down tindakan akan muncul di bagian atas. Klik Select a Google Cloud project.

3241a59811e3c84a.png

Mulai ketik PROJECT ID Anda dan project Anda akan muncul dalam daftar.

c5358fc837588fe.png

Pilih PROJECT_ID Anda dari daftar project.

Status bar bawah diperbarui untuk menampilkan project ID Anda. Jika tidak, Anda mungkin perlu memuat ulang tab Cloud Shell Editor.

Klik ikon Duet AI d97fc4e7b594c3af.png di menu sebelah kiri, lalu jendela chat Duet AI akan muncul. Jika Anda mendapatkan pesan yang bertuliskan Pilih Project GCP. Klik dan pilih ulang project.

Anda sekarang melihat jendela chat Duet AI

781f888360229ca6.png

3. Menyiapkan infrastruktur

d3234d237f00fdbb.png

Untuk menjalankan layanan pengiriman baru di GCP, Anda memerlukan resource GCP berikut:

  1. Instance Cloud SQL, dengan database.
  2. Cluster GKE untuk menjalankan layanan dalam container.
  3. Artifact Registry untuk menyimpan image Docker.
  4. Cloud Source Repository untuk kode.

Di terminal Cloud Shell, buat clone repo berikut dan jalankan perintah berikut untuk menyiapkan infrastruktur di project GCP Anda.

# 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. Mengembangkan layanan Flask Python

9745ba5c70782e76.png

Layanan yang akan kita buat pada akhirnya akan terdiri dari file berikut. Anda tidak perlu membuat file ini sekarang dan akan membuatnya satu per satu dengan mengikuti petunjuk di bawah:

  1. package-service.yaml - Spesifikasi Open API untuk layanan paket yang memiliki data seperti tinggi, lebar, berat, dan petunjuk penanganan khusus.
  2. data_model.py - Model data untuk spesifikasi API package-service. Juga membuat tabel packages di DB product_details.
  3. connect_connector.py - Koneksi CloudSQL (menentukan mesin, Sesi, dan ORM Dasar)
  4. db_init.py - Membuat contoh data ke dalam tabel packages.
  5. main.py - Layanan Python Flask dengan endpoint GET untuk mengambil detail paket dari data packages berdasarkan product_id.
  6. test.py - Pengujian unit
  7. requirement.txt - Persyaratan Python
  8. Dockerfile - Untuk memasukkan aplikasi ini ke dalam container

Jika Anda mengalami masalah yang sulit selama latihan, semua file akhir berada di LAMPIRAN codelab ini sebagai referensi.

Pada langkah sebelumnya, Anda telah membuat Cloud Source Repository. Buat cloning repositori: Anda akan membuat file aplikasi di folder repositori yang di-clone.

Di terminal Cloud Shell, jalankan perintah berikut untuk membuat clone repositori.

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

Buka sidebar chat Duet AI dari menu sebelah kiri Cloud Shell Editor. Ikonnya terlihat seperti 8b135a000b259175.png. Anda kini dapat menggunakan Duet AI untuk bantuan kode.

package-service.yaml

Tanpa membuka file apa pun, minta Duet untuk membuat spesifikasi Open API untuk layanan pengiriman.

Perintah 1: Buat spesifikasi yaml OpenAPI untuk layanan yang menyediakan informasi pengiriman dan paket berdasarkan ID produk numerik. Layanan harus menyertakan informasi tentang tinggi, lebar, kedalaman, berat paket, dan petunjuk penanganan khusus.

ba12626f491a1204.png

Ada tiga opsi yang tercantum di kanan atas jendela kode yang dihasilkan.

Anda dapat COPY 71194556d8061dae.pngkode dan MENEMPELKANNYA ke dalam file.

Anda dapat ADD df645de8c65607a.png kode ke file yang sedang dibuka di Editor.

Atau Anda dapat OPEN a4c7ed6d845df343.png kode dalam file baru.

Klik OPEN a4c7ed6d845df343.png kode di file baru.

Klik CTRL/CMD + s untuk menyimpan file, dan simpan file di folder aplikasi dengan nama file yang disebut package-service.yaml. Klik OK.

f6ebd5b836949366.png

File akhir ada di bagian LAMPIRAN codelab ini. Jika tidak, lakukan perubahan yang sesuai secara manual.

Anda juga dapat mencoba berbagai perintah untuk melihat respons Duet AI.

Reset histori percakapan Duet AI dengan mengklik ikon sampah f574ca2c1e114856.png di bagian atas sidebar Duet AI.

data_model.py

Selanjutnya, Anda membuat file python model data untuk layanan berdasarkan spesifikasi OpenAPI.

Dengan file package-service.yaml terbuka, masukkan perintah berikut.

Perintah 1: Menggunakan ORM sqlalchemy python, buat model data untuk layanan API ini. Sertakan juga fungsi terpisah dan titik entri utama yang membuat tabel database.

b873a6a28bd28ca1.png

Mari kita lihat setiap bagian yang dihasilkan. Duet AI tetaplah asisten, dan meskipun dapat membantu menulis kode dengan cepat, Anda tetap harus meninjau konten yang dihasilkan dan memahaminya saat Anda menulis.

Pertama, ada Class bernama Package dari kind Base yang menentukan model data untuk database packages seperti berikut:

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))

Selanjutnya, Anda memerlukan fungsi yang membuat tabel di database seperti berikut:

def create_tables(engine):
    Base.metadata.create_all(engine)

Terakhir, Anda memerlukan fungsi utama yang menjalankan fungsi create_tables untuk benar-benar membuat tabel di database CloudSQL, seperti berikut:

if __name__ == '__main__':
    from sqlalchemy import create_engine

    engine = create_engine('sqlite:///shipping.db')
    create_tables(engine)

    print('Tables created successfully.')

Perhatikan bahwa fungsi main membuat mesin menggunakan database sqlite lokal. Untuk menggunakan CloudSQL, Anda harus mengubahnya. Anda akan melakukannya nanti.

Menggunakan OPEN a4c7ed6d845df343.png kode dalam alur kerja file baru seperti sebelumnya. Simpan kode dalam file bernama data_model.py (perhatikan garis bawah dalam nama, bukan tanda hubung).

Reset histori percakapan Duet AI dengan mengklik ikon sampah f574ca2c1e114856.png di bagian atas sidebar Duet AI.

connect-connector.py

Buat konektor CloudSQL.

Dengan file data_model.py terbuka, masukkan perintah berikut.

Perintah 1: Menggunakan library cloud-sql-python-connector, Buat fungsi yang Menginisialisasi kumpulan koneksi untuk instance Cloud SQL Postgres.

ed05cb6ff85d34c5.png

Perhatikan bahwa respons tidak menggunakan library cloud-sql-python-connector. Anda dapat menyempurnakan perintah, untuk memberikan sedikit dorongan kepada Duet, dengan menambahkan detail ke rangkaian percakapan yang sama.

Mari kita gunakan perintah lain.

Perintah 2: Harus menggunakan library cloud-sql-python-connector.

d09095b44dde35bf.png

Pastikan menggunakan library cloud-sql-python-connector.

Menggunakan OPEN a4c7ed6d845df343.png kode dalam alur kerja file baru seperti sebelumnya. Simpan kode dalam file bernama connect_conector.py. Anda mungkin perlu mengimpor library pg8000 secara manual, lihat file di bawah.

Hapus histori chat Duet AI, dan dengan file connect_connector.py terbuka, buat ORM DB engine, sessionmaker, dan base yang akan digunakan dalam aplikasi.

Perintah 1: Buat class engine, sessionmaker, dan Base ORM menggunakan metode connect_with_connector

6e4214b72ab13a63.png

Respons dapat menambahkan engine, Session, dan Base ke file connect_connector.py.

File akhir ada di bagian LAMPIRAN codelab ini. Jika tidak, lakukan perubahan yang sesuai secara manual.

Anda juga dapat mencoba berbagai perintah untuk melihat potensi variasi respons Duet AI.

Reset histori percakapan Duet AI dengan mengklik ikon sampah f574ca2c1e114856.png di bagian atas sidebar Duet AI.

Memperbarui data_model.py

Anda harus menggunakan mesin yang dibuat pada langkah sebelumnya (dalam file connect_connector.py) untuk membuat tabel di database CloudSQL.

Hapus histori chat Duet AI. Buka file data_model.py. Coba perintah berikut.

Perintah 1: Di fungsi utama, impor dan gunakan engine dari connect_connector.py

2e768c9b6c523b9a.png

Anda akan melihat respons yang mengimpor engine dari connect_connector (untuk CloudSQL). create_table menggunakan mesin tersebut (bukan DB lokal sqlite default).

Perbarui file data_model.py.

File akhir ada di bagian LAMPIRAN codelab ini. Jika tidak, lakukan perubahan yang sesuai secara manual.

Anda juga dapat mencoba berbagai perintah untuk melihat berbagai respons Duet AI.

Reset histori percakapan Duet AI dengan mengklik ikon sampah f574ca2c1e114856.png di bagian atas sidebar Duet AI.

requirements.txt

Buat file requirements.txt untuk aplikasi.

Buka file connect_connector.py dan data_model.py, lalu masukkan perintah berikut.

Perintah 1: Buat file persyaratan pip untuk model dan layanan data ini

Perintah 2: Buat file persyaratan pip untuk model dan layanan data ini menggunakan versi terbaru

69fae373bc5c6a18.png

Pastikan nama dan versinya sudah benar. Misalnya, dalam respons di atas, nama dan versi google-cloud-sql-connecter keduanya salah. Perbaiki versi secara manual dan buat file requirements.txt yang terlihat seperti ini:

cloud-sql-python-connector==1.2.4
sqlalchemy==1.4.36
pg8000==1.22.0

Di terminal perintah, jalankan perintah berikut:

pip3 install -r requirements.txt

Reset histori percakapan Duet AI dengan mengklik ikon sampah f574ca2c1e114856.png di bagian atas sidebar Duet AI.

Membuat tabel paket di CloudSQL

Tetapkan variabel lingkungan untuk konektor database 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

Sekarang jalankan data_model.py.

python data_model.py

Outputnya mirip dengan berikut ini (periksa kode untuk melihat apa yang sebenarnya diharapkan):

Tables created successfully.

Hubungkan ke instance CloudSQL dan periksa apakah database telah dibuat.

gcloud sql connect ${INSTANCE_NAME} --user=evolution --database=product_details

Setelah memasukkan sandi (juga evolution), dapatkan tabel.

product_details=> \dt

Outputnya mirip dengan hal berikut ini:

           List of relations
 Schema |   Name   | Type  |   Owner   
--------+----------+-------+-----------
 public | packages | table | evolution
(1 row)

Anda juga dapat memeriksa model data dan detail tabel.

product_details=> \d+ packages

Outputnya mirip dengan hal berikut ini:

                                                                        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

Ketik \q untuk keluar dari Cloud SQL.

db_init.py

Selanjutnya, mari tambahkan beberapa data contoh ke tabel packages.

Hapus histori chat Duet AI. Dengan file data_model.py terbuka, coba perintah berikut.

Perintah 1: Buat fungsi yang membuat 10 baris paket contoh dan melakukan commit ke tabel paket

Perintah 2: Menggunakan sesi dari connect_connector, buat fungsi yang membuat 10 baris paket contoh dan terapkan ke tabel paket

34a9afc5f04ba5.png

Menggunakan OPEN a4c7ed6d845df343.png kode dalam alur kerja file baru seperti sebelumnya. Simpan kode dalam file bernama db_init.py.

File akhir ada di bagian LAMPIRAN codelab ini. Jika tidak, lakukan perubahan yang sesuai secara manual.

Anda juga dapat mencoba berbagai perintah untuk melihat berbagai respons Duet AI.

Reset histori percakapan Duet AI dengan mengklik ikon sampah f574ca2c1e114856.png di bagian atas sidebar Duet AI.

Membuat data paket sampel

Jalankan db_init.py dari command line.

python db_init.py

Outputnya mirip dengan hal berikut ini:

Packages created successfully.

Hubungkan ke instance CloudSQL lagi dan verifikasi bahwa contoh data telah ditambahkan ke tabel paket.

Hubungkan ke instance CloudSQL dan periksa apakah database telah dibuat.

gcloud sql connect ${INSTANCE_NAME} --user=evolution --database=product_details

Setelah memasukkan sandi (juga evolution), dapatkan semua data dari tabel paket.

product_details=> SELECT * FROM packages;

Outputnya mirip dengan hal berikut ini:

 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)

Ketik \q untuk keluar dari Cloud SQL.

main.py

Dengan file data_model.py, package-service.yaml, dan connect_connector.py terbuka, buat main.py untuk aplikasi.

Perintah 1: Menggunakan library flask python - buat implementasi yang menggunakan endpoint REST http untuk layanan ini

Perintah 2: Menggunakan library python flask - buat implementasi yang menggunakan endpoint REST http untuk layanan ini. Impor dan gunakan SessionMaker dari connect_conector.py untuk data paket.

Perintah 3: Menggunakan library flask python - buat penerapan yang menggunakan endpoint REST http untuk layanan ini. Impor dan gunakan Package dari data_model.py dan SessionMaker dari connect_conector.py untuk data paket.

Perintah 4: Menggunakan library flask python - buat penerapan yang menggunakan endpoint REST http untuk layanan ini. Impor dan gunakan Package dari data_model.py dan SessionMaker dari connect_conector.py untuk data paket. Gunakan IP host 0.0.0.0 untuk app.run

6d794fc52a90e6ae.png

Perbarui persyaratan untuk main.py.

Perintah: Buat file persyaratan untuk main.py

1cc0b318d2d4ca2f.png

Tambahkan ini ke file requirements.txt. Pastikan untuk menggunakan Flask versi 3.0.0.

Menggunakan OPEN a4c7ed6d845df343.png alur kerja kode dalam file baru seperti sebelumnya. Simpan kode dalam file bernama main.py.

File akhir ada di bagian LAMPIRAN codelab ini. Jika tidak, lakukan perubahan yang sesuai secara manual.

Reset histori percakapan Duet AI dengan mengklik ikon sampah f574ca2c1e114856.png di bagian atas sidebar Duet AI.

5. Menguji dan menjalankan aplikasi

Instal persyaratan.

pip3 install -r requirements.txt

Jalankan main.py.

python main.py

Outputnya mirip dengan hal berikut ini:

 * 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

Dari terminal kedua, uji endpoint /packages/<product_id>.

curl localhost:5000/packages/1

Outputnya mirip dengan hal berikut ini:

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

Anda juga dapat menguji ID produk lain dalam data contoh.

Masukkan CTRL_C untuk keluar dari container docker yang sedang berjalan di terminal.

Menghasilkan pengujian unit

Dengan file main.py terbuka, buat pengujian unit.

Perintah 1: Buat pengujian unit.

e861e5b63e1b2657.png

Menggunakan OPEN a4c7ed6d845df343.png kode dalam alur kerja file baru seperti sebelumnya. Simpan kode dalam file bernama test.py.

Dalam fungsi test_get_package, product_id harus ditentukan. Anda dapat menambahkannya secara manual.

File akhir ada di bagian LAMPIRAN codelab ini. Jika tidak, lakukan perubahan yang sesuai secara manual.

Reset histori percakapan Duet AI dengan mengklik ikon sampah f574ca2c1e114856.png di bagian atas sidebar Duet AI.

Menjalankan pengujian unit

Jalankan pengujian unit.

python test.py

Outputnya mirip dengan hal berikut ini:

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

OK

Tutup semua file di Cloud Shell Editor dan hapus histori percakapan dengan mengklik ikon sampah 1ecccfe10d6c540.png di status bar atas.

Dockerfile

Buat Dockerfile untuk aplikasi ini.

Buka main.py dan coba perintah berikut.

Perintah 1: Buat Dockerfile untuk aplikasi ini.

Perintah 2: Buat Dockerfile untuk aplikasi ini. Salin semua file ke container.

9c473caea437a5c3.png

Anda juga perlu menyetel ENVARS untuk INSTANCE_CONNECTION_NAME, DB_USER, DB_PASS, dan DB_NAME. Anda dapat melakukannya secara manual. Dockerfile Anda akan terlihat seperti berikut:

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

Menggunakan OPEN a4c7ed6d845df343.png kode dalam alur kerja file baru seperti sebelumnya. Simpan kode dalam file bernama Dockerfile.

File akhir ada di bagian LAMPIRAN codelab ini. Jika tidak, lakukan perubahan yang sesuai secara manual.

Menjalankan aplikasi secara lokal

Dengan Dockerfile terbuka, coba perintah berikut.

Perintah 1: Bagaimana cara menjalankan container secara lokal menggunakan Dockerfile ini

570fd5c296ca8c83.png

Ikuti petunjuknya.

# Build
docker build -t shipping .
# And run
docker run -p 5000:5000 -it shipping

Outputnya mirip dengan hal berikut ini:

 * 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

Dari jendela terminal kedua, akses container.

curl localhost:5000/packages/1

Outputnya mirip dengan hal berikut ini:

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

Aplikasi dalam container berfungsi.

Masukkan CTRL_C untuk keluar dari container docker yang sedang berjalan di terminal.

Membangun image container di Artifact Registry

Bangun image container dan kirim ke 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

Container aplikasi kini berada di us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping yang dapat di-deploy ke GKE.

6. Men-deploy aplikasi ke cluster GKE

Cluster GKE Autopilot dibuat saat Anda membangun resource GCP untuk workshop ini. Hubungkan ke cluster GKE.

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

Anotasikan akun layanan default Kubernetes dengan akun layanan Google.

kubectl annotate serviceaccount default iam.gke.io/gcp-service-account=cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com

Outputnya mirip dengan hal berikut ini:

serviceaccount/default annotated

Siapkan dan terapkan file 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

Outputnya mirip dengan hal berikut ini:

deployment.apps/shipping created
service/shipping created

Tunggu hingga Pod berjalan dan Service memiliki alamat IP load balancer eksternal yang ditetapkan.

kubectl get pods
kubectl get service shipping

Outputnya mirip dengan hal berikut ini:

# 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

Untuk cluster GKE Autopilot, tunggu beberapa saat hingga resource siap.

Akses layanan melalui alamat EXTERNAL-IP.

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

Outputnya mirip dengan hal berikut ini:

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

7. Poin Tambahan: Memecahkan masalah aplikasi

Hapus peran IAM CloudSQL Client dari akun layanan cloudsqlsa. Hal ini menyebabkan error saat terhubung ke database CloudSQL.

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

Mulai ulang Pod pengiriman.

kubectl rollout restart deployment shipping

Setelah Pod dimulai ulang, coba akses layanan shipping lagi.

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

Outputnya mirip dengan hal berikut ini:

...
<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>

Periksa Log dengan membuka Kubernetes Engine > Workloads

d225b1916c829167.png

Klik deployment shipping, lalu tab Logs.

1d0459141483d6a7.png

Klik ikon Lihat di Log Explorer df8b9d19a9fe4c73.png di sisi kanan status bar. Tindakan ini akan membuka jendela Log Explorer baru.

e86d1c265e176bc4.png

Klik salah satu entri error Traceback, lalu klik Explain this Log Entry.

d6af045cf03008bc.png

Anda dapat membaca penjelasan error.

Selanjutnya, minta Duet AI membantu memecahkan masalah error.

Coba perintah berikut.

Perintah 1: Bantu saya memecahkan masalah error ini

9288dd6045369167.png

Masukkan pesan error dalam perintah.

Perintah 2: Dilarang: Akun utama IAM yang diautentikasi tampaknya tidak diizinkan untuk membuat permintaan API. Pastikan ‘Cloud SQL Admin API' diaktifkan dalam project GCP Anda dan peran ‘Cloud SQL Client' telah diberikan kepada akun utama IAM

f1e64fbdc435d31c.png

Lalu.

Perintah 3: Bagaimana cara menetapkan peran Klien Cloud SQL ke akun layanan Google menggunakan gcloud?

bb8926b995a8875c.png

Tetapkan peran Klien Cloud SQL ke cloudsqlsa.

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

Tunggu beberapa saat, lalu coba akses aplikasi lagi.

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

Outputnya mirip dengan hal berikut ini:

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

Anda telah berhasil menggunakan Duet AI di Cloud Logging, Log Explorer, dan fitur Log Explainer untuk memecahkan masalah.

8. Kesimpulan

Selamat! Anda berhasil menyelesaikan codelab ini.

Dalam codelab ini, Anda telah mempelajari hal-hal berikut:

  1. Aktifkan Duet AI di project GCP Anda dan konfigurasikan untuk digunakan di IDE dan Konsol Cloud.
  2. Gunakan Duet AI untuk pembuatan, penyelesaian, dan penjelasan kode.
  3. Menggunakan Duet AI untuk menjelaskan dan memecahkan masalah aplikasi.
  4. Fitur Duet AI seperti chat IDE dan chat multi-giliran, pembuatan kode inline vs. chat, tindakan cerdas seperti penjelasan kode dan pengakuan pembacaan, dan banyak lagi.

9. Lampiran

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

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