Aller au contenu

Atomes de traitement explicables pour documents et données

Une bibliothèque Python qui consolide des systèmes de traitement documentaire en production en petits atomes typés et traçables, rangés en familles nommées, cartographiés dans un Atlas généré et assemblés en recettes validées qui rendent des verdicts tri-états et explicables.

Contexte

Des systèmes de production pour le rapprochement documentaire et l’OCR, développés pour des clients tels qu’un grossiste distributeur et un cabinet d’expertise comptable, ont laissé plusieurs bases de code résolvant chacune les mêmes sous-problèmes (routage des pages, réglage de l’OCR, extraction par LLM, comparaison de champs) avec leurs propres bogues. La bibliothèque d’atomes les consolide en un seul paquet. Sa question centrale est celle qui sous-tendait les systèmes d’origine : peut-on automatiser un contrôle documentaire de sorte qu’un humain puisse auditer et contester chaque verdict ? Extraire un champ ne suffit pas. Le système doit indiquer si deux documents concordent, pourquoi, et sur la base de quels éléments.

Approche

Tout est construit à partir d’atomes. Un atome a une seule responsabilité, des entrées et sorties typées, aucun état global et des dépendances injectées (client LLM, moteur OCR, stockage). Une chaîne de traitement est une composition d’atomes, soit écrite en code, soit déclarée sous forme de recette YAML validée au chargement, avant toute exécution.

Le catalogue

Les 459 atomes sont regroupés en 32 familles, un paquet Python chacune, rangées le long de la chaîne de traitement : capter le monde, le comprendre, rapprocher et décider, restituer, puis exploiter en production. Deux paquets supplémentaires les assemblent : steps (77 étapes nommées et paramétrées) et recipes (chargement et validation des recettes YAML).

SérieFamilleAtomesRôle
Soclecore25types pivots, chaîne de traitement, configuration, résilience (reprises, limites de débit), fichiers, concurrence
Capterconnect40HTTP résilient, boîtes aux lettres (Graph, IMAP), SFTP, OneDrive, source ERP en lecture seule, données ouvertes, piste d’audit
google24Gmail, Sheets, Drive, Apps Script, avec exécution résiliente
web17robots web indépendants du pilote (Selenium, Playwright) : attentes, squelette à reprise, formulaires
pdf9texte natif positionné, décision d’OCR, rendu, pages, doublons
ocr9PaddleOCR avec réglages de production, EasyOCR
layout3géométrie de page : lignes, colonnes, redressement, rendu monospace
audio16transcription par morceaux, post-traitement des segments, recalage micro ↔ écran
vision32flux vidéo / RTSP, détection, suivi, profondeur, segmentation, calibration
vlm10lecture d’écran par modèle de vision-langage : détection de changement, localisation de libellés
geo11mesures géodésiques, position combinée de relevés GPS, filtrage par distance aux lignes, SQL spatial
calendar4jours fériés, jours et horaires ouvrés
Comprendretext32nombres et montants, dates, normalisation, champs par motifs, identifiants
segment7pages → documents logiques, numéros de pièce typés, nature de page
classify12classement par nom de fichier, expéditeur, motifs pondérés, TF-IDF, visuel, LLM, cascades
llm24contrat indépendant du fournisseur, fournisseurs, pool, prompts, extraction structurée
anchor5champs et tableaux situés par rapport aux libellés imprimés, texte natif ou OCR
kb8base de connaissances tracée : journal d’événements validé, replié en index SQLite
Rapprochermatch25EAN/GTIN, index, score multicritère, affectation optimale, résolution d’entités
compare9comparateurs tri-états et explicables de champs, d’enregistrements et d’ensembles
check9contrôles génériques tri-états : totaux, TVA, balance, complétude, vraisemblance
reconcile12appariement d’ensembles, chaînes commande → livraison → facture, N-voies, lettrage, rapprochement bancaire
validate14moteur de règles, identifiants, cohérence des montants, verdicts LLM corrigés, décision finale
rules8langage de conditions sûr, tables « premier match » explicables, escalade, machines à états
events11événements horodatés : fenêtres, veille des événements attendus, sessions, transitions de statut
analytics18analyses supply chain sans pandas : demande, ruptures, taux de service, stock de sécurité
Restituerexport8CSV pour Excel FR, classeurs Excel partagés, rapports HTML / Markdown / PDF
report6écarts persistables, synthèses, file de revue
render12livrables HTML : diagrammes Mermaid pré-rendus, graphiques ECharts, cartes GeoJSON
diagram6diagrammes de processus : lecture draw.io / BPMN JSON, rendu Mermaid et BPMN XML
Exploiterops26haute disponibilité (battements, élection), démon à déclencheurs horaires, surveillance, contrôles préalables
qa7non-régression rédactionnelle (fichiers dorés), rejeu de simulations, accord inter-annotateurs

