Aller au contenu principal
Leçon 10 sur 67 · Claude sur Amazon Bedrock

Données structurées

Leçon 10 sur 67 Mis à jour le 5 novembre 2026 Développeur
Sur cette page
  1. Le problème
  2. L’ancienne recette, et pourquoi elle ne marche plus
  3. Les sorties structurées
  4. Les règles du schéma
  5. Le premier appel est lent
  6. Traiter le résultat
  7. Au-delà du JSON
  8. À vous de jouer
  9. Points clés à retenir

Quand un programme doit lire la réponse de Claude, un problème revient sans cesse : Claude entoure volontiers les données d’explications, de titres et de Markdown. Très bien dans une conversation, rédhibitoire pour un parseur. Cette leçon montre comment obtenir un JSON propre et garanti, avec les sorties structurées de l’API Converse.

Le problème

Imaginez une application web qui génère des règles AWS EventBridge. L’utilisateur décrit ce qu’il veut surveiller, clique sur « Générer », et attend un JSON qu’il peut copier tel quel dans sa console. Par défaut, Claude répond plutôt ainsi :

# Règle EventBridge

```json
{
  "source": ["aws.ec2"],
  "detail-type": ["EC2 Instance State-change Notification"],
  "detail": {"state": ["running"]}
}
```

Cette règle capture les changements d'état des instances EC2.

Un titre, un bloc de code, une phrase de conclusion : parfait pour de la documentation, mais la donnée utile est noyée dans son emballage, et json.loads échoue sur l’ensemble.

L’ancienne recette, et pourquoi elle ne marche plus

Le cours officiel combine les deux techniques de la leçon 9 : il pré-remplit le message assistant avec l’ouverture d’un bloc de code JSON, puis coupe la génération avec une séquence d’arrêt sur les trois accents graves qui le ferment. Claude saute ainsi l’en-tête et s’arrête avant la conclusion. Avec Haiku 5.5, cette recette échoue dès la première étape, puisque le pré-remplissage est refusé. Elle a un successeur plus solide.

Les sorties structurées

Les sorties structurées contraignent la réponse de Claude à un schéma JSON que vous fournissez. Avec l’API Converse, le schéma passe dans outputConfig.textFormat, sous forme de chaîne JSON. Notre fonction chat gagne un paramètre pour le transmettre :

import json


def chat(messages, system=None, stop_sequences=None, output_schema=None):
    params = {"modelId": model_id, "messages": messages}
    if system:
        params["system"] = [{"text": system}]
    if stop_sequences:
        params["inferenceConfig"] = {"stopSequences": stop_sequences}
    if output_schema:
        params["outputConfig"] = {
            "textFormat": {
                "type": "json_schema",
                "structure": {
                    "jsonSchema": {
                        "schema": json.dumps(output_schema),
                        "name": "reponse",
                    }
                },
            }
        }

    response = client.converse(**params)
    content = response["output"]["message"]["content"]
    return "".join(block["text"] for block in content if "text" in block)

Pour la règle EventBridge, le schéma décrit les trois champs attendus :

SCHEMA_REGLE = {
    "type": "object",
    "properties": {
        "source": {"type": "array", "items": {"type": "string"}},
        "detail-type": {"type": "array", "items": {"type": "string"}},
        "detail": {
            "type": "object",
            "properties": {"state": {"type": "array", "items": {"type": "string"}}},
            "required": ["state"],
            "additionalProperties": False,
        },
    },
    "required": ["source", "detail-type", "detail"],
    "additionalProperties": False,
}

messages = []
add_user_message(messages, "Génère une règle EventBridge qui détecte les arrêts d'instances EC2.")
text = chat(messages, output_schema=SCHEMA_REGLE)

Bedrock compile le schéma en grammaire, puis restreint la génération aux tokens que cette grammaire autorise : Claude ne peut produire que du JSON conforme, sans préambule ni conclusion.

