Picarones / docs /reference /specification.md
Claude
chore(versioning): reposition project as 0.9.0 (pre-1.0)
416bee1 unverified

Picarones — Spécifications fonctionnelles et techniques

Plateforme de banc d'essai d'OCR / HTR / VLM et de pipelines de post-correction pour documents patrimoniaux.

Version 0.9.0 (pré-1.0) — Mai 2026. Politique de versionning : ../explanation/versioning.md.

Itération de spec 2 (révision éditoriale du document, distincte du numéro de version du logiciel ; mai 2026).

Note de lecture : ce document décrit ce que Picarones fait aujourd'hui, dans la version 0.9.0. Pour les non-fonctionnalités assumées (ce que Picarones ne fait pas et ne fera pas dans la lignée 0.x — par exemple la recommandation prescriptive, l'export PDF, les adapters Kraken/AWS Textract), voir la section §10.

Pour la cartographie technique du code et les règles de contribution interne, voir CLAUDE.md. Ce document reste tourné « public » (vocabulaire bibliothécaire, exemples patrimoniaux). Les deux documents sont complémentaires, pas redondants.


Table des matières

  1. Vision et positionnement
  2. Architecture en 8 couches concentriques
  3. Module 1 — Corpus et imports
  4. Module 2 — Adaptateurs OCR / HTR
  5. Module 3 — Pipelines OCR+LLM et pipelines composables
  6. Module 4 — Métriques et analyses
  7. Module 5 — Rapport HTML interactif
  8. Module 6 — Interface web et CLI
  9. Reproductibilité et sécurité
  10. Limites assumées et non-fonctionnalités
  11. Roadmap d'évolution
  12. Migration v1 → v2 — annexe historique

1. Vision et positionnement

1.1 Problématique

Les équipes OCR/HTR travaillant sur des fonds patrimoniaux (manuscrits, imprimés anciens, archives) disposent d'un paysage hétérogène — moteurs locaux (Tesseract, Pero OCR), services cloud (Mistral OCR, Google Vision, Azure Document Intelligence), modèles fine-tunés maison, VLMs (GPT-4o, Claude, Mistral Large) — sans outil unifié pour les comparer rigoureusement sur leurs propres corpus.

Les outils existants (ocrevalUAtion, dinglehopper) sont soit obsolètes, soit limités au CER/WER, soit non adaptés aux spécificités des documents historiques : glyphes anciens, ligatures, abréviations, graphies variables, pathologies d'image, ordre de lecture multi-colonnes, structure ALTO/PAGE.

À cela s'ajoute une question de recherche émergente : est-ce qu'une couche de correction par LLM améliore réellement la sortie OCR, de combien, sur quels types d'erreurs, et sans introduire d'over-normalisation moderne ? Aucun outil existant ne permet de tester et mesurer cela rigoureusement.

1.2 Philosophie : un banc d'essai, pas un atelier

Picarones est conçu comme un banc d'essai :

  • L'utilisateur amène son golden dataset annoté (paires image + vérité terrain). Sans VT, pas de benchmark.
  • Picarones exécute les IA candidates et mesure l'écart à la VT.
  • Picarones classe les résultats avec rigueur statistique.
  • Picarones n'arbitre pas le débat éditorial. Il ne dit pas si un moteur diplomatique vaut mieux qu'un moteur modernisant — il rapporte les chiffres et laisse le chercheur, l'archiviste ou le paléographe trancher selon ses critères propres.

Cette philosophie est tenue jusque dans le moteur narratif factuel : chaque phrase de la synthèse en tête du rapport est traçable à un payload de Fact qui provient du JSON d'entrée (garde-fou anti-hallucination prouvé par tests).

1.3 Contributions scientifiques

Au-delà de la simple agrégation de moteurs, Picarones apporte plusieurs briques nouvelles dans l'écosystème OCR/HTR open-source :

  • Registre typé de métriques (Sprint 34) : chaque métrique est enregistrée pour une jonction de types ArtifactType (TEXT/ALTO/PAGE/ENTITIES/READING_ORDER) ; un pipeline composé peut alors calculer automatiquement la métrique adéquate à chaque jonction de son DAG.
  • Interface BaseModule générique (Sprint 33) : OCR, mappeur VLM→ALTO, rewriter ALTO→ALTO, classifieur d'entités texte→entités partagent la même API ; le runner les enchaîne sans privilégier un type particulier.
  • GT multi-niveaux (Sprint 32) : un document peut porter simultanément une vérité terrain texte, ALTO, PAGE, entités, et reading order — chacune calibrée à son niveau d'évaluation.
  • Moteur narratif factuel anti-hallucination (Sprint 19+) : 20+ détecteurs déterministes produisent une synthèse en langage naturel dont chaque chiffre est traçable au payload d'un Fact. Aucune intervention LLM, garde-fou prouvé par test (test_sprint23_anti_hallucination).
  • Test multi-moteurs Friedman + Nemenyi + Critical Difference Diagram (Sprint 18, Demšar 2006) : référence canonique pour la comparaison statistique de classifieurs, transposée à l'OCR.
  • Pareto coût / vitesse / CO₂ (Sprint 20) : positionnement tri-objectifs avec front explicite, table de pricing surchargeable.
  • Métriques philologiques transversales (Sprints 55–60) : six modules couvrant l'imprimé ancien, le médiéval, les archives modernes (XIXᵉ–XXᵉ), avec scores éditoriaux séparés (préservation stricte vs équivalence diplomatique).