Recettes nommées

Chacune des 17 recettes est une liste YAML d’étapes nommées <famille>.<atome>. Trois exemples :

  • invoice_multi_doc : un lot de PDF multidocuments devient un ensemble de documents logiques contrôlés. io.collect → pdf.read → segment.documents → classify.documents → llm.extract → validate.ids → validate.amounts → validate.decide → export.csv → google.sheets.upsert → connect.notify. Chaque document finit valide, à vérifier ou invalide.
  • doc_reconciliation : un dossier de factures, d’avoirs et de bons de livraison, contrôlé par rapport aux commandes. L’extraction LLM gardée (llm.extract_docs) est recoupée avec une extraction par motifs (extract.regex, compare.extractions, reconcile.fields), puis viennent check.document et check.completeness, les lignes face à la commande (compare.reference), la chaîne commande → livraison → facture (reconcile.nway), et enfin un fichier d’écarts et une file de revue (report.discrepancies, report.review). 17 étapes.
  • meeting_transcript : un enregistrement de réunion devient une transcription horodatée avec locuteurs. audio.decode → audio.vad → audio.transcribe → audio.diarize → audio.speakers → audio.segments → export.csv → export.transcript → connect.notify.

Les autres sont notamment delivery_vs_order, ledger_reconciliation, invoice_dedup, article_base_cleaning, stock_policy, mail_to_sheet, draft_mails, pdf_text_extract, rubric_eval, screen_session, camera_flow et process_from_transcript.

L’Atlas

L’Atlas est une page HTML unique, consultable hors ligne, générée à partir du code lui-même (arbres syntaxiques et YAML), sans aucune donnée saisie à la main. Il dessine le catalogue comme un tableau périodique : chaque famille est un élément doté d’un symbole, chaque module un atome, chaque recette une molécule. Il signale aussi les atomes sans documentation, sans test ou sans exemple d’usage.

Atlas, série « Capter » : un élément par famille (connect, google, web, pdf, ocr, layout, audio, vision, vlm, geo, calendar), avec ses atomes en dessous La série « Capter » du tableau périodique. Chaque case est une famille, avec son symbole, son nombre de modules et sa taille en milliers de lignes ; chaque tuile en dessous est un atome.

Atlas, série « Rapprocher » : match, compare, check, reconcile, validate, rules, events, analytics La série « Rapprocher » : les familles qui apparient, comparent, contrôlent et décident.

Fiche de l’atome compare.fields dans l’Atlas : rôle, règles de dominance et signature complète La fiche d’un atome (compare.fields) : à quoi il sert, d’après sa docstring, puis chaque nom public avec sa signature complète.

La recette invoice_multi_doc vue comme une molécule : 11 étapes reliées par les clés de contexte qu’elles se transmettent La recette invoice_multi_doc en molécule : 11 étapes, les clés de contexte qui les relient et les services requis (en pointillé lorsqu’ils sont facultatifs).

