คู่มือเวิร์กช็อปแนะนำด้านเทคนิคสำหรับ Duet AI สำหรับนักพัฒนาซอฟต์แวร์ Codelab

1. วัตถุประสงค์

เวิร์กช็อปนี้มีจุดประสงค์เพื่อมอบการศึกษาเกี่ยวกับ Duet AI ในทางปฏิบัติแก่ผู้ใช้และผู้ประกอบวิชาชีพ

ในโค้ดแล็บนี้ คุณจะได้เรียนรู้สิ่งต่อไปนี้

  1. เปิดใช้งาน Duet AI ในโปรเจ็กต์ GCP และกำหนดค่าให้ใช้ใน IDE และ Cloud Console
  2. ใช้ Duet AI เพื่อสร้าง เติมให้สมบูรณ์ และอธิบายโค้ด
  3. ใช้ Duet AI เพื่ออธิบายและแก้ปัญหาแอปพลิเคชัน
  4. ฟีเจอร์ Duet AI เช่น แชท IDE และแชทแบบหลายรอบ แชทเทียบกับการสร้างโค้ดในบรรทัด การดำเนินการอัจฉริยะ เช่น คำอธิบายโค้ดและการรับทราบการท่องจำ และอื่นๆ

การบรรยาย

กิจกรรมในเวิร์กช็อปนี้จะเกิดขึ้นในบริบทที่เป็นเรื่องราวเพื่อแสดงให้เห็นว่า Duet AI สำหรับนักพัฒนาซอฟต์แวร์ถูกนำมาใช้ในการพัฒนาในแต่ละวันอย่างไร

นักพัฒนาแอปคนใหม่เข้าร่วมบริษัทอีคอมเมิร์ซ โดยมีหน้าที่เพิ่มบริการใหม่ลงในแอปพลิเคชันอีคอมเมิร์ซที่มีอยู่ (ซึ่งประกอบด้วยหลายบริการ) บริการใหม่นี้จะให้ข้อมูลเพิ่มเติม (ขนาด น้ำหนัก ฯลฯ) เกี่ยวกับผลิตภัณฑ์ในแคตตาล็อกผลิตภัณฑ์ บริการนี้จะช่วยให้คุณทราบค่าจัดส่งที่ถูกลง/ดีขึ้นตามขนาดและน้ำหนักของผลิตภัณฑ์

เนื่องจากนักพัฒนาซอฟต์แวร์เพิ่งเข้ามาทำงานในบริษัท จึงจะใช้ Duet AI เพื่อสร้าง อธิบาย และจัดทำเอกสารโค้ด

หลังจากเขียนโค้ดบริการแล้ว ผู้ดูแลระบบแพลตฟอร์มจะใช้ Duet AI (แชท) เพื่อช่วยสร้างอาร์ติแฟกต์ (คอนเทนเนอร์ Docker) และทรัพยากรที่จำเป็นในการติดตั้งใช้งานอาร์ติแฟกต์ใน GCP (เช่น Artifact Registry, สิทธิ์ IAM, ที่เก็บโค้ด, โครงสร้างพื้นฐานด้านการประมวลผล เช่น GKE หรือ Cloud Run เป็นต้น)

เมื่อแอปพลิเคชันได้รับการติดตั้งใช้งานใน GCP แล้ว ผู้ปฏิบัติงานแอปพลิเคชัน/SRE จะใช้ Duet AI (และ Cloud Ops) เพื่อช่วยแก้ปัญหาข้อผิดพลาดในบริการใหม่

ลักษณะตัวตน

เวิร์กช็อปนี้ครอบคลุมลักษณะตัวตนต่อไปนี้

  1. นักพัฒนาแอปพลิเคชัน - ต้องมีความรู้ด้านการเขียนโปรแกรมและการพัฒนาซอฟต์แวร์

การอบรมเชิงปฏิบัติการ Duet AI รูปแบบนี้มีไว้สำหรับนักพัฒนาแอปเท่านั้น ไม่จำเป็นต้องมีความรู้เกี่ยวกับทรัพยากรระบบคลาวด์ของ GCP ดูสคริปต์สำหรับวิธีสร้างทรัพยากร GCP ที่จำเป็นในการเรียกใช้แอปพลิเคชันนี้ได้ที่นี่ คุณสามารถทำตามวิธีการในคู่มือนี้เพื่อติดตั้งใช้งานทรัพยากร GCP ที่จำเป็น

2. การเตรียมสภาพแวดล้อม

การเปิดใช้งาน Duet AI

คุณเปิดใช้งาน Duet AI ในโปรเจ็กต์ GCP ได้ทั้งผ่าน API (gcloud หรือเครื่องมือ IaC เช่น Terraform) หรือผ่าน UI ของ Cloud Console

หากต้องการเปิดใช้งาน Duet AI ในโปรเจ็กต์ Google Cloud ให้เปิดใช้ Cloud AI Companion API และให้บทบาท Identity and Access Management (IAM) ของผู้ใช้ Cloud AI Companion และผู้มีสิทธิ์ดูการใช้งานบริการแก่ผู้ใช้

ผ่าน gcloud

เปิดใช้งาน Cloud Shell

กำหนดค่า PROJECT_ID, USER และเปิดใช้ Cloud AI Companion API

export PROJECT_ID=<YOUR PROJECT ID>
export USER=<YOUR USERNAME> # Use your full LDAP, e.g. name@example.com
gcloud config set project ${PROJECT_ID}
gcloud services enable cloudaicompanion.googleapis.com --project ${PROJECT_ID}

เอาต์พุตจะมีลักษณะดังนี้

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

