ai-agents-for-beginners

Comment concevoir de bons agents IA

(Cliquez sur l’image ci-dessus pour voir la vidéo de cette leçon)

Modèle de conception d’utilisation d’outils

Les outils sont intéressants car ils permettent aux agents IA d’avoir une gamme plus large de capacités. Au lieu que l’agent dispose d’un ensemble limité d’actions qu’il peut effectuer, en ajoutant un outil, l’agent peut maintenant réaliser une grande variété d’actions. Dans ce chapitre, nous allons examiner le modèle de conception d’utilisation d’outils, qui décrit comment les agents IA peuvent utiliser des outils spécifiques pour atteindre leurs objectifs.

Introduction

Dans cette leçon, nous cherchons à répondre aux questions suivantes :

Objectifs d’apprentissage

Après avoir terminé cette leçon, vous serez capable de :

Qu’est-ce que le modèle de conception d’utilisation d’outils ?

Le modèle de conception d’utilisation d’outils se concentre sur la capacité donnée aux modèles de langage de grande taille (LLM) d’interagir avec des outils externes afin d’atteindre des objectifs spécifiques. Les outils sont des codes pouvant être exécutés par un agent pour réaliser des actions. Un outil peut être une fonction simple telle qu’une calculatrice, ou un appel API vers un service tiers comme la consultation du cours boursier ou les prévisions météorologiques. Dans le contexte des agents IA, les outils sont conçus pour être exécutés par les agents en réponse à des appels de fonctions générés par le modèle.

Quels sont les cas d’usage auxquels il peut être appliqué ?

Les agents IA peuvent tirer parti des outils pour accomplir des tâches complexes, récupérer des informations ou prendre des décisions. Le modèle de conception d’utilisation d’outils est fréquemment utilisé dans des scénarios nécessitant une interaction dynamique avec des systèmes externes, tels que des bases de données, des services web ou des interprètes de code. Cette capacité est utile pour plusieurs cas d’usage différents, notamment :

Quels sont les éléments/blocs de construction nécessaires pour mettre en œuvre le modèle de conception d’utilisation d’outils ?

Ces blocs de construction permettent à l’agent IA d’exécuter une large gamme de tâches. Examinons les éléments clés nécessaires à la mise en œuvre du modèle de conception d’utilisation d’outils :

Examinons maintenant plus en détail l’appel de fonctions/outils.

Appel de fonctions/outils

L’appel de fonctions est le principal moyen permettant aux modèles de langage de grande taille (LLM) d’interagir avec des outils. Vous verrez souvent « fonction » et « outil » utilisés de manière interchangeable parce que les « fonctions » (blocs de code réutilisables) sont les « outils » utilisés par les agents pour réaliser des tâches. Pour que le code d’une fonction soit invoqué, un LLM doit comparer la requête de l’utilisateur avec la description des fonctions. Pour cela, un schéma contenant les descriptions de toutes les fonctions disponibles est envoyé au LLM. Le LLM sélectionne alors la fonction la plus appropriée pour la tâche et renvoie son nom ainsi que ses arguments. La fonction sélectionnée est invoquée, sa réponse est renvoyée au LLM, qui utilise cette information pour répondre à la requête de l’utilisateur.

Pour les développeurs souhaitant implémenter l’appel de fonctions pour les agents, vous aurez besoin de :

  1. Un modèle LLM qui prend en charge l’appel de fonctions
  2. Un schéma contenant les descriptions des fonctions
  3. Le code pour chaque fonction décrite