Méthodes

  • Résultats tri-états. Chaque comparaison renvoie ok ∈ {True, False, None} (conforme / écart / non concluant) avec un code de motif nommé et une trace. Une valeur manquante ou illisible compte comme non concluante, jamais comme une anomalie. Les résultats non concluants sont tout de même comptabilisés, et non écartés en silence.
  • Routage hybride texte natif/OCR. Chaque page PDF est classée comme native, OCR ou vide, selon la quantité de texte natif qu’elle contient et la part de ce texte couverte par des images. L’OCR n’est exécuté que là où il est nécessaire.
  • Extraction LLM ancrée. L’extraction JSON structurée est validée par rapport à des schémas Pydantic. Chaque valeur extraite est ensuite vérifiée mot pour mot dans le texte source, de sorte que les valeurs altérées ou inventées sont signalées.
  • Rapprochement inter-documents. Factures, bons de livraison et commandes sont comparés ligne à ligne à l’aide de tolérances nommées et de règles de dominance. Par exemple, un montant de ligne concordant peut l’emporter sur un écart de prix.
  • Provenance. Chaque atome porté comporte un en-tête Provenance: et une entrée qui le relie à repo@commit:path:lines dans le code de production d’origine. Les bogues découverts lors du portage ont été corrigés, et chaque correction est couverte par un test de non-régression.
  • Architecture contrôlée. Le découpage en couches est vérifié par 30 contrats d’import : un atome n’importe que le paquet core. Un typage strict, un seuil de couverture ≥ 80 % et une vérification de l’absence de noms de clients dans le code source sont également imposés.
  • Abstraction du matériel. Les atomes de vision et d’audio ciblent cuda, mps ou cpu via un seul paramètre.
  • Évaluation de bout en bout. Les tests s’exécutent avec de vrais moteurs (PaddleOCR, Ollama qwen3:8b et qwen3-vl:8b) sur des données à vérité terrain connue. Chaque métrique est consignée face à un seuil dans un rapport JSON/HTML. Les métriques qui n’atteignent pas leur seuil sont conservées et affichées comme en échec.

Résultats

Base de code (arborescence actuelle) : 459 modules d’atomes répartis en 32 familles, 77 étapes paramétrées, 17 recettes YAML, 30 contrats d’import. La suite collecte 2 959 tests unitaires et de recettes, plus 109 tests de bout en bout exécutés séparément. Les 17 recettes disposent toutes d’au moins un test de bout en bout, et 34 des 35 éléments de l’Atlas sont testés de bout en bout.

Scores de bout en bout sélectionnés (documents synthétiques à vérité terrain connue, modèles 8B locaux) :

TâcheMoteurMesure
Rapprochement facture + bon de livraison / commandeqwen3:8btypes de documents et champs 14/14 ; écarts attendus 5/5 ; 0 faux écart sur le cas conforme
Extraction JSON par LLM (4 factures natives)qwen3:8bJSON valide 4/4 ; champs exacts 28/28 ; toutes les valeurs volontairement altérées détectées par l’ancrage
OCR sur une étiquette photographiéePaddleOCRrappel des mots 0,94 sur la photo brute ; un défaut de rehaussement du contraste (0,65–0,71) a été identifié et corrigé (0,88–0,94)
Reconstruction de tableaux à partir de l’OCRPaddleOCR100 % de cellules exactes (police proportionnelle), 95 % (chasse fixe)

Limites & suite

  • L’ancrage verbatim ne peut pas détecter une valeur présente dans le document mais placée dans le mauvais champ : un champ absent a été rempli à tort dans 1 cas sur 8.
  • Le modèle 8B a jugé un écart de quantité de +50 % comme un écart « mineur », contrairement à la consigne. Les verdicts du LLM sont donc normalisés et maintenus en aval de règles déterministes.
  • Les scores proviennent principalement de données synthétiques. Un jeu de test sur documents réels est en cours de constitution en dehors du dépôt, et seuls les cas ayant fait l’objet d’une revue sont notés.
  • Prochaines étapes : mesurer le taux de rapprochement automatique et le taux de faux positifs sur des données de production.

Stack technique

Python · Pydantic · PyYAML · PaddleOCR · Ollama (qwen3:8b, qwen3-vl:8b) · Mistral / Anthropic / OpenAI APIs · pytest · mypy · import-linter · ruff