มอบบทบาทผู้ใช้ Cloud AI Companion และผู้ดูการใช้งานบริการ Identity and Access Management (IAM) ให้กับบัญชีผู้ใช้ Cloud Companion API อยู่เบื้องหลังฟีเจอร์ทั้งใน IDE และคอนโซลที่เราจะใช้ สิทธิ์ผู้ดูการใช้งานบริการใช้เพื่อตรวจสอบอย่างรวดเร็วก่อนเปิดใช้ UI ในคอนโซล (เพื่อให้ UI ของ 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

ผ่าน Cloud Console

หากต้องการเปิดใช้ API ให้ไปที่หน้า Cloud AI Companion API ในคอนโซล Google Cloud

เลือกโปรเจ็กต์ในเครื่องมือเลือกโปรเจ็กต์

คลิกเปิดใช้

หน้าเว็บจะอัปเดตและแสดงสถานะเป็นเปิดใช้ ตอนนี้ Duet AI พร้อมให้บริการในโปรเจ็กต์ Google Cloud ที่เลือกสำหรับผู้ใช้ทุกคนที่มีบทบาท IAM ที่จำเป็นแล้ว

หากต้องการให้บทบาท IAM ที่จำเป็นต่อการใช้ Duet AI ให้ไปที่หน้า IAM

ในคอลัมน์หลัก ให้ค้นหาผู้ใช้ที่คุณต้องการเปิดใช้สิทธิ์เข้าถึง Duet AI แล้วคลิกไอคอนดินสอ ✏️ แก้ไขหลักในแถวนั้น

ในแผงการเข้าถึงแก้ไข ให้คลิกเพิ่มเพิ่มบทบาทอื่น

ในส่วนเลือกบทบาท ให้เลือกผู้ใช้ Cloud AI Companion

คลิกเพิ่มบทบาทอื่น แล้วเลือกผู้ดูการใช้งานบริการ

คลิกบันทึก

การตั้งค่า 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 Editor

โปรดทราบว่า Cloud Workstations อาจใช้เวลา 20-30 นาทีในการตั้งค่า

หากต้องการใช้ทันที ให้ใช้โปรแกรมแก้ไข Cloud Shell

เปิด Cloud Shell Editor โดยคลิกไอคอนดินสอ ✏️ ในแถบเมนูด้านบนของ Cloud Shell

Cloud Shell Editor มี UI และ UX ที่คล้ายกับ VSCode มาก

d6a6565f83576063.png

คลิก CTRL (ใน Windows)/CMD (ใน Mac) + , (คอมมา) เพื่อเข้าสู่แผงการตั้งค่า

พิมพ์ "Duet AI" ในแถบค้นหา

ตรวจสอบหรือเปิดใช้ Cloudcode › Duet AI: เปิดใช้ และ Cloudcode › Duet AI › คำแนะนำในบรรทัด: เปิดใช้ Auto

111b8d587330ec74.png

คลิก Cloud Code - Sign In ในแถบสถานะด้านล่าง แล้วทำตามเวิร์กโฟลว์การลงชื่อเข้าใช้

หากคุณลงชื่อเข้าใช้อยู่แล้ว แถบสถานะจะแสดง Cloud Code - ไม่มีโปรเจ็กต์

คลิก Cloud Code - ไม่มีโปรเจ็กต์ แล้วแผงแบบเลื่อนลงของการดำเนินการจะปรากฏที่ด้านบน คลิกเลือกโปรเจ็กต์ Google Cloud

3241a59811e3c84a.png

เริ่มพิมพ์รหัสโปรเจ็กต์ แล้วโปรเจ็กต์ควรจะปรากฏในรายการ

c5358fc837588fe.png

เลือก PROJECT_ID จากรายการโปรเจ็กต์

แถบสถานะด้านล่างจะอัปเดตเพื่อแสดงรหัสโปรเจ็กต์ หากไม่ปรากฏ คุณอาจต้องรีเฟรชแท็บ Cloud Shell Editor

คลิกไอคอน Duet AI d97fc4e7b594c3af.pngในแถบเมนูด้านซ้าย แล้วหน้าต่างแชทของ Duet AI จะปรากฏขึ้น หากคุณได้รับข้อความที่ระบุว่า "เลือกโปรเจ็กต์ GCP" คลิกและเลือกโปรเจ็กต์อีกครั้ง

ตอนนี้คุณจะเห็นหน้าต่างแชทของ Duet AI

781f888360229ca6.png

3. การตั้งค่าโครงสร้างพื้นฐาน

d3234d237f00fdbb.png

หากต้องการเรียกใช้บริการจัดส่งใหม่ใน GCP คุณต้องมีทรัพยากร GCP ต่อไปนี้

  1. อินสแตนซ์ Cloud SQL ที่มีฐานข้อมูล
  2. คลัสเตอร์ GKE เพื่อเรียกใช้บริการที่ทำงานในคอนเทนเนอร์
  3. Artifact Registry สำหรับจัดเก็บอิมเมจ Docker
  4. ที่เก็บของ Cloud Source สำหรับโค้ด

ในเทอร์มินัล 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

4. การพัฒนาบริการ Flask ของ Python

9745ba5c70782e76.png

บริการที่เราจะสร้างประกอบด้วยไฟล์ต่อไปนี้ คุณไม่จำเป็นต้องสร้างไฟล์เหล่านี้ในตอนนี้ และจะสร้างไฟล์เหล่านี้ทีละไฟล์ตามวิธีการด้านล่าง

  1. package-service.yaml - ข้อกำหนดของ Open API สำหรับบริการแพ็กเกจที่มีข้อมูล เช่น ความสูง ความกว้าง น้ำหนัก และวิธีการจัดการพิเศษ
  2. data_model.py - รูปแบบข้อมูลสำหรับข้อกำหนด API ของบริการแพ็กเกจ และสร้างตาราง packages ในฐานข้อมูล product_details ด้วย
  3. connect_connector.py - การเชื่อมต่อ CloudSQL (กำหนดเครื่องมือ, เซสชัน และ ORM พื้นฐาน)
  4. db_init.py - สร้างข้อมูลตัวอย่างลงในตาราง packages
  5. main.py - บริการ Python Flask ที่มีปลายทาง GET เพื่อดึงรายละเอียดแพ็กเกจจากข้อมูล packages ตาม product_id
  6. test.py - การทดสอบหน่วย
  7. requirement.txt - ข้อกำหนดของ Python
  8. Dockerfile - หากต้องการสร้างคอนเทนเนอร์สำหรับแอปพลิเคชันนี้

หากพบปัญหาที่แก้ไขไม่ได้ในระหว่างแบบฝึกหัด ไฟล์สุดท้ายทั้งหมดจะอยู่ในภาคผนวกของ Codelab นี้เพื่อใช้อ้างอิง

ในขั้นตอนก่อนหน้า คุณได้สร้าง Cloud Source Repositories โคลนที่เก็บ คุณจะสร้างไฟล์แอปพลิเคชันในโฟลเดอร์ที่เก็บที่โคลน

ในเทอร์มินัล Cloud Shell ให้เรียกใช้คำสั่งต่อไปนี้เพื่อโคลนที่เก็บ

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

เปิดแถบด้านข้างของแชท Duet AI จากเมนูด้านซ้ายของ Cloud Shell Editor ไอคอนมีลักษณะดังนี้ 8b135a000b259175.png ตอนนี้คุณใช้ Duet AI เพื่อรับความช่วยเหลือด้านโค้ดได้แล้ว

package-service.yaml

โดยไม่ต้องเปิดไฟล์ใดๆ ให้ขอให้ Duet สร้างข้อกำหนดของ Open API สำหรับบริการจัดส่ง

พรอมต์ 1: สร้างข้อกำหนด OpenAPI yaml สำหรับบริการที่ให้ข้อมูลการจัดส่งและพัสดุภัณฑ์โดยระบุรหัสผลิตภัณฑ์ที่เป็นตัวเลข บริการควรมีข้อมูลเกี่ยวกับความสูง ความกว้าง ความลึก น้ำหนัก และวิธีการจัดการพิเศษของแพ็กเกจ

ba12626f491a1204.png

มี 3 ตัวเลือกที่แสดงที่ด้านขวาบนของหน้าต่างโค้ดที่สร้างขึ้น

คุณสามารถCOPY 71194556d8061dae.pngโค้ดแล้ววางลงในไฟล์ได้

คุณสามารถ ADD df645de8c65607a.png โค้ดไปยังไฟล์ที่เปิดอยู่ในเครื่องมือแก้ไขได้

หรือจะOPEN a4c7ed6d845df343.pngโค้ดในไฟล์ใหม่ก็ได้

คลิก OPEN a4c7ed6d845df343.png รหัสในไฟล์ใหม่

คลิก CTRL/CMD + s เพื่อบันทึกไฟล์ และจัดเก็บไฟล์ไว้ในโฟลเดอร์แอปพลิเคชันโดยใช้ชื่อไฟล์ว่า package-service.yaml คลิก ตกลง

f6ebd5b836949366.png

ไฟล์สุดท้ายอยู่ในส่วนภาคผนวกของ Codelab นี้ หากไม่ ให้ทำการเปลี่ยนแปลงที่เหมาะสมด้วยตนเอง

นอกจากนี้ คุณยังลองใช้พรอมต์ต่างๆ เพื่อดูคำตอบของ Duet AI ได้ด้วย

รีเซ็ตประวัติการแชทของ Duet AI โดยคลิกไอคอนถังขยะ f574ca2c1e114856.png ที่ด้านบนของแถบด้านข้างของ Duet AI

data_model.py

จากนั้นสร้างไฟล์ Python โมเดลข้อมูลสำหรับบริการตามข้อกำหนด OpenAPI

เมื่อเปิดไฟล์ package-service.yaml แล้ว ให้ป้อนพรอมต์ต่อไปนี้

พรอมต์ 1: ใช้ ORM ของ SQLAlchemy ใน Python เพื่อสร้างโมเดลข้อมูลสำหรับบริการ API นี้ รวมถึงฟังก์ชันแยกต่างหากและจุดแรกเข้าหลักที่สร้างตารางฐานข้อมูลด้วย

b873a6a28bd28ca1.png

มาดูแต่ละส่วนที่สร้างขึ้นกัน Duet AI ยังคงเป็นผู้ช่วย และแม้ว่าจะช่วยเขียนโค้ดได้อย่างรวดเร็ว แต่คุณก็ยังควรตรวจสอบเนื้อหาที่สร้างขึ้นและทำความเข้าใจเนื้อหาไปพร้อมๆ กัน

ก่อนอื่นจะมีคลาสชื่อ Package ของประเภทBase ที่กำหนดโมเดลข้อมูลสำหรับฐานข้อมูล packages ดังนี้

class Package(Base):
    __tablename__ = 'packages'

    id = Column(Integer, primary_key=True)
    product_id = Column(String(255))
    height = Column(Float)
    width = Column(Float)
    depth = Column(Float)
    weight = Column(Float)
    special_handling_instructions = Column(String(255))

จากนั้นคุณต้องมีฟังก์ชันที่สร้างตารางในฐานข้อมูลดังต่อไปนี้

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

สุดท้าย คุณต้องมีฟังก์ชันหลักที่เรียกใช้ฟังก์ชัน create_tables เพื่อสร้างตารางในฐานข้อมูล CloudSQL จริงๆ ดังนี้

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

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

    print('Tables created successfully.')

โปรดทราบว่าฟังก์ชัน main จะสร้างเครื่องมือโดยใช้ฐานข้อมูล sqlite ในเครื่อง หากต้องการใช้ CloudSQL คุณจะต้องเปลี่ยน คุณจะดำเนินการนี้ในภายหลัง

ใช้ OPEN a4c7ed6d845df343.png รหัสในเวิร์กโฟลว์ไฟล์ใหม่เช่นเดิม บันทึกโค้ดในไฟล์ชื่อ data_model.py (โปรดสังเกตเครื่องหมายขีดล่างในชื่อ ไม่ใช่ขีดกลาง)

รีเซ็ตประวัติการแชทของ Duet AI โดยคลิกไอคอนถังขยะ f574ca2c1e114856.png ที่ด้านบนของแถบด้านข้างของ Duet AI

connect-connector.py

สร้างตัวเชื่อมต่อ CloudSQL

เมื่อเปิดไฟล์ data_model.py แล้ว ให้ป้อนพรอมต์ต่อไปนี้

พรอมต์ 1: ใช้ไลบรารี cloud-sql-python-connector สร้างฟังก์ชันที่เริ่มต้นพูลการเชื่อมต่อสำหรับอินสแตนซ์ Cloud SQL ของ Postgres

ed05cb6ff85d34c5.png

โปรดทราบว่าคำตอบไม่ได้ใช้cloud-sql-python-connector คุณสามารถปรับแต่งพรอมต์เพื่อกระตุ้น Duet เล็กน้อยได้โดยการเพิ่มรายละเอียดลงในแชทเธรดเดียวกัน

มาใช้พรอมต์อื่นกัน

พรอมต์ 2: ต้องใช้ไลบรารี cloud-sql-python-connector

d09095b44dde35bf.png

ตรวจสอบว่าใช้ไลบรารี cloud-sql-python-connector

ใช้ OPEN a4c7ed6d845df343.png รหัสในเวิร์กโฟลว์ไฟล์ใหม่เช่นเดิม บันทึกโค้ดในไฟล์ชื่อ connect_conector.py คุณอาจต้องนำเข้าpg8000ไลบรารีด้วยตนเอง โปรดดูไฟล์ด้านล่าง

ล้างประวัติการแชทของ Duet AI และเมื่อเปิดไฟล์ connect_connector.py แล้ว ให้สร้าง ORM DB engine, sessionmaker และ base เพื่อใช้ในแอปพลิเคชัน

พรอมต์ 1: สร้างคลาส Engine, Sessionmaker และ Base ORM โดยใช้เมธอด connect_with_connector

6e4214b72ab13a63.png

คำตอบอาจต่อท้าย engine, Session และ Base ไปยังไฟล์ connect_connector.py

ไฟล์สุดท้ายอยู่ในส่วนภาคผนวกของ Codelab นี้ หากไม่ ให้ทำการเปลี่ยนแปลงที่เหมาะสมด้วยตนเอง

นอกจากนี้ คุณยังลองใช้พรอมต์ต่างๆ เพื่อดูคำตอบที่ Duet AI อาจตอบได้ด้วย

รีเซ็ตประวัติการแชทของ Duet AI โดยคลิกไอคอนถังขยะ f574ca2c1e114856.png ที่ด้านบนของแถบด้านข้างของ Duet AI

การอัปเดต data_model.py

คุณต้องใช้เครื่องมือที่สร้างขึ้นในขั้นตอนก่อนหน้า (ในไฟล์ connect_connector.py) เพื่อสร้างตารางในฐานข้อมูล CloudSQL

ล้างประวัติการแชทกับ Duet AI เปิดไฟล์ data_model.py ลองใช้พรอมต์ต่อไปนี้

พรอมต์ 1: ในฟังก์ชันหลัก ให้นำเข้าและใช้เครื่องมือจาก connect_connector.py

2e768c9b6c523b9a.png

คุณควรเห็นการนำเข้าคำตอบ engine จาก connect_connector (สำหรับ CloudSQL) create_table จะใช้เครื่องมือดังกล่าว (แทน sqlite DB ในเครื่องเริ่มต้น)

อัปเดตไฟล์ data_model.py

ไฟล์สุดท้ายอยู่ในส่วนภาคผนวกของ Codelab นี้ หากไม่ ให้ทำการเปลี่ยนแปลงที่เหมาะสมด้วยตนเอง

นอกจากนี้ คุณยังลองใช้พรอมต์ต่างๆ เพื่อดูคำตอบที่หลากหลายของ Duet AI ได้ด้วย

รีเซ็ตประวัติการแชทของ Duet AI โดยคลิกไอคอนถังขยะ f574ca2c1e114856.png ที่ด้านบนของแถบด้านข้างของ Duet AI

requirements.txt

สร้างไฟล์ requirements.txt สำหรับแอปพลิเคชัน

เปิดทั้ง connect_connector.py และไฟล์ data_model.py แล้วป้อนพรอมต์ต่อไปนี้

พรอมต์ 1: สร้างไฟล์ข้อกำหนด pip สำหรับโมเดลข้อมูลและบริการนี้

พรอมต์ 2: สร้างไฟล์ข้อกำหนด pip สำหรับโมเดลข้อมูลและบริการนี้โดยใช้เวอร์ชันล่าสุด

69fae373bc5c6a18.png

ตรวจสอบว่าชื่อและเวอร์ชันถูกต้อง ตัวอย่างเช่น ในคำตอบด้านบน ทั้งgoogle-cloud-sql-connecterชื่อและเวอร์ชันไม่ถูกต้อง แก้ไขเวอร์ชันด้วยตนเองและสร้างไฟล์ requirements.txt ที่มีลักษณะดังนี้

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

ในเทอร์มินัลคำสั่ง ให้เรียกใช้คำสั่งต่อไปนี้

pip3 install -r requirements.txt

รีเซ็ตประวัติการแชทของ Duet AI โดยคลิกไอคอนถังขยะ f574ca2c1e114856.png ที่ด้านบนของแถบด้านข้างของ Duet AI

การสร้างตารางแพ็กเกจใน CloudSQL

ตั้งค่าตัวแปรสภาพแวดล้อมสำหรับเครื่องมือเชื่อมต่อฐานข้อมูล CloudSQL

export INSTANCE_NAME=$(gcloud sql instances list --format='value(name)')
export INSTANCE_CONNECTION_NAME=$(gcloud sql instances describe ${INSTANCE_NAME} --format="value(connectionName)")
export DB_USER=evolution
export DB_PASS=evolution
export DB_NAME=product_details

ตอนนี้ให้เรียกใช้ data_model.py

python data_model.py

เอาต์พุตจะมีลักษณะคล้ายกับเอาต์พุตต่อไปนี้ (ตรวจสอบโค้ดเพื่อดูว่าคาดหวังอะไร)

Tables created successfully.

เชื่อมต่อกับอินสแตนซ์ Cloud SQL และตรวจสอบว่าได้สร้างฐานข้อมูลแล้ว

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

หลังจากป้อนรหัสผ่าน (ซึ่งก็คือ evolution) แล้ว ให้รับตาราง

product_details=> \dt

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

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

นอกจากนี้ คุณยังตรวจสอบโมเดลข้อมูลและรายละเอียดตารางได้ด้วย

product_details=> \d+ packages

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

                                                                        Table "public.packages"
            Column             |       Type        | Collation | Nullable |               Default                | Storage  | Compression | Stats target | Description 
-------------------------------+-------------------+-----------+----------+--------------------------------------+----------+-------------+--------------+-------------
 id                            | integer           |           | not null | nextval('packages_id_seq'::regclass) | plain    |             |              | 
 product_id                    | integer           |           | not null |                                      | plain    |             |              | 
 height                        | double precision  |           | not null |                                      | plain    |             |              | 
 width                         | double precision  |           | not null |                                      | plain    |             |              | 
 depth                         | double precision  |           | not null |                                      | plain    |             |              | 
 weight                        | double precision  |           | not null |                                      | plain    |             |              | 
 special_handling_instructions | character varying |           |          |                                      | extended |             |              | 
Indexes:
    "packages_pkey" PRIMARY KEY, btree (id)
Access method: heap

พิมพ์ \q เพื่อออกจาก Cloud SQL

db_init.py

ต่อไป มาเพิ่มข้อมูลตัวอย่างลงในpackagesกัน

ล้างประวัติการแชทกับ Duet AI เมื่อเปิดไฟล์ data_model.py แล้ว ให้ลองใช้พรอมต์ต่อไปนี้

พรอมต์ 1: สร้างฟังก์ชันที่สร้างแถวแพ็กเกจตัวอย่าง 10 แถวและส่งไปยังตารางแพ็กเกจ

พรอมต์ 2: ใช้เซสชันจาก connect_connector สร้างฟังก์ชันที่สร้างแถวแพ็กเกจตัวอย่าง 10 แถวและส่งไปยังตารางแพ็กเกจ

34a9afc5f04ba5.png

ใช้ OPEN a4c7ed6d845df343.png รหัสในเวิร์กโฟลว์ไฟล์ใหม่เช่นเดิม บันทึกโค้ดในไฟล์ชื่อ db_init.py

ไฟล์สุดท้ายอยู่ในส่วนภาคผนวกของ Codelab นี้ หากไม่ ให้ทำการเปลี่ยนแปลงที่เหมาะสมด้วยตนเอง

นอกจากนี้ คุณยังลองใช้พรอมต์ต่างๆ เพื่อดูคำตอบที่หลากหลายของ Duet AI ได้ด้วย

รีเซ็ตประวัติการแชทของ Duet AI โดยคลิกไอคอนถังขยะ f574ca2c1e114856.png ที่ด้านบนของแถบด้านข้างของ Duet AI

การสร้างข้อมูลแพ็กเกจตัวอย่าง

เรียกใช้ db_init.py จากบรรทัดคำสั่ง

python db_init.py

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

Packages created successfully.

เชื่อมต่อกับอินสแตนซ์ CloudSQL อีกครั้งและตรวจสอบว่าได้เพิ่มข้อมูลตัวอย่างลงในตารางแพ็กเกจแล้ว

เชื่อมต่อกับอินสแตนซ์ Cloud SQL และตรวจสอบว่าได้สร้างฐานข้อมูลแล้ว

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

หลังจากป้อนรหัสผ่าน (หรือ evolution) แล้ว ให้รับข้อมูลทั้งหมดจากตารางแพ็กเกจ

product_details=> SELECT * FROM packages;

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

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

พิมพ์ \q เพื่อออกจาก Cloud SQL

main.py

เมื่อเปิดไฟล์ data_model.py, package-service.yaml และ connect_connector.py แล้ว ให้สร้าง main.py สำหรับแอปพลิเคชัน

พรอมต์ 1: ใช้ไลบรารี Flask ของ Python - สร้างการติดตั้งใช้งานที่ใช้ปลายทาง REST ของ HTTP สำหรับบริการนี้

พรอมต์ 2: ใช้ไลบรารี Flask ของ Python - สร้างการติดตั้งใช้งานที่ใช้ปลายทาง REST ของ HTTP สำหรับบริการนี้ นำเข้าและใช้ SessionMaker จาก connect_conector.py สำหรับข้อมูลแพ็กเกจ

พรอมต์ 3: ใช้ไลบรารี Python Flask - สร้างการติดตั้งใช้งานที่ใช้ปลายทาง REST ของ HTTP สำหรับบริการนี้ นำเข้าและใช้แพ็กเกจจาก data_model.py และ SessionMaker จาก connect_conector.py สำหรับข้อมูลแพ็กเกจ

พรอมต์ 4: การใช้ไลบรารี Flask ของ Python - สร้างการติดตั้งใช้งานที่ใช้ปลายทาง REST ของ HTTP สำหรับบริการนี้ นำเข้าและใช้แพ็กเกจจาก data_model.py และ SessionMaker จาก connect_conector.py สำหรับข้อมูลแพ็กเกจ ใช้ IP โฮสต์ 0.0.0.0 สำหรับ app.run

6d794fc52a90e6ae.png

อัปเดตข้อกำหนดสำหรับ main.py

พรอมต์: สร้างไฟล์ข้อกำหนดสำหรับ main.py

1cc0b318d2d4ca2f.png

เพิ่มข้อความนี้ลงในไฟล์ requirements.txt ตรวจสอบว่าใช้ Flask เวอร์ชัน 3.0.0

ใช้ OPEN a4c7ed6d845df343.png รหัสในเวิร์กโฟลว์ไฟล์ใหม่เช่นเดิม บันทึกโค้ดในไฟล์ชื่อ main.py

ไฟล์สุดท้ายอยู่ในส่วนภาคผนวกของ Codelab นี้ หากไม่ ให้ทำการเปลี่ยนแปลงที่เหมาะสมด้วยตนเอง

รีเซ็ตประวัติการแชทของ Duet AI โดยคลิกไอคอนถังขยะ f574ca2c1e114856.png ที่ด้านบนของแถบด้านข้างของ Duet AI

5. การทดสอบและเรียกใช้แอปพลิเคชัน

ติดตั้งข้อกำหนด

pip3 install -r requirements.txt

เรียกใช้ main.py

python main.py

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

 * Serving Flask app 'main'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://10.88.0.3:5000
Press CTRL+C to quit

จากเทอร์มินัลที่ 2 ให้ทดสอบปลายทาง /packages/<product_id>

curl localhost:5000/packages/1

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

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

นอกจากนี้ คุณยังทดสอบรหัสผลิตภัณฑ์อื่นๆ ในข้อมูลตัวอย่างได้ด้วย

ป้อน CTRL_C เพื่อออกจากคอนเทนเนอร์ Docker ที่กำลังทำงานในเทอร์มินัล

การสร้างการทดสอบ 1 หน่วย

เมื่อไฟล์ main.py เปิดอยู่ ให้สร้าง Unit Test

พรอมต์ 1: สร้างการทดสอบหน่วย

e861e5b63e1b2657.png

ใช้ OPEN a4c7ed6d845df343.png รหัสในเวิร์กโฟลว์ไฟล์ใหม่เช่นเดิม บันทึกโค้ดในไฟล์ชื่อ test.py

ในฟังก์ชัน test_get_package ต้องกำหนด product_id คุณเพิ่มด้วยตนเองได้

ไฟล์สุดท้ายอยู่ในส่วนภาคผนวกของ Codelab นี้ หากไม่ ให้ทำการเปลี่ยนแปลงที่เหมาะสมด้วยตนเอง

รีเซ็ตประวัติการแชทของ Duet AI โดยคลิกไอคอนถังขยะ f574ca2c1e114856.png ที่ด้านบนของแถบด้านข้างของ Duet AI

การเรียกใช้การทดสอบหน่วย

เรียกใช้การทดสอบหน่วย

python test.py

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

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

OK

ปิดไฟล์ทั้งหมดใน Cloud Shell Editor และล้างประวัติการแชทโดยคลิกไอคอนถังขยะ 1ecccfe10d6c540.png ในแถบสถานะด้านบน

Dockerfile

สร้าง Dockerfile สำหรับแอปพลิเคชันนี้

เปิด main.py แล้วลองใช้พรอมต์ต่อไปนี้

พรอมต์ 1: สร้าง Dockerfile สำหรับแอปพลิเคชันนี้

พรอมต์ 2: สร้าง Dockerfile สำหรับแอปพลิเคชันนี้ คัดลอกไฟล์ทั้งหมดไปยังคอนเทนเนอร์

9c473caea437a5c3.png

นอกจากนี้ คุณยังต้องตั้งค่า ENVARS สำหรับ INSTANCE_CONNECTION_NAME, DB_USER, DB_PASS และ DB_NAME ด้วย คุณทำได้ด้วยตนเอง Dockerfile ควรมีลักษณะดังนี้

FROM python:3.10-slim

WORKDIR /app

COPY . ./

RUN pip install -r requirements.txt

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

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

ใช้ OPEN a4c7ed6d845df343.png รหัสในเวิร์กโฟลว์ไฟล์ใหม่เช่นเดิม บันทึกโค้ดในไฟล์ชื่อ Dockerfile

ไฟล์สุดท้ายอยู่ในส่วนภาคผนวกของ Codelab นี้ หากไม่ ให้ทำการเปลี่ยนแปลงที่เหมาะสมด้วยตนเอง

การเรียกใช้แอปพลิเคชันในเครื่อง

เมื่อDockerfileเปิดอยู่ ให้ลองใช้พรอมต์ต่อไปนี้

พรอมต์ 1: ฉันจะเรียกใช้คอนเทนเนอร์ในเครื่องโดยใช้ Dockerfile นี้ได้อย่างไร

570fd5c296ca8c83.png

ทำตามวิธีการ

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

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

 * Serving Flask app 'main'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://172.17.0.2:5000
Press CTRL+C to quit

เข้าถึงคอนเทนเนอร์จากหน้าต่างเทอร์มินัลที่ 2

curl localhost:5000/packages/1

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

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

แอปพลิเคชันที่สร้างโดยใช้คอนเทนเนอร์ทำงานได้

ป้อน CTRL_C เพื่อออกจากคอนเทนเนอร์ Docker ที่กำลังทำงานในเทอร์มินัล

การสร้างอิมเมจคอนเทนเนอร์ใน Artifact Registry

สร้างอิมเมจคอนเทนเนอร์และพุชไปยัง Artifact Registry

cd ~/shipping
gcloud auth configure-docker us-central1-docker.pkg.dev
docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping .
docker push us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping

ตอนนี้คอนเทนเนอร์แอปพลิเคชันอยู่ที่ us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping ซึ่งสามารถนำไปใช้ใน GKE ได้

6. การทำให้แอปพลิเคชันใช้งานได้กับคลัสเตอร์ GKE

ระบบได้สร้างคลัสเตอร์ GKE Autopilot เมื่อคุณสร้างทรัพยากร GCP สำหรับเวิร์กช็อปนี้ เชื่อมต่อกับคลัสเตอร์ GKE

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

ใส่คำอธิบายประกอบบัญชีบริการเริ่มต้นของ Kubernetes ด้วยบัญชีบริการของ Google

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

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

serviceaccount/default annotated

เตรียมและใช้ไฟล์ k8s.yaml

cp ~/duetaidev/k8s.yaml_tmpl ~/shipping/.
export INSTANCE_NAME=$(gcloud sql instances list --format='value(name)')
export INSTANCE_CONNECTION_NAME=$(gcloud sql instances describe ${INSTANCE_NAME} --format="value(connectionName)")
export IMAGE_REPO=us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping
envsubst < ~/shipping/k8s.yaml_tmpl > k8s.yaml
kubectl apply -f k8s.yaml

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

deployment.apps/shipping created
service/shipping created

รอจนกว่าพ็อดจะทำงานและบริการมีที่อยู่ IP ของตัวจัดสรรภาระงานภายนอกที่กำหนด

kubectl get pods
kubectl get service shipping

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

# kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
shipping-f5d6f8d5-56cvk   1/1     Running   0          4m47s
shipping-f5d6f8d5-cj4vv   1/1     Running   0          4m48s
shipping-f5d6f8d5-rrdj2   1/1     Running   0          4m47s

# kubectl get service shipping
NAME       TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)        AGE
shipping   LoadBalancer   34.118.225.125   34.16.39.182   80:30076/TCP   5m41s