Utilisons l’exemple de récupération de l’heure actuelle dans une ville pour illustrer :

  1. Initialiser un LLM qui supporte l’appel de fonctions :

    Tous les modèles ne supportent pas l’appel de fonctions, il est donc important de vérifier que le LLM que vous utilisez le fait. Azure OpenAI supporte l’appel de fonctions. Nous pouvons commencer par initialiser le client Azure OpenAI.

     # Initialiser le client Azure OpenAI
     client = AzureOpenAI(
         azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
         api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
         api_version="2024-05-01-preview"
     )
    
  2. Créer un schéma de fonction :

    Ensuite, nous définirons un schéma JSON contenant le nom de la fonction, la description de ce que fait la fonction, ainsi que les noms et descriptions des paramètres de la fonction. Nous passerons ensuite ce schéma au client créé précédemment, ainsi que la requête de l’utilisateur pour obtenir l’heure à San Francisco. Il est important de noter qu’un appel d’outil est ce qui est retourné, pas la réponse finale à la question. Comme mentionné précédemment, le LLM renvoie le nom de la fonction qu’il a sélectionnée pour la tâche, ainsi que les arguments qui lui seront passés.

     # Description de la fonction pour que le modèle lise
     tools = [
         {
             "type": "function",
             "function": {
                 "name": "get_current_time",
                 "description": "Get the current time in a given location",
                 "parameters": {
                     "type": "object",
                     "properties": {
                         "location": {
                             "type": "string",
                             "description": "The city name, e.g. San Francisco",
                         },
                     },
                     "required": ["location"],
                 },
             }
         }
     ]
    
      
     # Message initial de l'utilisateur
     messages = [{"role": "user", "content": "What's the current time in San Francisco"}] 
      
     # Premier appel API : Demander au modèle d'utiliser la fonction
       response = client.chat.completions.create(
           model=deployment_name,
           messages=messages,
           tools=tools,
           tool_choice="auto",
       )
      
       # Traiter la réponse du modèle
       response_message = response.choices[0].message
       messages.append(response_message)
      
       print("Model's response:")  
    
       print(response_message)
      
    
     Model's response:
     ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_pOsKdUlqvdyttYB67MOj434b', function=Function(arguments='{"location":"San Francisco"}', name='get_current_time'), type='function')])
    
  3. Le code de la fonction nécessaire pour réaliser la tâche :

    Maintenant que le LLM a choisi la fonction à exécuter, le code qui réalise la tâche doit être implémenté et exécuté. Nous pouvons implémenter ce code pour obtenir l’heure actuelle en Python. Nous devrons également écrire le code pour extraire le nom et les arguments de la réponse (response_message) afin d’obtenir le résultat final.

       def get_current_time(location):
         """Get the current time for a given location"""
         print(f"get_current_time called with location: {location}")  
         location_lower = location.lower()
            
         for key, timezone in TIMEZONE_DATA.items():
             if key in location_lower:
                 print(f"Timezone found for {key}")  
                 current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
                 return json.dumps({
                     "location": location,
                     "current_time": current_time
                 })
          
         print(f"No timezone data found for {location_lower}")  
         return json.dumps({"location": location, "current_time": "unknown"})
    
      # Gérer les appels de fonctions
       if response_message.tool_calls:
           for tool_call in response_message.tool_calls:
               if tool_call.function.name == "get_current_time":
         
                   function_args = json.loads(tool_call.function.arguments)
         
                   time_response = get_current_time(
                       location=function_args.get("location")
                   )
         
                   messages.append({
                       "tool_call_id": tool_call.id,
                       "role": "tool",
                       "name": "get_current_time",
                       "content": time_response,
                   })
       else:
           print("No tool calls were made by the model.")  
      
       # Deuxième appel API : Obtenir la réponse finale du modèle
       final_response = client.chat.completions.create(
           model=deployment_name,
           messages=messages,
       )
      
       return final_response.choices[0].message.content
    
       get_current_time called with location: San Francisco
       Timezone found for san francisco
       The current time in San Francisco is 09:24 AM.
    

L’appel de fonctions est au cœur de la plupart, sinon de toutes les conceptions d’utilisation d’outils par les agents, mais son implémentation de zéro peut parfois être difficile. Comme nous l’avons vu dans Leçon 2, les frameworks agentiques nous fournissent des blocs de construction préfabriqués pour implémenter l’utilisation d’outils.

Exemples d’utilisation d’outils avec des frameworks agentiques

Voici quelques exemples de mise en œuvre du modèle de conception d’utilisation d’outils avec différents frameworks agentiques :

Semantic Kernel

Semantic Kernel est un framework IA open source pour les développeurs .NET, Python et Java travaillant avec des modèles de langage de grande taille (LLM). Il simplifie le processus d’appel de fonctions en décrivant automatiquement vos fonctions et leurs paramètres au modèle via un processus appelé sérialisation. Il gère également la communication aller-retour entre le modèle et votre code. Un autre avantage d’utiliser un framework agentique comme Semantic Kernel est qu’il permet d’accéder à des outils préconçus comme File Search et Code Interpreter.

Le diagramme suivant illustre le processus d’appel de fonctions avec Semantic Kernel :

function calling

Dans Semantic Kernel, les fonctions/outils sont appelés Plugins. Nous pouvons transformer la fonction get_current_time vue précédemment en plugin en la convertissant en classe contenant cette fonction. Nous pouvons également importer le décorateur kernel_function, qui prend en charge la description de la fonction. Lorsque vous créez un kernel avec le GetCurrentTimePlugin, le kernel sérialise automatiquement la fonction et ses paramètres, créant le schéma à envoyer au LLM dans ce processus.

from semantic_kernel.functions import kernel_function

class GetCurrentTimePlugin:
    async def __init__(self, location):
        self.location = location

    @kernel_function(
        description="Get the current time for a given location"
    )
    def get_current_time(location: str = ""):
        ...

from semantic_kernel import Kernel

# Créer le noyau
kernel = Kernel()

# Créer le plugin
get_current_time_plugin = GetCurrentTimePlugin(location)

# Ajouter le plugin au noyau
kernel.add_plugin(get_current_time_plugin)

