Aller au contenu principal

Envoyer Plusieurs Images dans un Message

Mis à jour le 29 juillet 2026

Analyser plusieurs images à la fois

L’API Vision de Mistral ne se limite pas à une seule image par message. Vous pouvez envoyer plusieurs images dans un même appel pour demander au modèle de les comparer, les synthétiser ou les analyser conjointement. La différence avec deux appels séparés est essentielle : dans un appel unique, le modèle dispose des deux images en même temps et peut raisonner sur leurs relations, ce qu’aucune agrégation de réponses individuelles ne permettrait.

Cette capacité ouvre les cas d’usage où la question porte sur l’écart plutôt que sur le contenu : comparaison avant/après, analyse de séries de documents, vérification de conformité visuelle.

Structure d’un message multi-images

Le principe est simple : ajoutez plusieurs éléments image_url dans le tableau content :

message = {
    "role": "user",
    "content": [
        {"type": "text", "text": "Comparez ces deux images et décrivez les différences."},
        {"type": "image_url", "image_url": "https://exemple.com/image1.jpg"},
        {"type": "image_url", "image_url": "https://exemple.com/image2.jpg"}
    ]
}

Rien n’impose l’homogénéité : vous pouvez mélanger des images par URL et en Base64 dans le même message, ce qui est fréquent quand une référence hébergée doit être confrontée à un fichier local fraîchement produit.

Exemple : comparaison de deux images

Prenons un contrôle de réception en entrepôt. La photo de référence du produit conforme est confrontée à celle de l’échantillon reçu, avec un prompt système qui installe le rôle d’inspecteur :

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 expert en contrôle qualité. Comparez les images fournies avec précision."
        },
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": "Voici deux photos du même produit. La première est la référence, la seconde est l'échantillon reçu. Identifiez toutes les différences."
                },
                {"type": "image_url", "image_url": "https://exemple.com/reference.jpg"},
                {"type": "image_url", "image_url": "https://exemple.com/echantillon.jpg"}
            ]
        }
    ]
)

print(response.choices[0].message.content)

Le texte précise explicitement l’ordre — « la première est la référence » — car le modèle ne peut pas le deviner.

Intercaler texte et images

Cette désignation par l’ordre atteint vite ses limites au-delà de deux images. La méthode plus robuste consiste à annoncer chaque image juste avant de la fournir, en alternant les éléments text et image_url :

response = client.chat.complete(
    model="mistral-large-latest",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Voici le plan architectural original :"},
                {"type": "image_url", "image_url": "https://exemple.com/plan-original.png"},
                {"type": "text", "text": "Et voici la photo du bâtiment construit :"},
                {"type": "image_url", "image_url": "https://exemple.com/photo-batiment.jpg"},
                {"type": "text", "text": "Le bâtiment est-il conforme au plan ? Listez les écarts."}
            ]
        }
    ]
)

Chaque image porte désormais son étiquette, et la question finale arrive une fois tout le matériel présenté. Ce format améliore nettement la compréhension du modèle : il sait que le plan est la norme et la photo l’objet à évaluer, alors que l’inverse produirait un rapport d’écarts inversé.

Traitement par lot avec Base64

Pour un dossier d’images locales, la construction du content devient programmatique. On assemble la liste par une boucle, en encodant chaque fichier à la volée :

import base64
import os
from pathlib import Path
from mistralai import Mistral

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")
    ext = Path(chemin).suffix.lower()
    mime = {"jpg": "jpeg", "jpeg": "jpeg", "png": "png", "webp": "webp"}.get(ext.lstrip("."), "jpeg")
    return f"data:image/{mime};base64,{b64}"

# Charger toutes les images d'un dossier
dossier = Path("captures/")
images = sorted(dossier.glob("*.png"))

# Construire le contenu du message
content = [{"type": "text", "text": f"Analysez ces {len(images)} captures d'écran et résumez les éléments communs."}]
for img in images[:5]:  # Limiter à 5 images max
    content.append({"type": "image_url", "image_url": encoder_image(img)})

