Créer avec l’IA

Comment créer une boucle d’agent simple avec l’API d’OpenAI?

· Par Robert Scales · 4 min de lecture

Réponse courte

Une boucle d’agent demande au modèle d’écrire une pensée et une action dans un format texte fixe; votre programme lit cette action, exécute l’outil correspondant et renvoie le résultat comme message suivant. Vous répétez réfléchir, agir et observer jusqu’à ce que le modèle écrive une réponse finale, avec une limite stricte d’étapes et de jetons pour qu’il ne puisse jamais s’emballer.

Des projets comme Auto-GPT ont l’air compliqués, mais leur cœur est une courte boucle que vous pouvez écrire vous-même en une quarantaine de lignes de Python. En construire une est la meilleure façon de voir ce qu’est vraiment un agent : non pas un nouveau type de modèle, mais des requêtes de clavardage ordinaires reliées par votre propre code, et c’est votre code qui décide de ce qui se passe réellement dans le monde.

Le modèle vient d’un article de recherche de 2022 intitulé ReAct, pour reasoning and acting (raisonner et agir). Ses auteurs faisaient alterner un modèle de langage entre l’écriture de son raisonnement et une action, comme une recherche au moyen d’un outil Wikipédia simple, puis la lecture de ce qui revenait. Consulter ainsi une source externe réduisait les faits inventés par rapport au raisonnement seul.

Les trois mouvements : réfléchir, agir, observer

Chaque passage dans la boucle compte trois parties.

  1. Réfléchir. Le modèle écrit une courte ligne de raisonnement sur ce qu’il doit faire ensuite.
  2. Agir. Il nomme un outil et son entrée, dans un format que votre programme peut lire.
  3. Observer. Votre programme exécute l’outil et renvoie le résultat sous forme de nouveau message.

Le modèle n’exécute jamais rien lui-même. L’API ChatGPT ne renvoie que du texte. Pour l’instant, elle n’a aucun moyen intégré d’appeler vos fonctions; l’« action » n’est donc qu’une ligne de texte que votre code cherche à l’aide d’une expression régulière (une règle de reconnaissance de motifs dans le texte), avant de décider s’il y obéit.

Le format de conversation sur lequel vous bâtissez

Depuis le 1er mars, l’API d’OpenAI offre gpt-3.5-turbo, le modèle derrière ChatGPT, au moyen d’un point d’accès de complétion de conversation (chat completions). Au lieu d’un seul bloc de texte, vous envoyez une liste de messages, chacun avec un rôle (system, user ou assistant) et son contenu. La réponse revient avec le message du modèle, une raison de fin et le décompte des jetons utilisés, ces petits morceaux de texte selon lesquels l’API facture. À 0,002 $ US par 1 000 jetons, c’est assez bon marché pour expérimenter.

Une remarque pratique tirée du guide d’OpenAI : la version actuelle de gpt-3.5-turbo ne porte pas beaucoup attention au message système; mieux vaut donc placer les consignes importantes dans un message de l’utilisateur. L’exemple ci-dessous fait exactement cela.

Un exemple concret en Python

Cet agent répond à une petite question de budget à l’aide de deux outils jouets : une recherche de prix et un additionneur. Les prix sont inventés pour l’illustration. Il utilise la bibliothèque Python openai (version 0.27) et lit votre clé d’API dans une variable d’environnement.

import os, re, openai
openai.api_key = os.getenv("OPENAI_API_KEY")

PRICES = {"train": 89, "hôtel": 145, "musée": 22}   # prix fictifs

def lookup(item):
    return str(PRICES.get(item.strip().lower(), "article inconnu"))

def add(numbers):
    try:
        return str(sum(float(n) for n in numbers.split(",")))
    except ValueError:
        return "Erreur : add a besoin de nombres séparés par des virgules"

TOOLS = {"lookup": lookup, "add": add}

INSTRUCTIONS = """Résous la tâche une étape à la fois. Outils :
lookup[article]   renvoie le prix d’un article
add[n1, n2]       renvoie la somme des nombres
Réponds exactement dans ce format, une action par réponse :
THOUGHT: ton raisonnement
ACTION: outil[entrée]
Quand tu connais la réponse, réponds :
THOUGHT: ton raisonnement
FINAL: ta réponse"""

MAX_STEPS = 6          # limite stricte du nombre de passages dans la boucle
TOKEN_BUDGET = 6000    # limite stricte du total de jetons facturés

