Agents IA : parcours d’apprentissage

Agent IA en Python : un atelier sur la boucle et les outils

Une boucle d’agent en Python relie planificateur, exécution contrôlée des outils, observations et règle d’arrêt. Cet atelier utilise un planificateur déterministe pour rendre la mécanique reproductible sans clé API. Pour ajouter un modèle de langage, remplacez la planification via une interface documentée en gardant les contrôles d’exécution dans l’application.

Une équipe réelle travaille autour d’ordinateurs

Il faut Python 3 et des notions de fonctions et dictionnaires. Le fichier emploie seulement la bibliothèque standard, un catalogue fictif et la console. Il ne fait aucune requête réseau et ne modifie pas de fichiers. Examinez sa trace avant de le changer.

Idées essentielles

  • Commencez avec une recherche et des fiches fictives.
  • Validez nom et arguments avant l’exécution.
  • Représentez explicitement une fiche absente.
  • Gardez la limite des étapes hors du planificateur.

Préparer l’entrée et le critère d’acceptation

Enregistrez le fichier sous ai-agent-lab.py et lancez python3 ai-agent-lab.py. La clé 'ai' doit retourner la fiche stockée après une recherche et une décision finale. La trace montre outil, entrée validée et résultat. Une clé absente termine avec unknown, sans titre inventé. Ces attentes appartiennent à l’exercice ; elles ne constituent pas un benchmark de modèles. Écrivez avant l’exécution ce que vous vérifiez, afin d’évaluer le comportement plutôt que toute sortie affichée.

[1][2]

Comprendre le planificateur déterministe

La fonction demande d’abord une recherche. Après une observation, elle propose un résultat basé sur cette observation. C’est un simulateur d’étude de la boucle. Les décisions sont fixées dans le code : il ne démontre ni raisonnement de modèle ni compréhension du langage. Il permet de reproduire un comportement et d’observer les effets d’un changement du contrôleur ou de l’état, sans réponse d’API variable. Cette étape sépare l’étude mécanique de l’intégration future.

Garder un registre d’outils limité

Le registre contient uniquement lookup. L’exécution vérifie type d’action, nom enregistré et argument unique key. La recherche exige une chaîne courte. Ne remplacez pas ce contrôle par l’exécution de Python ou de commandes produits par un modèle. Le modèle futur peut proposer une recherche structurée, mais registre et validation décident toujours de l’appel réel. Étudiez une proposition refusée : sa structure correcte ne lui donne pas automatiquement l’autorisation d’exécuter n’importe quelle opération.

[3]

Inspecter les absences et les limites

Lisez statut et réponse ensemble. done correspond à une fiche retournée ; unknown à une clé absente ; stopped à un budget épuisé. Essayez une seule étape : la recherche s’exécute, mais la décision finale n’a plus d’étape disponible. Le statut reste arrêté. Une information intermédiaire ne suffit pas à prouver la fin du travail. Cette distinction aide à communiquer un arrêt avec précision et à préserver les questions qu’il reste à résoudre.

Atelier Python

"""VITON13 SCHOOL: a deterministic teaching loop, without a model or network."""
import json

CATALOGUE = {
    "ai": {"title": "Applied AI", "topics": ["goals", "tools", "checks"]},
    "design": {"title": "Design", "topics": ["brief", "prototype", "review"]},
}


def lookup(key):
    if not isinstance(key, str) or not 0 < len(key) <= 32:
        raise ValueError("key must be a string of 1-32 characters")
    return CATALOGUE.get(key)


TOOLS = {"lookup": lookup}


def plan(state):
    """A simulator: replace this proposal function to study model integration."""
    if not state["observations"]:
        return {"type": "tool", "name": "lookup", "args": {"key": state["key"]}}
    return {"type": "final", "answer": state["observations"][-1]["result"]}


def run(key, planner=plan, max_steps=3):
    if type(max_steps) is not int or max_steps < 1:
        raise ValueError("max_steps must be a positive integer")
    state = {"key": key, "observations": []}
    for _ in range(max_steps):
        action = planner(state)
        if not isinstance(action, dict):
            raise ValueError("proposal must be an object")
        if action.get("type") == "final":
            if not state["observations"]:
                raise ValueError("final result requires an observation")
            result = state["observations"][-1]["result"]
            if action.get("answer") != result:
                raise ValueError("final answer must match the retrieved record")
            return {
                "status": "done" if result is not None else "unknown",
                "answer": result, "trace": state["observations"],
            }
        if action.get("type") != "tool" or action.get("name") not in TOOLS:
            raise ValueError("tool is not allowed")
        args = action.get("args")
        if not isinstance(args, dict) or set(args) != {"key"}:
            raise ValueError("lookup requires exactly one key argument")
        if args["key"] != state["key"]:
            raise ValueError("lookup is outside the requested key")
        result = TOOLS[action["name"]](**args)
        state["observations"].append({
            "tool": action["name"], "input": dict(args), "result": result,
        })
    return {"status": "stopped", "answer": None, "trace": state["observations"]}


if __name__ == "__main__":
    print(json.dumps(run("ai"), indent=2))
Télécharger l’exemple Python ↓

Connecter le modèle après les contrôles

Remplacez la planification par un adaptateur renvoyant la même structure via l’interface documentée du fournisseur. Transmettez objectif et observations utiles, validez la proposition et exécutez hors du modèle. Testez mauvais nom, arguments incorrects, fiche absente et réponse sans preuve. L’adaptateur doit aussi gérer erreurs du fournisseur et limites d’usage. Le laboratoire donne la base du contrôle ; l’intégration complète exige ses propres vérifications avec les critères conservés et des cas représentatifs supplémentaires.

En mots simples

L’atelier est une maquette de la mécanique. Un planificateur fixe remplace la partie qui propose l’action. Vous observez outil, carnet et arrêt avant de connecter un modèle susceptible de choisir autrement.

À vous de jouer

Lancez la clé connue, une clé inconnue et un budget d’une étape. Remplacez ensuite le planificateur par un demandeur d’outil non enregistré. Prédisez chaque sortie, puis comparez.

Résultat attendu

Un résultat sourcé, un résultat unknown, un résultat stopped et une proposition rejetée. L’outil interdit ne doit jamais s’exécuter.

Vérifiez votre réponse: Qu’est-ce qui change avec un modèle de langage ?

La génération de propositions. Permissions, validation, état et limites restent des responsabilités du code.

Questions et réponses

L’exemple exige-t-il une API payante ?

Non. L’exemple utilise une fonction déterministe et un dictionnaire local, sans compte ni clé API. Un adaptateur de modèle est une extension séparée, dont l’accès et le coût dépendent du fournisseur. Son comportement doit être testé même si la boucle pédagogique fonctionne.

Puis-je déployer cet exemple en production ?

L’atelier enseigne la boucle avec des fiches fictives. Une application réelle nécessite modèle, authentification, reprise, droits d’accès, observabilité et vérifications propres à la tâche. Construisez et testez ces éléments. Une exécution correcte en classe ne prouve pas que l’application est prête à être déployée.

Exécutez l’exemple, inspectez les statuts et testez une proposition interdite. Préservez ces contrôles en connectant le modèle.

Sources et lectures

  1. Python documentation — Control flow ↗Sources consultées:
  2. Python documentation — Data structures ↗Sources consultées:
  3. Anthropic — Writing effective tools for agents ↗Sources consultées: