Parser les documents : texte, tableaux, OCR
Le router : une décision, un seul endroit
Premier node du pipeline, le router choisit la route d'extraction â et c'est le SEUL endroit du code qui connaisse cette logique :
source visuelle (PDF, image) + clĂ© Mistral configurĂ©e â route VISION (OCR)
PDF sans clĂ© Mistral â route TEXTE (pdfplumber)
image sans clĂ© Mistral â ERREUR (fail loud, pas de page vide)
txt / csv / xlsx / eml / json â route TEXTE toujours
Le principe cardinal : deux routes, un contrat. Texte ou vision, la sortie est le mĂȘme StructuredOrder (le schĂ©ma partagĂ© validĂ© Pydantic) â tout l'aval (validator, matchers) ignore la provenance du document.
La route texte : aplatir proprement
- PDF (pdfplumber) : par page,
extract_text()+extract_tables()â les tableaux sont rendus en lignescellule | cellule | celluleinjectĂ©es dans le texte (le LLM lit trĂšs bien ce format) ET conservĂ©s en structurĂ©. Le tout enasyncio.to_thread(pdfplumber est sync et CPU-bound â module 1 !). Un PDF scannĂ© ressort vide de pdfplumber : c'est le signal qu'il fallait la route vision ; - Excel/CSV (pandas) : lecture par feuille,
dropna(how="all"), bornĂ©e Ă 1000 lignes ; pour les CSV, une cascade d'essais encodage/sĂ©parateur (utf-8avec,/;/tab, puislatin-1, puis le sniffing automatique) â les CSV du monde rĂ©el sont un zoo, on tente du plus probable au plus permissif.
La route vision : le document natif au modĂšle
Pour les scans et images, le pipeline n'aplatit rien : le PDF/image part en base64 Ă mistral-ocr-latest avec le schĂ©ma d'annotation dĂ©rivĂ© du mĂȘme StructuredOrder et le mĂȘme prompt systĂšme â document en entrĂ©e, JSON structurĂ© en sortie, en un seul appel. Le context_text de l'email accompagne le document ici aussi.
Ce choix (OCR structurant plutĂŽt qu'OCR texte puis LLM) supprime une Ă©tape entiĂšre de perte : les positions de tableaux, les colonnes alignĂ©es visuellement â tout ce que l'aplatissement texte dĂ©truit â restent exploitables par le modĂšle de vision.
Les limites d'entrée : connaßtre ses plafonds
Tout pipeline d'extraction a des plafonds, et les connaßtre évite les mystÚres de prod :
- 1000 lignes lues maximum sur la route texte (la borne pandas) ;
- ~200 lignes structurĂ©es en pratique : le budget de sortie LLM (16k tokens) est le vrai plafond â et au-delĂ , le document est rejetĂ© entiĂšrement (fail loud), pas tronquĂ© en silence : un rĂ©sultat partiel non signalĂ© serait pire qu'une erreur ;
- la route vision (OCR) va plus loin â encore un argument pour elle sur les gros bons scannĂ©s.
La solution structurelle en chantier : le chunking avec contexte â dĂ©couper les grosses commandes en lots, en rĂ©-envoyant Ă chaque lot le contexte nĂ©cessaire (en-tĂȘtes de tableaux, consignes). Et la sagesse d'expĂ©rience qui guide son design, hĂ©ritĂ©e d'un produit prĂ©cĂ©dent de l'Ă©quipe : la qualitĂ© d'extraction se dĂ©grade bien avant la limite technique (~100 lignes, le modĂšle « s'emmĂȘle ») â les chunks efficaces y Ă©taient de ~40 lignes. Leçon gĂ©nĂ©rale : le plafond de qualitĂ© d'un LLM arrive avant son plafond de tokens â dimensionne tes lots sur le premier, pas le second.
Que fait le pipeline d'une image de bon de commande si la clé Mistral n'est pas configurée ?