Une application exploite plus facilement un objet validé qu’un bloc de texte à parser. Instructor adapte les clients de modèles pour demander une réponse conforme à un modèle Pydantic, valider le résultat et, si vous l’autorisez, renvoyer les erreurs au modèle pour une nouvelle tentative.
Le problème du « JSON presque valide »
Demander « réponds en JSON » ne suffit pas. Le modèle peut ajouter du Markdown, oublier un champ, changer un type ou produire une valeur hors domaine. Un parseur JSON vérifie la syntaxe ; il ne vérifie pas qu’une priorité vaut de 1 à 3 ou qu’une adresse possède la forme attendue.
Pydantic exprime ces contraintes dans un schéma utilisé à la fois pour guider le modèle et valider la réponse.
Définir la sortie attendue
from typing import Literal
from pydantic import BaseModel, Field
class TicketAnalyse(BaseModel):
resume: str = Field(min_length=10, max_length=240)
priorite: Literal["basse", "normale", "haute"]
equipe: Literal["facturation", "technique", "commercial"]
confiance: float = Field(ge=0, le=1)Le schéma doit décrire ce dont le programme a réellement besoin. Évitez les dizaines de champs facultatifs : ils augmentent l’ambiguïté et rendent l’évaluation plus difficile.
Appeler le modèle avec Instructor
L’API exacte dépend du fournisseur et de la version du client. Une forme courante consiste à créer un client Instructor puis à passer le modèle Pydantic comme response_model :
import instructor
from openai import OpenAI
client = instructor.from_openai(OpenAI())
analyse = client.chat.completions.create(
model="gpt-5",
response_model=TicketAnalyse,
messages=[
{
"role": "user",
"content": (
"Analyse ce ticket sans inventer de contexte : "
"Le paiement est débité deux fois depuis ce matin."
),
}
],
)
print(analyse.priorite)Le résultat est un objet TicketAnalyse, pas une chaîne JSON. Le code aval bénéficie des types et des erreurs de validation explicites.
Validation de forme et validation métier
Pydantic peut vérifier des longueurs, bornes, formats et relations déterministes. Il ne peut pas savoir à lui seul si le résumé est fidèle au ticket ou si l’équipe choisie est pertinente.
Séparez trois niveaux :
- **syntaxe** : le résultat peut-il être décodé ?
- **schéma** : champs, types et contraintes sont-ils valides ?
- **sémantique** : la réponse est-elle exacte et utile pour ce cas ?
Les deux premiers niveaux sont automatisables. Le troisième nécessite règles métier, données de référence, évaluations et parfois validation humaine.
Utiliser les nouvelles tentatives avec prudence
Instructor peut renvoyer au modèle les erreurs de validation. Cela aide à corriger une valeur hors borne ou un champ manquant. Définissez un petit nombre maximal de reprises : chaque tentative augmente latence et coût, et une erreur sémantique ne disparaît pas nécessairement.
analyse = client.chat.completions.create(
model="gpt-5",
response_model=TicketAnalyse,
max_retries=2,
messages=[...],
)Une configuration max_retries=2 signifie généralement l’essai initial puis jusqu’à deux reprises. Enregistrez le nombre d’essais et la cause finale sans conserver de données sensibles inutiles.
Concevoir un bon schéma
- Utilisez des
Literalou énumérations pour les catégories fermées. - Ajoutez une description lorsque le nom du champ ne suffit pas.
- Fixez des bornes réalistes aux nombres et aux textes.
- Préférez plusieurs petits objets à un schéma profondément imbriqué.
- Distinguez « inconnu » d’une valeur vide lorsque cette nuance compte.
- Ne demandez pas au modèle un identifiant qu’il peut retrouver dans vos données : faites la résolution côté application.
Si le modèle doit citer une source, demandez un extrait ou un identifiant contrôlable puis vérifiez qu’il existe réellement dans le contexte fourni.
Gérer les échecs dans l’application
La validation peut encore échouer après les reprises. Prévoyez un chemin explicite : placer la tâche en revue, demander une information manquante, appliquer une valeur sûre ou renvoyer une erreur contrôlée.
Ne convertissez pas silencieusement toute erreur en objet par défaut. Cela masquerait les dégradations du modèle et contaminerait les données métier.
Tester la fiabilité
Créez un jeu de tickets normaux, ambigus, contradictoires et malveillants. Mesurez :
- taux de validation au premier essai ;
- taux après reprise ;
- exactitude de chaque champ ;
- coût et latence ;
- fréquence des valeurs « inconnues » ;
- erreurs qui auraient un impact métier.
Testez également le schéma sans modèle avec des objets invalides. Les validateurs déterministes méritent leurs propres tests unitaires.
À retenir
Instructor et Pydantic transforment une sortie probabiliste en contrat logiciel mieux contrôlé. Ils réduisent les erreurs de format ; ils ne remplacent ni la vérification factuelle ni les règles d’autorisation. Un petit schéma, des reprises bornées et un chemin d’échec visible donnent de meilleurs résultats qu’une validation excessivement complexe.