สำหรับคลัสเตอร์ GKE Autopilot ให้รอสักครู่จนกว่าทรัพยากรจะพร้อม

เข้าถึงบริการผ่านที่อยู่ EXTERNAL-IP

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

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

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

7. คะแนนพิเศษ: การแก้ปัญหาแอปพลิเคชัน

นำบทบาท IAM ของไคลเอ็นต์ Cloud SQL ออกจากcloudsqlsaบัญชีบริการ ซึ่งจะทำให้เกิดข้อผิดพลาดในการเชื่อมต่อกับฐานข้อมูล CloudSQL

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

รีสตาร์ทพ็อดการจัดส่ง

kubectl rollout restart deployment shipping

หลังจากที่พ็อดรีสตาร์ทแล้ว ให้ลองเข้าถึงบริการ shipping อีกครั้ง

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

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

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

ตรวจสอบบันทึกโดยไปที่ Kubernetes Engine > ภาระงาน

d225b1916c829167.png

คลิกshippingการติดตั้งใช้งาน แล้วคลิกแท็บบันทึก

1d0459141483d6a7.png

คลิกไอคอนดูใน Log Explorer df8b9d19a9fe4c73.png ที่ด้านขวาของแถบสถานะ ซึ่งจะเป็นการเปิดหน้าต่างเครื่องมือสำรวจบันทึกใหม่

