Guida al workshop pratico su Duet AI per sviluppatori codelab

1. Obiettivi

Lo scopo di questo workshop è fornire una formazione pratica su Duet AI a utenti e professionisti.

In questo codelab, imparerai quanto segue:

  1. Attiva Duet AI nel tuo progetto Google Cloud e configuralo per l'utilizzo in un IDE e nella console Cloud.
  2. Usa Duet AI per la generazione, il completamento e la spiegazione del codice.
  3. Utilizza Duet AI per spiegare e risolvere un problema dell'applicazione.
  4. Funzionalità di Duet AI come la chat IDE e la chat multi-turno, la generazione di codice in chat e in linea, le azioni intelligenti come la spiegazione del codice e la conferma delle citazioni e altro ancora.

Narrative

Per mostrare come Duet AI per gli sviluppatori viene utilizzato in modo autentico nello sviluppo quotidiano, le attività di questo workshop si svolgono in un contesto narrativo.

Un nuovo sviluppatore entra a far parte di un'azienda di e-commerce. Ha il compito di aggiungere un nuovo servizio all'applicazione di e-commerce esistente (composta da più servizi). Il nuovo servizio fornisce informazioni aggiuntive (dimensioni, peso e così via) sui prodotti presenti nel catalogo. Questo servizio consentirà costi di spedizione migliori/più economici in base alle dimensioni e al peso dei prodotti.

Poiché lo sviluppatore non ha esperienza con l'azienda, utilizzerà Duet AI per la generazione, la spiegazione e la documentazione del codice.

Dopo la codifica del servizio, un amministratore di piattaforma utilizzerà Duet AI (chat) per creare l'artefatto (container Docker) e le risorse necessarie per il deployment dell'artefatto in Google Cloud (ad esempio Artifact Registry, autorizzazioni IAM, un repository di codice, un'infrastruttura di calcolo, ad esempio GKE o CloudRun e così via)

Una volta eseguito il deployment dell'applicazione in Google Cloud, un operatore dell'applicazione/SRE utilizzerà Duet AI (e Cloud Ops) per risolvere un errore nel nuovo servizio.

Utente tipo

Il workshop riguarda i seguenti utenti tipo:

  1. Sviluppatore di applicazioni: è richiesta una certa conoscenza della programmazione e dello sviluppo software.

Questa variante del workshop Duet AI è riservata agli sviluppatori. Non è richiesta alcuna conoscenza delle risorse cloud di Google Cloud. Gli script per la creazione delle risorse Google Cloud richieste per l'esecuzione dell'applicazione sono disponibili qui. Puoi seguire le istruzioni in questa guida per eseguire il deployment delle risorse Google Cloud richieste.

2. preparazione dell'ambiente

Attivazione di Duet AI

Puoi attivare Duet AI in un progetto Google Cloud tramite API (strumenti gcloud o IaC come Terraform) o tramite l'interfaccia utente della console Cloud.

Per attivare Duet AI in un progetto Google Cloud, devi abilitare l'API Cloud AI Companion e concedere agli utenti i ruoli Identity and Access Management (IAM) Cloud AI Companion User e Service Usage Viewer.

Tramite gcloud

Attiva Cloud Shell:

Configura PROJECT_ID, USER e abilita l'API Cloud AI Companion.

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}

L'output è simile al seguente:

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

Concedi i ruoli Identity and Access Management (IAM) Cloud AI Companion User e Service Usage Viewer all'account USER. L'API Cloud Companion è alla base delle funzionalità sia nell'IDE che nella console che utilizzeremo. L'autorizzazione Visualizzatore utilizzo dei servizi viene utilizzata come controllo rapido prima di abilitare l'UI nella console (in modo che la UI di Duet venga visualizzata solo nei progetti in cui l'API è abilitata).

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

L'output è simile al seguente:

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

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

Tramite Cloud Console

