Analyser des Graphiques avec la Vision API
Mis à jour le 29 juillet 2026
Lire les graphiques comme un analyste
Les graphiques — barres, lignes, camemberts, aires — sont omniprésents dans les rapports d’entreprise, les tableaux de bord et les publications scientifiques. Ils posent un problème particulier : l’information y est enfermée dans une image, souvent sans que les données source soient jointes. Un rapport annuel en PDF contient trente courbes dont personne ne possède plus le fichier Excel.
La Vision API de Mistral sait les lire, interpréter les tendances et extraire des données chiffrées. Cette leçon montre comment formuler des prompts qui produisent un résultat exploitable plutôt qu’un commentaire vague, et comment structurer les résultats obtenus.
Principes de l’analyse de graphiques
Livré à lui-même, le modèle produit une phrase générique du type « ce graphique montre une évolution des ventes ». Un prompt efficace force au contraire un parcours ordonné : identifier le type de graphique (barres, lignes, camembert, scatter), lire les axes et légendes avec leurs unités et leurs échelles, extraire les valeurs par approximation de la position visuelle, puis seulement interpréter les tendances — hausse, baisse, saisonnalité, anomalies. L’ordre importe : une interprétation formulée avant la lecture des axes est une interprétation inventée.
Analyser un graphique en barres
Le message système est l’endroit naturel pour inscrire cette méthode, une fois pour toutes, indépendamment de l’image analysée :
from mistralai import Mistral
import os
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
response = client.chat.complete(
model="mistral-large-latest",
messages=[
{
"role": "system",
"content": """Vous êtes un analyste de données expert. Quand vous analysez un graphique :
1. Identifiez le type de graphique et son titre
2. Décrivez les axes (labels, unités, échelle)
3. Listez les valeurs principales que vous pouvez lire
4. Identifiez les tendances, points hauts/bas, anomalies
5. Rédigez une conclusion en 2-3 phrases"""
},
{
"role": "user",
"content": [
{"type": "text", "text": "Analysez ce graphique en barres du chiffre d'affaires trimestriel."},
{"type": "image_url", "image_url": "https://exemple.com/ca-trimestriel.png"}
]
}
]
)
print(response.choices[0].message.content)
Le prompt système structure la réponse du modèle en étapes logiques, ce qui améliore à la fois la précision et la lisibilité. Vous obtenez un rapport comparable d’un graphique à l’autre, condition indispensable si ces réponses doivent ensuite être traitées automatiquement.
Extraire des données numériques
Pour obtenir des données exploitables plutôt qu’une description, la consigne doit être explicitement restrictive. Le modèle a une propension naturelle à commenter ; il faut la lui interdire :
response = client.chat.complete(
model="mistral-large-latest",
messages=[
{
"role": "system",
"content": "Vous êtes un extracteur de données. Analysez le graphique et retournez les données sous forme de tableau markdown. Ne commentez pas, ne décrivez pas -- extrayez uniquement les données."
},
{
"role": "user",
"content": [
{"type": "text", "text": "Extrayez les données de ce graphique en barres dans un tableau."},
{"type": "image_url", "image_url": "https://exemple.com/ventes-mensuelles.png"}
]
}
]
)
Le modèle retournera quelque chose comme :
| Mois | Ventes (k€) |
|----------|-------------|
| Janvier | 120 |
| Février | 135 |
| Mars | 148 |
Ce format se parse en quelques lignes de code et s’importe directement dans un tableur ou un DataFrame.
Analyser un graphique en lignes (tendances)
Les graphiques en lignes se prêtent particulièrement à l’analyse de tendances, et la question peut alors devenir un questionnaire complet posé dans le message utilisateur :
prompt_tendance = """Analysez ce graphique en lignes et répondez :
1. Quelle est la tendance générale (hausse, baisse, stable) ?
2. Y a-t-il des points d'inflexion ? Si oui, à quelles dates ?
3. Observez-vous une saisonnalité ?
4. Quelle est la valeur approximative au début et à la fin de la période ?
5. Quelle projection faites-vous pour le prochain trimestre ?"""
response = client.chat.complete(
model="mistral-large-latest",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt_tendance},
{"type": "image_url", "image_url": "https://exemple.com/evolution-prix.png"}
]
}
]
)
La cinquième question est d’une autre nature que les quatre premières : elle demande une extrapolation, pas une lecture. Traitez sa réponse comme une hypothèse à valider, jamais comme une donnée.
Analyser un camembert (répartition)
Sur les diagrammes circulaires, la question porte sur les proportions et la concentration plutôt que sur l’évolution :
prompt_camembert = """Analysez ce diagramme circulaire :
- Listez chaque segment avec son pourcentage approximatif
- Identifiez le segment dominant
- Indiquez si la répartition est concentrée ou dispersée
Retournez les données dans un tableau markdown."""
response = client.chat.complete(
model="mistral-large-latest",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt_camembert},
{"type": "image_url", "image_url": "https://exemple.com/repartition-marche.png"}
]
}
]
)
Vérifiez systématiquement que la somme des pourcentages retournés avoisine 100 : un total à 87 % signale une lecture incomplète, un segment oublié ou masqué par la légende.
Pipeline d’analyse de rapport
Ces appels isolés deviennent utiles à l’échelle d’un rapport entier. Le script suivant parcourt un dossier de graphiques exportés, demande à chaque fois une sortie JSON normalisée, et consigne le tout dans un fichier unique :
import base64
from pathlib import Path
from mistralai import Mistral
import json
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
def encoder_image(chemin):
with open(chemin, "rb") as f:
b64 = base64.standard_b64encode(f.read()).decode("utf-8")
return f"data:image/png;base64,{b64}"
def analyser_graphique(chemin_image, question=None):
"""Analyse un graphique et retourne les données structurées."""
if question is None:
question = "Analysez ce graphique. Retournez un JSON avec : type (bar/line/pie/other), titre, données (tableau de {label, valeur}), tendance, et resume."
response = client.chat.complete(
model="mistral-large-latest",
messages=[
{
"role": "system",
"content": "Retournez uniquement du JSON valide, sans blocs de code markdown."
},
{
"role": "user",
"content": [
{"type": "text", "text": question},
{"type": "image_url", "image_url": encoder_image(chemin_image)}
]
}
]
)
return response.choices[0].message.content
# Analyser tous les graphiques d'un dossier
dossier = Path("rapport/graphiques/")
resultats = {}
for fichier in sorted(dossier.glob("*.png")):
print(f"Analyse de {fichier.name}...")
resultats[fichier.name] = analyser_graphique(fichier)
# Sauvegarder les résultats
with open("rapport/analyse_graphiques.json", "w", encoding="utf-8") as f:
json.dump(resultats, f, ensure_ascii=False, indent=2)
La consigne « sans blocs de code markdown » évite l’irritant classique du JSON enveloppé dans des triples backticks, qui fait échouer le parsing.
Limites de l’analyse de graphiques
Quatre situations mettent le modèle en difficulté, et vous devez les connaître avant de bâtir un processus dessus. Les valeurs précises, d’abord : elles sont estimées à partir de la position visuelle des barres ou des points, avec une marge d’erreur de 5 à 10 %. Les graphiques surchargés ensuite, où la multiplication des séries, des légendes et des petits textes brouille la lecture. La basse résolution, qui rend les labels flous ou pixelisés illisibles — souvenez-vous du redimensionnement interne décrit en leçon 2. Les graphiques 3D enfin, dont la perspective fausse mécaniquement la lecture des hauteurs.
La conclusion pratique est nette : pour une extraction précise, préférez l’export CSV des données source lorsqu’il existe. La Vision API est idéale pour l’analyse rapide et la synthèse, pas pour remplacer un tableur. Elle brille quand la donnée source a disparu ; elle est un mauvais choix quand elle est à portée de main.
Points clés à retenir
- Utilisez Mistral Large 3 pour l’analyse de graphiques — la précision est critique
- Structurez votre prompt en étapes : type, axes, valeurs, tendances, conclusion
- Demandez explicitement un format de sortie (tableau markdown, JSON) pour des données exploitables
- Le modèle estime les valeurs avec une marge de 5-10 % — ne l’utilisez pas pour des chiffres exacts
- Combinez la Vision API avec un export CSV pour le meilleur des deux mondes