Aller au contenu principal

Schémas JSON et validation

Schemas JSON et validation

La qualite de vos schemas JSON determine directement la fiabilite du function calling. Un schema bien concu guide le modele vers des appels corrects, tandis qu’un schema flou produit des arguments imprevisibles.

Structure d’un schema de fonction

Chaque fonction declaree dans tools suit le format JSON Schema. Voici la structure complete :

tool_definition = {
    "type": "function",
    "name": "creer_facture",
    "description": "Creer une facture pour un client existant",
    "parameters": {
        "type": "object",
        "properties": {
            "client_id": {
                "type": "string",
                "description": "Identifiant unique du client (format: CLI-XXXXX)"
            },
            "lignes": {
                "type": "array",
                "description": "Liste des lignes de facturation",
                "items": {
                    "type": "object",
                    "properties": {
                        "description": {
                            "type": "string",
                            "description": "Description du produit ou service"
                        },
                        "quantite": {
                            "type": "integer",
                            "minimum": 1,
                            "description": "Nombre d'unites"
                        },
                        "prix_unitaire": {
                            "type": "number",
                            "minimum": 0,
                            "description": "Prix HT par unite en euros"
                        }
                    },
                    "required": ["description", "quantite", "prix_unitaire"]
                }
            },
            "devise": {
                "type": "string",
                "enum": ["EUR", "USD", "GBP"],
                "default": "EUR"
            },
            "echeance_jours": {
                "type": "integer",
                "enum": [30, 45, 60, 90],
                "description": "Delai de paiement en jours"
            }
        },
        "required": ["client_id", "lignes"],
        "additionalProperties": false
    },
    "strict": true
}

Le mode strict

Le parametre strict: true active le Structured Outputs pour le function calling. Le modele est alors garanti de produire des arguments conformes au schema :

tools = [{
    "type": "function",
    "name": "enregistrer_commande",
    "description": "Enregistrer une nouvelle commande",
    "parameters": {
        "type": "object",
        "properties": {
            "produit": {"type": "string"},
            "quantite": {"type": "integer"},
            "urgent": {"type": "boolean"}
        },
        "required": ["produit", "quantite", "urgent"],
        "additionalProperties": false
    },
    "strict": true
}]

Contraintes du mode strict

En mode strict, certaines regles s’appliquent :

  • Tous les champs doivent etre dans required
  • additionalProperties doit etre false
  • Les types optionnels utilisent anyOf avec null
  • Pas de pattern, minLength, maxLength au premier niveau
# Champ optionnel en mode strict
"commentaire": {
    "anyOf": [
        {"type": "string"},
        {"type": "null"}
    ],
    "description": "Commentaire libre optionnel"
}

Validation cote client

Meme avec le mode strict, validez toujours les arguments recus avant execution :

import json
from jsonschema import validate, ValidationError

SCHEMA_FACTURE = {
    "type": "object",
    "properties": {
        "client_id": {"type": "string", "pattern": "^CLI-[0-9]{5}$"},
        "lignes": {
            "type": "array",
            "minItems": 1,
            "items": {
                "type": "object",
                "properties": {
                    "description": {"type": "string", "minLength": 1},
                    "quantite": {"type": "integer", "minimum": 1},
                    "prix_unitaire": {"type": "number", "minimum": 0}
                },
                "required": ["description", "quantite", "prix_unitaire"]
            }
        }
    },
    "required": ["client_id", "lignes"]
}

def executer_fonction(name: str, arguments: str) -> str:
    args = json.loads(arguments)

    try:
        validate(instance=args, schema=SCHEMA_FACTURE)
    except ValidationError as e:
        return json.dumps({"error": f"Arguments invalides: {e.message}"})

    # Logique metier apres validation
    return creer_facture(**args)

Descriptions efficaces

La description est le levier principal pour guider le modele. Quelques regles :

# Mauvais : trop vague
{
    "name": "get_data",
    "description": "Recuperer des donnees"
}

# Bon : specifique et contextuel
{
    "name": "rechercher_produits_catalogue",
    "description": "Rechercher des produits dans le catalogue e-commerce. "
                   "Retourne nom, prix, stock et categorie. "
                   "Utiliser pour les questions sur la disponibilite ou les prix."
}

Descriptions des parametres

Chaque parametre merite une description precise :

"properties": {
    "date_debut": {
        "type": "string",
        "description": "Date de debut au format ISO 8601 (YYYY-MM-DD). "
                       "Par defaut, date du jour si non specifie."
    },
    "statut": {
        "type": "string",
        "enum": ["actif", "inactif", "suspendu"],
        "description": "Filtrer par statut du compte. "
                       "'actif' = comptes en service, "
                       "'suspendu' = comptes temporairement geles."
    }
}

Schemas imbriques et references

Pour des structures complexes, decomposez en sous-schemas :

adresse_schema = {
    "type": "object",
    "properties": {
        "rue": {"type": "string"},
        "code_postal": {"type": "string"},
        "ville": {"type": "string"},
        "pays": {"type": "string", "enum": ["FR", "BE", "CH", "LU"]}
    },
    "required": ["rue", "code_postal", "ville", "pays"]
}

tools = [{
    "type": "function",
    "name": "creer_livraison",
    "description": "Creer une livraison avec adresses d'expedition et destination",
    "parameters": {
        "type": "object",
        "properties": {
            "expedition": adresse_schema,
            "destination": adresse_schema,
            "poids_kg": {"type": "number", "minimum": 0.1}
        },
        "required": ["expedition", "destination", "poids_kg"],
        "additionalProperties": false
    },
    "strict": true
}]

Points cles a retenir

  • Activez strict: true pour garantir la conformite des arguments
  • Validez quand meme cote client avec jsonschema pour les regles metier
  • Redigez des descriptions precises : c’est le premier levier de qualite
  • Utilisez enum pour contraindre les valeurs acceptees
  • Decomposez les schemas complexes en sous-structures reutilisables