LLM Multimodaux : Quand Texte et Image Fusionnent par l IA

LLM Multimodaux : Quand Texte et Image Fusionnent par l IA

Et si votre système IA pouvait lire un contrat, voir les graphiques qu’il contient, comprendre les photos jointes, et produire une analyse cohérente de l’ensemble — exactement comme le ferait un collaborateur humain ? Jusqu’en 2023, traitement du texte et analyse d’image étaient deux problèmes distincts, nécessitant deux systèmes IA différents. Aujourd’hui, les LLM multimodaux — des modèles capables de traiter simultanément texte, images, et parfois audio ou vidéo — redéfinissent ce qu’une IA peut accomplir. Selon Goldman Sachs, 40 % des tâches de travail du savoir impliquent une combinaison de texte et d’éléments visuels. Les LLM multimodaux s’attaquent à ce territoire inexploré.

Qu’est-ce que la multimodalité en IA ?

Un modèle de langage classique (GPT-3, Claude 1, LLaMA 2) ne traite que du texte. Pour analyser une image, il fallait passer par un modèle de vision séparé (ResNet, CLIP, DALL-E Encoder) qui transformait l’image en vecteur numérique, puis alimenter ce vecteur au modèle de texte.

Les LLM multimodaux modernes intègrent nativement les deux modalités dans une architecture unifiée :

  • GPT-4V / GPT-4o (OpenAI) : texte + images, GPT-4o ajoute l’audio
  • Claude 3 / Claude 3.5 / Claude 4 (Anthropic) : texte + images avec fenêtre de contexte très large
  • Gemini 1.5 Pro / 2.0 (Google) : texte + images + audio + vidéo + code, fenêtre de 1M tokens
  • LLaVA, InternVL, Qwen-VL : modèles open source déployables en local

L’avantage fondamental : le modèle comprend les relations entre texte et image. Il ne se contente pas de décrire l’image séparément — il raisonne sur le contexte combiné.

Cas d’usage concrets pour les entreprises

1. Compréhension de documents complexes

Les rapports financiers, les présentations PowerPoint exportées en PDF, les tableaux de bord contiennent des graphiques et des données visuelles que l’OCR classique ne peut pas interpréter.

import anthropic
import base64
from pathlib import Path

client = anthropic.Anthropic()

def analyze_financial_chart(image_path: str, question: str) -> str:
    """Analyse un graphique financier et répond à une question."""
    
    with open(image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode("utf-8")
    
    # Détection du type MIME
    ext = Path(image_path).suffix.lower()
    media_type_map = {
        ".jpg": "image/jpeg", ".jpeg": "image/jpeg",
        ".png": "image/png", ".gif": "image/gif",
        ".webp": "image/webp"
    }
    media_type = media_type_map.get(ext, "image/jpeg")
    
    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=1500,
        messages=[{
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": media_type,
                        "data": image_data
                    }
                },
                {
                    "type": "text",
                    "text": f"""Tu es un analyste financier expert.
Analyse ce graphique/document financier et réponds à la question suivante :

{question}

Sois précis et cite les données visuelles que tu observes."""
                }
            ]
        }]
    )
    
    return response.content[0].text

# Exemples d'utilisation
analysis = analyze_financial_chart(
    "rapport_trimestriel_q3.png",
    "Quelle est la tendance des ventes sur les 3 derniers trimestres ? Y a-t-il des anomalies ?"
)

2. Analyse de produits e-commerce

Pour un distributeur ou un fabricant, analyser automatiquement des photos produits et en extraire des attributs structurés représente un gain de temps considérable.

def analyze_product_image(image_path: str) -> dict:
    """Extrait les attributs d'un produit depuis une photo."""
    
    with open(image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode("utf-8")
    
    prompt = """Analyse cette image produit et extrais les informations au format JSON :
{
  "categorie": "catégorie principale du produit",
  "couleurs": ["liste des couleurs visibles"],
  "matiere_apparente": "matière principale si identifiable",
  "style": "style/ambiance (ex: moderne, vintage, industriel, scandinave)",
  "usage_probable": "usage principal du produit",
  "qualite_photo": "bonne/moyenne/mauvaise",
  "fond_neutre": true/false,
  "description_seo": "description optimisée SEO de 150 caractères"
}

Réponds uniquement avec le JSON valide."""
    
    response = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=500,
        messages=[{
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/jpeg",
                        "data": image_data
                    }
                },
                {"type": "text", "text": prompt}
            ]
        }]
    )
    
    import json
    return json.loads(response.content[0].text)

3. Contrôle qualité visuel

Dans la production industrielle ou l’artisanat, détecter les défauts visuels manuellement est lent et sujet à la fatigue humaine.

def quality_control_check(product_image: str, reference_image: str) -> dict:
    """Compare un produit à une référence et détecte les défauts."""
    
    def load_image(path: str) -> str:
        with open(path, "rb") as f:
            return base64.b64encode(f.read()).decode("utf-8")
    
    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=800,
        messages=[{
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": "Image de référence (produit conforme) :"
                },
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/jpeg",
                        "data": load_image(reference_image)
                    }
                },
                {
                    "type": "text",
                    "text": "Produit à contrôler :"
                },
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/jpeg",
                        "data": load_image(product_image)
                    }
                },
                {
                    "type": "text",
                    "text": """Compare ces deux images et fournis un JSON :
{
  "conforme": true/false,
  "defauts": ["liste des défauts détectés"],
  "localisation_defauts": "description de la zone affectée",
  "severite": "critique/majeur/mineur/aucun",
  "action_recommandee": "accepter/retoucher/rejeter"
}"""
                }
            ]
        }]
    )
    
    import json
    return json.loads(response.content[0].text)

