Développer des applications LLM avec le SDK Vertex AI

1. Introduction

Présentation

Vous êtes développeur dans une entreprise de marketing de voyage. Votre service commercial a décidé qu'il avait besoin d'une nouvelle application de chat pour rivaliser avec les grandes entreprises de réservation et de recherche. Ils ont également entendu parler de l'IA générative, mais ils n'en savent pas beaucoup plus. D'autres services ont entendu parler de cette initiative et se demandent comment elle pourrait également améliorer leur expérience client.

Objectifs de l'atelier

Dans cet atelier, vous allez créer un chatbot d'assistant de voyage à l'aide du modèle Gemini 2.5 Flash sur Vertex AI.

L'application doit :

  • Aide les utilisateurs à poser des questions sur les voyages, à réserver des voyages et à en savoir plus sur les lieux qu'ils prévoient de visiter
  • Permet aux utilisateurs d'obtenir de l'aide concernant leurs plans de voyage spécifiques
  • être capable d'extraire des données en temps réel, comme la météo, à l'aide d'outils ;

Vous allez travailler dans un environnement Google Cloud préconfiguré, plus précisément dans l'éditeur Cloud Shell. Une interface utilisateur d'application Web de base est déjà configurée pour vous, ainsi que les autorisations nécessaires pour accéder à Vertex AI. Cette application a été créée à l'aide de Streamlit.

Points abordés

Dans cet atelier, vous allez apprendre à effectuer les tâches suivantes :

2. Configuration du projet

Compte Google

Si vous ne possédez pas encore de compte Google personnel, vous devez en créer un.

Utilisez un compte personnel au lieu d'un compte professionnel ou scolaire.

Se connecter à la console Google Cloud

Connectez-vous à la console Google Cloud à l'aide d'un compte Google personnel.

Activer la facturation

Utiliser 5 $de crédits Google Cloud (facultatif)

Pour suivre cet atelier, vous avez besoin d'un compte de facturation avec un certain crédit. Si vous prévoyez d'utiliser votre propre facturation, vous pouvez ignorer cette étape.

  1. Cliquez sur ce lien et connectez-vous avec un compte Google personnel.Vous verrez quelque chose comme ceci :Cliquez pour autoriser Cloud Shell.
  2. Cliquez sur le bouton CLIQUEZ ICI POUR ACCÉDER À VOS CRÉDITS. Vous serez redirigé vers une page permettant de configurer votre profil de facturation.Cliquez pour autoriser Cloud Shell.
  3. Cliquez sur Confirmer.

Vous êtes désormais connecté à un compte de facturation d'essai Google Cloud Platform.

Capture d'écran de la vue d'ensemble de la facturation

Configurer un compte de facturation personnel

Si vous avez configuré la facturation à l'aide de crédits Google Cloud, vous pouvez ignorer cette étape.

Pour configurer un compte de facturation personnel, cliquez ici pour activer la facturation dans la console Cloud.

Remarques :

  • Cet atelier devrait vous coûter moins de 1 USD en ressources Cloud.
  • Vous pouvez suivre les étapes à la fin de cet atelier pour supprimer les ressources et éviter ainsi que des frais supplémentaires ne vous soient facturés.
  • Les nouveaux utilisateurs peuvent bénéficier d'un essai sans frais pour un crédit de 300$.

Créer un projet (facultatif)

Si vous n'avez pas de projet que vous souhaitez utiliser pour cet atelier, créez-en un.

3. Ouvrir l'éditeur Cloud Shell

  1. Cliquez sur ce lien pour accéder directement à l'éditeur Cloud Shell.
  2. Si vous êtes invité à autoriser l'accès à un moment donné, cliquez sur Autoriser pour continuer.Cliquez pour autoriser Cloud Shell.
  3. Si le terminal ne s'affiche pas en bas de l'écran, ouvrez-le :
    • Cliquez sur Afficher.
    • Cliquez sur TerminalOuvrir un nouveau terminal dans l'éditeur Cloud Shell.
  4. Dans le terminal, définissez votre projet à l'aide de la commande suivante :
    gcloud config set project [PROJECT_ID]
    
    • Exemple :
      gcloud config set project lab-project-id-example
      
    • Si vous ne vous souvenez pas de l'ID de votre projet, vous pouvez lister tous vos ID de projet avec la commande suivante :
      gcloud projects list | awk '/PROJECT_ID/{print $2}'
      
      Définir l'ID du projet dans le terminal de l'éditeur Cloud Shell
  5. Le message suivant doit s'afficher :
    Updated property [core/project].
    
    >aside negative Si un `WARNING` s'affiche et que la question `Do you want to continue (Y/n)?` (Voulez-vous continuer (O/N) ?) vous est posée, cela signifie probablement que vous avez saisi l'ID du projet de manière incorrecte. Appuyez sur "n", puis sur "Entrée", et réessayez d'exécuter la commande "gcloud config set project". >

4. Activer les API

Pour utiliser le SDK Vertex AI et interagir avec le modèle Gemini, vous devez activer l'API Vertex AI dans votre projet Google Cloud.

  1. Dans le terminal, activez les API :
    gcloud services enable \
      aiplatform.googleapis.com
    

Présentation du SDK Vertex AI pour Python