1.4 Utilisateurs cibles

Profil Cas d'usage typique
Ingénieur OCR/ML Pipeline programmatique, métriques fines, export JSON, intégration CI/CD via picarones run --fail-if-cer-above
Chargé de numérisation Rapport HTML autonome, comparaison A vs B, lecture du Pareto coût/qualité
Responsable de projet Vue agrégée multi-corpus, analyse coût/bénéfice des APIs cloud, suivi longitudinal SQLite
Chercheur en humanités numériques Métriques philologiques, corpus HTR-United, taxonomie d'erreurs en 10 classes, glossaire contextuel
Paléographe / éditeur critique Diff visuel par document, bascule diplomatique / normalisé, profil philologique séparant strict et expansion
DSI institutionnel Déploiement intranet derrière SSO, RGPD, observabilité (cf. docs/operations/)

2. Architecture en 8 couches concentriques

domain → formats → evaluation → pipeline → adapters → app → reports_v2 → interfaces

Règle de dépendance : les imports vont uniquement de l'extérieur vers l'intérieur (de gauche à droite dans le diagramme). La règle est appliquée par tests/architecture/test_layer_dependencies.py qui parse l'AST de chaque fichier et bloque toute violation au merge.

Note sur le legacy : le projet est en cours de retrait du legacy. Une arborescence historique (picarones/{core,measurements,engines,llm,pipelines, report,modules}) cohabite encore et est en train de disparaître phase par phase. Cf. docs/archive/2026-migration/legacy-retirement-plan.md pour le statut et le calendrier. Tout nouveau code va dans l'arborescence canonique ; les chemins legacy existants sont des shims minimaux destinés à être supprimés.

2.1 picarones/domain/ — types purs

Cercle le plus interne. Stdlib + Pydantic uniquement, aucune I/O, aucun framework, aucun module legacy.

Module Contenu
artifacts.py Artifact, ArtifactType (10 types : IMAGE, RAW_TEXT, CORRECTED_TEXT, ALTO_XML, PAGE_XML, CANONICAL_DOCUMENT, ENTITIES, READING_ORDER, ALIGNMENT, CONFIDENCES)
corpus.py CorpusSpec
documents.py DocumentRef
evaluation_spec.py MetricSpec, EvaluationView, EvaluationSpec
pipeline_spec.py PipelineSpec, PipelineStep, INITIAL_STEP_ID
projection_spec.py ProjectionSpec
provenance.py ProvenanceRecord
run_manifest.py RunManifest
module_protocol.py BaseModule (ABC, voie de retrait au profit de StepExecutor)
facts.py Fact, FactType, FactImportance, DetectorRegistry
errors.py Hiérarchie d'exceptions (PicaronesError, AdapterStepError, …)

2.2 picarones/formats/ — parsing / sérialisation

ALTO 4, PAGE XML, JSON, XML utilitaires. Stdlib + lxml + defusedxml. Pas de logique métier.

2.3 picarones/evaluation/ — métriques et calcul

Cœur de la valeur ajoutée. Stdlib + numpy + scipy + jiwer + spacy + rapidfuzz.

Sous-paquet Contenu
metrics/ ~30 métriques (CER, WER, MUFI, philological, NER, calibration, taxonomy, …)
statistics/ Wilcoxon, Friedman/Nemenyi, bootstrap, Pareto, clustering, CDD
views/, projectors/ EvaluationView (Sprint S13+), projecteurs AltoToText, PageToText, CanonicalToText
corpus.py Document, Corpus, GTLevel, payloads (legacy en cours de retrait)
metric_registry.py, metric_hooks.py, metric_result.py Registres typés + hooks + dataclasses résultats
pipeline.py, pipeline_benchmark.py, pipeline_comparison.py PipelineRunner legacy + orchestration corpus-wide (en cours de convergence vers pipeline.executor)
benchmark_result.py BenchmarkResult, EngineReport, DocumentResult, sérialisation JSON
engines/ OCR engines legacy (BaseOCREngine-based) — temporairement avant suppression complète
_diff_utils.py compute_word_diff, compute_char_diff, diff_stats

2.4 picarones/pipeline/ — orchestration canonique

PipelineExecutor instance-based, StepExecutor Protocol, ExecutionPlan immuable. Cible canonique pour le bench d'axe B (pipelines composées).

2.5 picarones/adapters/ — adapters externes

Adapters OCR / LLM / VLM consommant des libs externes (pytesseract, mistralai, openai, anthropic, google.cloud, azure.*, pero_ocr, ollama). Implémentent StepExecutor.