e86d1c265e176bc4.png

คลิกรายการข้อผิดพลาดรายการใดรายการหนึ่ง Traceback แล้วคลิกอธิบายรายการบันทึกนี้

d6af045cf03008bc.png

คุณสามารถอ่านคำอธิบายของข้อผิดพลาดได้

จากนั้นมาดูวิธีให้ Duet AI ช่วยแก้ปัญหาข้อผิดพลาดกัน

ลองใช้พรอมต์ต่อไปนี้

พรอมต์ 1: ช่วยฉันแก้ปัญหาข้อผิดพลาดนี้

9288dd6045369167.png

ป้อนข้อความแสดงข้อผิดพลาดในพรอมต์

พรอมต์ 2: Forbidden: ดูเหมือนว่า Principal ของ IAM ที่ได้รับการตรวจสอบสิทธิ์จะไม่มีสิทธิ์ส่งคำขอ API ตรวจสอบว่าได้เปิดใช้ "Cloud SQL Admin API" ในโปรเจ็กต์ GCP และได้มอบบทบาท "ไคลเอ็นต์ Cloud SQL" ให้กับหลักการ IAM แล้ว

f1e64fbdc435d31c.png

จากนั้น

พรอมต์ 3: ฉันจะมอบหมายบทบาทไคลเอ็นต์ Cloud SQL ให้กับบัญชีบริการของ Google โดยใช้ gcloud ได้อย่างไร