Per abilitare l'API, vai alla pagina dell'API Cloud AI Companion nella console Google Cloud.

Nel selettore di progetti, seleziona un progetto.

Fai clic su Abilita.

La pagina si aggiorna e mostra lo stato Attivato. Duet AI è ora disponibile nel progetto Google Cloud selezionato per tutti gli utenti che dispongono dei ruoli IAM richiesti.

Per concedere i ruoli IAM necessari per utilizzare Duet AI, vai alla pagina IAM.

Nella colonna Entità, trova l'utente USER per cui vuoi abilitare l'accesso a Duet AI, quindi fai clic sull'icona a forma di matita ✏️ Modifica entità nella riga corrispondente.

Nel riquadro di accesso Modifica, fai clic su Aggiungi Aggiungi un altro ruolo.

In Seleziona un ruolo, seleziona Cloud AI Companion User (Utente Cloud AI Companion).

Fai clic su Aggiungi un altro ruolo e seleziona Service Usage Viewer.

Fai clic su Salva.

Configurazione di IDE

Gli sviluppatori possono scegliere tra una varietà di IDE a seconda delle loro esigenze. L'assistenza per il codice di Duet AI è disponibile in più IDE come Visual Studio Code, IDE JetBrains (IntelliJ, PyCharm, GoLand, WebStorm e altri), Cloud Workstations e editor di Cloud Shell.

In questo lab puoi utilizzare Cloud Workstations o l'editor di Cloud Shell.

Questo workshop utilizza l'editor di Cloud Shell.

Tieni presente che la configurazione di Cloud Workstations può richiedere 20-30 minuti.

Per utilizzarle immediatamente, usa l'editor di Cloud Shell.

Apri l'editor di Cloud Shell facendo clic sull'icona a forma di matita ✏️ nella barra dei menu in alto di Cloud Shell.

L'editor di Cloud Shell ha una UI e una UX molto simili a VSCode.

d6a6565f83576063.png

Fai clic su Ctrl (in Windows)/CMD (su Mac) + , (virgola) per accedere al riquadro Impostazioni.

Nella barra di ricerca, digita "duet ai".

Assicurati o abilita Cloudcode › Duet AI: Abilita e Cloudcode › Duet AI › Inline Suggestions: Abilita Auto

111b8d587330ec74.png

Nella barra di stato in basso, fai clic su Cloud Code - Accedi e segui il flusso di lavoro di accesso.

Se hai già eseguito l'accesso, la barra di stato mostra Cloud Code - Nessun progetto.

Fai clic su Cloud Code - Nessun progetto per visualizzare in alto un riquadro a discesa delle azioni. Fai clic su Seleziona un progetto Google Cloud.

3241a59811e3c84a.png

Inizia a digitare l'ID PROGETTO e il progetto verrà visualizzato nell'elenco.

c5358fc837588fe.png

Seleziona il tuo PROJECT_ID dall'elenco dei progetti.

La barra di stato in basso si aggiorna mostrando il tuo ID progetto. In caso contrario, potresti dover aggiornare la scheda dell'editor di Cloud Shell.

Fai clic sull'icona di Duet AI d97fc4e7b594c3af.pngnella barra dei menu a sinistra e verrà visualizzata la finestra della chat di Duet AI. Se viene visualizzato il messaggio Seleziona progetto Google Cloud. Fai clic e seleziona nuovamente il progetto.

Ora vedi la finestra della chat di Duet AI

781f888360229ca6.png

3. Configurazione dell'infrastruttura

d3234d237f00fdbb.png

Per eseguire il nuovo servizio di spedizione in Google Cloud, ti occorrono le seguenti risorse Google Cloud:

  1. Un'istanza Cloud SQL con un database.
  2. Un cluster GKE per eseguire il servizio containerizzato.
  3. Un Artifact Registry per archiviare l'immagine Docker.
  4. Un repository di codice sorgente Cloud per il codice.

