Chargement

Implémentation de plusieurs tours

Leçon 2815 min

La création d'un système de conversation avec des outils nécessite l'implémentation d'une boucle qui continue d'appeler Claude jusqu'à ce qu'il arrête de demander l'utilisation d'outils. Lorsque Claude ne demande plus d'outils, cela signale qu'il a une réponse finale prête pour l'utilisateur.

Détection des demandes d'outils

La clé pour savoir si Claude souhaite utiliser un outil réside dans le champ stop_reason du message de réponse. Lorsque Claude décide qu'il doit appeler un outil, ce champ est défini sur "tool_use". Cela nous donne un moyen simple de vérifier si nous devons poursuivre la boucle de conversation :

python
if response.stop_reason != "tool_use":
    break  # Claude is done, no more tools needed

La boucle de conversation

La fonction de conversation principale suit un modèle simple :

python
def run_conversation(messages):
    while True:
        response = chat(messages, tools=[get_current_datetime_schema])
        add_assistant_message(messages, response)
        print(text_from_message(response))
        
        if response.stop_reason != "tool_use":
            break
            
        tool_results = run_tools(response)
        add_user_message(messages, tool_results)
    
    return messages

Cette boucle continue jusqu'à ce que Claude fournisse une réponse finale sans demander d'outils.

Gestion de plusieurs appels d'outils

Claude peut demander plusieurs outils dans une seule réponse. Le contenu du message contient une liste de blocs, et nous devons traiter chaque bloc d'utilisation d'outils séparément :

La fonction run_tools gère cela en filtrant les blocs d'utilisation d'outils et en traitant chacun d'eux :

python
def run_tools(message):
    tool_requests = [
        block for block in message.content if block.type == "tool_use"
    ]
    tool_result_blocks = []
    
    for tool_request in tool_requests:
        # Traiter chaque demande d'outil...

Blocs de résultats d'outils

Pour chaque bloc d'utilisation d'outils, nous devons créer un bloc de résultat d'outil correspondant. Ces blocs ont des champs requis spécifiques :

Le bloc de résultat d'outil doit inclure le même ID que le bloc d'utilisation d'outils d'origine, mais dans le champ tool_use_id :

python
tool_result_block = {
    "type": "tool_result",
    "tool_use_id": tool_request.id,
    "content": json.dumps(tool_output),
    "is_error": False
}

Gestion des erreurs

Une exécution robuste des outils nécessite la gestion des erreurs potentielles. Lorsqu'un outil échoue, nous devons toujours renvoyer un bloc de résultat d'outil, mais avec des informations sur l'erreur :

python
try:
    tool_output = run_tool(tool_request.name, tool_request.input)
    tool_result_block = {
        "type": "tool_result",
        "tool_use_id": tool_request.id,
        "content": json.dumps(tool_output),
        "is_error": False
    }
except Exception as e:
    tool_result_block = {
        "type": "tool_result", 
        "tool_use_id": tool_request.id,
        "content": f"Error: {e}",
        "is_error": True
    }

Routage évolutif des outils

Pour prendre en charge plusieurs outils, créez une fonction de routage distincte au lieu de coder en dur les noms des outils :

python
def run_tool(tool_name, tool_input):
    if tool_name == "get_current_datetime":
        return get_current_datetime(**tool_input)
    elif tool_name == "other_tool":
        return other_tool_function(**tool_input)
    # Ajoutez d'autres outils si nécessaire

Cette approche permet d'ajouter facilement de nouveaux outils sans modifier la logique de conversation principale.

Flux de travail complet

La conversation complète à plusieurs tours fonctionne comme suit :

  • Envoyer le message de l'utilisateur à Claude avec les outils disponibles
  • Claude répond avec du texte et/ou des blocs d'utilisation d'outils
  • Exécuter les outils demandés et créer des blocs de résultats d'outils
  • Renvoyer les résultats des outils à Claude sous forme de message utilisateur
  • Répéter jusqu'à ce que Claude fournisse une réponse finale sans demande d'outils

Cela crée une expérience fluide où Claude peut effectuer plusieurs appels d'outils sur plusieurs tours de conversation afin de recueillir toutes les informations nécessaires avant de fournir une réponse finale complète à l'utilisateur.