Sous-paquet Contenu
ocr/ TesseractAdapter, PeroOCRAdapter, MistralOCRAdapter, GoogleVisionAdapter, AzureDocIntelAdapter, PrecomputedAdapter
llm/ BaseLLMAdapter + Mistral / OpenAI / Anthropic / Ollama
vlm/ Adapters VLM (zero-shot OCR via vision-language models)
corpus/ Loaders externes : IIIF, Gallica, HTR-United, HuggingFace
storage/ ArtifactStore, JobStore (S29 + S47)
legacy_engines/, legacy_modules/ Engines + modules legacy BaseModule-based (en cours de retrait, cf. Phase 7.A)

2.6 picarones/app/ — services applicatifs

BenchmarkService, CorpusRunner, RunOrchestrator. Orchestrent les pipelines canoniques sur corpus.

2.7 picarones/reports/ — rendu HTML / JSON / CSV

Rapport final consommant un BenchmarkResult ou RunResult. 22 renderers thématiques + 5 vues (advanced_taxonomy, diagnostics, economics, pipeline, robustness) + ReportGenerator orchestrateur + templates Jinja2 + glossaire bilingue (25 entrées) + i18n FR/EN.

2.8 picarones/interfaces/ — entrées utilisateur

CLI Click, Web FastAPI, IIIF/Gallica/eScriptorium importers exposés en interface.


3. Module 1 — Corpus et imports

3.1 Formats de vérité terrain acceptés

Format Extension Niveau GT Usage typique
Texte brut image.gt.txt TEXT Convention Tesseract, HTR-United
ALTO XML v4 .gt.alto.xml ALTO Standard bibliothèques nationales, eScriptorium export
PAGE XML 2019 .gt.page.xml PAGE Transkribus, OCRopus
Entités nommées .gt.entities.json ENTITIES Format HIPE simplifié
Reading order .gt.reading_order.json READING_ORDER Liste ordonnée de region IDs

Le loader (load_corpus_from_directory) détecte automatiquement chacun de ces niveaux à côté de l'image. Un même document peut porter plusieurs niveaux simultanément (Sprint 32).

3.2 Sources d'import

Local

Import d'un dossier de paires image / GT. Détection automatique du format. Filtrage des fichiers macOS ._*.

IIIF

Import par URL de manifeste IIIF v2 et v3. Compatible Gallica (BnF), Bodleian, BL, Vatican, e-codices, Europeana, et tout entrepôt IIIF-compliant. Sélection par range de canvas.

HuggingFace Datasets

