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 additionalPropertiesdoit etrefalse- Les types optionnels utilisent
anyOfavecnull - Pas de
pattern,minLength,maxLengthau 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: truepour garantir la conformite des arguments - Validez quand meme cote client avec
jsonschemapour les regles metier - Redigez des descriptions precises : c’est le premier levier de qualite
- Utilisez
enumpour contraindre les valeurs acceptees - Decomposez les schemas complexes en sous-structures reutilisables