4. Extraction de données depuis des tableaux et formulaires

Un usage particulièrement puissant : extraire des données depuis des tableaux photographiés ou des formulaires manuscrits, là où l’OCR classique échoue.

def extract_table_from_image(image_path: str) -> list[dict]:
    """Extrait les données d'un tableau visible dans une image."""
    
    with open(image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode("utf-8")
    
    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=2000,
        messages=[{
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/jpeg",
                        "data": image_data
                    }
                },
                {
                    "type": "text",
                    "text": """Extrais toutes les données de ce tableau sous forme de JSON.
Format attendu : liste d'objets où chaque objet est une ligne du tableau.
Les clés sont les en-têtes de colonnes.
Réponds uniquement avec le JSON valide."""
                }
            ]
        }]
    )
    
    import json
    return json.loads(response.content[0].text)

Comparaison des modèles multimodaux

ModèleForcesLimitesCoût approx.
Claude 3.5 SonnetPrécision analyse, contexte long (200K tokens), raisonnementPlus lent que Haiku~3 $/M tokens input
GPT-4oRapidité, multimodal complet (audio), écosystèmeFenêtre contexte plus courte~5 $/M tokens input
Gemini 1.5 ProVidéo native, 1M tokens contexte, Google CloudHallucinations sur détails fins~3.5 $/M tokens input
LLaVA 1.6 (local)Gratuit, données restent on-premiseMoins précis sur tâches complexesInfrastructure locale
Qwen-VL (local)Excellent sur documents asiatiquesMoins polyvalentInfrastructure locale

Recommandation PME : commencer avec Claude Haiku pour les tâches d’extraction simples (coût 5 à 10 fois inférieur), basculer sur Sonnet ou GPT-4o pour les analyses complexes qui nécessitent du raisonnement.

Traitement en lot (batch processing)

Pour analyser des centaines ou milliers d’images, le traitement séquentiel est trop lent. Voici un pattern d’exécution parallèle avec contrôle du débit :

import asyncio
from anthropic import AsyncAnthropic

async_client = AsyncAnthropic()

async def analyze_image_async(image_path: str, prompt: str) -> dict:
    with open(image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode("utf-8")
    
    response = await async_client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=500,
        messages=[{
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/jpeg",
                        "data": image_data
                    }
                },
                {"type": "text", "text": prompt}
            ]
        }]
    )
    
    return {"path": image_path, "result": response.content[0].text}

async def batch_analyze(image_paths: list[str], prompt: str, concurrency: int = 5) -> list[dict]:
    """Analyse un lot d'images avec contrôle de la concurrence."""
    semaphore = asyncio.Semaphore(concurrency)
    
    async def analyze_with_limit(path: str) -> dict:
        async with semaphore:
            return await analyze_image_async(path, prompt)
    
    tasks = [analyze_with_limit(p) for p in image_paths]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    
    # Filtrage des erreurs
    return [r for r in results if not isinstance(r, Exception)]

# Lancement
import glob
image_files = glob.glob("products/*.jpg")
results = asyncio.run(batch_analyze(image_files, "Décris ce produit en JSON"))

Considérations pratiques pour les PME

Qualité des images : les LLM multimodaux sont robustes aux images imparfaites (légèrement floues, mal éclairées), mais pas miraculeuses. Une image de 800×600 pixels minimum est recommandée pour les documents textuels.

Coût par image : une image compte comme environ 1 000 à 2 000 tokens selon sa taille. Pour 1 000 images analysées avec Claude Haiku, comptez 5-15 € selon la complexité du prompt.

Confidentialité : les mêmes règles que pour les LLM texte s’appliquent. Pour des images sensibles (documents RH, données financières, photos de production propriétaires), envisagez un déploiement local avec LLaVA ou Qwen-VL.

Limite actuelle : les LLM multimodaux ne “voient” pas exactement comme un humain. Ils excellent dans la compréhension sémantique et contextuelle, mais peuvent rater des détails fins (couleurs très proches, micro-textes de moins de 8px, patterns complexes sur fond chargé).

Ce qu’il faut retenir

Les LLM multimodaux suppriment la frontière artificielle entre analyse textuelle et visuelle. Pour une PME, cela ouvre des automatisations auparavant impossibles : analyse de catalogues produits, traitement de documents mixtes (texte + graphiques), contrôle qualité visuel, extraction de données depuis des photos. Les coûts restent accessibles (quelques centimes par image), et des modèles open source permettent un déploiement local pour les données sensibles.

La clé est de commencer par un cas d’usage précis, mesurer la précision sur un échantillon représentatif, et itérer sur le prompt avant de passer à l’échelle.

Vous avez des données visuelles à analyser automatiquement ? Brio Novia conçoit des pipelines multimodaux adaptés à votre secteur. Écrivez-nous à contact@brio-novia.eu pour discuter de votre cas d’usage.