Nel terminale Cloud Shell, clona il seguente repository ed esegui i comandi seguenti per configurare l'infrastruttura nel tuo progetto Google Cloud.

# 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. Sviluppo di un servizio Python Flask

9745ba5c70782e76.png

Il servizio che creeremo sarà composto in definitiva dai seguenti file. Non è necessario creare questi file adesso; dovrai crearli uno alla volta seguendo le istruzioni riportate di seguito:

  1. package-service.yaml: una specifica API aperta per il servizio pacchetti e contenente dati quali altezza, larghezza, peso e istruzioni di gestione speciali.
  2. data_model.py: modello dei dati per la specifica dell'API Package-Service. Crea anche la tabella packages nel database product_details.
  3. connect_connector.py - Connessione Cloud SQL (definisce motore, sessione e ORM di base)
  4. db_init.py - Genera dati di esempio nella tabella packages.
  5. main.py - Un servizio Python Flask con un endpoint GET per recuperare i dettagli del pacchetto dai dati packages in base a product_id.
  6. test.py - Test delle unità
  7. requirement.txt: requisiti Python
  8. Dockerfile - Per containerizzare questa applicazione

Se riscontri problemi durante gli esercizi, tutti i file finali si trovano nell'APPENDICE di questo codelab come riferimento.

Nel passaggio precedente, hai creato un repository di codice sorgente Cloud. Clonare il repository. Creerai i file dell'applicazione nella cartella del repository clonato.

Nel terminale Cloud Shell, esegui questo comando per clonare il repository.

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

Apri la barra laterale della chat di Duet AI dal menu a sinistra dell'editor di Cloud Shell. L'icona è simile a 8b135a000b259175.png. Ora puoi utilizzare Duet AI per l'assistenza per la programmazione.

package-service.yaml

Senza alcun file aperto, chiedi a Duet di generare una specifica OpenAPI per il servizio di spedizione.

Prompt 1: genera una specifica yaml OpenAPI per un servizio che fornisce informazioni sulla spedizione e sul pacco tramite un ID prodotto numerico. Il servizio deve includere informazioni su altezza, larghezza, profondità e peso dei pacchi ed eventuali istruzioni speciali per la gestione.

ba12626f491a1204.png

Ci sono tre opzioni elencate in alto a destra nella finestra del codice generato.

Puoi COPY 71194556d8061dae.pngil codice e incollarlo in un file.

Puoi ADD df645de8c65607a.png modificare il codice nel file attualmente aperto nell'Editor.

In alternativa, puoi OPEN a4c7ed6d845df343.png il codice in un nuovo file.

Fai clic sul OPEN a4c7ed6d845df343.png del codice in un nuovo file.

Fai clic su CTRL/CMD + s per salvare il file e archivialo nella cartella dell'applicazione con il nome file denominato package-service.yaml. Fai clic su OK.

f6ebd5b836949366.png

Il file finale si trova nella sezione APPENDICE di questo codelab. In caso contrario, apporta le modifiche appropriate manualmente.

Puoi anche provare vari prompt per vedere le risposte di Duet AI.

Reimposta la cronologia chat di Duet AI facendo clic sull'icona del cestino f574ca2c1e114856.png nella parte superiore della barra laterale di Duet AI.

data_model.py

Quindi, creerai il file Python del modello dei dati per il servizio in base alla specifica OpenAPI.

Con il file package-service.yaml aperto, inserisci il seguente prompt.

Prompt 1: utilizzando il mapper ORM Python sqlalchemy, genera un modello dati per questo servizio API. Includi anche una funzione separata e un punto di ingresso principale che crea le tabelle del database.

b873a6a28bd28ca1.png

Diamo un'occhiata a ogni parte generata. Duet AI è ancora un assistente e, sebbene possa aiutarti a scrivere codice rapidamente, dovresti comunque rivedere i contenuti generati e comprenderli man mano che procedi.