Pour interagir avec les modèles hébergés sur Vertex AI depuis votre application Python, vous devez utiliser le SDK Vertex AI pour Python. Ce SDK simplifie le processus d'envoi de requêtes, de spécification des paramètres du modèle et de réception des réponses, sans avoir à gérer directement la complexité des appels d'API sous-jacents.

Vous trouverez une documentation complète sur le SDK Vertex AI pour Python ici : Présentation du SDK Vertex AI pour Python | Google Cloud.

5. Créer un environnement virtuel et installer les dépendances

Avant de commencer un projet Python, il est recommandé de créer un environnement virtuel. Cela isole les dépendances du projet, ce qui évite les conflits avec d'autres projets ou les packages Python globaux du système.

  1. Créez un dossier nommé wanderbot pour stocker le code de votre application d'assistant de voyage. Exécutez le code suivant dans le terminal :
    mkdir wanderbot && cd wanderbot
    
  2. Créez et activez un environnement virtuel :
    uv venv --python 3.12
    source .venv/bin/activate
    
    Le préfixe (wanderbot) s'affiche devant l'invite de votre terminal, ce qui indique que l'environnement virtuel est actif. Cela ressemblerait à quelque chose comme ceci :

    Capture d'écran du terminal avec un environnement virtuel actif

6. Créer des fichiers de démarrage pour wanderbot

  1. Créez et ouvrez un fichier app.py pour l'application. Exécutez le code suivant dans le terminal :
    cloudshell edit app.py
    
    La commande cloudshell edit ouvre le fichier app.py dans l'éditeur au-dessus du terminal.
  2. Collez le code de démarrage de l'application suivant dans app.py :
    import streamlit as st
    from google import genai
    from google.genai import types
    import requests
    import logging
    
    # --- Defining variables and parameters  ---
    REGION = "global"
    PROJECT_ID = None # TO DO: Insert Project ID
    GEMINI_MODEL_NAME = "gemini-2.5-flash"
    
    temperature = .2
    top_p = 0.95
    
    system_instructions = None
    
    # --- Tooling ---
    # TODO: Define the weather tool function declaration
    
    # TODO: Define the get_current_temperature function
    
    
    # --- Initialize the Vertex AI Client ---
    try:
        # TODO: Initialize the Vertex AI client
    
        print(f"VertexAI Client initialized successfully with model {GEMINI_MODEL_NAME}")
    except Exception as e:
        st.error(f"Error initializing VertexAI client: {e}")
        st.stop()
    
    
    # TODO: Add the get_chat function here in Task 15.
    
    
    # --- Call the Model ---
    def call_model(prompt: str, model_name: str) -> str:
        """
        This function interacts with a large language model (LLM) to generate text based on a given prompt and system instructions. 
        It will be replaced in a later step with a more advanced version that handles tooling.
        """
        try:
    
            # TODO: Prepare the content for the model
    
            # TODO: Define generate_content configuration (needed for system instructions and parameters)
    
            # TODO: Define response
    
            logging.info(f"[call_model_response] LLM Response: \"{response.text}\"")
            # TODO: Uncomment the below "return response.text" line
            # return response.text
    
        except Exception as e:
            return f"Error: {e}"
    
    
    # --- Presentation Tier (Streamlit) ---
    # Set the title of the Streamlit application
    st.title("Travel Chat Bot")
    
    # Initialize session state variables if they don't exist
    if "messages" not in st.session_state:
        # Initialize the chat history with a welcome message
        st.session_state["messages"] = [
            {"role": "assistant", "content": "How can I help you today?"}
        ]
    
    # Display the chat history
    for msg in st.session_state.messages:
        st.chat_message(msg["role"]).write(msg["content"])
    
    # Get user input
    if prompt := st.chat_input():
        # Add the user's message to the chat history
        st.session_state.messages.append({"role": "user", "content": prompt})
        # Display the user's message
        st.chat_message("user").write(prompt)
    
        # Show a spinner while waiting for the model's response
        with st.spinner("Thinking..."):
            # Get the model's response using the call_model function
            model_response = call_model(prompt, GEMINI_MODEL_NAME)
            # Add the model's response to the chat history
            st.session_state.messages.append(
                {"role": "assistant", "content": model_response}
            )
            # Display the model's response
            st.chat_message("assistant").write(model_response)
    
  3. Créez et ouvrez un fichier requirements.txt pour le code de l'application. Exécutez le code suivant dans le terminal :
    cloudshell edit requirements.txt
    
    La commande cloudshell edit ouvre le fichier requirements.txt dans l'éditeur au-dessus du terminal.
  4. Collez le code de démarrage de l'application suivant dans requirements.txt.
    google-genai
    streamlit
    requests
    
  5. Installez les dépendances Python requises pour ce projet. Exécutez le code suivant dans le terminal :
    uv pip install -r requirements.txt
    

7. Explorer le code

Les fichiers que vous avez créés incluent une interface de base pour l'application de chat. dont les suivants :

  • app.py : fichier dans lequel nous allons travailler. Il contient actuellement les éléments suivants :
    • importations nécessaires
    • des variables d'environnement et des paramètres (dont certains sont des espaces réservés).
    • une fonction call_model vide que nous allons remplir
    • Code Streamlit pour l'application de chat front-end
  • requirements.txt :
    • inclut les exigences d'installation pour exécuter app.py.

Il est maintenant temps d'explorer le code !

Ouvrir le chat Gemini Code Assist