bb8926b995a8875c.png

มอบหมายบทบาทไคลเอ็นต์ Cloud SQL ให้กับ cloudsqlsa

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

โปรดรอสักครู่แล้วลองเข้าถึงแอปพลิเคชันอีกครั้ง

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

เอาต์พุตจะคล้ายกับตัวอย่างต่อไปนี้

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

คุณใช้ Duet AI ใน Cloud Logging, Log Explorer และฟีเจอร์ Log Explainer เพื่อแก้ปัญหาเรียบร้อยแล้ว

8. บทสรุป

ยินดีด้วย คุณทำ Codelab นี้เสร็จเรียบร้อยแล้ว

ในโค้ดแล็บนี้ คุณได้เรียนรู้สิ่งต่อไปนี้

  1. เปิดใช้งาน Duet AI ในโปรเจ็กต์ GCP และกำหนดค่าให้ใช้ใน IDE และ Cloud Console
  2. ใช้ Duet AI เพื่อสร้าง เติมให้สมบูรณ์ และอธิบายโค้ด
  3. ใช้ Duet AI เพื่ออธิบายและแก้ปัญหาแอปพลิเคชัน
  4. ฟีเจอร์ Duet AI เช่น แชท IDE และแชทแบบหลายรอบ แชทเทียบกับการสร้างโค้ดในบรรทัด การดำเนินการอัจฉริยะ เช่น คำอธิบายโค้ดและการรับทราบการท่องจำ และอื่นๆ

