Geliştiriciler için Duet AI Teknik Uygulamalı Atölye Kılavuzu

1. Hedefler

Bu atölyenin amacı, kullanıcılara ve uygulayıcılara Duet AI ile ilgili uygulamalı eğitim vermektir.

Bu codelab'de şunları öğreneceksiniz:

  1. GCP projenizde Duet AI'ı etkinleştirin ve IDE ile Cloud Console'da kullanılacak şekilde yapılandırın.
  2. Kod oluşturma, tamamlama ve açıklama için Duet AI'ı kullanın.
  3. Duet AI'ı kullanarak bir uygulama sorununu açıklama ve giderme
  4. IDE sohbeti ve çok dönüşlü sohbet, sohbet ile satır içi kod oluşturma, kod açıklaması ve alıntı onayı gibi akıllı işlemler gibi Duet AI özellikleri.

Anlatım

Bu atölye çalışmasındaki etkinlikler, Duet AI for Developers'ın günlük geliştirme sürecinde nasıl gerçekçi bir şekilde kullanıldığını göstermek için bir anlatı bağlamında gerçekleşir.

Bir e-ticaret şirketine yeni bir geliştirici katıldığında Mevcut e-ticaret uygulamasına (birden fazla hizmetten oluşur) yeni bir hizmet eklemekle görevlendirilirler. Yeni hizmet, ürün kataloğundaki ürünler hakkında ek bilgiler (boyutlar, ağırlık vb.) sağlar. Bu hizmet, ürün boyutlarına ve ağırlıklarına göre daha iyi/daha ucuz kargo maliyetleri sunar.

Geliştirici şirkette yeni olduğu için kod oluşturma, açıklama ve doküman oluşturma işlemlerinde Duet AI'ı kullanacak.

Hizmet kodlandıktan sonra platform yöneticisi, yapının (Docker container) oluşturulmasına ve yapının GCP'ye dağıtılması için gereken kaynakların (ör.Artifact Registry, IAM izinleri, kod deposu, bilgi işlem altyapısı yani GKE veya CloudRun vb.) oluşturulmasına yardımcı olması için Duet AI'ı (sohbet) kullanır.