Du schéma au JSON garanti Cinq étapes : un schéma Python avec additionalProperties à False, le schéma en chaîne JSON dans outputConfig, une génération contrainte par une grammaire mise en cache 24 heures, json.loads après vérification de stopReason, puis les contrôles métier. DONNÉES STRUCTURÉES Du schéma au JSON garanti 1 Schéma additionalProperties à False partout 2 outputConfig le schéma en chaîne JSON 3 Grammaire compilée au premier appel, en cache 24 h 4 json.loads après vérification de stopReason 5 Contrôles le format est garanti, pas le fond Premier appel avec un nouveau schéma : jusqu'à 90 secondes. Réglez read_timeout à 120.
D'après la documentation AWS (Get validated JSON results from models) et la leçon « Structured data » (Claude Academy, Claude with Amazon Bedrock).

Les règles du schéma

D’après la documentation AWS au 5 novembre 2026 :

  • Chaque objet du schéma doit déclarer "additionalProperties": False. Sinon, Bedrock répond par une ValidationException.
  • Les bornes numériques (minimum, maximum), les longueurs de chaîne (minLength, maxLength) et les schémas récursifs ne sont pas pris en charge. Décrivez ces contraintes dans le texte de la demande, et vérifiez-les dans votre code.
  • Un schéma compte au plus 12 propriétés facultatives, c’est-à-dire absentes de required, toutes profondeurs confondues.
  • Les sorties structurées sont incompatibles avec les citations, que la section 6 présente.

Le premier appel est lent

La première requête qui utilise un nouveau schéma compile la grammaire, ce qui peut prendre jusqu’à environ 90 secondes. Les requêtes suivantes réutilisent la grammaire, gardée en cache 24 heures, et répondent à la vitesse habituelle. Or le client boto3 abandonne la lecture d’une réponse au bout de 60 secondes par défaut. AWS recommande donc un délai d’au moins 120 secondes :

import boto3
from botocore.config import Config

client = boto3.client(
    "bedrock-runtime",
    region_name="us-east-1",
    config=Config(read_timeout=120),
)

Traiter le résultat

Il ne reste qu’à convertir le texte en dictionnaire Python :

regle = json.loads(text)
print(regle["detail"]["state"])

Deux réserves. Le format est garanti, pas le fond : une règle parfaitement conforme peut viser le mauvais état ou le mauvais service, gardez vos contrôles métier. Et si la réponse atteint la limite de tokens, la génération s’arrête avec stopReason à max_tokens et le JSON est incomplet, même avec un schéma. En production, vérifiez stopReason avant json.loads.

Au-delà du JSON

Les sorties structurées produisent du JSON. Pour du code Python, du CSV ou un fichier de configuration, faites porter le contenu par un champ texte du schéma, par exemple {"code": "..."}, puis extrayez-le.

À vous de jouer

Votre extracteur. Écrivez un schéma pour extraire d’un courriel le nom de l’expéditeur, la date d’un rendez-vous et une liste d’actions, puis testez-le sur trois courriels différents. Mesurez la durée du premier appel et celle du deuxième.

Une réponse jamais incomplète. Modifiez chat pour qu’elle lève une exception quand stopReason vaut max_tokens. Provoquez le cas avec inferenceConfig={"maxTokens": 50} et un schéma qui demande un long texte.

Sources officielles : Structured data (Claude Academy) · Get validated JSON results from models (documentation AWS) · Structured outputs (documentation Claude)

Points clés à retenir

  • Par défaut, Claude emballe les données de texte et de Markdown, ce qui casse un parseur.
  • Le couple pré-remplissage et séquence d’arrêt du cours officiel ne fonctionne plus avec Haiku 5.5.
  • Les sorties structurées garantissent un JSON conforme au schéma : sur Converse, outputConfig.textFormat, avec le schéma en chaîne JSON.
  • "additionalProperties": False sur chaque objet ; pas de bornes numériques ni de longueurs de chaîne.
  • Le premier appel avec un nouveau schéma peut prendre 90 secondes : réglez read_timeout à 120.
  • Le format est garanti, pas le fond ; vérifiez stopReason avant json.loads.