La fenêtre de chat Gemini Code Assist devrait déjà être ouverte dans un panneau à droite de l'éditeur Cloud Shell. Si le chat Gemini Code Assist n'est pas déjà ouvert, vous pouvez l'ouvrir en procédant comme suit :

  1. Cliquez sur le bouton Gemini Code Assist (Cliquez ici pour activer Gemini Code Assist) en haut de l'écran.
  2. Sélectionnez Ouvrir le chat Gemini Code Assist.Menu Gemini Code Assist

Utiliser Gemini Code Assist pour comprendre le code

Vous pouvez utiliser le chat Gemini Code Assist pour mieux comprendre le code.

  1. Mettez en surbrillance ou sélectionnez la section de code souhaitée.
  2. Tapez "Explique-moi ce code" dans le chat Gemini.
  3. Appuyez sur Entrée pour envoyer

Vidéo montrant la mise en surbrillance d'une partie du code, la saisie de "Explique-moi ça" dans Gemini Code Assist et l'obtention d'une réponse.

8. Lancer l'application Web

Avant de connecter cette application à un LLM, lancez-la pour voir comment elle se comporte initialement.

  1. Depuis le répertoire wanderbot, exécutez la commande suivante dans le terminal pour démarrer l'application Streamlit et la rendre accessible localement dans votre environnement Cloud Shell :
    streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080
    
    Laissez cette fenêtre de terminal ouverte, car l'application Streamlit continuera de s'exécuter. Vous pouvez ouvrir une nouvelle fenêtre de terminal dans Cloud Shell pour exécuter d'autres commandes.
  2. Après avoir exécuté la commande, cliquez sur le bouton Aperçu sur le Web en haut de l'éditeur Cloud Shell, puis sélectionnez Prévisualiser sur le port 8080.
    le menu d'aperçu ouvert, avec

     Une interface de chat simple s'affiche pour votre application de voyage.
  3. Saisissez un message (par exemple, Hi!), puis appuyez sur ENTRÉE.

     Vous remarquerez que le message s'affiche dans l'historique du chat, mais vous recevrez un message d'erreur au lieu d'une réponse de l'assistant. En effet, l'application n'est pas encore connectée à un grand modèle de langage. Observez ce comportement pour comprendre le point de départ de l'atelier.

9. Initialiser le client Vertex AI

Explorer les modèles disponibles dans Vertex AI

La plate-forme Vertex AI de Google Cloud donne accès à différents modèles d'IA générative. Avant d'en intégrer un, vous pouvez explorer les options disponibles dans la console Google Cloud.

  1. Dans la console Google Cloud, accédez à Model Garden. Pour ce faire, recherchez "Model Garden" dans la barre de recherche en haut de l'écran, puis sélectionnez Vertex AI.(spectacles )
  2. Parcourez les modèles disponibles. Vous pouvez filtrer les résultats par modalités, types de tâches et fonctionnalités, par exemple.

Pour cet atelier, vous allez utiliser le modèle Gemini 2.5 Flash, qui est un bon choix pour créer des applications de chat réactives en raison de sa rapidité.

Initialiser le client Vertex AI

Vous allez maintenant modifier la section --- Initialize the Vertex AI Client --- dans app.py pour initialiser le client Vertex AI. Cet objet client sera utilisé pour envoyer des requêtes au modèle.

  1. Ouvrez app.py dans l'éditeur Cloud Shell.
  2. Dans app.py, recherchez la ligne PROJECT_ID = None.
  3. Remplacez None par l'ID de votre projet Google Cloud entre guillemets. (par exemple, PROJECT_ID = "google-cloud-labs")
     Si vous ne vous souvenez pas de votre ID de projet, vous pouvez l'obtenir en exécutant la commande suivante :
    gcloud projects list | awk '/PROJECT_ID/{print $2}'
    
  4. Définissez le client : dans le bloc try, initialisez le client Vertex AI.
        client = genai.Client(
            vertexai=True,
            project=PROJECT_ID,
            location=REGION,
        )
    

Initialisation du client Vertex AI mise à jour

À ce stade, la section "Initialiser le client Vertex AI" se présente comme suit :

# --- Initialize the Vertex AI Client ---
try:
    client = genai.Client(
        vertexai=True,
        project=PROJECT_ID,
        location=REGION,
    )
    print(f"VertexAI Client initialized successfully with model {GEMINI_MODEL_NAME}")
except Exception as e:
    st.error(f"Error initializing VertexAI client: {e}")
    st.stop()

10. Préparer les données et appeler le modèle

Vous allez maintenant préparer le contenu à envoyer au modèle et appeler le modèle Gemini.

  1. Recherchez la section --- Call the Model --- où la fonction call_model est définie.
  2. Définir le contenu : sous # TODO: Prepare the content for the model , définissez le contenu d'entrée qui sera envoyé au modèle. Pour une requête de base, il s'agit du message saisi par l'utilisateur.
            contents = [prompt]
    
  3. Définissez la réponse : collez ce code sous # TODO: Define response.
            response = client.models.generate_content(
                model=model_name,
                contents=contents,
            )
    
  4. Renvoyez la réponse : annulez la mise en commentaire de la ligne suivante :
            return response.text
    
  5. Examinez la ligne où la fonction call_model est appelée, vers le bas du fichier dans le bloc with. Si vous ne comprenez pas ce qui se passe ici, mettez la ligne en surbrillance et demandez à Gemini Code Assist de vous l'expliquer.