9. ภาคผนวก

package-service.yaml

swagger: "2.0"
info:
 title: Shipping and Package Information API
 description: This API provides information about shipping and packages.
 version: 1.0.0
host: shipping.googleapis.com
schemes:
 - https
produces:
 - application/json
paths:
 /packages/{product_id}:
   get:
     summary: Get information about a package
     description: This method returns information about a package, including its height, width, depth, weight, and any special handling instructions.
     parameters:
       - name: product_id
         in: path
         required: true
         type: integer
         format: int64
     responses:
       "200":
         description: A successful response
         schema:
           type: object
           properties:
             height:
               type: integer
               format: int64
             width:
               type: integer
               format: int64
             depth:
               type: integer
               format: int64
             weight:
               type: integer
               format: int64
             special_handling_instructions:
               type: string
       "404":
         description: The product_id was not found

data_model.py

from sqlalchemy import Column, Integer, String, Float
from sqlalchemy.ext.declarative import declarative_base

from connect_connector import engine

Base = declarative_base()

class Package(Base):
    __tablename__ = 'packages'

    id = Column(Integer, primary_key=True)
    product_id = Column(Integer, nullable=False)
    height = Column(Float, nullable=False)
    width = Column(Float, nullable=False)
    depth = Column(Float, nullable=False)
    weight = Column(Float, nullable=False)
    special_handling_instructions = Column(String, nullable=True)

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