Innanzitutto, c'è una Class denominata Package di kind Base che definisce il modello dei dati per il database packages come segue:

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

Successivamente, hai bisogno di una funzione che crei la tabella nel database come segue:

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

Infine, è necessaria una funzione principale che esegua la funzione create_tables per creare effettivamente la tabella nel database Cloud SQL, come riportato di seguito:

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

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

    print('Tables created successfully.')

Tieni presente che la funzione main crea un motore utilizzando un database sqlite locale. Per utilizzare Cloud SQL, devi modificarlo. Questo sarà possibile dopo.

Utilizzando OPEN a4c7ed6d845df343.png il codice in un nuovo flusso di lavoro di file come prima. Salva il codice in un file denominato data_model.py (nota il trattino basso nel nome e non un trattino).

Reimposta la cronologia chat di Duet AI facendo clic sull'icona del cestino f574ca2c1e114856.png nella parte superiore della barra laterale di Duet AI.

connect-connector.py

Creare il connettore Cloud SQL.

Con il file data_model.py aperto, inserisci i seguenti prompt.

Prompt 1: utilizzando la libreria cloud-sql-python-connector, genera una funzione che inizializza un pool di connessioni per un'istanza Cloud SQL di Postgres.

ed05cb6ff85d34c5.png

Tieni presente che la risposta non utilizza la libreria cloud-sql-python-connector. Puoi perfezionare i prompt per dare a Duet un sollecito, aggiungendo specifiche allo stesso thread della chat.

Usiamo un altro prompt.

Prompt 2: devi utilizzare la libreria cloud-sql-python-connector.

d09095b44dde35bf.png

Assicurati che utilizzi la raccolta cloud-sql-python-connector.

Utilizzando OPEN a4c7ed6d845df343.png il codice in un nuovo flusso di lavoro di file come prima. Salva il codice in un file denominato connect_conector.py. Potresti dover importare manualmente la libreria pg8000. Consulta il file di seguito.

Cancella la cronologia chat di Duet AI e, con il file connect_connector.py aperto, genera gli ORM DB engine, sessionmaker e base da utilizzare nell'applicazione.

Prompt 1: crea un motore, una classe sessionmaker e un ORM di base utilizzando il metodo connect_with_connector

6e4214b72ab13a63.png

La risposta può aggiungere engine, Session e Base al file connect_connector.py.

Il file finale si trova nella sezione APPENDICE di questo codelab. In caso contrario, apporta le modifiche appropriate manualmente.

Puoi anche provare vari prompt per vedere la potenziale variazione delle risposte di Duet AI.

Reimposta la cronologia chat di Duet AI facendo clic sull'icona del cestino f574ca2c1e114856.png nella parte superiore della barra laterale di Duet AI.

Aggiornamento di data_model.py

Devi usare il motore che hai creato nel passaggio precedente (nel file connect_connector.py) per creare una tabella nel database Cloud SQL.

Cancella la cronologia chat di Duet AI. Apri il file data_model.py. Prova il seguente prompt.

Prompt 1: nella funzione principale, importa e utilizza il motore da connect_connector.py

2e768c9b6c523b9a.png

Dovresti vedere la risposta che importa engine da connect_connector (per Cloud SQL). create_table utilizza questo motore (anziché il database locale sqlite predefinito).

Aggiorna il file data_model.py.

Il file finale si trova nella sezione APPENDICE di questo codelab. In caso contrario, apporta le modifiche appropriate manualmente.

Puoi anche provare vari prompt per vedere varie risposte di Duet AI.

Reimposta la cronologia chat di Duet AI facendo clic sull'icona del cestino f574ca2c1e114856.png nella parte superiore della barra laterale di Duet AI.

requirements.txt

Crea un file requirements.txt per l'applicazione.

Apri sia connect_connector.py sia il file data_model.py e inserisci il seguente prompt.

Prompt 1: genera un file dei requisiti pip per questo modello di dati e questo servizio