Une façon plus explicite de définir contents

La méthode de définition de contents ci-dessus fonctionne, car le SDK est suffisamment intelligent pour comprendre qu'une liste contenant des chaînes représente la saisie de texte par l'utilisateur. Il le met automatiquement en forme pour l'API du modèle.

Toutefois, la manière la plus explicite et fondamentale de structurer l'entrée consiste à utiliser les objets types.Part et types.Content, comme suit :

user_message_parts = [types.Part.from_text(text=prompt)]
contents = [
    types.Content(
        role="user", # Indicates the content is from the user
        parts=user_message_parts, # A list, allowing multiple types of content
    ),
]

Fonction call_model mise à jour

À ce stade, la fonction call_model devrait se présenter comme suit :

def call_model(prompt: str, model_name: str) -> str:
    """
    This function interacts with a large language model (LLM) to generate text based on a given prompt and system instructions. 
    It will be replaced in a later step with a more advanced version that handles tooling.
    """
    try:

        contents = [prompt]

        # TODO: Define generate_content configuration (needed later for system instructions and parameters)

        response = client.models.generate_content(
            model=model_name,
            contents=contents,
        )
        logging.info(f"[call_model_response] LLM Response: \"{response.text}\"")

        return response.text
    except Exception as e:
        return f"Error: {e}"

11. Tester l'application associée

  1. Dans le terminal, arrêtez le processus en cours d'exécution (CTRL+C).
  2. Réexécutez la commande pour redémarrer l'application Streamlit.
    streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080
    
  3. Actualisez l'application Streamlit. Si l'application Streamlit est toujours en cours d'exécution, vous pouvez simplement actualiser la page d'aperçu Web dans votre navigateur.
  4. Saisissez ensuite une question dans la zone de saisie du chat, par exemple :
    What is the best time of year to go to Iceland?
    
  5. Appuyez sur Entrée.

     L'application devrait afficher votre message, un indicateur de chargement "Réflexion en cours…", puis une réponse générée par le modèle Gemini. Si c'est le cas, vous avez réussi à connecter votre application Web à un LLM sur Vertex AI. 🙌 🥳

12. Définir des instructions système

Bien que la connexion de base fonctionne, la qualité et le style des réponses du LLM sont fortement influencés par les entrées qu'il reçoit. L'ingénierie des prompts consiste à concevoir et à affiner ces entrées (requêtes) pour guider le modèle vers la génération du résultat souhaité.

Pour ce faire, vous allez commencer par créer des instructions système et les transmettre au modèle.