if __name__ == '__main__':
    create_tables()

    print('Tables created successfully.')

connect_connector.py

import os

from google.cloud.sql.connector import Connector, IPTypes
import sqlalchemy

# You may need to manually import pg8000 and Base as follows
import pg8000
from sqlalchemy.ext.declarative import declarative_base


def connect_with_connector() -> sqlalchemy.engine.base.Engine:
   """Initializes a connection pool for a Cloud SQL instance of Postgres."""
   # Note: Saving credentials in environment variables is convenient, but not
   # secure - consider a more secure solution such as
   # Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
   # keep secrets safe.
   instance_connection_name = os.environ[
       "INSTANCE_CONNECTION_NAME"
   ]  # e.g. 'project:region:instance'
   db_user = os.environ["DB_USER"]  # e.g. 'my-database-user'
   db_pass = os.environ["DB_PASS"]  # e.g. 'my-database-password'
   db_name = os.environ["DB_NAME"]  # e.g. 'my-database'

   ip_type = IPTypes.PRIVATE if os.environ.get("PRIVATE_IP") else IPTypes.PUBLIC

   connector = Connector()

   def getconn() -> sqlalchemy.engine.base.Engine:
       conn: sqlalchemy.engine.base.Engine = connector.connect(
           instance_connection_name,
           "pg8000",
           user=db_user,
           password=db_pass,
           db=db_name,
           ip_type=ip_type,
       )
       return conn

   pool = sqlalchemy.create_engine(
       "postgresql+pg8000://",
       creator=getconn,
       # ...
   )
   return pool

