1. Objectifs
L'objectif de cet atelier est de proposer des formations pratiques sur Duet AI aux utilisateurs et aux professionnels.
Dans cet atelier de programmation, vous allez apprendre à:
- Activez Duet AI dans votre projet GCP et configurez-le pour l'utiliser dans un IDE et dans la console Cloud.
- Utilisez Duet AI pour générer, compléter et expliquer du code.
- Utiliser Duet AI pour expliquer et résoudre un problème lié à une application
- Fonctionnalités de Duet AI telles que le chat IDE et le chat multitours, la génération de code par chat ou intégrée, des actions intelligentes comme l'explication du code et la confirmation de la récitation, et plus encore.
Narrative
Pour montrer comment Duet AI pour les développeurs est utilisé de manière authentique dans le développement quotidien, les activités de cet atelier se déroulent dans un contexte narratif.
Un nouveau développeur rejoint une entreprise d'e-commerce. Il est chargé d'ajouter un nouveau service à l'application d'e-commerce existante (composée de plusieurs services). Le nouveau service fournit des informations supplémentaires (dimensions, poids, etc.) sur les produits du catalogue de produits. Ce service permettra de réduire les frais de port en fonction des dimensions et du poids des produits.
Comme le développeur débute dans l'entreprise, il utilisera Duet AI pour générer du code, les explications et la documentation.
Une fois le service codé, un administrateur de la plate-forme utilise Duet AI (chat) pour créer l'artefact (conteneur Docker) et les ressources nécessaires pour le déployer sur GCP (par exemple, Artifact Registry, autorisations IAM, dépôt de code, infrastructure de calcul GKE ou Cloud Run, etc.).
Une fois l'application déployée sur GCP, un opérateur d'application/un ingénieur SRE utilise Duet AI (et Cloud Ops) pour l'aider à corriger une erreur dans le nouveau service.
Persona
L'atelier aborde le persona suivant:
- Développeur d'applications : certaines connaissances en programmation et en développement logiciel sont requises.
Cette variante de l'atelier Duet AI est réservée aux développeurs. Aucune connaissance des ressources cloud GCP n'est requise. Les scripts permettant de créer les ressources GCP nécessaires à l'exécution de cette application sont disponibles ici. Vous pouvez suivre les instructions de ce guide pour déployer les ressources GCP requises.
2. Préparer l'environnement
Activer Duet AI
Vous pouvez activer Duet AI dans un projet GCP via l'API (outils gcloud ou IaC tels que Terraform) ou via l'interface utilisateur de la console Cloud.
Pour activer Duet AI dans un projet Google Cloud, vous devez activer l'API Cloud AI Companion, et attribuer les rôles Identity and Access Management (IAM) "Utilisateur de Cloud AI Companion" et "Lecteur Service Usage" aux utilisateurs.
Via gcloud
Activez Cloud Shell :
Configurez vos PROJECT_ID
et USER
, puis activez 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}
La sortie ressemble à ceci:
Updated property [core/project]. Operation "operations/acat.p2-60565640195-f37dc7fe-b093-4451-9b12-934649e2a435" finished successfully.
Attribuez les rôles Identity and Access Management (IAM) "Utilisateur Cloud AI Companion" et "Lecteur Service Usage" au compte UTILISATEUR. L'API Cloud Companion se trouve derrière les fonctionnalités de l'IDE et de la console que nous allons utiliser. L'autorisation "Lecteur de l'utilisation du service" sert de vérification rapide avant d'activer l'UI dans la console (afin que l'UI Duet ne s'affiche que dans les projets dans lesquels l'API est activée).
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
La sortie ressemble à ceci:
... - members: - user:<YOUR USER ACCOUNT> role: roles/cloudaicompanion.user ... - members: - user:<YOUR USER ACCOUNT> role: roles/serviceusage.serviceUsageViewer
Via la console Cloud
Pour activer l'API, accédez à la page de l'API Cloud AI Companion dans la console Google Cloud.
Dans le sélecteur de projet, choisissez un projet.
Cliquez sur Activer.
La page est mise à jour et affiche l'état Activé. Duet AI est désormais disponible dans le projet Google Cloud sélectionné pour tous les utilisateurs disposant des rôles IAM requis.
Pour attribuer les rôles IAM requis pour utiliser Duet AI, accédez à la page IAM.
Dans la colonne Compte principal, recherchez le compte UTILISATEUR pour lequel vous souhaitez activer l'accès à Duet AI, puis cliquez sur l'icône en forme de crayon ✏️ Modifier le compte principal sur cette ligne.
Dans le volet d'accès Modifier, cliquez sur Ajouter un autre rôle.
Dans "Sélectionner un rôle", sélectionnez Utilisateur Cloud AI Companion.
Cliquez sur Ajouter un autre rôle et sélectionnez Lecteur Service Usage.
Cliquez sur Enregistrer.
Configurer l'IDE
Les développeurs peuvent choisir parmi une variété d'IDE qui répondent le mieux à leurs besoins. L'aide au codage de Duet AI est disponible dans plusieurs IDE tels que Visual Studio Code, les IDE JetBrains (IntelliJ, PyCharm, GoLand, WebStorm, etc.), Cloud Workstations et l'éditeur Cloud Shell.
Dans cet atelier, vous pouvez utiliser Cloud Workstations ou l'éditeur Cloud Shell.
Cet atelier utilise l'éditeur Cloud Shell.
Notez que la configuration de Cloud Workstations peut prendre entre 20 et 30 minutes.
Pour l'utiliser immédiatement, utilisez l'éditeur Cloud Shell.
Ouvrez l'éditeur Cloud Shell en cliquant sur l'icône en forme de crayon ✏️ dans la barre de menu supérieure de Cloud Shell.
L'éditeur Cloud Shell possède une interface utilisateur et une expérience utilisateur très semblables à ceux de VSCode.
Cliquez sur les touches CTRL (sous Windows)/CMD (sous Mac) + , (virgule) pour accéder au volet "Paramètres".
Dans la barre de recherche, saisissez "duet ai".
Vérifiez ou activez Cloudcode › Duet AI: Activer et Cloudcode › Duet AI › Suggestions intégrées: Activer automatiquement
Dans la barre d'état inférieure, cliquez sur Cloud Code - Connexion et suivez le workflow de connexion.
Si vous êtes déjà connecté, la barre d'état indique Cloud Code – Aucun projet.
Cliquez sur "Cloud Code - No project" (Cloud Code – Aucun projet). Un volet déroulant "Action" s'affiche en haut de l'écran. Cliquez sur Sélectionner un projet Google Cloud.
Commencez à saisir votre ID de projet. Votre projet devrait apparaître dans la liste.
Sélectionnez votre ID de projet dans la liste des projets.
La barre d'état inférieure est mise à jour pour afficher l'ID de votre projet. Si ce n'est pas le cas, vous devrez peut-être actualiser l'onglet de l'éditeur Cloud Shell.
Cliquez sur l'icône Duet AI dans la barre de menu de gauche. La fenêtre de chat Duet AI s'affiche. Si vous recevez le message "Select GCP Project" (Sélectionner un projet GCP). Cliquez sur le projet et sélectionnez-le à nouveau.
La fenêtre de chat Duet AI s'affiche désormais
3. Configurer l'infrastructure
Pour exécuter le nouveau service de livraison dans GCP, vous avez besoin des ressources GCP suivantes:
- Une instance Cloud SQL, avec une base de données
- Un cluster GKE pour exécuter le service conteneurisé
- Un dépôt Artifact Registry pour stocker l'image Docker
- Un dépôt Cloud Source Repositories pour le code
Dans le terminal Cloud Shell, clonez le dépôt suivant et exécutez les commandes suivantes pour configurer l'infrastructure dans votre projet 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. Développer un service Python Flask
Le service que nous allons créer se composera au final des fichiers suivants. Vous n'avez pas besoin de créer ces fichiers maintenant. Vous allez les créer un par un en suivant les instructions ci-dessous:
package-service.yaml
: spécification OpenAPI pour le service de packages qui contient des données telles que la hauteur, la largeur, le poids et des instructions de manipulation spéciales.data_model.py
: modèle de données pour la spécification de l'API package-service. Crée également la tablepackages
dans la base de données product_details.connect_connector.py
: connexion Cloud SQL (définit un moteur, une session et un ORM de base)db_init.py
: génère des exemples de données dans la tablepackages
.main.py
: service Python Flask avec un point de terminaisonGET
pour récupérer les détails du package à partir des donnéespackages
en fonction de product_id.test.py
- Test unitairerequirement.txt
: configuration requise pour PythonDockerfile
- Pour conteneuriser l'application
Si vous rencontrez des problèmes persistants au cours des exercices, sachez que vous trouverez tous les fichiers finaux dans l'ANNEXE de cet atelier de programmation, à titre de référence.
À l'étape précédente, vous avez créé un dépôt Cloud Source Repositories. Clonez le dépôt. Vous allez créer les fichiers de l'application dans le dossier du dépôt cloné.
Dans le terminal Cloud Shell, exécutez la commande suivante pour cloner le dépôt.
cd ~ gcloud source repos clone shipping shipping cd ~/shipping
Ouvrez la barre latérale de chat Duet AI depuis le menu de gauche de l'éditeur Cloud Shell. L'icône ressemble à . Vous pouvez désormais utiliser Duet AI pour l'assistance au codage.
package-service.yaml
Lorsque aucun fichier n'est ouvert, demandez à Duet de générer une spécification OpenAPI pour le service de livraison.
Invite 1: générez une spécification OpenAPI yaml pour un service fournissant des informations sur la livraison et le colis en fonction d'un ID produit numérique. Le service doit inclure des informations sur la hauteur, la largeur, la profondeur et le poids des colis, ainsi que toute instruction de manipulation particulière.
Trois options sont listées en haut à droite de la fenêtre du code généré.
Vous pouvez COPY
le code et le coller dans un fichier.
Vous pouvez ADD
le code dans le fichier actuellement ouvert dans l'éditeur.
Vous pouvez également OPEN
le code dans un nouveau fichier.
Cliquez sur OPEN
le code dans un nouveau fichier.
Cliquez sur CTRL/CMD + s
pour enregistrer le fichier et enregistrez-le dans le dossier de l'application sous le nom package-service.yaml
. Cliquez sur OK.
Le fichier final se trouve dans la section ANNEXE de cet atelier de programmation. Si ce n'est pas le cas, apportez manuellement les modifications appropriées.
Vous pouvez également essayer différentes requêtes pour voir les réponses de Duet AI.
Pour réinitialiser l'historique des discussions de Duet AI, cliquez sur l'icône Corbeille en haut de la barre latérale de Duet AI.
data_model.py
Créez ensuite le fichier Python du modèle de données du service basé sur la spécification OpenAPI.
Une fois le fichier package-service.yaml
ouvert, saisissez la requête suivante.
Invite 1: À l'aide de l'ORM Python sqlalchemy, générez un modèle de données pour ce service d'API. Incluez également une fonction distincte et un point d'entrée principal qui crée les tables de base de données.
Examinons chaque partie générée. Duet AI reste un assistant. Bien qu'il puisse vous aider à rédiger rapidement du code, vous devez continuer à examiner le contenu généré et à le comprendre au fur et à mesure.
Tout d'abord, il existe une classe appelée Package
de genre Base
qui définit le modèle de données de la base de données packages
comme suit:
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))
Ensuite, vous avez besoin d'une fonction qui crée la table dans la base de données, comme ceci:
def create_tables(engine):
Base.metadata.create_all(engine)
Enfin, vous avez besoin d'une fonction principale qui exécute la fonction create_tables
pour créer la table dans la base de données CloudSQL, comme suit:
if __name__ == '__main__':
from sqlalchemy import create_engine
engine = create_engine('sqlite:///shipping.db')
create_tables(engine)
print('Tables created successfully.')
Notez que la fonction main
crée un moteur à l'aide d'une base de données sqlite
locale. Pour utiliser Cloud SQL, vous devez le modifier. Vous le ferez un peu plus tard.
Utiliser OPEN
le code dans un nouveau workflow de fichier, comme précédemment. Enregistrez le code dans un fichier nommé
data_model.py
(notez le trait de soulignement dans le nom et non un tiret).
Pour réinitialiser l'historique des discussions de Duet AI, cliquez sur l'icône Corbeille en haut de la barre latérale de Duet AI.
connect-connector.py
Créez le connecteur Cloud SQL.
Une fois le fichier data_model.py
ouvert, saisissez les invites suivantes.
Invite 1: À l'aide de la bibliothèque cloud-sql-python-connector, générez une fonction qui initialise un pool de connexions pour une instance Cloud SQL de Postgres.
Notez que la réponse n'utilise pas la bibliothèque cloud-sql-python-connector
. Vous pouvez affiner les requêtes et donner un coup de pouce à Duet en ajoutant des détails au même fil de discussion.
Utilisons une autre requête.
Invite 2: Vous devez utiliser la bibliothèque cloud-sql-python-connector.
Assurez-vous qu'il utilise la bibliothèque cloud-sql-python-connector
.
Utiliser OPEN
le code dans un nouveau workflow de fichier, comme précédemment. Enregistrez le code dans un fichier nommé
connect_conector.py
. Vous devrez peut-être importer manuellement la bibliothèque pg8000
. Veuillez consulter le fichier ci-dessous.
Effacez l'historique des discussions de Duet AI et, une fois le fichier connect_connector.py
ouvert, générez l'ORM DB engine
, sessionmaker
et base
à utiliser dans l'application.
Invite 1: Créer un moteur, une classe sessionmaker et un ORM de base à l'aide de la méthode connect_with_connector
La réponse peut ajouter engine
, Session
et Base
au fichier connect_connector.py
.
Le fichier final se trouve dans la section ANNEXE de cet atelier de programmation. Si ce n'est pas le cas, apportez manuellement les modifications appropriées.
Vous pouvez également essayer différentes requêtes pour voir les variations potentielles des réponses de Duet AI.
Pour réinitialiser l'historique des discussions de Duet AI, cliquez sur l'icône Corbeille en haut de la barre latérale de Duet AI.
Mise à jour de data_model.py...
Vous devez utiliser le moteur créé à l'étape précédente (dans le fichier connect_connector.py
) pour créer une table dans la base de données CloudSQL.
Effacer l'historique des discussions de Duet AI. Ouvrez le fichier data_model.py
. Essayez l'invite suivante.
Invite 1: Dans la fonction principale, importez et utilisez le moteur à partir du fichier connect_connector.py
Vous devriez obtenir une réponse indiquant l'importation de engine
à partir de connect_connector
(pour Cloud SQL). create_table
utilise ce moteur (au lieu de la base de données locale sqlite
par défaut).
Mettez à jour le fichier data_model.py
.
Le fichier final se trouve dans la section ANNEXE de cet atelier de programmation. Si ce n'est pas le cas, apportez manuellement les modifications appropriées.
Vous pouvez également essayer différentes requêtes pour voir les différentes réponses de Duet AI.
Pour réinitialiser l'historique des discussions de Duet AI, cliquez sur l'icône Corbeille en haut de la barre latérale de Duet AI.
requirements.txt
Créez un fichier requirements.txt
pour l'application.
Ouvrez connect_connector.py
et le fichier data_model.py
, puis saisissez l'invite suivante.
Invite 1: Générez un fichier d'exigences pip pour ce modèle de données et ce service
Invite 2: Générez un fichier d'exigences pip pour ce modèle de données et ce service à l'aide des dernières versions
Vérifiez que les noms et les versions sont corrects. Par exemple, dans la réponse ci-dessus, le nom et la version de google-cloud-sql-connecter
sont incorrects. Corrigez manuellement les versions, puis créez un fichier requirements.txt
semblable à celui-ci:
cloud-sql-python-connector==1.2.4
sqlalchemy==1.4.36
pg8000==1.22.0
Dans le terminal de commande, exécutez la commande suivante:
pip3 install -r requirements.txt
Pour réinitialiser l'historique des discussions de Duet AI, cliquez sur l'icône Corbeille en haut de la barre latérale de Duet AI.
Créer une table des packages dans Cloud SQL
Définissez les variables d'environnement du connecteur de base de données 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
Exécutez maintenant data_model.py.
python data_model.py
Le résultat ressemble à ce qui suit (vérifiez le code pour voir ce qui est réellement attendu):
Tables created successfully.
Connectez-vous à l'instance Cloud SQL et vérifiez que la base de données a été créée.
gcloud sql connect ${INSTANCE_NAME} --user=evolution --database=product_details
Après avoir saisi le mot de passe (également appelé évolution), récupérez les tables.
product_details=> \dt
Le résultat ressemble à ce qui suit :
List of relations Schema | Name | Type | Owner --------+----------+-------+----------- public | packages | table | evolution (1 row)
Vous pouvez également vérifier le modèle de données et les détails de la table.
product_details=> \d+ packages
Le résultat ressemble à ce qui suit :
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
Saisissez \q
pour quitter Cloud SQL.
db_init.py
Ajoutons maintenant des exemples de données à la table packages
.
Effacer l'historique des discussions de Duet AI. Une fois le fichier data_model.py
ouvert, essayez les invites suivantes.
Invite 1: Générez une fonction qui crée 10 exemples de lignes de packages et les valide dans la table des packages.
Invite 2: À l'aide de la session de connect_connector, générez une fonction qui crée 10 exemples de lignes de packages et les valide dans la table des packages
Utiliser OPEN
le code dans un nouveau workflow de fichier, comme précédemment. Enregistrez le code dans un fichier nommé
db_init.py
.
Le fichier final se trouve dans la section ANNEXE de cet atelier de programmation. Si ce n'est pas le cas, apportez manuellement les modifications appropriées.
Vous pouvez également essayer différentes requêtes pour voir les différentes réponses de Duet AI.
Pour réinitialiser l'historique des discussions de Duet AI, cliquez sur l'icône Corbeille en haut de la barre latérale de Duet AI.
Créer des exemples de données de packages
Exécutez db_init.py
à partir de la ligne de commande.
python db_init.py
Le résultat ressemble à ce qui suit :
Packages created successfully.
Connectez-vous à nouveau à l'instance Cloud SQL et vérifiez que les exemples de données ont bien été ajoutés à la table des packages.
Connectez-vous à l'instance Cloud SQL et vérifiez que la base de données a été créée.
gcloud sql connect ${INSTANCE_NAME} --user=evolution --database=product_details
Après avoir saisi le mot de passe (également appelé évolution), récupérez toutes les données de la table des packages.
product_details=> SELECT * FROM packages;
Le résultat ressemble à ce qui suit :
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)
Saisissez \q
pour quitter Cloud SQL.
main.py
Une fois les fichiers data_model.py
, package-service.yaml
et connect_connector.py
ouverts, créez un main.py
pour l'application.
Invite 1: À l'aide de la bibliothèque Python flask – Créez une implémentation qui utilise des points de terminaison HTTP REST pour ce service
Invite 2: À l'aide de la bibliothèque Python flask, créez une implémentation qui utilise des points de terminaison HTTP REST pour ce service. importer et utiliser SessionMaker de connect_conector.py vers pour les données de packages.
Invite 3: À l'aide de la bibliothèque Python flask, créez une implémentation qui utilise des points de terminaison HTTP REST pour ce service. importer et utiliser le package à partir de data_model.py et le SessionMaker de connect_conector.py vers pour les données de packages.
Invite 4: À l'aide de la bibliothèque Python flask – Créez une implémentation qui utilise des points de terminaison HTTP REST pour ce service. importer et utiliser le package à partir de data_model.py et le SessionMaker de connect_conector.py vers pour les données de packages. Utiliser l'adresse IP de l'hôte 0.0.0.0 pour app.run
Mettez à jour les exigences pour main.py
.
Invite: Créez un fichier d'exigences pour main.py
Ajouter au fichier requirements.txt
. Veillez à utiliser la version 3.0.0 de Flask.
Utiliser OPEN
le code dans un nouveau workflow de fichier, comme précédemment. Enregistrez le code dans un fichier nommé
main.py
.
Le fichier final se trouve dans la section ANNEXE de cet atelier de programmation. Si ce n'est pas le cas, apportez manuellement les modifications appropriées.
Pour réinitialiser l'historique des discussions de Duet AI, cliquez sur l'icône Corbeille en haut de la barre latérale de Duet AI.
5. Tester et exécuter l'application
Installez la configuration requise.
pip3 install -r requirements.txt
Exécutez main.py
.
python main.py
Le résultat ressemble à ce qui suit :
* 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
À partir d'un deuxième terminal, testez le point de terminaison /packages/<product_id>
.
curl localhost:5000/packages/1
Le résultat ressemble à ce qui suit :
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
Vous pouvez également tester n'importe quel autre ID produit dans vos exemples de données.
Saisissez CTRL_C
pour quitter le conteneur Docker en cours d'exécution dans le terminal.
Générer des tests unitaires
Ouvrez le fichier main.py
et générez des tests unitaires.
Invite 1: Générez des tests unitaires.
Utiliser OPEN
le code dans un nouveau workflow de fichier, comme précédemment. Enregistrez le code dans un fichier nommé
test.py
.
Dans la fonction test_get_package
, un product_id
doit être défini. Vous pouvez l'ajouter manuellement.
Le fichier final se trouve dans la section ANNEXE de cet atelier de programmation. Si ce n'est pas le cas, apportez manuellement les modifications appropriées.
Pour réinitialiser l'historique des discussions de Duet AI, cliquez sur l'icône Corbeille en haut de la barre latérale de Duet AI.
L'exécution des tests unitaires
Exécutez le test unitaire.
python test.py
Le résultat ressemble à ce qui suit :
. ---------------------------------------------------------------------- Ran 1 test in 1.061s OK
Fermez tous les fichiers dans l'éditeur Cloud Shell et effacez l'historique des discussions en cliquant sur l'icône Corbeille dans la barre d'état en haut.
Dockerfile
Créez un Dockerfile
pour cette application.
Ouvrez main.py
et essayez les invites suivantes.
Invite 1: Générez un Dockerfile pour cette application.
Invite 2: Générez un Dockerfile pour cette application. Copiez tous les fichiers dans le conteneur.
Vous devez également définir ENVARS
pour INSTANCE_CONNECTION_NAME
, DB_USER
, DB_PASS
et DB_NAME
. Vous pouvez le faire manuellement. Votre Dockerfile doit se présenter comme suit:
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"]
Utiliser OPEN
le code dans un nouveau workflow de fichier, comme précédemment. Enregistrez le code dans un fichier nommé "Dockerfile".
Le fichier final se trouve dans la section ANNEXE de cet atelier de programmation. Si ce n'est pas le cas, apportez manuellement les modifications appropriées.
Exécuter l'application localement
Lorsque Dockerfile
est ouvert, essayez l'invite suivante.
Invite 1: Comment exécuter localement un conteneur à l'aide de ce Dockerfile ?
Suivez les instructions.
# Build docker build -t shipping . # And run docker run -p 5000:5000 -it shipping
Le résultat ressemble à ce qui suit :
* 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
À partir d'une deuxième fenêtre de terminal, accédez au conteneur.
curl localhost:5000/packages/1
Le résultat ressemble à ce qui suit :
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
L'application conteneurisée fonctionne.
Saisissez CTRL_C
pour quitter le conteneur Docker en cours d'exécution dans le terminal.
Créer une image de conteneur dans Artifact Registry
Créez l'image de conteneur et transférez-la vers 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
Le conteneur d'application se trouve maintenant dans us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping
, qui peut être déployé sur GKE.
6. Déployer l'application sur le cluster GKE
Un cluster GKE Autopilot a été créé lorsque vous avez créé les ressources GCP pour cet atelier. Se connecter au cluster GKE
gcloud container clusters get-credentials gke1 \ --region=us-central1
Annotez le compte de service Kubernetes par défaut avec le compte de service Google.
kubectl annotate serviceaccount default iam.gke.io/gcp-service-account=cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com
Le résultat ressemble à ce qui suit :
serviceaccount/default annotated
Préparez et appliquez le fichier 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
Le résultat ressemble à ce qui suit :
deployment.apps/shipping created service/shipping created
Attendez que les pods soient en cours d'exécution et qu'une adresse IP d'équilibreur de charge externe soit attribuée au service.
kubectl get pods kubectl get service shipping
Le résultat ressemble à ce qui suit :
# 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
Pour les clusters GKE Autopilot, attendez quelques instants que les ressources soient prêtes.
Accédez au service via l'adresse EXTERNAL-IP
.
export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://${EXTERNAL_IP}/packages/1
Le résultat ressemble à ce qui suit :
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
7. Autres informations: résoudre les problèmes liés à la demande
Supprimez le rôle IAM du client Cloud SQL du compte de service cloudsqlsa
. Cela provoque une erreur de connexion à la base de données Cloud SQL.
gcloud projects remove-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/cloudsql.client"
Redémarrez le pod de livraison.
kubectl rollout restart deployment shipping
Une fois le pod redémarré, essayez à nouveau d'accéder au service shipping
.
export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://${EXTERNAL_IP}/packages/1
Le résultat ressemble à ce qui suit :
... <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>
Inspectez les journaux en accédant à Kubernetes Engine > Charges de travail
Cliquez sur le déploiement shipping
, puis sur l'onglet Journaux.
Cliquez sur l'icône Afficher dans l'explorateur de journaux à droite de la barre d'état. Une nouvelle fenêtre Explorateur de journaux s'ouvre.
Cliquez sur l'une des entrées d'erreur Traceback
, puis sur Expliquer cette entrée de journal.
Vous pouvez lire l'explication de l'erreur.
Laissons à présent Duet AI pour vous aider à corriger l'erreur.
Essayez l'invite suivante.
Invite 1: Aidez-moi à résoudre cette erreur
Saisissez le message d'erreur dans l'invite.
Invite 2: Interdit: le compte principal IAM authentifié ne semble pas autorisé à envoyer une requête API. Validez l'API Cloud SQL Admin est activé dans votre projet GCP et dans votre "client Cloud SQL" ; a été attribué au compte principal IAM
Et ensuite.
Invite 3: Comment attribuer le rôle "Client Cloud SQL" à un compte de service Google à l'aide de gcloud ?
Attribuez le rôle "Client Cloud SQL" à cloudsqlsa
.
gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/cloudsql.client"
Patientez quelques instants, puis réessayez d'accéder à l'application.
export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://${EXTERNAL_IP}/packages/1
Le résultat ressemble à ce qui suit :
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
Vous avez utilisé Duet AI dans Cloud Logging, l'explorateur de journaux et la fonctionnalité Explication de journaux pour résoudre le problème.
8. Conclusion
Félicitations ! Vous avez terminé cet atelier de programmation.
Dans cet atelier de programmation, vous avez appris ce qui suit:
- Activez Duet AI dans votre projet GCP et configurez-le pour l'utiliser dans un IDE et dans la console Cloud.
- Utilisez Duet AI pour générer, compléter et expliquer du code.
- Utiliser Duet AI pour expliquer et résoudre un problème lié à une application
- Fonctionnalités de Duet AI telles que le chat IDE et le chat multitours, la génération de code par chat ou intégrée, des actions intelligentes comme l'explication du code et la confirmation de la récitation, et plus encore.
9. Annexe
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"]