Uygulama GCP'ye dağıtıldıktan sonra uygulama operatörü/SRE, yeni hizmetteki bir hatayı gidermeye yardımcı olması için Duet AI'ı (ve Cloud Ops'u) kullanır.

Karakter

Atölyede aşağıdaki karakter ele alınmaktadır:

  1. Uygulama Geliştiricisi: Programlama ve yazılım geliştirme konusunda bilgi sahibi olmak gerekir.

Duet AI atölyesinin bu varyasyonu yalnızca geliştiriciler içindir. GCP bulut kaynakları hakkında bilgi sahibi olmanız gerekmez. Bu uygulamayı çalıştırmak için gerekli GCP kaynaklarını oluşturma komut dosyalarını burada bulabilirsiniz. Gerekli GCP kaynaklarını dağıtmak için bu kılavuzdaki talimatları uygulayabilirsiniz.

2. Ortamı hazırlama

Duet AI'ı etkinleştirme

GCP projesinde Duet AI'ı etkinleştirmek için API'yi (gcloud veya Terraform gibi IaC araçları) ya da Cloud Console kullanıcı arayüzünü kullanabilirsiniz.

Bir Google Cloud projesinde Duet AI'ı etkinleştirmek için Cloud AI Companion API'yi etkinleştirir ve kullanıcılara Cloud AI Companion User ile Hizmet Kullanımı Görüntüleyici Identity and Access Management (IAM) rollerini verirsiniz.

gcloud aracılığıyla

Cloud Shell'i etkinleştirin:

PROJECT_ID ve USER hizmetlerinizi yapılandırın ve Cloud AI Companion API'yi etkinleştirin.

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ış şu şekilde görünür:

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

KULLANICI hesabına Cloud AI Companion Kullanıcısı ve Hizmet Kullanımı Görüntüleyici Identity and Access Management (IAM) rollerini verin. Cloud Companion API, hem IDE hem de konsolda kullanacağımız özelliklerin arkasında yer alır. Hizmet Kullanımı Görüntüleyici izni, konsolda kullanıcı arayüzünü etkinleştirmeden önce hızlı bir kontrol olarak kullanılır (böylece Duet kullanıcı arayüzü yalnızca API'nin etkinleştirildiği projelerde görünür).

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ış şu şekilde görünür:

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

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

Cloud Console aracılığıyla

API'yi etkinleştirmek için Google Cloud Console'da Cloud AI Companion API sayfasına gidin.

Proje seçicide bir proje seçin.

Etkinleştir'i tıklayın.

Sayfa güncellenir ve Etkin durumu gösterilir. Duet AI, gerekli IAM rollerine sahip tüm kullanıcılar tarafından artık seçili Google Cloud projesinde kullanılabilir.

Duet AI'ı kullanmak için gereken IAM rollerini vermek üzere IAM sayfasına gidin.

Asıl sorumlu sütununda, Duet AI'a erişimi etkinleştirmek istediğiniz KULLANICI'yı bulun ve ardından o satırda kurşun kalem simgesini ✏️ Asıl sorumlu düzenle'yi tıklayın.

Erişimi düzenle bölmesinde Başka bir rol ekle'yi tıklayın.

Rol seçin bölümünde Cloud AI Companion Kullanıcısı'nı seçin.

Başka rol ekle'yi tıklayın ve Hizmet Kullanımı Görüntüleyici'yi seçin.

Kaydet'i tıklayın.

IDE'yi ayarlama

Geliştiriciler, ihtiyaçlarına en uygun çeşitli IDE'ler arasından seçim yapabilir. Duet AI kodlama yardımı; Visual Studio Code, JetBrains IDE'leri (IntelliJ, PyCharm, GoLand, WebStorm ve daha fazlası), Cloud Workstations, Cloud Shell Editor gibi birden fazla IDE'de kullanılabilir.

Bu laboratuvarda Cloud Workstations veya Cloud Shell Düzenleyici'yi kullanabilirsiniz.

Bu atölyede Cloud Shell Düzenleyici kullanılır.

Cloud Workstations'ın kurulumunun 20-30 dakika sürebileceğini unutmayın.

Hemen kullanmak için Cloud Shell Düzenleyici'yi kullanın.

Cloud Shell'inizin üst menü çubuğundaki kalem simgesini ✏️ tıklayarak Cloud Shell Düzenleyici'yi açın.

Cloud Shell Editor'ın kullanıcı arayüzü ve kullanıcı deneyimi, VSCode'a çok benzer.

d6a6565f83576063.png

Ayarlar bölmesine girmek için CTRL (Windows'da)/CMD (Mac'te) + , (virgül) tuşlarına basın.

Arama çubuğuna "duet ai" yazın.

Cloudcode › Duet AI: Enable ve Cloudcode › Duet AI › Inline Suggestions: Enable Auto'nun etkin olduğundan emin olun veya bu seçenekleri etkinleştirin.

111b8d587330ec74.png

Alt durum çubuğunda Cloud Code - Sign In'i (Cloud Code - Oturum Aç) tıklayın ve oturum açma iş akışını uygulayın.

Zaten oturum açtıysanız durum çubuğunda Cloud Code - No project (Cloud Code - Proje yok) gösterilir.

Cloud Code - No project'i (Cloud Code - Proje Yok) tıkladığınızda üstte bir işlem açılır bölmesi görünür. Google Cloud projesi seçin'i tıklayın.

3241a59811e3c84a.png

PROJE KİMLİĞİNİZİ yazmaya başlayın. Projeniz listede görünür.

c5358fc837588fe.png

Proje listesinden PROJECT_ID değerinizi seçin.

Alttaki durum çubuğu, proje kimliğinizi gösterecek şekilde güncellenir. Aksi takdirde Cloud Shell Düzenleyici sekmenizi yenilemeniz gerekebilir.

Sol taraftaki menü çubuğunda Duet AI simgesini d97fc4e7b594c3af.png tıkladığınızda Duet AI sohbet penceresi görünür. "GCP projesi seçin" mesajını alırsanız. Projeyi tıklayıp yeniden seçin.

Artık Duet AI sohbet penceresini görüyorsunuz.

781f888360229ca6.png

3. Altyapı kurulumu

d3234d237f00fdbb.png

Yeni kargo hizmetini GCP'de çalıştırmak için aşağıdaki GCP kaynaklarına ihtiyacınız vardır:

  1. Veritabanı içeren bir Cloud SQL örneği.
  2. Container'a alınmış hizmeti çalıştırmak için bir GKE kümesi.
  3. Docker görüntüsünü depolamak için bir Artifact Registry.
  4. Kod için bir Cloud Source Repository.

Cloud Shell terminalinde aşağıdaki depoyu klonlayın ve GCP projenizde altyapıyı ayarlamak için aşağıdaki komutları çalıştırı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. Python Flask hizmeti geliştirme

9745ba5c70782e76.png

Oluşturacağımız hizmet nihayetinde aşağıdaki dosyalardan oluşacak. Bu dosyaları şimdi oluşturmanız gerekmez. Aşağıdaki talimatları uygulayarak bunları tek tek oluşturacaksınız:

  1. package-service.yaml: Paket hizmeti için yükseklik, genişlik, ağırlık ve özel işlem talimatları gibi verileri içeren bir Açık API spesifikasyonu.
  2. data_model.py - Paket hizmeti API spesifikasyonu için veri modeli. Ayrıca product_details DB'de packages tablosunu oluşturur.
  3. connect_connector.py - CloudSQL bağlantısı (motoru, oturumu ve Base ORM'yi tanımlar)
  4. db_init.py: packages tablosunda örnek veriler oluşturur.
  5. main.py: packages verilerinden paket ayrıntılarını product_id'ye göre almak için GET uç noktasına sahip bir Python Flask hizmeti.
  6. test.py - Birim testi
  7. requirement.txt - Python gereksinimleri
  8. Dockerfile - Bu uygulamayı kapsayıcıya almak için

Alıştırmalar sırasında takıldığınız noktalar olursa referans için son dosyaların tümünü bu codelab'in EK bölümünde bulabilirsiniz.

Önceki adımda bir Cloud Source Repository oluşturmuştunuz. Depoyu klonlayın. Uygulama dosyalarını klonlanan depo klasöründe oluşturacaksınız.

Cloud Shell terminalinde aşağıdaki komutu çalıştırarak depoyu klonlayın.

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

Cloud Shell Düzenleyici'nin sol menüsünden Duet AI sohbet kenar çubuğunu açın. Simge 8b135a000b259175.png şeklindedir. Artık kod yazma konusunda yardım almak için Duet AI'ı kullanabilirsiniz.

package-service.yaml

Herhangi bir dosya açık değilken Duet'ten kargo hizmeti için bir Open API spesifikasyonu oluşturmasını isteyin.

İstem 1: Sayısal bir ürün kimliği verildiğinde kargo ve paket bilgileri sağlayan bir hizmet için OpenAPI yaml spesifikasyonu oluştur. Hizmet, paketlerin yüksekliği, genişliği, derinliği, ağırlığı ve özel taşıma talimatları hakkında bilgi içermelidir.

ba12626f491a1204.png

Oluşturulan kod penceresinin sağ üst kısmında üç seçenek listelenir.

Kodu COPY 71194556d8061dae.pngve bir dosyaya YAPIŞTIRabilirsiniz.

Kodu, düzenleyicide şu anda açık olan dosyaya ADD df645de8c65607a.png edebilirsiniz.

İsterseniz kodu yeni bir dosyaya OPEN a4c7ed6d845df343.png de edebilirsiniz.

OPEN a4c7ed6d845df343.png kodu yeni bir dosyaya yapıştırın.

Dosyayı kaydetmek için CTRL/CMD + s simgesini tıklayın ve dosyayı uygulama klasöründe package-service.yaml adlı dosya adıyla saklayın. Tamam'ı tıklayın.

f6ebd5b836949366.png

Son dosya, bu codelab'in EK bölümünde yer alır. Aksi takdirde, gerekli değişiklikleri manuel olarak yapın.

Duet AI'ın yanıtlarını görmek için çeşitli istemleri de deneyebilirsiniz.

Duet AI sohbet geçmişini sıfırlamak için Duet AI kenar çubuğunun üst kısmındaki çöp kutusu simgesini f574ca2c1e114856.png tıklayın.

data_model.py

Ardından, OpenAPI spesifikasyonuna göre hizmet için veri modeli Python dosyasını oluşturursunuz.

package-service.yaml dosyası açıkken aşağıdaki istemi girin.

İstem 1: Python sqlalchemy ORM'yi kullanarak bu API hizmeti için bir veri modeli oluştur. Ayrıca, veritabanı tablolarını oluşturan ayrı bir işlev ve ana giriş noktası da ekleyin.

b873a6a28bd28ca1.png

Oluşturulan her bir parçaya göz atalım. Duet AI hâlâ bir asistan olduğundan kodu hızlı bir şekilde yazmanıza yardımcı olsa da oluşturulan içeriği incelemeye ve anlamaya devam etmeniz gerekir.

İlk olarak, packages veritabanının veri modelini aşağıdaki gibi tanımlayan tür Base sınıfı Package vardır:

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

Ardından, veritabanında tablo oluşturan aşağıdaki gibi bir işleve ihtiyacınız vardır:

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

Son olarak, CloudSQL veritabanında tabloyu oluşturmak için create_tables işlevini çalıştıran bir ana işlev gerekir. Örneğin:

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

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

    print('Tables created successfully.')

main işlevinin, yerel bir sqlite veritabanı kullanarak motor oluşturduğunu unutmayın. CloudSQL'i kullanmak için bunu değiştirmeniz gerekir. Bunu biraz sonra yaparsınız.

Kodu, yeni bir dosya iş akışında daha önce olduğu gibi OPEN a4c7ed6d845df343.png kullanarak. Kodu data_model.py adlı bir dosyaya kaydedin (adın alt çizgi içerdiğini ve tire içermediğini unutmayın).

Duet AI sohbet geçmişini sıfırlamak için Duet AI kenar çubuğunun üst kısmındaki çöp kutusu simgesini f574ca2c1e114856.png tıklayın.

connect-connector.py

Cloud SQL bağlayıcısını oluşturun.

data_model.py dosyası açıkken aşağıdaki istemleri girin.

İstem 1: cloud-sql-python-connector kitaplığını kullanarak Postgres'in Cloud SQL örneği için bağlantı havuzu başlatan bir işlev oluştur.

ed05cb6ff85d34c5.png

Yanıtın cloud-sql-python-connector kitaplığını kullanmadığını unutmayın. Aynı sohbet dizisine ayrıntılar ekleyerek istemleri hassaslaştırabilir ve Duet'e yol gösterebilirsiniz.

Başka bir istem kullanalım.

İstem 2: cloud-sql-python-connector kitaplığı kullanılmalıdır.

d09095b44dde35bf.png

cloud-sql-python-connector kitaplığını kullandığından emin olun.

Kodu, yeni bir dosya iş akışında daha önce olduğu gibi OPEN a4c7ed6d845df343.png kullanarak. Kodu connect_conector.py adlı bir dosyaya kaydedin. pg8000 kitaplığını manuel olarak içe aktarmanız gerekebilir. Lütfen aşağıdaki dosyaya bakın.

Duet AI sohbet geçmişini temizleyin ve connect_connector.py dosyası açıkken uygulamada kullanılacak DB engine, sessionmaker ve base ORM'lerini oluşturun.

1. istem: connect_with_connector yöntemini kullanarak bir motor, sessionmaker sınıfı ve Base ORM oluşturun

6e4214b72ab13a63.png

Yanıt, engine, Session ve Base karakterlerini connect_connector.py dosyasına ekleyebilir.

Son dosya, bu codelab'in EK bölümünde yer alır. Aksi takdirde, gerekli değişiklikleri manuel olarak yapın.

Duet AI'ın yanıtlarındaki olası çeşitliliği görmek için çeşitli istemleri de deneyebilirsiniz.

Duet AI sohbet geçmişini sıfırlamak için Duet AI kenar çubuğunun üst kısmındaki çöp kutusu simgesini f574ca2c1e114856.png tıklayın.

data_model.py dosyasını güncelleme

CloudSQL veritabanında tablo oluşturmak için önceki adımda (connect_connector.py dosyasında) oluşturduğunuz motoru kullanmanız gerekir.

Duet AI sohbet geçmişini temizleyin. data_model.py dosyasını açın. Aşağıdaki istemi deneyin.

İstem 1: Ana işlevde, connect_connector.py dosyasından motoru içe aktarın ve kullanın

2e768c9b6c523b9a.png

connect_connector (CloudSQL için) dosyasından engine içe aktarılırken yanıtı görmeniz gerekir. create_table, varsayılan sqlite yerel veritabanı yerine bu motoru kullanır.

data_model.py dosyasını güncelleyin.

Son dosya, bu codelab'in EK bölümünde yer alır. Aksi takdirde, gerekli değişiklikleri manuel olarak yapın.

Duet AI'ın çeşitli yanıtlarını görmek için farklı istemler de deneyebilirsiniz.

Duet AI sohbet geçmişini sıfırlamak için Duet AI kenar çubuğunun üst kısmındaki çöp kutusu simgesini f574ca2c1e114856.png tıklayın.

requirements.txt

Uygulama için bir requirements.txt dosyası oluşturun.

Hem connect_connector.py hem de data_model.py dosyasını açın ve aşağıdaki istemi girin.

1. istem: Bu veri modeli ve hizmet için bir pip requirements dosyası oluştur

2. istem: En son sürümleri kullanarak bu veri modeli ve hizmet için bir pip requirements dosyası oluştur

69fae373bc5c6a18.png

Adların ve sürümlerin doğru olduğunu doğrulayın. Örneğin, yukarıdaki yanıtta hem google-cloud-sql-connecter adı hem de sürümü yanlış. Sürümleri manuel olarak düzeltin ve requirements.txt dosyası oluşturun.

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

Komut terminalinde aşağıdakileri çalıştırın:

pip3 install -r requirements.txt

Duet AI sohbet geçmişini sıfırlamak için Duet AI kenar çubuğunun üst kısmındaki çöp kutusu simgesini f574ca2c1e114856.png tıklayın.

CloudSQL'de paket tablosu oluşturma

CloudSQL veritabanı bağlayıcısı için ortam değişkenlerini ayarlayın.

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

Şimdi data_model.py dosyasını çalıştırın.

python data_model.py

Çıkış aşağıdaki gibidir (gerçekte ne beklendiğini görmek için kodu kontrol edin):

Tables created successfully.

Cloud SQL örneğine bağlanın ve veritabanının oluşturulduğunu kontrol edin.

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

Şifreyi (evolution) girdikten sonra tabloları alın.

product_details=> \dt

Çıkış şuna benzer:

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

Veri modeli ve tablo ayrıntılarını da kontrol edebilirsiniz.

product_details=> \d+ packages

Çıkış şuna benzer:

                                                                        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

Cloud SQL'den çıkmak için \q yazın.

db_init.py

Şimdi packages tablosuna bazı örnek veriler ekleyelim.

Duet AI sohbet geçmişini temizleyin. data_model.py dosyası açıkken aşağıdaki istemleri deneyin.

İstem 1: 10 örnek paket satırı oluşturan ve bunları paketler tablosuna işleyen bir işlev oluştur

İstem 2: connect_connector oturumunu kullanarak 10 örnek paket satırı oluşturan ve bunları paketler tablosuna işleyen bir işlev oluşturun

34a9afc5f04ba5.png

Kodu, yeni bir dosya iş akışında daha önce olduğu gibi OPEN a4c7ed6d845df343.png kullanarak. Kodu db_init.py adlı bir dosyaya kaydedin.

Son dosya, bu codelab'in EK bölümünde yer alır. Aksi takdirde, gerekli değişiklikleri manuel olarak yapın.

Duet AI'ın çeşitli yanıtlarını görmek için farklı istemler de deneyebilirsiniz.

Duet AI sohbet geçmişini sıfırlamak için Duet AI kenar çubuğunun üst kısmındaki çöp kutusu simgesini f574ca2c1e114856.png tıklayın.

Örnek paket verileri oluşturma

db_init.py komutunu komut satırından çalıştırın.

python db_init.py

Çıkış şuna benzer:

Packages created successfully.

Cloud SQL örneğine tekrar bağlanın ve örnek verilerin packages tablosuna eklendiğini doğrulayın.

Cloud SQL örneğine bağlanın ve veritabanının oluşturulduğunu kontrol edin.

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

Şifreyi (aynı zamanda evolution) girdikten sonra packages tablosundaki tüm verileri alın.

product_details=> SELECT * FROM packages;

Çıkış şuna benzer:

 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)

Cloud SQL'den çıkmak için \q yazın.

main.py

data_model.py, package-service.yaml ve connect_connector.py dosyaları açıkken uygulama için main.py oluşturun.

İstem 1: Python Flask kitaplığını kullanarak bu hizmet için HTTP REST uç noktalarını kullanan bir uygulama oluşturun.

İstem 2: Python Flask kitaplığını kullanarak bu hizmet için HTTP REST uç noktalarını kullanan bir uygulama oluşturun. Paket verileri için connect_connector.py dosyasından SessionMaker'ı içe aktarın ve kullanın.

İstem 3: Python Flask kitaplığını kullanarak bu hizmet için HTTP REST uç noktalarını kullanan bir uygulama oluşturun. Paket verileri için data_model.py dosyasından Package'ı ve connect_connector.py dosyasından SessionMaker'ı içe aktarıp kullanın.

İstem 4: Python Flask kitaplığını kullanarak bu hizmet için HTTP REST uç noktalarını kullanan bir uygulama oluşturun. Paket verileri için data_model.py dosyasından Package'ı ve connect_connector.py dosyasından SessionMaker'ı içe aktarıp kullanın. app.run için ana makine IP'si 0.0.0.0'ı kullanma

6d794fc52a90e6ae.png

main.py ile ilgili koşulları güncelleyin.

İstem: main.py için requirements dosyası oluştur

1cc0b318d2d4ca2f.png

Bunu requirements.txt dosyasına ekleyin. Flask 3.0.0 sürümünü kullandığınızdan emin olun.

OPEN a4c7ed6d845df343.png kodunu yeni bir dosya iş akışında eskisi gibi kullanın. Kodu main.py adlı bir dosyaya kaydedin.

Son dosya, bu codelab'in EK bölümünde yer alır. Aksi takdirde, gerekli değişiklikleri manuel olarak yapın.

Duet AI sohbet geçmişini sıfırlamak için Duet AI kenar çubuğunun üst kısmındaki çöp kutusu simgesini f574ca2c1e114856.png tıklayın.

5. Uygulamayı test etme ve çalıştırma

Gereksinimleri yükleyin.

pip3 install -r requirements.txt

main.py komutunu çalıştırın.

python main.py

Çıkış şuna benzer:

 * 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

İkinci bir terminalden /packages/<product_id> uç noktasını test edin.

curl localhost:5000/packages/1

Çıkış şuna benzer:

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

Örnek verilerinizdeki diğer ürün kimliklerini de test edebilirsiniz.

Terminalde çalışan Docker container'ından çıkmak için CTRL_C girin.

Birim testleri oluşturma

main.py dosyası açıkken birim testleri oluşturun.

1. istem: Birim testleri oluştur.

e861e5b63e1b2657.png

Kodu, yeni bir dosya iş akışında daha önce olduğu gibi OPEN a4c7ed6d845df343.png kullanarak. Kodu test.py adlı bir dosyaya kaydedin.

test_get_package işlevinde bir product_id tanımlanmalıdır. Manuel olarak ekleyebilirsiniz.

Son dosya, bu codelab'in EK bölümünde yer alır. Aksi takdirde, gerekli değişiklikleri manuel olarak yapın.

Duet AI sohbet geçmişini sıfırlamak için Duet AI kenar çubuğunun üst kısmındaki çöp kutusu simgesini f574ca2c1e114856.png tıklayın.

Birim testlerini çalıştırma

Birim testini çalıştırın.

python test.py

Çıkış şuna benzer:

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

OK

Cloud Shell Düzenleyici'deki tüm dosyaları kapatın ve üst durum çubuğundaki çöp kutusu simgesini 1ecccfe10d6c540.png tıklayarak sohbet geçmişini temizleyin.

Dockerfile

Bu uygulama için Dockerfile oluşturun.

main.py bağlantısını açıp aşağıdaki istemleri deneyin.

1. istem: Bu uygulama için bir Dockerfile oluştur.

2. istem: Bu uygulama için bir Dockerfile oluştur. Tüm dosyaları kapsayıcıya kopyalayın.

9c473caea437a5c3.png

Ayrıca INSTANCE_CONNECTION_NAME, DB_USER, DB_PASS ve DB_NAME için ENVARS değerini ayarlamanız gerekir. Bunu manuel olarak yapabilirsiniz. Dockerfile'ınız aşağıdaki gibi görünmelidir:

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

Kodu, yeni bir dosya iş akışında daha önce olduğu gibi OPEN a4c7ed6d845df343.png kullanarak. Kodu Dockerfile adlı bir dosyaya kaydedin.

Son dosya, bu codelab'in EK bölümünde yer alır. Aksi takdirde, gerekli değişiklikleri manuel olarak yapın.

Uygulamayı yerel olarak çalıştırma

Dockerfile açıkken aşağıdaki istemi deneyin.

1. istem: Bu Dockerfile'ı kullanarak bir kapsayıcıyı yerel olarak nasıl çalıştırırım?

570fd5c296ca8c83.png

Talimatları uygulayın.

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

Çıkış şuna benzer:

 * 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

İkinci bir terminal penceresinden kapsayıcıya erişin.

curl localhost:5000/packages/1

Çıkış şuna benzer:

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

Kapsayıcıya alınmış uygulama çalışıyor.

Terminalde çalışan Docker container'ından çıkmak için CTRL_C girin.

Artifact Registry'de container görüntüsü oluşturma

Container görüntüsünü oluşturun ve Artifact Registry'ye aktarın.

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

Uygulama container'ı artık us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping konumunda bulunuyor ve GKE'ye dağıtılabilir.

6. Uygulamayı GKE kümesine dağıtma

Bu atölye çalışması için GCP kaynaklarını oluşturduğunuzda bir GKE Autopilot kümesi oluşturuldu. GKE kümesine bağlanın.

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

Kubernetes varsayılan hizmet hesabına Google hizmet hesabıyla ek açıklama ekleyin.

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

Çıkış şuna benzer:

serviceaccount/default annotated

k8s.yaml dosyasını hazırlayın ve uygulayın.

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ış şuna benzer:

deployment.apps/shipping created
service/shipping created

Pod'lar çalışana ve hizmete harici yük dengeleyici IP adresi atanana kadar bekleyin.

kubectl get pods
kubectl get service shipping

Çıkış şuna benzer:

# 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 kümelerinde kaynaklar hazır olana kadar birkaç dakika bekleyin.

EXTERNAL-IP adresinden hizmete erişin.

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

Çıkış şuna benzer:

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

7. Ek kredi: Uygulamada sorun giderme

CloudSQL Client IAM rolünü cloudsqlsa hizmet hesabından kaldırın. Bu durum, CloudSQL veritabanına bağlanırken hataya neden olur.

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

Kargo Pod'unu yeniden başlatın.

kubectl rollout restart deployment shipping

Pod yeniden başlatıldıktan sonra shipping hizmetine tekrar erişmeyi deneyin.

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

Çıkış şuna benzer:

...
<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 > İş Yükleri'ne giderek günlükleri inceleyin.

d225b1916c829167.png

shipping dağıtımını ve ardından Günlükler sekmesini tıklayın.

1d0459141483d6a7.png

Durum çubuğunun sağ tarafındaki Günlük Gezgini'nde görüntüle simgesini df8b9d19a9fe4c73.png tıklayın. Bu işlem yeni bir Log Explorer penceresi açar.

e86d1c265e176bc4.png

Traceback hata girişlerinden birini ve ardından Bu günlük girişini açıkla'yı tıklayın.

d6af045cf03008bc.png

Hatanın açıklamasını okuyabilirsiniz.

Ardından, hatayı gidermeye yardımcı olması için Duet AI'ı kullanalım.

Aşağıdaki istemi deneyin.

1. istem: Bu hatayı gidermeme yardımcı ol

9288dd6045369167.png

İsteme hata mesajını girin.

2. istem: Yasaklandı: Kimliği doğrulanmış IAM sorumlusu, API isteği yapmaya yetkili görünmüyor. GCP projenizde "Cloud SQL Admin API"nin etkinleştirildiğini ve IAM asıl kullanıcısına "Cloud SQL İstemcisi" rolünün verildiğini doğrulayın

f1e64fbdc435d31c.png

Ve sonra.

3. istem: gcloud'u kullanarak bir Google hizmet hesabına Cloud SQL İstemcisi rolünü nasıl atarım?

bb8926b995a8875c.png

Cloud SQL İstemcisi rolünü cloudsqlsa hizmet hesabına atayın.

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

Birkaç dakika bekleyip uygulamaya tekrar erişmeyi deneyin.

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

Çıkış şuna benzer:

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

Sorunu gidermek için Cloud Logging, Günlük Gezgini ve Günlük Açıklayıcı özelliğinde Duet AI'ı başarıyla kullandınız.

8. Sonuç

Tebrikler! Bu codelab'i başarıyla tamamladınız.

Bu kod laboratuvarında şunları öğrendiniz:

  1. GCP projenizde Duet AI'ı etkinleştirin ve IDE ile Cloud Console'da kullanılacak şekilde yapılandırın.
  2. Kod oluşturma, tamamlama ve açıklama için Duet AI'ı kullanın.
  3. Duet AI'ı kullanarak bir uygulama sorununu açıklama ve giderme
  4. IDE sohbeti ve çok dönüşlü sohbet, sohbet ile satır içi kod oluşturma, kod açıklaması ve alıntı onayı gibi akıllı işlemler gibi Duet AI özellikleri.

9. Ek

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