# Create a connection pool
engine = connect_with_connector()

# Create a sessionmaker class to create new sessions
SessionMaker = sqlalchemy.orm.sessionmaker(bind=engine)

# Create a Base class for ORM
# You may need to manually fix the following
Base = declarative_base()

db_init.py

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from connect_connector import engine

from data_model import Package

def create_packages():
    # Create a session
    session = sessionmaker(bind=engine)()

    # Create 10 sample packages
    for i in range(10):
        package = Package(
            product_id=i,
            height=10.0,
            width=10.0,
            depth=10.0,
            weight=10.0,
            special_handling_instructions="No special handling instructions."
        )

        # Add the package to the session
        session.add(package)

    # Commit the changes
    session.commit()

if __name__ == '__main__':
    create_packages()

    print('Packages created successfully.')

main.py

from flask import Flask, request, jsonify

from data_model import Package
from connect_connector import SessionMaker

app = Flask(__name__)

session_maker = SessionMaker()

@app.route("/packages/<int:product_id>", methods=["GET"])
def get_package(product_id):
  """Get information about a package."""

  session = session_maker

  package = session.query(Package).filter(Package.product_id == product_id).first()

  if package is None:
    return jsonify({"message": "Package not found."}), 404

  return jsonify(
      {
          "height": package.height,
          "width": package.width,
          "depth": package.depth,
          "weight": package.weight,
          "special_handling_instructions": package.special_handling_instructions,
      }
  ), 200

if __name__ == "__main__":
  app.run(host="0.0.0.0")

test.py

import unittest

from data_model import Package
from connect_connector import SessionMaker

from main import app

class TestPackage(unittest.TestCase):

    def setUp(self):
        self.session_maker = SessionMaker()

    def tearDown(self):
        self.session_maker.close()

    def test_get_package(self):
        """Test the `get_package()` function."""

        package = Package(
        product_id=11, # Ensure that the product_id different from the sample data
        height=10,
        width=10,
        depth=10,
        weight=10,
        special_handling_instructions="Fragile",
        )

        session = self.session_maker

        session.add(package)
        session.commit()

        response = app.test_client().get("/packages/11")

        self.assertEqual(response.status_code, 200)

        self.assertEqual(
            response.json,
            {
                "height": 10,
                "width": 10,
                "depth": 10,
                "weight": 10,
                "special_handling_instructions": "Fragile",
            },
        )

if __name__ == "__main__":
    unittest.main()

requirements.txt

cloud-sql-python-connector==1.2.4
sqlalchemy==1.4.36
pg8000==1.22.0
Flask==3.0.0
gunicorn==20.1.0
psycopg2-binary==2.9.3

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