response = client.chat.complete(
    model="mistral-small-latest",
    messages=[{"role": "user", "content": content}]
)

print(response.choices[0].message.content)

Le images[:5] est le garde-fou du script. Sans lui, un dossier contenant deux cents captures partirait intégralement dans un seul appel — avec les conséquences décrites juste après.

Limites du multi-images

Il n’existe pas de limite stricte documentée sur le nombre d’images, mais deux effets se conjuguent au-delà de cinq à dix : la qualité d’analyse se dégrade, l’attention du modèle se diluant entre les images, et le coût en tokens grimpe fortement. Rappelez-vous l’ordre de grandeur de la leçon 2 : chaque image consomme 800 à 1 500 tokens, si bien que cinq images représentent déjà 5 000 à 7 500 tokens de prompt avant même votre question. Le total — images, texte et réponse — doit par ailleurs tenir dans la fenêtre de contexte du modèle, plafond qu’un lot d’images atteint bien plus vite qu’un document texte.

Cette fonction chiffre l’addition avant l’appel plutôt qu’après la facture :

def estimer_cout_multi_images(nb_images, tokens_par_image=1000, tokens_texte=100, tokens_reponse=500):
    """Estime le nombre total de tokens pour un appel multi-images."""
    total_input = (nb_images * tokens_par_image) + tokens_texte
    total = total_input + tokens_reponse

    print(f"Images : {nb_images} x {tokens_par_image} = {nb_images * tokens_par_image} tokens")
    print(f"Texte prompt : {tokens_texte} tokens")
    print(f"Réponse estimée : {tokens_reponse} tokens")
    print(f"Total estimé : {total} tokens")
    return total

estimer_cout_multi_images(3)
# Images : 3 x 1000 = 3000 tokens
# Texte prompt : 100 tokens
# Réponse estimée : 500 tokens
# Total estimé : 3600 tokens

Stratégie pour les grands volumes

Passé cinq images, changez d’approche plutôt que d’insister. Trois voies existent, souvent combinées. L’analyse séquentielle traite les images une par une puis agrège les résultats — le coût reste linéaire et la précision par image est maximale. Le groupement par lots envoie des paquets de trois à cinq images, ce qui préserve un minimum de comparaison intra-lot. Le pré-filtrage, enfin, utilise un modèle léger comme Small pour écarter les images non pertinentes avant de confier les cas importants à Large.

La première voie s’écrit ainsi, avec une synthèse finale qui ne manipule plus que du texte :

# Analyse séquentielle avec agrégation
resultats = []
for img_path in images:
    response = client.chat.complete(
        model="mistral-small-latest",
        messages=[{
            "role": "user",
            "content": [
                {"type": "text", "text": "Décrivez brièvement le contenu de cette image."},
                {"type": "image_url", "image_url": encoder_image(img_path)}
            ]
        }]
    )
    resultats.append(response.choices[0].message.content)

# Synthèse finale (texte seul)
synthese = client.chat.complete(
    model="mistral-small-latest",
    messages=[{
        "role": "user",
        "content": f"Voici les descriptions de {len(resultats)} images :\n\n" +
                   "\n---\n".join(resultats) +
                   "\n\nFaites une synthèse globale."
    }]
)

L’astuce est dans le second appel : il ne contient aucune image, donc aucun token visuel. Vous synthétisez cinquante images pour le prix de quelques centaines de tokens de texte.

Points clés à retenir

  • Vous pouvez envoyer plusieurs images dans un même message en ajoutant plusieurs éléments image_url
  • Intercalez du texte entre les images pour fournir du contexte au modèle
  • Chaque image ajoute 800-1500 tokens — estimez vos coûts avant l’appel
  • Au-delà de 5 images, préférez une stratégie séquentielle ou par lots
  • URL et Base64 peuvent être mélangés dans le même message