Vous utiliserez Demander à Gemini pour vous aider à trouver des instructions système utiles.

  1. Dans app.py, recherchez la variable system_instructions, qui est actuellement définie sur None.
    system_instructions = None
    
    Vous allez remplacer None par une chaîne multiligne qui fournit des instructions à notre bot d'assistance de voyage.
  2. Demander à Gemini Code Assist : transmettez le prompt suivant à Gemini Code Assist (ou créez le vôtre) :
    I am a developer at a travel marketing company, and my sales department has decided that they need a new chat application to keep up with the bigger booking and search companies. I'm building a simple travel assistant chatbot using the Gemini 2.5 Flash model on Vertex AI.
    
    The application should:
    - Helps users ask questions about travel, book travel, and learn about places they are going to go
    - Provides users ways to get help about their specific travel plans
    - Provides all this in a production quality way (multiple environments, logging and monitoring, etc.)
    
    Please create system instructions appropriate for that chat app. Be thorough.
    
    Do not alter the code in any way beyond providing me with system instructions.
    
  3. Définissez system_instructions : définissez system_instructions sur les instructions système que vous avez générées à l'aide de Gemini Code Assist. Vous pouvez également utiliser ces instructions système, qui ont été créées par Gemini avec une requête similaire.
    system_instructions = """
    You are a sophisticated travel assistant chatbot designed to provide comprehensive support to users throughout their travel journey. Your capabilities include answering travel-related questions, assisting with booking travel arrangements, offering detailed information about destinations, and providing support for existing travel plans.
    
    **Core Functionalities:**
    
    1.  **Travel Information and Recommendations:**
        *   Answer user inquiries about travel destinations, including popular attractions, local customs, visa requirements, weather conditions, and safety advice.
        *   Provide personalized recommendations for destinations, activities, and accommodations based on user preferences, interests, and budget.
        *   Offer insights into the best times to visit specific locations, considering factors like weather, crowds, and pricing.
        *   Suggest alternative destinations or activities if the user's initial choices are unavailable or unsuitable.
    
    2.  **Booking Assistance:**
        *   Facilitate the booking of flights, hotels, rental cars, tours, and activities.
        *   Search for available options based on user-specified criteria such as dates, destinations, budget, and preferences.
        *   Present clear and concise information about available options, including pricing, amenities, and booking terms.
        *   Guide users through the booking process, ensuring accurate information and secure transactions.
        *   Provide booking confirmations and relevant details, such as booking references and contact information.
    
    3.  **Travel Planning and Itinerary Management:**
        *   Assist users in creating detailed travel itineraries, including flights, accommodations, activities, and transportation.
        *   Offer suggestions for optimizing travel plans, such as minimizing travel time or maximizing sightseeing opportunities.
        *   Provide tools for managing and modifying existing itineraries, including adding or removing activities, changing booking dates, or upgrading accommodations.
        *   Offer reminders and notifications for upcoming travel events, such as flight check-in or tour departure times.
    
    4.  **Customer Support and Troubleshooting:**
        *   Provide prompt and helpful support to users with questions or issues related to their travel plans.
        *   Assist with resolving booking discrepancies, cancellations, or modifications.
        *   Offer guidance on travel-related emergencies, such as lost luggage or travel delays.
        *   Provide access to relevant contact information for airlines, hotels, and other travel providers.
    
    **Interaction Guidelines:**
    
    *   **Professionalism:** Maintain a polite, respectful, and professional tone in all interactions.
    *   **Clarity and Conciseness:** Provide clear, concise, and easy-to-understand information. Avoid jargon or technical terms unless necessary and always explain them.
    *   **Accuracy:** Ensure all information provided is accurate and up-to-date. Double-check details before sharing them with users. If unsure about something, admit that you don't know and offer to find the information.
    *   **Personalization:** Tailor your responses and recommendations to the specific needs and preferences of each user.
    *   **Proactive Assistance:** Anticipate user needs and offer relevant information or suggestions proactively.
    *   **Error Handling:** Gracefully handle user errors or misunderstandings. Provide helpful guidance and alternative options when necessary.
    *   **Confidentiality:** Respect user privacy and handle personal information with the utmost confidentiality and in compliance with data protection regulations.
    
    **Example Interactions:**
    
    **User:** "I want to go on a beach vacation in the Caribbean. I have a budget of $2000 per person for a week."
    **Chatbot:** "Certainly! The Caribbean offers many beautiful beach destinations within your budget. Some popular options include Punta Cana in the Dominican Republic, Cancun in Mexico, and Montego Bay in Jamaica. These destinations offer stunning beaches, all-inclusive resorts, and various activities. Would you like me to search for flights and accommodations for these locations based on your travel dates?"
    
    **User:** "My flight is delayed. What should I do?"
    **Chatbot:** "I'm sorry to hear about the delay. Please check with the airline for the updated departure time and any assistance they can offer. You may be entitled to compensation or rebooking options depending on the length of the delay and the airline's policy. Do you have your flight number handy so I can look up the current status for you?"
    
    **User:** "Tell me about the best time to visit Japan."
    **Chatbot:** "Japan is a fantastic destination with distinct seasons offering unique experiences. Spring (March-May) is famous for the beautiful cherry blossoms, while autumn (September-November) boasts stunning fall foliage. Both seasons have pleasant temperatures, making them ideal for sightseeing. Summer (June-August) can be hot and humid, but it's a great time for festivals and outdoor activities in the mountains. Winter (December-February) offers opportunities for skiing and snowboarding in the Japanese Alps, though some areas may experience heavy snowfall. To recommend the best time for you, could you tell me what you'd like to experience in Japan?"
    
    By following these instructions, you will be able to provide exceptional travel assistance and create a positive experience for every user.
    """
    
  4. Définissez la configuration generate_content : initialisez un objet de configuration auquel vous transmettrez ces instructions système. Comme system_instructions est défini globalement dans notre script, la fonction peut y accéder directement.
            generate_content_config = types.GenerateContentConfig(
                system_instruction=[
                    types.Part.from_text(text=system_instructions)
                ],
            )
            logging.info(f"[generate_config_details] System Instruction: {generate_content_config.system_instruction[0].text}")
    
  5. Pour ajouter les instructions système à la réponse, ajoutez un paramètre config à la méthode generate content et définissez-le sur l'objet generate_content_config créé ci-dessus.
            response = client.models.generate_content(
                model=model_name,
                contents=contents,
                config=generate_content_config, # This is the new line
            )
    

Fonction call_model mise à jour

La fonction call_model complète se présente désormais comme suit :

def call_model(prompt: str, model_name: str) -> str:
    """
    This function interacts with a large language model (LLM) to generate text based on a given prompt and system instructions. 
    It will be replaced in a later step with a more advanced version that handles tooling.
    """
    try:
        contents = [prompt]

        generate_content_config = types.GenerateContentConfig(
            system_instruction=[
                types.Part.from_text(text=system_instructions)
            ],
        )
        logging.info(f"[generate_config_details] System Instruction: {generate_content_config.system_instruction[0].text}")
        response = client.models.generate_content(
            model=model_name,
            contents=contents,
            config=generate_content_config,
        )

        logging.info(f"[call_model_response] LLM Response: \"{response.text}\"")
        
        return response.text
    except Exception as e:
        return f"Error: {e}"

13. Tester l'application avec les instructions système

  1. Dans le terminal, arrêtez le processus en cours d'exécution (CTRL+C).
  2. Réexécutez la commande pour redémarrer l'application Streamlit.
    streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080
    
  3. Actualisez l'application Streamlit. Si l'application Streamlit est toujours en cours d'exécution, vous pouvez simplement actualiser la page d'aperçu Web dans votre navigateur.
  4. Essayez la même question que précédemment :
    What is the best time of year to go to Iceland?
    
  5. Appuyez sur Entrée.
     Compare sa réponse à celle qu'il a donnée la dernière fois.

14. Définir un outil météo

