Aller au contenu principal

Extraction de métadonnées structurées

Extraire exactement ce dont vous avez besoin

L’annotation de document ne se limite pas à extraire du texte brut. Elle permet d’obtenir des données structurées, typées et validées, directement exploitables dans vos systèmes. Dans cette leçon, vous apprendrez à concevoir des schémas d’extraction avancés.

Schémas Pydantic avancés

Types complexes et optionnels

from pydantic import BaseModel, Field
from typing import Optional
from enum import Enum

class TypeDocument(str, Enum):
    FACTURE = "facture"
    CONTRAT = "contrat"
    RAPPORT = "rapport"
    FORMULAIRE = "formulaire"
    AUTRE = "autre"

class Adresse(BaseModel):
    rue: Optional[str] = Field(None, description="Numéro et rue")
    code_postal: Optional[str] = Field(None, description="Code postal")
    ville: Optional[str] = Field(None, description="Ville")
    pays: str = Field(default="France", description="Pays")

class EntiteJuridique(BaseModel):
    nom: str = Field(..., description="Raison sociale")
    siret: Optional[str] = Field(None, description="Numéro SIRET")
    adresse: Optional[Adresse] = Field(None, description="Adresse postale")
    email: Optional[str] = Field(None, description="Adresse email")

class ExtractionDocument(BaseModel):
    type_document: TypeDocument = Field(
        ..., description="Type du document"
    )
    date: Optional[str] = Field(
        None, description="Date principale (YYYY-MM-DD)"
    )
    emetteur: EntiteJuridique = Field(
        ..., description="Entité qui émet le document"
    )
    destinataire: Optional[EntiteJuridique] = Field(
        None, description="Entité destinataire"
    )
    resume: str = Field(
        ..., description="Résumé en 2-3 phrases du contenu"
    )
    langue: str = Field(
        ..., description="Langue du document (code ISO 639-1)"
    )

Listes et données répétitives

Pour extraire des éléments multiples (lignes de facture, clauses, etc.) :

from pydantic import BaseModel, Field

class LigneFacture(BaseModel):
    description: str = Field(..., description="Description du produit/service")
    quantite: float = Field(..., description="Quantité")
    prix_unitaire: float = Field(..., description="Prix unitaire HT")
    montant: float = Field(..., description="Montant total HT de la ligne")

class FactureDetaillee(BaseModel):
    fournisseur: str = Field(..., description="Nom du fournisseur")
    numero: str = Field(..., description="Numéro de facture")
    date: str = Field(..., description="Date (YYYY-MM-DD)")
    lignes: list[LigneFacture] = Field(
        ..., description="Lignes de la facture"
    )
    sous_total_ht: float = Field(..., description="Sous-total HT")
    tva: float = Field(..., description="Montant TVA")
    total_ttc: float = Field(..., description="Total TTC")
    conditions_paiement: str = Field(
        ..., description="Conditions de paiement mentionnées"
    )

Champs booléens et cases à cocher

Le modèle excelle dans l’extraction de formulaires à cases à cocher :

from pydantic import BaseModel, Field

class ReponseFormulaire(BaseModel):
    question: str = Field(..., description="Intitulé de la question")
    reponse: bool = Field(..., description="True si coché, False sinon")

class FormulaireMedical(BaseModel):
    nom_patient: str = Field(..., description="Nom complet du patient")
    age: Optional[int] = Field(None, description="Âge du patient")
    sexe: Optional[str] = Field(None, description="Sexe (M/F)")
    numero_patient: Optional[str] = Field(None, description="ID patient")
    telephone: Optional[str] = Field(
        None, description="Numéro de téléphone (null si non fourni)"
    )
    reponses: list[ReponseFormulaire] = Field(
        ..., description="Réponses aux questions du formulaire"
    )

Comme démontré par l’équipe Mistral, le modèle est capable de :

  • Reconnaître si une case est cochée ou non
  • Inférer qu’un champ est absent plutôt que d’inventer une valeur
  • Extraire les questions associées à chaque case

Appel complet avec schéma avancé

import os
import json
from mistralai import Mistral
from mistralai.extra import response_format_from_pydantic_model

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])

ocr_response = client.ocr.process(
    model="mistral-ocr-latest",
    document={
        "type": "document_base64",
        "document_base64": document_base64
    },
    document_annotation_format=response_format_from_pydantic_model(
        FactureDetaillee
    ),
    document_annotation_prompt=(
        "Ce document est une facture. Extrais toutes les lignes "
        "de facturation avec leurs montants."
    )
)

# Extraction et validation
for page in ocr_response.pages:
    if page.document_annotation:
        facture = FactureDetaillee.model_validate_json(
            page.document_annotation
        )

        print(f"Facture {facture.numero} - {facture.fournisseur}")
        print(f"Date : {facture.date}")
        print(f"\nLignes :")
        for ligne in facture.lignes:
            print(f"  - {ligne.description}: {ligne.quantite} x "
                  f"{ligne.prix_unitaire}€ = {ligne.montant}€")
        print(f"\nTotal TTC : {facture.total_ttc}€")

Bonnes pratiques pour les schémas

  • Descriptions précises : chaque Field doit avoir une description claire et sans ambiguïté
  • Types optionnels : utilisez Optional pour les champs qui peuvent être absents
  • Valeurs par défaut : fournissez des défauts sensés (default="France" pour le pays)
  • Enums : utilisez des enums pour les champs à valeurs limitées
  • Imbrication : structurez vos schémas en sous-modèles réutilisables
  • Descriptions en français : le modèle comprend les descriptions dans la langue du document

Points clés à retenir

  • Les schémas Pydantic permettent d’extraire des données typées et validées
  • Utilisez des types complexes (listes, enums, modèles imbriqués) pour des extractions précises
  • Le modèle gère les champs optionnels et les cases à cocher avec fiabilité
  • Les descriptions des champs guident l’extraction : soyez précis et explicite
  • Combinez le document_annotation_prompt avec le schéma pour un contexte maximal