Prompt 2: genera un file dei requisiti pip per questo modello di dati e questo servizio utilizzando le versioni più recenti

69fae373bc5c6a18.png

Verifica che i nomi e le versioni siano corretti. Ad esempio, nella risposta precedente, il nome e la versione di google-cloud-sql-connecter sono entrambi errati. Correggi manualmente le versioni e crea un file requirements.txt simile al seguente:

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

Nel terminale di comando, esegui questo comando:

pip3 install -r requirements.txt

Reimposta la cronologia chat di Duet AI facendo clic sull'icona del cestino f574ca2c1e114856.png nella parte superiore della barra laterale di Duet AI.

Creazione della tabella dei pacchetti in Cloud SQL

Imposta le variabili di ambiente per il connettore di database Cloud SQL.

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

Ora esegui data_model.py.

python data_model.py

L'output è simile al seguente (controlla il codice per vedere cosa è effettivamente previsto):

Tables created successfully.

Connettiti all'istanza Cloud SQL e verifica che il database sia stato creato.

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

Dopo aver inserito la password (anch'essa evolution), ottieni le tabelle.

product_details=> \dt

L'output è simile al seguente:

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

Puoi anche controllare il modello dei dati e i dettagli della tabella.

product_details=> \d+ packages

L'output è simile al seguente:

                                                                        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

Digita \q per uscire da Cloud SQL.

db_init.py

Successivamente, aggiungiamo alcuni dati di esempio alla tabella packages.

Cancella la cronologia chat di Duet AI. Con il file data_model.py aperto, prova i seguenti prompt.

Prompt 1: genera una funzione che crea 10 righe di pacchetti di esempio e ne esegue il commit nella tabella pacchetti

Prompt 2: utilizzando la sessione di connect_connector, genera una funzione che crea 10 righe di pacchetti di esempio e ne esegue il commit nella tabella pacchetti.

34a9afc5f04ba5.png

Utilizzando OPEN a4c7ed6d845df343.png il codice in un nuovo flusso di lavoro di file come prima. Salva il codice in un file denominato db_init.py.

Il file finale si trova nella sezione APPENDICE di questo codelab. In caso contrario, apporta le modifiche appropriate manualmente.

Puoi anche provare vari prompt per vedere varie risposte di Duet AI.

Reimposta la cronologia chat di Duet AI facendo clic sull'icona del cestino f574ca2c1e114856.png nella parte superiore della barra laterale di Duet AI.

Creazione di dati dei pacchetti di esempio

Esegui db_init.py dalla riga di comando.

python db_init.py

L'output è simile al seguente:

Packages created successfully.

Connettiti di nuovo all'istanza Cloud SQL e verifica che i dati di esempio siano aggiunti alla tabella dei pacchetti.

Connettiti all'istanza Cloud SQL e verifica che il database sia stato creato.

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

Dopo aver inserito la password (anch'essa evolution), recupera tutti i dati dalla tabella dei pacchetti.

product_details=> SELECT * FROM packages;

L'output è simile al seguente:

 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)

Digita \q per uscire da Cloud SQL.

main.py

Con i file data_model.py, package-service.yaml e connect_connector.py aperti, crea un main.py per l'applicazione.

Prompt 1: Utilizzo della libreria Python Flask. Crea un'implementazione che utilizzi endpoint REST HTTP per questo servizio

Prompt 2: Utilizzo della libreria Python Flask, crea un'implementazione che utilizzi endpoint REST HTTP per questo servizio. importare e utilizzare SessionMaker da connect_conector.py a per i dati dei pacchetti.

Prompt 3: Utilizzando la libreria Python Flask, crea un'implementazione che utilizzi endpoint REST HTTP per questo servizio. importare e utilizzare Package da data_model.py e SessionMaker da connect_conector.py a per i dati dei pacchetti.

Prompt 4: Utilizzando la libreria Python Flask, crea un'implementazione che utilizzi endpoint REST HTTP per questo servizio. importare e utilizzare Package da data_model.py e SessionMaker da connect_conector.py a per i dati dei pacchetti. Utilizza l'IP host 0.0.0.0 per app.run

6d794fc52a90e6ae.png

Aggiorna i requisiti per main.py.

Prompt: crea il file dei requisiti per main.py

1cc0b318d2d4ca2f.png

Aggiungi questo al file requirements.txt. Assicurati di utilizzare Flask versione 3.0.0.

Utilizzando OPEN a4c7ed6d845df343.png il codice in un nuovo flusso di lavoro di file come prima. Salva il codice in un file denominato main.py.

Il file finale si trova nella sezione APPENDICE di questo codelab. In caso contrario, apporta le modifiche appropriate manualmente.

Reimposta la cronologia chat di Duet AI facendo clic sull'icona del cestino f574ca2c1e114856.png nella parte superiore della barra laterale di Duet AI.

5. Testare ed eseguire l'applicazione

Installa i requisiti.

pip3 install -r requirements.txt

Esegui main.py.

python main.py

L'output è simile al seguente:

 * 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

Da un secondo terminale, testa l'endpoint /packages/<product_id>.

curl localhost:5000/packages/1

L'output è simile al seguente:

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

Puoi anche testare qualsiasi altro ID prodotto nei dati di esempio.

Inserisci CTRL_C per uscire dal container Docker in esecuzione nel terminale.

Generazione dei test delle unità in corso...

Con il file main.py aperto, genera test delle unità.

Prompt 1: genera i test delle unità.

e861e5b63e1b2657.png

Utilizzando OPEN a4c7ed6d845df343.png il codice in un nuovo flusso di lavoro di file come prima. Salva il codice in un file denominato test.py.

Nella funzione test_get_package è necessario definire un product_id. Puoi aggiungerlo manualmente.

Il file finale si trova nella sezione APPENDICE di questo codelab. In caso contrario, apporta le modifiche appropriate manualmente.

Reimposta la cronologia chat di Duet AI facendo clic sull'icona del cestino f574ca2c1e114856.png nella parte superiore della barra laterale di Duet AI.

Esecuzione dei test delle unità

Esegui il test delle unità.

python test.py

L'output è simile al seguente:

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

OK

Chiudi tutti i file nell'editor di Cloud Shell e cancella la cronologia chat facendo clic sull'icona del cestino 1ebbfe10d6c540.png nella barra di stato in alto.

Dockerfile

Crea un Dockerfile per questa applicazione.

Apri main.py e prova i seguenti prompt.

Prompt 1: genera un Dockerfile per questa applicazione.

Prompt 2: genera un Dockerfile per questa applicazione. Copia tutti i file nel container.

9c473caea437a5c3.png

Devi anche impostare ENVARS per INSTANCE_CONNECTION_NAME, DB_USER, DB_PASS e DB_NAME. Puoi farlo manualmente. Il Dockerfile dovrebbe avere il seguente aspetto:

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

Utilizzando OPEN a4c7ed6d845df343.png il codice in un nuovo flusso di lavoro di file come prima. Salva il codice in un file denominato Dockerfile.

Il file finale si trova nella sezione APPENDICE di questo codelab. In caso contrario, apporta le modifiche appropriate manualmente.

Esecuzione dell'applicazione in locale

Con il Dockerfile aperto, prova il seguente prompt.

Prompt 1: come posso eseguire localmente un container utilizzando questo Dockerfile

570fd5c296ca8c83.png

Segui le istruzioni.

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

L'output è simile al seguente:

 * 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

Accedi al container da una seconda finestra del terminale.

curl localhost:5000/packages/1

L'output è simile al seguente:

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

L'applicazione containerizzata funziona.

Inserisci CTRL_C per uscire dal container Docker in esecuzione nel terminale.

Creazione dell'immagine container in Artifact Registry

Crea l'immagine container ed esegui il push ad 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

Il container dell'applicazione si trova ora in us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping, di cui è possibile eseguire il deployment in GKE.

6. Deployment dell'applicazione nel cluster GKE in corso

Un cluster GKE Autopilot è stato creato quando hai creato le risorse Google Cloud per questo workshop. Connettiti al cluster GKE.

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

Annota l'account di servizio predefinito di Kubernetes con l'account di servizio Google.

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

L'output è simile al seguente:

serviceaccount/default annotated

Prepara e applica il 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

L'output è simile al seguente:

deployment.apps/shipping created
service/shipping created

Attendi che i pod siano in esecuzione e che al servizio venga assegnato un indirizzo IP del bilanciatore del carico esterno.

kubectl get pods
kubectl get service shipping

L'output è simile al seguente:

# 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

Per i cluster GKE Autopilot, attendi qualche istante finché le risorse non sono pronte.

Accedi al servizio tramite l'indirizzo EXTERNAL-IP.

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

L'output è simile al seguente:

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

7. Credito aggiuntivo: risoluzione dei problemi relativi alla richiesta di partecipazione

Rimuovi il ruolo IAM Client Cloud SQL dall'account di servizio cloudsqlsa. Questo causa un errore di connessione al database Cloud SQL.

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

Riavvia il pod di spedizione.

kubectl rollout restart deployment shipping

Dopo il riavvio del pod, prova ad accedere di nuovo al servizio shipping.

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

L'output è simile al seguente:

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

Ispeziona i log da Kubernetes Engine > Carichi di lavoro

d225b1916c829167.png

Fai clic sul deployment shipping e quindi sulla scheda Log.

1d0459141483d6a7.png

Fai clic sull'icona Visualizza in Esplora log df8b9d19a9fe4c73.pngsul lato destro della barra di stato. Si apre una nuova finestra Esplora log.

e86d1c265e176bc4.png

Fai clic su una delle voci di errore Traceback, quindi fai clic su Spiega questa voce di log.

d6af045cf03008bc.png

Puoi leggere la spiegazione dell'errore.

Chiedi a Duet AI di aiutarti a risolvere l'errore.

Prova il seguente prompt.

Prompt 1: aiutami a risolvere questo errore

9288dd6045369167.png

Inserisci il messaggio di errore nella richiesta.

Prompt 2: accesso vietato: l'entità IAM autenticata non sembra autorizzata a effettuare una richiesta API. Verifica "API Cloud SQL Admin" sia abilitato all'interno del tuo progetto Google Cloud e "Client Cloud SQL" è stato concesso il ruolo IAM all'entità IAM

f1e64fbdc435d31c.png

E poi...

Prompt 3: come posso assegnare il ruolo Client Cloud SQL a un account di servizio Google utilizzando gcloud?

bb8926b995a8875c.png

Assegna il ruolo Client Cloud SQL a cloudsqlsa.

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

Attendi qualche istante e riprova ad accedere all'applicazione.

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

L'output è simile al seguente:

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

Hai utilizzato correttamente Duet AI in Cloud Logging, Esplora log e nella funzionalità Spiegazione dei log per risolvere il problema.

8. Conclusione

Complimenti! Hai completato questo codelab.

In questo codelab hai appreso quanto segue:

  1. Attiva Duet AI nel tuo progetto Google Cloud e configuralo per l'utilizzo in un IDE e nella console Cloud.
  2. Usa Duet AI per la generazione, il completamento e la spiegazione del codice.
  3. Utilizza Duet AI per spiegare e risolvere un problema dell'applicazione.
  4. Funzionalità di Duet AI come la chat IDE e la chat multi-turno, la generazione di codice in chat e in linea, le azioni intelligenti come la spiegazione del codice e la conferma delle citazioni e altro ancora.

9. Appendice

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