Par Eric Burel - Formateur chez LBKE
Publié le
Les grands modèles de langage (LLM) renvoient souvent des réponses qui mélangent du texte explicatif avec du contenu spécifique, par exemple au format XML.
Cet article présente deux techniques pratiques pour isoler un contenu XML dans les réponses non structurées des LLM.
Les balises XML (eXtensible Markup Language) fournissent un moyen clair de marquer le début et la fin d’un contenu spécifique dans un texte.
Elles se présentent sous la forme <tag>contenu</tag>
. Mais le tag peut aussi être mélangé avec du texte libre, car les LLM aiment être polis dans leurs réponses.
Voici un exemple de réponse que pourrait produire le LLM en réponse à la question “combien font 2 et 2 ?” :
Voici ma réponse à la question :
<résultat>
4
</résultat>
Bon courage pour ton devoir de maths.
As-tu d'autres questions?
Les modèles Claude d’Anthropic sont par exemple connus pour apprécier le format XML. Le framework LLM LangChain offre plusieurs outils pour analyser et extraire du contenu à partir de sorties LLM formatées en XML.
Mais d’abord, détaillons l’intérêt d’utiliser un format structuré dans une application IA fondée sur les LLM.
LangChain est comme son nom l’indique un framework qui raisonne en termes de “chaînes”, via un langage simple appelé “LCEL”.
Une chaîne très classique est constitué de trois étapes principales :
Vous verrez souvent le code suivant dans les applications LangChain en Python :
# On définit une chaîne de traitement
# - prompt_template : un prompt de LLM avec des "trous" pour les variables
# - model : un connecteur pour un modèle LLM
# - output_parser : un parser qui extrait des données de la réponse du LLM
chain = prompt_template | model | output_parser
# On invoque la chaîne
chain.invoke({"operation": "addition", "a": 2, "b": 2})
Bien que l’ingénierie de prompt ou “prompt engineering” reçoive beaucoup d’attention, l’extraction de données structurées à partir des réponses est tout aussi importante.
Comme l’explique la documentation LangChain sur les Output Parsers, l’analyse de sortie structurée aide à convertir les sorties du modèle en formats structurés - une capacité clé pour les systèmes en production.
Les balises XML créent des frontières claires entre le texte libre et le contenu structuré. Cela les rend parfaites pour les applications qui doivent isoler des éléments spécifiques comme :
LangChain inclut un XMLOutputParser
qui extrait le contenu des balises XML dans les réponses LLM. Ce parser convertit le texte XML en un dictionnaire Python où chaque balise devient une clé.
Voici un exemple simple qui extrait le contenu d’une balise <program>
:
from langchain_core.output_parsers import XMLOutputParser
parser = XMLOutputParser()
chain = prompt_template | model | parser
# On ajoute une petite fonction qui récupère le champ "program"
# qui a été généré par le parser XML
final_chain = chain | (lambda x: x["program"])
result = final_chain*.invoke(
{"input": "Write a Python function to calculate fibonacci numbers"}
)
Pour garantir que la réponse du LLM soit bien du XML valide, la méthode get_format_instructions()
du parser génère des instructions qui indiquent le format attendu. Vous pouvez les inclure dans votre template de prompt.
Le XMLOutputParser
standard fonctionne bien avec des sorties correctement structurées.
Cependant, les LLM incluent souvent des balises XML dans un texte explicatif plus long. Utiliser la fonction get_format_instructions()
dans un prompt incite fortement le LLM à produire du XML valide, mais cela n’est pas non plus garanti.
Typiquement, le LLM peut ajouter des explications avant ou après le XML, même si on lui indique de ne pas le faire.
Lorsque la structure du XML est simple, on peut préférer une approche plus flexible, en créant une petite fonction réutilisable qui détecte une balise spécifique dans le texte.
Voici un exemple d’implémentation :
import re
def XMLTagExtractor(tag_name):
"""
Exemple: XMLTagExtractor("program") génère un nouveau parser
qui extrait la balise <program> d'une réponse LLM
"""
def extractor(xml_string):
# Create a regex pattern that matches the opening and closing tags
pattern = r"<" + tag_name + r">(.+?)</" + tag_name + r">"
# Search for the pattern, allowing for newlines within the content
match = re.search(pattern, xml_string, re.DOTALL)
if match:
return match.group(1).strip()
else:
raise KeyError(f"Tag {tag_name} not found")
return extractor
On peut utiliser cette fonction directement dans une chaîne LangChain:
parser = XMLTagExtractor("program")
chain = prompt_template | model | parser
Cette fonction peut extraire du contenu même à partir de sorties imparfaitement formatées. Voici un exemple d’utilisation plus détaillé :
code_extractor = XMLOutputParser("code")
llm_response = """I've created a function to sort a list:
<code>
def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr
</code>
This implementation has O(n²) time complexity."""
code = code_extractor(llm_response)
print(code) # On obtient juste la fonction
L’extraction de données structurées à partir des réponses LLM est essentielle pour construire des applications d’IA fiables. C’est une compétence attendu du nouveau métier de développeur LLM.
Les capacités d’analyse XML de LangChain vous offrent plusieurs options, de l’extraction simple de balises aux workflows avancés avec du XML complexe.
La combinaison de parsers intégrés et de la création de petites fonctions réutilisables offre la flexibilité nécessaire pour gérer les sorties de différents fournisseurs de LLM.
Si vous souhaitez maîtriser ces techniques, LBKE propose une formation LangChain qui couvre les concepts fondamentaux de ce framework LLM.
À mesure que vous affinez vos applications LLM, vous pourriez vouloir explorer d’autres formats de sortie structurés.
Quelques alternatives incluent :
Pour des workflows plus complexes, LangGraph offre un framework pour construire des systèmes d’agents, et peut s’appuyer sur des appels de fonction pour gérer des données structurées.
L’essentiel est de sélectionner la bonne technique pour vos besoins spécifiques. Quelle que soit la méthode choisie, les sorties structurées vous aideront à construire des applications IA plus fiables.
Vous avez apprécié cette ressource ?
Découvrez toutes nos formations Next.js, Astro.js et LangChain en présentiel ou en distanciel
Eric Burel est ingénieur diplômé de l'ENSIMAG. Il est co-fondateur de LBKE et a contribué à la création de plusieurs startups technologiques en tant que développeur freelance.
Eric est impliqué dans l'open source en tant que membre du collectif Devographics, qui organise les enquêtes annuelles "State of" JavaScript, React et AI.
Il contribue aussi au domaine de l'intelligence artificielle en tant que membre de la communauté LangChain.
Depuis 2018, Eric intervient comme formateur en entreprise et enseignant en école d'ingénieur, dans le domaine du développement web et du développement LLM.
Ses années d'expérience en tant que consultant lui ont permis de développer une culture technique large, qu'il mobilise pour créer des formations qui répondent aux besoins concrets des participants.
Il partage régulièrement ses connaissances à travers des articles publiés sur Smashing Magazine, sur son blog et via les cours en ligne NextPatterns et AstroPatterns.
Si vous passez par Montpellier, vous le croiserez sûrement au détour d'un meetup MontpellierJS ou Gen-AI !