Aller au contenu principal

Outils pour les données structurées

Mis à jour le 30 juillet 2026

Nous avons déjà arraché du JSON à Claude par le pré-remplissage et les séquences d’arrêt — la méthode fonctionne, mais elle reste un pari : on espère que le modèle respectera le format, et le moindre écart casse le parsing en aval. Cette leçon présente l’alternative robuste, fondée sur un détournement astucieux de l’utilisation d’outils : puisque les arguments d’un appel d’outil sont générés en JSON strictement conforme à un schéma, il suffit de déclarer un outil dont les paramètres sont la structure qu’on veut obtenir.

Le principe

Créez un schéma JSON définissant la structure exacte des données à extraire, et présentez-le à Claude comme un outil à appeler. La subtilité : cet outil n’a pas besoin d’exister. Aucune fonction Python derrière, aucune exécution prévue — on ne s’intéresse qu’aux arguments que Claude génère pour l’appeler. Là où le pré-remplissage demandait au modèle de rédiger du JSON dans du texte libre, l’appel d’outil le fait passer par le mécanisme de génération contrainte de l’API : les champs, leurs types et leur imbrication suivent le schéma déclaré. Le format n’est plus une consigne, c’est un rail.

Contrôler l’utilisation des outils

Un maillon manque encore : par défaut, Claude reste libre de ne pas appeler l’outil. Le paramètre tool_choice règle ce comportement :

  • {"type": "auto"} : Claude décide s’il a besoin d’un outil (défaut)
  • {"type": "any"} : Claude doit utiliser un outil, au choix
  • {"type": "tool", "name": "NOM_OUTIL"} : Claude doit utiliser l’outil spécifié

Pour l’extraction de données structurées, c’est la troisième option qu’il faut : elle force le modèle à appeler précisément notre outil de structuration, à chaque requête, sans texte d’accompagnement possible. Les deux premières gardent leur usage dans les vraies boucles d’outils — auto pour les assistants généralistes, any quand répondre sans outil n’aurait pas de sens.

Exemple d’implémentation

Assemblons le tout pour extraire les métadonnées d’un article :

article_summary_schema = {
    "name": "article_summary",
    "description": "Extrait des données structurées d'articles",
    "input_schema": {
        "type": "object",
        "properties": {
            "title": {"type": "string"},
            "author": {"type": "string"},
            "key_insights": {
                "type": "array",
                "items": {"type": "string"}
            }
        }
    }
}

response = chat(
    messages,
    tools=[article_summary_schema],
    tool_choice={"type": "tool", "name": "article_summary"}
)

structured_data = response.content[0].input

Trois observations sur ce code. Le schéma montre que la structure peut être riche : key_insights est un tableau de chaînes, et rien n’empêche d’imbriquer des objets dans des objets pour des extractions complexes. Le tool_choice verrouille la sortie : la réponse contiendra un bloc tool_use, et uniquement cela. Et la dernière ligne récolte le fruit : response.content[0].input est déjà un dictionnaire Python — les arguments de l’appel, parsés par le SDK. Pas de json.loads, pas de nettoyage de backticks, pas de texte parasite à découper : la donnée arrive prête à l’emploi.

Quand utiliser quelle approche

Les deux techniques cohabitent dans une boîte à outils de praticien. Le pré-remplissage avec séquences d’arrêt reste imbattable en simplicité : deux lignes, aucun schéma à écrire — parfait pour un script ponctuel ou une exploration en notebook. L’approche par outils demande plus de mise en place, mais elle apporte ce que la production exige : un format contraint par l’API plutôt que promis par le modèle, et une donnée qui arrive déjà parsée. Dès qu’un pipeline automatisé consomme la sortie sans relecture humaine, c’est elle qu’il faut choisir.

Points clés à retenir

  • L’astuce : déclarer un outil fictif dont les paramètres sont la structure cible — seuls ses arguments nous intéressent
  • Les arguments d’appel sont générés en conformité avec le schéma : le format devient un rail, plus une consigne
  • tool_choice: {"type": "tool", "name": ...} force l’appel de l’outil de structuration à chaque requête
  • response.content[0].input livre un dictionnaire Python déjà parsé — aucun post-traitement
  • Pré-remplissage = simplicité pour l’exploration ; outils = robustesse pour les pipelines de production