Jusqu'à présent, notre chatbot est compétent, mais ses connaissances sont limitées aux données sur lesquelles il a été entraîné. Il ne peut pas accéder aux informations en temps réel. Pour un bot de voyage, la possibilité d'extraire des données en direct, comme les prévisions météo, est un avantage considérable.

C'est là que l'outillage, également appelé appel de fonction, entre en jeu. Nous pouvons définir un ensemble d'outils (fonctions Python) que le LLM peut choisir d'appeler pour obtenir des informations externes.

Fonctionnement des outils

  1. Nous décrivons nos outils au modèle, y compris ce qu'ils font et les paramètres qu'ils prennent.
  2. L'utilisateur envoie un prompt (par exemple, Quel temps fait-il à Londres ?).
  3. Le modèle reçoit la requête et constate que l'utilisateur pose une question à laquelle il peut répondre à l'aide de l'un de ses outils.
  4. Au lieu de répondre avec du texte, le modèle répond avec un objet function_call spécial, indiquant l'outil qu'il souhaite appeler et les arguments à utiliser.
  5. Notre code Python reçoit ce function_call, exécute notre fonction get_current_temperature réelle avec les arguments fournis et obtient le résultat (par exemple, 15 °C).
  6. Nous renvoyons ce résultat au modèle.
  7. Le modèle reçoit le résultat et génère une réponse en langage naturel pour l'utilisateur (par exemple, "La température actuelle à Londres est de 15 °C.")

Ce processus permet au modèle de répondre à des questions qui vont bien au-delà de ses données d'entraînement, ce qui en fait un assistant beaucoup plus puissant et utile.

Définir un outil météo

Si un voyageur cherche des conseils sur les activités à faire et qu'il hésite entre plusieurs activités qui dépendent de la météo, un outil météo peut lui être utile. Créons un outil pour que notre modèle puisse obtenir la météo actuelle. Nous avons besoin de deux éléments : une déclaration de fonction qui décrit l'outil au modèle et la fonction Python qui l'implémente.

  1. Dans app.py, recherchez le commentaire # TODO: Define the weather tool function declaration.
  2. Sous ce commentaire, ajoutez la variable weather_function. Il s'agit d'un dictionnaire qui indique au modèle tout ce qu'il doit savoir sur l'objectif de la fonction, ses paramètres et les arguments requis.
    weather_function = {
        "name": "get_current_temperature",
        "description": "Gets the current temperature for a given location.",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "The city name, e.g. San Francisco",
                },
            },
            "required": ["location"],
        },
    }
    
  3. Ensuite, recherchez le commentaire # TODO: Define the get_current_temperature function. En dessous, ajoutez le code Python suivant. Cette fonction :
    • Appelez une API Geocoding pour obtenir les coordonnées du lieu.
    • Utilisez ces coordonnées pour appeler une API météo.
    • Renvoie une chaîne simple avec la température et l'unité.
    def get_current_temperature(location: str) -> str:
        """Gets the current temperature for a given location."""
    
        try:
            # --- Get Latitude and Longitude for the location ---
            geocode_url = f"https://geocoding-api.open-meteo.com/v1/search?name={location}&count=1&language=en&format=json"
            geocode_response = requests.get(geocode_url)
            geocode_data = geocode_response.json()
    
            if not geocode_data.get("results"):
                return f"Could not find coordinates for {location}."
    
            lat = geocode_data["results"][0]["latitude"]
            lon = geocode_data["results"][0]["longitude"]
    
            # --- Get Weather for the coordinates ---
            weather_url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}&current_weather=true"
            weather_response = requests.get(weather_url)
            weather_data = weather_response.json()
    
            temperature = weather_data["current_weather"]["temperature"]
            unit = "°C"
    
            return f"{temperature}{unit}"
    
        except Exception as e:
            return f"Error fetching weather: {e}"
    

15. Refactoriser pour le chat et les outils

Notre fonction call_model actuelle utilise un simple appel generate_content ponctuel. Cette approche est idéale pour les questions uniques, mais pas pour les conversations multitours, en particulier celles qui impliquent des échanges pour les outils.

Il est préférable d'utiliser une session de chat, qui conserve le contexte de la conversation. Nous allons maintenant refactoriser notre code pour utiliser une session de chat, ce qui est nécessaire pour implémenter correctement les outils.

  1. Supprimez la fonction call_model existante. Nous la remplacerons par une version plus avancée.
  2. À la place, ajoutez la nouvelle fonction call_model à partir du bloc de code ci-dessous. Cette nouvelle fonction contient la logique permettant de gérer la boucle d'appel d'outil dont nous avons parlé précédemment. Vous remarquerez qu'il comporte plusieurs commentaires TODO que nous compléterons lors des prochaines étapes.
    # --- Call the Model ---
    def call_model(prompt: str, model_name: str) -> str:
        """
        This function interacts with a large language model (LLM) to generate text based on a given prompt.
        It maintains a chat session and handles function calls from the model to external tools.
        """
        try:
            # TODO: Get the existing chat session or create a new one.
    
            message_content = prompt
    
            # Start the tool-calling loop
            while True:
                # TODO: Send the message to the model.
    
                # Check if the model wants to call a tool
                has_tool_calls = False
                for part in response.candidates[0].content.parts:
                    if part.function_call:
                        has_tool_calls = True
                        function_call = part.function_call
                        logging.info(f"Function to call: {function_call.name}")
                        logging.info(f"Arguments: {function_call.args}")
    
                        # TODO: Call the appropriate function if the model requests it.
    
                # If no tool call was made, break the loop
                if not has_tool_calls:
                    break
    
            # TODO: Return the model's final text response.
    
        except Exception as e:
            return f"Error: {e}"
    
  3. Ajoutons maintenant une fonction d'assistance pour gérer la session de chat. Au-dessus de la nouvelle fonction call_model, ajoutez la fonction get_chat. Cette fonction crée une session de chat avec nos instructions système et définitions d'outils, ou récupère celle existante. Il s'agit d'une bonne pratique pour organiser le code.
    def get_chat(model_name: str):
        if f"chat-{model_name}" not in st.session_state:
    
            # TODO: Define the tools configuration for the model
    
            # TODO: Define the generate_content configuration, including tools
    
            # TODO: Create a new chat session
    
            st.session_state[f"chat-{model_name}"] = chat
        return st.session_state[f"chat-{model_name}"]
    