def run(task):
    messages = [{"role": "user", "content": INSTRUCTIONS + "\n\nTâche : " + task}]
    used = 0
    for step in range(1, MAX_STEPS + 1):
        response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",
            messages=messages,
            temperature=0,
            max_tokens=200,
            stop=["OBSERVATION:"],
        )
        used += response["usage"]["total_tokens"]
        reply = response["choices"][0]["message"]["content"]
        print(f"--- étape {step} ---\n{reply}")
        messages.append({"role": "assistant", "content": reply})

        if "FINAL:" in reply:
            return reply.split("FINAL:", 1)[1].strip()

        match = re.search(r"ACTION:\s*(\w+)\[(.*?)\]", reply)
        if match and match.group(1) in TOOLS:
            observation = TOOLS[match.group(1)](match.group(2))
        else:
            observation = "Erreur : réponds avec un des outils de la liste, sous la forme outil[entrée]."
        messages.append({"role": "user", "content": "OBSERVATION: " + observation})

        if used > TOKEN_BUDGET:
            return f"Arrêt : budget de jetons épuisé après {step} étapes."
    return "Arrêt : limite d’étapes atteinte sans réponse finale."

print(run("Combien coûtent ensemble un billet de train, une nuit d’hôtel et une entrée au musée?"))

Une exécution typique, montrée ici à titre d’illustration, cherche les trois prix un à un, appelle add[89, 145, 22], reçoit 256.0 et répond par une réponse finale de 256 $. Cela fait cinq appels au modèle pour une seule question.

Quelques lignes font un travail discret mais important. temperature=0 rend les réponses plus prévisibles, ce qui aide le format à tenir. Le paramètre stop coupe la réponse si le modèle commence à écrire son propre OBSERVATION:; il ne peut donc pas inventer le résultat d’un outil. Et les actions inconnues ou mal formées reçoivent un message d’erreur au lieu de faire planter le programme, ce qui donne au modèle une chance de se corriger.

À essayer : lancez le script, puis ajoutez un troisième outil, comme convert[amount], qui convertit des dollars en euros à un taux fixe de votre choix. Mettez à jour les consignes, posez une question qui en a besoin et lisez les étapes affichées pour voir si le modèle utilise correctement le nouvel outil.

Comment l’empêcher de tourner en boucle sans fin?

Utilisez plusieurs freins, car chacun attrape un type de défaillance différent. La limite d’étapes (MAX_STEPS) est la plus simple : peu importe ce qu’écrit le modèle, la boucle for se termine. Le budget de jetons attrape le problème de coût, moins évident. Chaque appel renvoie toute la conversation; chaque étape coûte donc plus cher que la précédente, et compter usage après chaque appel maintient le total sous un plafond que vous fixez. En plus, fixez une limite de dépenses mensuelle dans les paramètres de votre compte OpenAI pour qu’un bogue dans votre propre code ne vous vaille pas une facture surprise.

Ajoutez ensuite des vérifications pour repérer un modèle qui tourne en rond. S’il demande deux fois de suite la même action avec la même entrée, vous pouvez arrêter ou répondre par une observation comme « Tu as déjà essayé ça; choisis une autre étape. » S’il ne respecte pas le format à répétition, mettez fin à l’exécution après deux ou trois erreurs au lieu de le laisser continuer d’essayer.

Enfin, gardez une personne dans la boucle pour tout ce qui a de vraies conséquences. Les outils en lecture seule, comme une recherche de prix, peuvent être automatisés sans danger. Un outil qui envoie des courriels, supprime des fichiers ou dépense de l’argent devrait faire une pause et vous demander d’approuver l’action d’abord, la même prudence qu’Auto-GPT applique par défaut. La boucle est à vous, les règles aussi.

Sources

  1. How to format inputs to ChatGPT models — OpenAI Cookbook on GitHub (commit of 2023-03-02), 2 mars 2023
  2. ReAct: Synergizing Reasoning and Acting in Language Models — arXiv (Shunyu Yao and six co-authors), 6 octobre 2022
  3. Introducing ChatGPT and Whisper APIs — OpenAI, 1 mars 2023

Recevez gratuitement le Guide de l’intelligence artificielle

Abonnez-vous à l’infolettre hebdomadaire et recevez le guide gratuit : ce qui a changé en IA cette semaine, une leçon, un prompt à essayer. Désabonnement en un clic.

Ce que nous faisons de votre adresse

Retour en haut

Affichage

Vos choix sont enregistrés dans ce navigateur seulement. Aucune donnée n’est transmise.

Taille du texte
100 %
Couleurs
Lecture
Autres réglages
Déclaration d’accessibilité