Recherche par filtre langue/script/époque/institution. Datasets patrimoniaux pré-référencés (IAM, RIMES, READ-BAD, Esposalles, HTR-United datasets). Statut : module extras/importers/huggingface.py marqué expérimental (UserWarning à l'import).

HTR-United

Listing du catalogue distant + import direct. Lecture des métadonnées (langue, script, institution, époque). En cas d'échec réseau ou parsing, fallback sur catalogue de démo + émission d'un Fact IMPORTER_FALLBACK_TRIGGERED (Sprint A3).

Gallica (API BnF)

Recherche par cote, titre, auteur, date. Récupération des images via API IIIF Gallica.

eScriptorium

Connexion à une instance distante via API. Statut expérimental.

Upload ZIP via navigateur

Endpoint POST /api/corpus/upload. Validation Pillow (décompression bombs), zip-slip prévenu, taille plafonnée (PICARONES_MAX_UPLOAD_MB).

3.3 Gestion des corpus

  • Corpus nommés et versionnés avec métadonnées descriptives.
  • Tags : type de script, langue, siècle, institution, état de conservation.
  • Stratification par script_type (Sprint 45-46) — vue stratifiée dans le rapport, détecteur narratif STRATIFICATION_RECOMMENDED qui invite l'utilisateur quand le corpus est hétérogène.

4. Module 2 — Adaptateurs OCR / HTR

4.1 Architecture des adaptateurs

Chaque moteur OCR est une classe Python qui hérite de BaseOCREngine (picarones/adapters/legacy_engines/base.py), elle-même héritière de BaseModule (Sprint 33). Une instance déclare son execution_mode ("io" ou "cpu") que le runner utilise pour choisir entre ThreadPoolExecutor (cloud APIs) et ProcessPoolExecutor (Tesseract, Pero).

Ajouter un nouveau moteur = créer une classe Python de ~50 lignes qui implémente _run_ocr(image_path) -> str et déclare son execution_mode.

4.2 Moteurs OCR livrés

Moteur Type Mode d'exécution Confidence native exposée ?
Tesseract 5 Local CLI CPU (ProcessPool) ✅ Sprint 47 (image_to_data)
Pero OCR Local Python CPU (ProcessPool) ✅ Sprint 48 (transcription_confidence ligne)
Mistral OCR Cloud API IO (ThreadPool) ✅ Sprint 49 (quand disponible côté API)
Google Vision Cloud API IO (ThreadPool) ✅ Sprint 50 (Word.confidence en mode DOCUMENT_TEXT_DETECTION)
Azure Doc Intelligence Cloud API IO (ThreadPool) ✅ Sprint 51 (Word.confidence)

Quand un moteur expose ses confidences natives, le runner calcule automatiquement les métriques de calibration (ECE, MCE, reliability diagram — Sprint 39-43).

4.3 Robustesse runtime

  • Erreurs HTTP cloud (4xx/5xx, timeout, body mal formé) : remontées dans EngineResult.error avec le code HTTP, jamais avalées silencieusement (Sprint A5 / m-10, 19 cas testés).
  • Crash isolé d'un document : le runner continue avec les autres documents. Le doc en échec a engine_error rempli.
  • Cancel mid-run : cancel_event.set() interrompt proprement.
  • Timeout par document : configurable via paramètre timeout_seconds.

5. Module 3 — Pipelines OCR+LLM et pipelines composables

5.1 Pipelines OCR+LLM historiques (Sprint 3+)

L'unité de comparaison est le concurrent — pas forcément un moteur seul, mais une chaîne produisant du texte à partir d'une image.

Mode Description Usage typique
zero_shot Le LLM/VLM reçoit l'image directement et transcrit Test si GPT-4o ou Claude peut remplacer un OCR sur des documents anciens
post_correction_texte OCR → texte brut → LLM corrige le texte LLM non multimodal (Llama local), grand volume
post_correction_image_texte OCR → LLM reçoit image ET texte brut Meilleure qualité ; le LLM voit le contexte visuel

Les prompts sont versionnés dans picarones/prompts/ (8 fichiers FR + EN), embarqués dans le snapshot du rapport pour reproductibilité.

5.2 Pipelines composables (Sprint 63+)

Au-delà des 3 modes historiques, Picarones livre une infrastructure générique : un pipeline est une liste d'étapes BaseModule qui produit un artefact à chaque étape (TEXT, ALTO, PAGE, ENTITIES…) ; à chaque jonction, le runner calcule automatiquement la métrique adéquate via compute_at_junction (registre typé Sprint 34).

# Spec YAML chargée par picarones pipeline run
name: ocr_then_corrector
steps:
  - name: ocr
    module: picarones.engines.tesseract.TesseractEngine
    args: { lang: "fra", psm: 6 }
  - name: post_correction
    module: my_module.MyLLMCorrector
    args: { model: "gpt-4o" }

picarones pipeline compare specs.yaml --corpus ./scans --output rapport.html exécute N pipelines sur le même corpus et produit un rapport comparatif. Conçu pour qu'un mainteneur tiers puisse contribuer ses propres modules sans toucher au cœur de Picarones (cf. docs/developer/module-policy.md, Sprint 97).

5.3 Détection d'over-normalisation LLM

Risque spécifique aux pipelines OCR+LLM : le LLM modernise à tort des graphies historiques légitimes. Picarones mesure :

  • Modernisation lexicale (Sprint 80) : top-N tokens GT systématiquement remplacés (maistre → maître dans 100 % des cas → signal exploitable).
  • Score d'absorption d'erreur (Sprint 94) : à chaque jonction OCR→LLM, calcule le taux de correction (parmi les erreurs avant, combien corrigées) et le taux d'introduction (parmi les erreurs après, combien nouvelles). Distingue un module qui corrige d'un module qui écrase.
  • Delta Flesch (Sprint 52) : sur les langues prises en charge, signale les LLM qui rendent le texte « trop moderne » par rapport à la GT.
  • Score d'ancrage (Sprint 10) : proportion des trigrammes produits par le LLM qui s'ancrent dans la GT — score bas = hallucination probable.

6. Module 4 — Métriques et analyses

6.1 Catalogue exhaustif des métriques

Picarones livre plus de 30 métriques organisées en familles. Pour chaque métrique : son nom, sa jonction de types, sa source, ses limites — voir le glossaire contextuel intégré au rapport HTML (25 entrées bilingues, ouvre via le ? à côté du nom de colonne) et picarones/report/glossary/{fr,en}.yaml.

Classique OCR/HTR

Métrique Jonction Source primaire
CER (raw, NFC, caseless, diplomatique) (TEXT, TEXT) Levenshtein character / jiwer
WER, MER, WIL (TEXT, TEXT) jiwer
Bootstrap CI 95 % dérivé Efron (1979)
Distribution CER par ligne, Gini dérivé Sprint 10
Détection hallucinations VLM (anchor score, length ratio) dérivé Sprint 10

Philologique (Sprints 52-60, 80, 84-85, 92-94)

Métrique Jonction Cible patrimoniale
Couverture MUFI (TEXT, TEXT) Manuscrits médiévaux
Score d'expansion d'abréviations Capelli (TEXT, TEXT) Médiéval
Précision par bloc Unicode (TEXT, TEXT) Imprimés anciens / médiéval
Préservation des marqueurs typographiques de l'imprimé ancien (long-s, ligatures, tildes nasaux) (TEXT, TEXT) XVIᵉ-XVIIIᵉ
Marqueurs des archives modernes (titres, ordinaux, monnaies, état civil…) (TEXT, TEXT) XIXᵉ-XXᵉ
Préservation des numéraux romains (5 statuts) (TEXT, TEXT) Toutes périodes
Recherchabilité fuzzy (Levenshtein distance ≤ 2) (TEXT, TEXT) Indexation Elastic / full-text
Précision sur séquences numériques (dates, foliotation, monnaies) (TEXT, TEXT) Archives, économie historique
Modernisation lexicale (top-N tokens GT modernisés) (TEXT, TEXT) Pipelines OCR+LLM
Delta Flesch (FR + EN) (TEXT, TEXT) Repère VLM hallucinant du français moderne
Score d'absorption d'erreur par jonction (TEXT, TEXT) Pipelines composées
Précision sur entités nommées (HIPE) (ENTITIES, ENTITIES) Indexation prosopographique
Reading order F1 (ICDAR 2015) (READING_ORDER, READING_ORDER) Manuscrits glosés, journaux multi-colonnes
Layout F1 par type de région (IoU 0.5) (ALTO, ALTO) Texte/glose/marginalia

Comparaison & décision (Sprints 18, 20, 35-37, 81, 89-92, 96)

Métrique Source primaire
Test multi-moteurs Friedman + post-hoc Nemenyi + CDD Demšar (2006)
Test pairé Wilcoxon Wilcoxon (1945)
Pareto coût / vitesse / CO₂ (multi-objectifs N dim) Pareto (1896)
Divergence taxonomique inter-moteurs (Jensen-Shannon) Lin (1991)
Oracle complementarity (recall borné supérieur) Sprint 35
Score de spécialisation inter-moteurs Sprint 89
Stabilité multi-runs (CV CER, accord identique) Sprint 83
Accord inter-annotateurs (Cohen κ, Krippendorff α) Cohen (1960), Krippendorff (1970)
Tendance longitudinale + change-point Pettitt Sprint 92
Throughput effectif (pages/h après correction humaine 5s/erreur) Sprint 91, HTR-United
Coût marginal par erreur évitée Sprint 91
Comparaison incrémentale ANOVA-like par slot Sprint 96

Note de traçabilité : les références primaires (Demšar 2006, Wilcoxon 1945, Efron 1979, etc.) sont citées dans les docstrings de chaque fonction de picarones/measurements/statistics/. Le glossaire contextuel relie chaque métrique à sa publication canonique (champ reference).

6.2 Profils de normalisation

11 profils livrés (picarones/formats/text/normalization.py, exposés via /api/normalization/profiles) : nfc, caseless, minimal, medieval_french, early_modern_french, medieval_latin, medieval_english, early_modern_english, secretary_hand, sans_ponctuation, sans_apostrophes.

Chaque profil applique un ensemble d'équivalences diplomatiques (ſ=s, u=v, i=j, ꝑ=per, þ=th, etc.). Un profil custom peut être chargé depuis YAML.

Traçabilité aux standards éditoriaux (MUFI v4.0, TEI P5 Unicode chapter 3.4, DEAF) : prévue Sprint A12 (item B-6 du plan de remédiation institutionnelle).

6.3 Taxonomie des erreurs en 10 classes

Catégorisation automatique de chaque erreur (Sprint 5) :

  1. Confusion visuelle (rn/m, l/1, O/0, u/n…)
  2. Erreur diacritique
  3. Erreur de casse
  4. Ligature non résolue
  5. Abréviation non développée
  6. Hapax (mot absent du lexique)
  7. Segmentation (fusion / fragmentation)
  8. Hors-vocabulaire
  9. Lacune (texte présent en GT, absent en OCR)
  10. Sur-normalisation LLM

6.4 Score de difficulté intrinsèque

Indicateur calculé indépendamment des moteurs (Sprint 7) :

  • variance du CER entre tous les concurrents (si tous ratent → document objectivement difficile),
  • métriques de qualité image,
  • densité de caractères spéciaux (ligatures, abréviations, diacritiques),
  • longueur et densité du texte.

Sépare deux questions distinctes : « est-ce que ce moteur est mauvais ? » vs « est-ce que ce document est objectivement difficile ? ».


7. Module 5 — Rapport HTML interactif

Le rapport est un fichier HTML auto-portant (Jinja2 server-side, Chart.js vendoré inline), lisible hors-ligne, embarquant toutes les données et visualisations.

7.1 Cinq vues + sections globales

Sections globales (en tête)

  • Synthèse narrative factuelle (Sprint 19+) : 3-5 phrases produites par 20+ détecteurs déterministes. Chaque chiffre rendu est traçable au payload du Fact correspondant (anti-hallucination prouvé par test).
  • Critical Difference Diagram (Sprint 18) : SVG server-side, Friedman + post-hoc Nemenyi.
  • Section inter-moteurs (Sprint 37) : matrice de divergence taxonomique + encart oracle complementarity.
  • Front Pareto (Sprint 20) : coût / vitesse / CO₂ avec toggles d'axes.
  • Section leviers d'amélioration (Sprint 51-82) : 5 leviers factuels (taxonomie récupérable, concentration Pareto, complémentarité, modernisation lexicale, déficit projeté de robustesse).

Vue Classement (Ranking)

Tableau triable : CER (médiane par défaut depuis Sprint 44), WER, MER, WIL, scores ligatures et diacritiques, Gini, score d'ancrage, sur-normalisation, etc. Vue stratifiée optionnelle par script_type (Sprint 45-46).

Vue Galerie (Gallery)

Grille de vignettes avec badge CER coloré. Filtres dynamiques (CER > X, qualité image, type de script, longueur GT). Tri multi-critères. Vue « Worst lines globale » (Sprint 72) qui transcende les documents et liste les lignes individuelles les plus mal transcrites.

Vue Document

Image originale + diff token coloré façon GitHub par moteur, scroll synchronisé N-way. Vue spécifique OCR+LLM : triple diff GT / sortie OCR brute / sortie après LLM.

Vue Analyses

Distribution CER (histogramme + densité), scatter plots qualité image vs CER, heatmap de confusion de caractères, diagrammes de fiabilité (calibration ECE/MCE — Sprint 43), graphiques de bootstrap CI 95 %, profil philologique par moteur (Sprint 62), throughput effectif (Sprint 91), tendances longitudinales (Sprint 92), DAG de pipeline composée (Sprint 95), etc.

Vue Caractères

Matrice de confusion Unicode interactive, tableau des caractères les plus souvent manqués par chaque moteur, CER par bloc Unicode (Sprint 55), analyse des ligatures.

7.2 Panneaux latéraux

  • Glossaire contextuel (Sprint 21) : ? à côté de chaque en-tête de colonne ; clic ouvre un panneau avec définition, ce qu'on mesure, usage, limites, référence primaire (25 entrées bilingues).
  • Mode avancé (Sprint 21) : choix de colonnes visibles, filtres par strate, opt-in score composite personnel (curseurs à 0 par défaut, formule visible, warning explicite « il n'existe pas de pondération universellement valide »), toggle palette daltonien-friendly (Sprint A7), URL stateful.

7.3 Exports

Format Statut
HTML autonome ✅ Livré
CSV (vue courante avec filtres) ✅ Livré
JSON (BenchmarkResult complet) ✅ Livré
Snapshot reproductibilité (versions, commit, lock) ✅ Sprint 27
Lazy images (rapport HTML + dossier report-assets/) ✅ Sprint A5 / M-16
PDF ❌ Non livré (cf. §10)
ALTO XML / PAGE XML / images annotées ❌ Non livré (cf. §10)

7.4 Accessibilité

Conformité WCAG 2.1 niveau AA (cf. docs/operations/accessibility.md) :

  • Skip-to-content link (WCAG 2.4.1).
  • role="img" + aria-label + table de données jumelle pour chaque graphique Chart.js (WCAG 1.1.1).
  • scope="col" sur tous les <th>.
  • Palette par défaut Okabe-Ito (daltonien-friendly), toggle vers l'ancienne palette via panneau Avancé ou ?palette=classic.
  • Bilinguisme intégral (skip-link, ARIA labels, captions des tables jumelles).
  • Audit RGAA externe planifié Sprint A15.

8. Module 6 — Interface web et CLI

8.1 Interface web FastAPI

  • Configuration de benchmark : sélection corpus, moteurs, normalisation.
  • Streaming SSE de la progression en temps réel (Last-Event-ID reconnexion supportée — Sprint 26).
  • Persistance des jobs en SQLite (mode WAL, thread-safe), reprise des jobs orphelins au boot.
  • Upload ZIP depuis le navigateur.
  • Imports HTR-United / HuggingFace via formulaire.
  • Bilingue FR/EN.
  • Healthcheck minimal /health (Sprint A4 / M-3).
  • Token CSRF (/api/csrf/token) + middleware (Sprint A4 / B-11) activable via PICARONES_CSRF_REQUIRED=1 pour les déploiements institutionnels derrière SSO.

8.2 Interface en ligne de commande (Click)

15 commandes :

picarones run         # benchmark
picarones report      # rapport HTML depuis JSON
picarones demo        # rapport démo synthétique
picarones compare     # compare deux runs JSON, exit-code 2 si régression
picarones diagnose    # workflow bench + leviers + recommandations factuelles
picarones economics   # workflow bench + throughput + coût projeté
picarones edition     # workflow bench + métriques philologiques
picarones pipeline    # run/compare pipelines composées YAML
picarones import      # IIIF / HF / HTR-United
picarones serve       # interface web locale
picarones history     # historique longitudinal SQLite
picarones robustness  # courbes CER vs dégradation
picarones engines     # liste les moteurs disponibles
picarones metrics     # CER/WER entre deux fichiers texte
picarones info        # version + system info

Toutes les commandes supportent --help. Workflows pré-câblés (diagnose, economics, edition) sont des combinaisons canoniques pour les profils utilisateurs typiques.

8.3 Intégration CI/CD

  • Mode headless (--no-progress).
  • Output JSON machine-readable.
  • Exit code 2 sur picarones compare si régression CER détectée.
  • Workflow GitHub Actions perf_regression.yml (Sprint A5 / M-14) — cron hebdomadaire + sur PR touchant le runner.

9. Reproductibilité et sécurité

9.1 Snapshots de reproductibilité (Sprint 27)

Chaque rapport HTML embarque un dict report_data["snapshots"] qui contient :

  • pricing — YAML brut intégral de picarones/data/pricing.yaml utilisé.
  • glossary — entrées du glossaire effectivement référencées.
  • normalization — profil sérialisé.
  • environment — version Picarones, Python, plateforme, commit git, paquets installés (top 200).

Procédure complète de re-jeu d'un benchmark à 5 ans d'écart : docs/reference/reproducibility-snapshots.md (Sprint A8 / M-12).

9.2 Reproductibilité des builds

  • Lock files requirements.lock + requirements-dev.lock générés via uv pip compile (Sprint A8).
  • Image Docker épinglée à un patch précis via ARG PYTHON_BASE_IMAGE (rotation trimestrielle).
  • Release pipeline GitHub Actions (Sprint A9) : tag v*.*.* → PyPI via OIDC trust + ghcr.io multi-arch + GitHub Release auto.

9.3 Sécurité institutionnelle

  • Mode public (PICARONES_PUBLIC_MODE=1) : refuse les moteurs cloud mutualisés et les pipelines LLM facturés à la clef serveur.
  • CSRF double-submit (PICARONES_CSRF_REQUIRED=1) — Sprint A4.
  • XML défendu par defusedxml partout (XXE / Billion Laughs).
  • Zip-slip prévenu par Path(member.filename).name.
  • Validation Pillow systématique (CVE bombes de décompression).
  • Rate limiting par IP + sémaphore de jobs concurrents.
  • CSP + en-têtes durcis (X-Content-Type-Options, Referrer-Policy).

Voir SECURITY.md pour la procédure complète.

9.4 RGPD et rétention

Politique documentée dans docs/operations/data-retention-rgpd.md (Sprint A11 / M-8). Purge automatique des uploads anciens configurable via PICARONES_UPLOAD_RETENTION_DAYS=7 par défaut.


10. Limites assumées et non-fonctionnalités

Cette section décrit explicitement ce que Picarones ne fait pas et ne fera pas dans la lignée 0.x. Plusieurs items étaient promis dans une itération antérieure de cette spec (SPECS v1, mars 2025) — leur abandon est un choix éditorial documenté ci-dessous, pas un oubli. Les mentions « v1.0 », « v1.1 », « v1.2 » dans les items ci-dessous renvoient à la roadmap historique de cette spec, pas à des versions logicielles publiées.

Toutes les fonctionnalités listées ci-dessous étaient promises ou évoquées dans SPECS v1 (itération de spec) et sont explicitement abandonnées, non implémentées ou reportées dans l'itération de spec actuelle (qui couvre le logiciel 0.9.0). Le test tests/docs/test_specs_consistency.py détecte cette section comme la déclaration officielle des non-fonctionnalités du projet.

10.1 Adapters OCR non livrés

  • Kraken : prévu v1.0 dans SPECS v1, jamais implémenté. Choix : ouverture en plugins externes via la politique de modules contribués (Sprint 97), pas un adapter intégré au cœur. Un utilisateur peut écrire son KrakenEngine(BaseOCREngine) et l'exécuter via les pipelines composables.
  • AWS Textract : prévu v1.1, abandonné. Pas de DPA Amazon signé, et le périmètre patrimonial est mieux servi par les trois clouds déjà intégrés (Mistral OCR, Google Vision, Azure DI).
  • Calamari : prévu v1.1, abandonné. Maintenance d'un adapter par moteur ≈ 50 PJ/an ; mieux vaut concentrer sur les 5 adapters livrés et ouvrir Calamari en plugin externe.
  • OCRopus4 : prévu v1.2, abandonné — projet historique en fin de vie.
  • Moteur custom YAML (type: cli / type: api) : prévu en SPECS v1.0, abandonné. Refondu en pipelines composables (Sprint 63-70) qui permettent de brancher n'importe quel module via une spec YAML — plus puissant que la déclaration d'engine custom imaginée à l'origine.

10.2 Exports non livrés

  • Export PDF du rapport. CSV + JSON + HTML autonome couvrent les usages observés. Reportable sur demande utilisateur si besoin tracé.
  • Export ALTO XML des sorties OCR.
  • Export PAGE XML des sorties OCR.
  • Export images annotées (PNG avec zones d'erreur surlignées).

10.3 Fonctionnalités explicitement abandonnées

  • Recommandation automatique « quel concurrent pour quel usage ». Promise dans SPECS v1 §7.1, abandonnée au profit du moteur narratif factuel (Sprint 19) et de la philosophie « Picarones mesure et classe — il ne tranche pas ». Les leviers d'amélioration (Sprint 51-82) restent factuels.
  • Score de consensus / vote majoritaire / ensemble : Picarones livre l'oracle borné supérieur (Sprint 35) et le score de spécialisation inter-moteurs (Sprint 89) — observations factuelles. Pas de mécanisme de vote actif intégré ; au chercheur de combiner les sorties s'il le décide.
  • Clustering automatique k-means des erreurs. Remplacé par la taxonomie discrète (Sprint 5) + co-occurrence Jaccard (Sprint 75) + heatmap intra-doc (Sprint 76).
  • Annotations inline du paléographe exportées en JSON. Non implémentées.
  • Badge SVG de qualité OCR pour CI. picarones compare avec exit code 2 sur régression couvre l'usage CI ; un badge SVG reste nice-to-have, non priorisé.
  • Dataset de référence embarqué de 100 documents patrimoniaux. Picarones est volontairement un banc d'essai sur votre golden dataset — le 100-doc corpus de référence imaginé en SPECS v1 §3.3 entrerait en concurrence avec les corpus institutionnels existants (HTR-United, Esposalles, IAM, RIMES, READ-BAD) et en fragmenterait l'écosystème. Les 5 documents synthétiques de Sprint A5 (tests/fixtures/reference_corpus/) servent uniquement à l'anti-régression CER en CI, pas à la valeur scientifique.

10.4 Fonctionnalités scientifiques planifiées

À livrer dans des sprints futurs :

  • CITATION.cff + DOI Zenodo + papier JOSS (Sprint A12 du plan institutionnel) — débloque la citation académique propre.
  • Traçabilité des profils de normalisation aux standards éditoriaux (MUFI v4.0, TEI P5, DEAF) — Sprint A12.
  • Citations primaires des méthodes statistiques dans les docstrings (Demšar 2006, Wilcoxon 1945, Efron 1979) — Sprint A12.

11. Roadmap d'évolution

Trois documents complémentaires pilotent l'évolution :

  • CHANGELOG.md — historique sprint par sprint, format Keep a Changelog.
  • docs/roadmap/backlog.md — backlog vivant des chantiers post-0.9.0.
  • docs/archive/ — audits institutionnels, plans de remédiation pré-rewrite, roadmap historique (2026-roadmap/evolution.md), changelog pré-rewrite.

L'état du plan institutionnel au 2 mai 2026 :

Phase Sprints Statut
Phase 0 — Garde-fous CI A1, A2 ✅ Terminée
Phase 1 — Hygiène architecturale A3 ✅ Terminée
Phase 2 — Robustesse runtime A4, A5 ✅ Terminée
Phase 3 — Accessibilité A6, A7 ✅ Terminée
Phase 4 — Reproductibilité ops A8, A9 ✅ Terminée
Phase 5 — Gouvernance A10, A11 ✅ Terminée
Phase 7 — Refonte doc produit A13, A14 (ce document) ✅ Terminée
Phase 6 — Publication scientifique A12 ⏳ Planifiée
Phase 8 — Validation externe A15 ⏳ Planifiée (calendrier externe)

12. Migration des itérations de spec (v1 → v2) — annexe historique

Cette section trace l'évolution éditoriale du document de spécification entre son itération 1 (SPECS v1, mars 2025) et son itération 2 (le présent document). Les indices « v1.0 », « v1.1 » dans la colonne de gauche désignent la roadmap historique de SPECS v1, pas des versions logicielles publiées. Pour la politique de versionning du logiciel, voir ../explanation/versioning.md.

Pour les lecteurs qui avaient pris connaissance de SPECS v1.0 (mars 2025) ou de l'Addendum Sprints 16-30, voici la table de migration des promesses changées :

SPECS v1 disait SPECS itération 2 documente Raison
Adapter Kraken (priorité v1.0) Ouvert en plugin externe Politique modules contribués Sprint 97 ; concentration sur 5 adapters cœur.
Adapter AWS Textract (v1.1) Abandonné Pas de DPA, périmètre couvert par 3 clouds existants.
Adapter Calamari (v1.1) Abandonné Maintenance par adapter ≈ 50 PJ/an ; mieux servi en plugin externe.
Adapter OCRopus4 (v1.2) Abandonné Projet historique en fin de vie.
Moteur custom YAML Refondu en pipelines composables Sprint 63-70 livre une infrastructure plus puissante.
Recommandation automatique Remplacée par moteur narratif factuel Pivot philosophique vers la neutralité éditoriale.
Export PDF Abandonné CSV + JSON + HTML couvrent les usages.
Export ALTO/PAGE/images annotées Abandonné Idem.
picarones estimate (preview coût) Remplacé par vue Pareto post hoc Sprint 20 livre la même information dans le rapport.
Score consensus / k-means Remplacé par oracle borné + taxonomie discrète + Jaccard Sprint 35, 5, 75 — équivalence fonctionnelle, formalisme différent.
Annotations inline JSON Abandonné Pas de demande utilisateur observée.
Badge SVG qualité OCR Abandonné picarones compare exit code 2 couvre la CI.
Dataset 100 docs embarqué Abandonné Banc d'essai sur votre golden dataset, pas un dataset de référence.
Prompt latin Pas livré Reportable sur demande.

À l'inverse, ~25 modules majeurs ajoutés depuis Sprint 30 sont documentés dans la nouvelle SPECS aux §6 (NER, reading order F1, layout F1, recherchabilité fuzzy, séquences numériques, 6 modules philologiques transversaux, narrative engine, Friedman+Nemenyi+CDD, Pareto, glossaire, métriques inter-moteurs, absorption d'erreur, pipelines composables, registre typé, audit modules, comparaison de runs, stratification, calibration, longitudinal, throughput effectif, etc.) — invisibles dans SPECS v1.


Picarones est conçu pour devenir une référence open-source d'évaluation OCR/HTR dans le champ patrimonial — métriques adaptées aux documents historiques, pipelines composables, intégration des standards bibliothéconomiques (IIIF, ALTO XML, PAGE XML, HTR-United, eScriptorium, Gallica), rapport interactif exportable, snapshot de reproductibilité.

Dernière mise à jour : 23 mai 2026 (repositionnement SemVer pré-1.0, couvre logiciel 0.9.0).