Lorsque l’on développe une application agentique fondée sur un LLM, le principal défi n’est pas seulement d’obtenir une réponse correcte, mais de la rendre directement exploitable.
Cet article explique comment les outputs structurés de LangChain permettent de passer d’une logique de parsing de texte fragile et complexe, à un flux de données fiable et validé au format JSON.
Cette approche réduit les erreurs de parsing, améliore la robustesse du pipeline et facilite la maintenance des applications IA, notamment dans des contextes de production où la cohérence du format de sortie est cruciale.
Les LLM produisent du texte, pas des données
Les modèles de langage génèrent toujours une simple chaîne de texte. Cela crée deux difficultés : le format n’est pas garanti, et le parsing est fragile. Par exemple, nous avons décrit dans un article précédent comment extraire du XML généré par le modèle Claude. Cette technique fonctionne, mais n’est fiable qu’environ 8 fois sur 10 sur le cas simple testé dans notre formation LangChain.
Le LLM peut insérer du texte parasite en préambule, mal fermer une balise XML etc.
Les outputs structurés résolvent ce problème en imposant au modèle de respecter un schéma explicite, validé automatiquement par LangChain lors de l’appel. Le résultat devient alors une donnée fiable, prête à être utilisée dans votre code.
Limites des prompts et du parsing manuel
Une approche simple consiste à demander un JSON dans le prompt, puis à parser le texte avec json.loads() ou le JSONOutputParser.
En pratique, le modèle peut introduire une erreur de syntaxe ou modifier la structure des champs. Ces problèmes exigent un post-traitement et rendent le pipeline instable.
prompt = "Renvoie un JSON avec les champs 'titre' et 'description'."
output = model.invoke(prompt)
# Exemple de JSON incorrect produit par le modèle :
# {
# "title": "Un article",,
# "desc" : "À propos de LangChain"
# }
data = json.loads(output.content) # Erreur !
Une simple virgule mal placée suffit à interrompre tout le processus. Les LLM ne garantissent pas une sortie parfaitement conforme, sauf en les contraignant à suivre un format prédéfini.
Utiliser un parser plus élaboré avec un schéma, par exemple via PydanticOutputParser, ne suffit pas pour autant ! En effet cela ne fait qu’améliorer la logique de traitement de la réponse du LLM, sans améliorer la réponse elle-même.
Pour aller plus loin, il faut mobiliser les outils.
Sortie structurée avec LangChain
La sortie structurée ou “structured output” s’appuie intelligemment sur le mécanisme de tool calling intégré dans les LLM modernes.
Plutôt que de demander gentiment au LLM de générer un objet JSON au bon format, on va lui fournir directement un outil pour cette tâche.
from typing import TypedDict, Literal
class YesNo(TypedDict):
is_it_yes_or_is_it_no: Literal["yes", "no"]
yes_no_model = model.with_structured_output(YesNo)
result = yes_no_model.invoke(
{"input": "C'est oui ou bien c'est non ?"}
)
print(result["is_it_yes_or_is_it_no"])
Si le résultat n’est pas conforme au schéma, une erreur est levée. Sinon, la sortie est garantie valide et directement exploitable — sans parsing manuel ni validation supplémentaire.
Comment cela fonctionne en pratique ? Les LLM récents sont préentraînés pour être capable d’appeler des outils, auxquels ils passent des paramètres… au format JSON structuré !
On bénéficie donc ici d’une capacité intégrée nativement au LLM, plutôt que de s’appuyer sur du prompt engineering générique.
Du parsing fragile aux appels d’outils fiables
Adopter les outputs structurés contribue à rendre vos agents LangChain plus robustes. Au lieu de faire confiance à un texte libre, vous donnez un cadre strict au LLM, via un outil.