Azure AI Agent Service

Azure AI Agent Service est un framework agentique plus récent conçu pour permettre aux développeurs de construire, déployer et mettre à l’échelle de manière sécurisée des agents IA de haute qualité et extensibles sans avoir à gérer les ressources de calcul et de stockage sous-jacentes. Il est particulièrement utile pour les applications d’entreprise puisqu’il s’agit d’un service entièrement géré avec une sécurité de niveau entreprise.

Comparé au développement direct avec l’API LLM, Azure AI Agent Service offre certains avantages, notamment :

Les outils disponibles dans Azure AI Agent Service peuvent être divisés en deux catégories :

  1. Outils de connaissance :
  2. Outils d’action :

Le service Agent nous permet d’utiliser ces outils ensemble sous forme de toolset. Il utilise également des threads qui gardent une trace de l’historique des messages d’une conversation particulière.

Imaginez que vous êtes un agent commercial chez une entreprise appelée Contoso. Vous souhaitez développer un agent conversationnel capable de répondre aux questions concernant vos données de vente.

L’image suivante illustre comment vous pourriez utiliser Azure AI Agent Service pour analyser vos données de ventes :

Agentic Service In Action

Pour utiliser l’un de ces outils avec le service, nous pouvons créer un client et définir un outil ou un ensemble d’outils (toolset). Pour implémenter cela concrètement, nous pouvons utiliser le code Python suivant. Le LLM pourra examiner le toolset et décider d’utiliser la fonction créée par l’utilisateur, fetch_sales_data_using_sqlite_query, ou l’interpréteur de code préconstruit selon la demande de l’utilisateur.

import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from fetch_sales_data_functions import fetch_sales_data_using_sqlite_query # fonction fetch_sales_data_using_sqlite_query qui se trouve dans un fichier fetch_sales_data_functions.py.
from azure.ai.projects.models import ToolSet, FunctionTool, CodeInterpreterTool

project_client = AIProjectClient.from_connection_string(
    credential=DefaultAzureCredential(),
    conn_str=os.environ["PROJECT_CONNECTION_STRING"],
)

# Initialiser l'ensemble d'outils
toolset = ToolSet()

# Initialiser l'agent d'appel de fonction avec la fonction fetch_sales_data_using_sqlite_query et l'ajouter à l'ensemble d'outils
fetch_data_function = FunctionTool(fetch_sales_data_using_sqlite_query)
toolset.add(fetch_data_function)

# Initialiser l'outil d'interprète de code et l'ajouter à l'ensemble d'outils.
code_interpreter = code_interpreter = CodeInterpreterTool()
toolset.add(code_interpreter)

agent = project_client.agents.create_agent(
    model="gpt-4o-mini", name="my-agent", instructions="You are helpful agent", 
    toolset=toolset
)

Quelles sont les considérations particulières pour utiliser le modèle de conception d’utilisation d’outils afin de construire des agents IA fiables ?

Une préoccupation courante concernant les requêtes SQL générées dynamiquement par les LLM concerne la sécurité, en particulier le risque d’injection SQL ou d’actions malveillantes, comme la suppression ou la manipulation de la base de données. Bien que ces préoccupations soient valables, elles peuvent être efficacement atténuées en configurant correctement les permissions d’accès à la base de données. Pour la plupart des bases, cela implique de configurer la base en lecture seule. Pour les services de bases de données comme PostgreSQL ou Azure SQL, l’application doit se voir attribuer un rôle en lecture seule (SELECT). Exécuter l’application dans un environnement sécurisé renforce encore la protection. Dans les scénarios d’entreprise, les données sont généralement extraites et transformées à partir des systèmes opérationnels vers une base de données ou un entrepôt de données en lecture seule avec un schéma convivial. Cette approche garantit que les données sont sécurisées, optimisées pour la performance et l’accessibilité, et que l’application a un accès restreint en lecture seule.

Exemples de codes

Vous avez d’autres questions sur l’utilisation des design patterns de l’outil ?

Rejoignez le Azure AI Foundry Discord pour rencontrer d’autres apprenants, participer aux heures de bureau et obtenir des réponses à vos questions sur les agents IA.

Ressources supplémentaires

Leçon précédente

Comprendre les Design Patterns Agentic

Leçon suivante

Agentic RAG


Avertissement :
Ce document a été traduit à l’aide du service de traduction automatique Co-op Translator. Bien que nous nous efforcions d’assurer l’exactitude, veuillez noter que les traductions automatisées peuvent contenir des erreurs ou des inexactitudes. Le document original dans sa langue d’origine doit être considéré comme la source faisant autorité. Pour les informations critiques, une traduction professionnelle humaine est recommandée. Nous déclinons toute responsabilité en cas de malentendus ou d’interprétations erronées résultant de l’utilisation de cette traduction.