Vous avez maintenant configuré la structure de notre logique de chat avancée et compatible avec les outils.

16. Implémenter la logique d'appel d'outil

À présent, remplissons TODOs pour rendre notre logique d'appel d'outil entièrement fonctionnelle.

Implémenter get_chat

  1. Dans la fonction get_chat sous le commentaire # TODO: Define the tools configuration..., définissez l'objet tools en créant une instance types.Tool à partir de notre déclaration weather_function.
            tools = types.Tool(function_declarations=[weather_function])
    
  2. Sous # TODO: Define the generate_content configuration..., définissez generate_content_config en veillant à transmettre l'objet tools au modèle. C'est ainsi que le modèle apprend à connaître les outils qu'il peut utiliser.
            generate_content_config = types.GenerateContentConfig(
                system_instruction=[types.Part.from_text(text=system_instructions)],
                tools=[tools] # Pass the tool definition here
            )
    
  3. Sous # TODO: Create a new chat session, créez l'objet de chat à l'aide de client.chats.create(), en transmettant le nom et la configuration de notre modèle.
            chat = client.chats.create(
                model=model_name,
                config=generate_content_config,
            )
    

Implémenter call_model

  1. Sous # TODO: Get the existing chat session... dans la fonction call_model, appelez notre nouvelle fonction d'assistance get_chat.
            chat = get_chat(model_name)
    
  2. Ensuite, recherchez # TODO: Send the message to the model. Envoyez le message de l'utilisateur à l'aide de la méthode chat.send_message().
                response = chat.send_message(message_content)
    
  3. Recherchez # TODO: Call the appropriate function.... C'est là que nous vérifions la fonction souhaitée par le modèle et l'exécutons.
                    if function_call.name == "get_current_temperature":
                      result = get_current_temperature(**function_call.args)
                    function_response_part = types.Part.from_function_response(
                        name=function_call.name,
                        response={"result": result},
                    )
                    message_content = [function_response_part]
  1. Enfin, recherchez # TODO: Return the model's final text response et ajoutez l'instruction de retour.
            return response.text
    

Fonction get_chat mise à jour

La fonction get_chat mise à jour devrait désormais se présenter comme suit :

def get_chat(model_name: str):
    if f"chat-{model_name}" not in st.session_state:
        #Tools
        tools = types.Tool(function_declarations=[weather_function])

        # Initialize a confiburation object
        generate_content_config = types.GenerateContentConfig(
            system_instruction=[types.Part.from_text(text=system_instructions)],
            tools=[tools]
        )
        chat = client.chats.create(
            model=model_name,
            config=generate_content_config,
        )
        st.session_state[f"chat-{model_name}"] = chat
    return st.session_state[f"chat-{model_name}"]

Fonction call_model mise à jour

La fonction call_model mise à jour devrait désormais se présenter comme suit :

def call_model(prompt: str, model_name: str) -> str:
    try:
        chat = get_chat(model_name)
        message_content = prompt
        
        while True:
            response = chat.send_message(message_content)
            has_tool_calls = False
            for part in response.candidates[0].content.parts:
                if part.function_call:
                    has_tool_calls = True
                    function_call = part.function_call
                    logging.info(f"Function to call: {function_call.name}")
                    logging.info(f"Arguments: {function_call.args}")
                    if function_call.name == "get_current_temperature":
                        result = get_current_temperature(**function_call.args)
                        function_response_part = types.Part.from_function_response(
                            name=function_call.name,
                            response={"result": result},
                        )
                        message_content = [function_response_part]
                elif part.text:
                    logging.info("No function call found in the response.")
                    logging.info(response.text)

            if not has_tool_calls:
                break

        return response.text

    except Exception as e:
        return f"Error: {e}"

17. Tester l'application avec les outils activés

Découvrons votre nouvelle fonctionnalité en action !

  1. Dans le terminal, arrêtez le processus en cours d'exécution (CTRL+C).
  2. Réexécutez la commande pour redémarrer l'application Streamlit.
    streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080
    
  3. Actualisez l'application Streamlit. Si l'application Streamlit est toujours en cours d'exécution, vous pouvez simplement actualiser la page d'aperçu Web dans votre navigateur.
  4. Posez maintenant une question qui devrait déclencher votre nouvel outil, par exemple :
    I'm looking for something to do in New York today. What do you recommend? Would it be a good day to go to Ellis Island?
    
  5. Appuyez sur ENTRÉE
    Comparez cette réponse aux précédentes. Qu'est-ce qui change ?
     Vous devriez voir une réponse qui intègre la température de votre fonction. Vérifiez également votre terminal Cloud Shell. Vous devriez voir des instructions d'impression confirmant que votre fonction Python a été exécutée.

18. Affiner la sortie du modèle avec des paramètres

Bravo ! Votre assistant de voyage peut désormais utiliser des outils pour récupérer des données externes en direct, ce qui le rend beaucoup plus puissant.

Maintenant que nous avons amélioré les capacités de notre modèle, affinons sa façon de répondre. Les paramètres du modèle vous permettent de contrôler le style et le caractère aléatoire du texte généré par le LLM. En ajustant ces paramètres, vous pouvez rendre la sortie du robot plus ciblée et déterministe, ou plus créative et variée.

Dans cet atelier, nous allons nous concentrer sur temperature et top_p. (Consultez la GenerateContentConfig dans notre documentation de référence de l'API pour obtenir la liste complète des paramètres configurables et leur description.)

  • temperature : contrôle le caractère aléatoire de la sortie. Une valeur faible (proche de 0) rend le résultat plus déterministe et ciblé, tandis qu'une valeur élevée (proche de 2) augmente l'aléatoire et la créativité. Pour un bot de questions/réponses ou un assistant, une température plus basse est généralement préférable pour obtenir des réponses plus cohérentes et factuelles.
  • top_p : probabilité cumulée maximale des jetons à prendre en compte lors de l'échantillonnage. Les jetons sont triés en fonction des probabilités qui leur sont attribuées, de sorte que seuls les jetons les plus probables sont pris en compte. Le modèle prend en compte les jetons les plus probables dont les probabilités s'additionnent à la valeur top_p. Une valeur inférieure limite les choix de jetons, ce qui entraîne une sortie moins variée.

Paramètres d'appel

  1. Recherchez les variables temperature et top_p définies en haut de app.py. Notez qu'elles n'ont pas encore été appelées.
  2. Ajoutez temperature et top_p aux paramètres définis dans GenerateContentConfig de la fonction call_model.
            generate_content_config = types.GenerateContentConfig(
                temperature=temperature,
                top_p=top_p,
                system_instruction=[types.Part.from_text(text=system_instructions)],
                tools=[tools] # Pass the tool definition here
            )
    
    

Fonction get_chat mise à jour

L'application get_chat se présente désormais comme suit :

def get_chat(model_name: str):
    if f"chat-{model_name}" not in st.session_state:
        #Tools
        tools = types.Tool(function_declarations=[weather_function])

        # Initialize a confiburation object
        generate_content_config = types.GenerateContentConfig(
            temperature=temperature,
            top_p=top_p,
            system_instruction=[types.Part.from_text(text=system_instructions)],
            tools=[tools] 
        )
        chat = client.chats.create(
            model=model_name,
            config=generate_content_config,
        )
        st.session_state[f"chat-{model_name}"] = chat
    return st.session_state[f"chat-{model_name}"]

19. Tester avec les paramètres du modèle

  1. Dans le terminal, arrêtez le processus en cours d'exécution (CTRL+C).
  2. Réexécutez la commande pour redémarrer l'application Streamlit.
    streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080
    
  3. Actualisez l'application Streamlit. Si l'application Streamlit est toujours en cours d'exécution, vous pouvez simplement actualiser la page d'aperçu Web dans votre navigateur.
  4. Reposez la même question que précédemment.
    I'm looking for something to do in New York today. What do you recommend? Would it be a good day to go to Ellis Island?
    
  5. Appuyez sur ENTRÉE
    Comparez cette réponse aux précédentes.

20. Félicitations !

Vous avez réussi à mettre à niveau votre application de questions/réponses avec l'outillage, une fonctionnalité puissante qui permet à votre application optimisée par Gemini d'interagir avec des systèmes externes et d'accéder à des informations en temps réel.

Continuer à expérimenter

Il existe de nombreuses options pour continuer à optimiser votre requête. Voici quelques exemples :

  • Ajustez temperature et top_p pour voir comment la réponse du LLM change.
  • Consultez la GenerateContentConfig dans notre documentation de référence de l'API pour obtenir la liste complète des paramètres configurables et de leurs descriptions. Essayez de définir d'autres paramètres et de les ajuster pour voir ce qui se passe.

Récapitulatif

Dans cet atelier, vous avez :

  • Utilisez l'éditeur Cloud Shell et le terminal pour le développement.
  • Utilisez le SDK Vertex AI pour Python afin de connecter votre application à un modèle Gemini.
  • Appliqué des instructions système et des paramètres de modèle pour guider les réponses du LLM.
  • Vous avez découvert le concept d'outillage (appels de fonction) et ses avantages.
  • Vous avez refactorisé votre code pour utiliser une session de chat avec état, une bonne pratique pour l'IA conversationnelle.
  • Définissez un outil pour le modèle à l'aide d'une déclaration de fonction.
  • Implémenté la fonction Python pour fournir la logique de l'outil.
  • Écrit le code pour gérer les demandes d'appel de fonction du modèle et renvoyer les résultats.