Spaces:
Sleeping
feat(sprint-A14): refonte intégrale de SPECS.md (B-12)
Browse filesSprint A14 — Refonte SPECS.md vers la v2.0 (3 PJ, item B-12).
État avant : SPECS v1.0 (mars 2025 + addendum Sprints 16-30) qui :
- promettait 9 fonctionnalités jamais livrées (Kraken, AWS Textract,
Calamari, OCRopus, moteur custom YAML, export PDF/ALTO/PAGE/images,
picarones estimate, recommandation auto, k-means, annotations
inline, badge SVG, dataset 100 docs, prompt latin) ;
- ignorait ~25 modules majeurs livrés depuis Sprint 30.
État après : 12 sections cohérentes avec le code réel au 2 mai 2026.
Sections principales :
§1 Vision et positionnement — banc d'essai, neutralité éditoriale,
contributions scientifiques (registre typé, BaseModule, narrative
anti-hallucination, Friedman+Nemenyi+CDD, Pareto, philologique).
§2 Architecture en 3 cercles — règle de dépendance enforcée par
tests/core/test_circle_dependencies.py (Sprint A3) ; cartographie
des sous-packages.
§3 Module 1 — Corpus et imports : 5 formats GT (TEXT/ALTO/PAGE/
ENTITIES/READING_ORDER, Sprint 32), 7 sources d'import, gestion
des fallbacks via Fact IMPORTER_FALLBACK_TRIGGERED.
§4 Module 2 — 5 adapters OCR avec confidence native exposée
(Sprints 47-51), execution_mode IO/CPU pour le runner.
§5 Module 3 — 3 modes pipelines OCR+LLM historiques + pipelines
composables YAML (Sprint 63-70) avec compute_at_junction
automatique. Détection over-normalisation : modernisation
lexicale, absorption d'erreur, delta Flesch, anchor score.
§6 Module 4 — catalogue exhaustif des métriques en 3 familles
(classique, philologique, comparaison & décision) avec leur
jonction de types et leur source primaire. ~30 métriques
listées (vs ~10 dans v1).
§7 Module 5 — rapport HTML : 5 vues + sections globales
(synthèse narrative, CDD, inter-engine, Pareto, leviers),
panneaux latéraux (glossaire 25 entrées, mode avancé),
accessibilité WCAG 2.1 AA (Sprint A6/A7).
§8 Module 6 — interface web FastAPI + CLI 15 commandes (incl.
workflows pré-câblés diagnose/economics/edition).
§9 Reproductibilité et sécurité — snapshots Sprint 27, lock files
Sprint A8, release pipeline Sprint A9, mode public + CSRF +
defusedxml + zip-slip + RGPD Sprint A11.
§10 LIMITES ASSUMÉES ET NON-FONCTIONNALITÉS — section centrale
qui liste explicitement les 9 promesses v1 abandonnées avec
leur raison. Marquée par les balises HTML
<!-- specs-check: known-abandoned-{start,end} --> consommées
par le test A2 test_specs_consistency.
§11 Roadmap — pointe CHANGELOG, evolution-2026, audits/.
§12 Migration v1 → v2 — annexe historique : table de migration
ligne par ligne pour les lecteurs qui avaient pris connaissance
de SPECS v1.
Tests :
- tests/docs/test_specs_consistency.py (Sprint A2) : 10/10 verts
avec la nouvelle structure (bloc known-abandoned).
- Aucune régression attendue (changement purement documentaire).
SPECS passe de 761 lignes (v1 + addendum) à 839 lignes (v2) — +10 %
mais couverture 100% du code réel et les non-fonctionnalités sont
explicitement listées.
|
@@ -1,799 +1,850 @@
|
|
| 1 |
-
# Picarones — Spécifications
|
| 2 |
|
| 3 |
-
> **Plateforme de
|
|
|
|
| 4 |
>
|
| 5 |
-
> Version
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
---
|
| 8 |
|
| 9 |
## Table des matières
|
| 10 |
|
| 11 |
-
1. [Vision
|
| 12 |
-
2. [Architecture
|
| 13 |
-
3. [Module 1 —
|
| 14 |
-
4. [Module 2 — Adaptateurs
|
| 15 |
-
5. [Module 3 — Pipelines OCR+LLM](#5-module-3--pipelines-ocrllm)
|
| 16 |
-
6. [Module 4 — Métriques et
|
| 17 |
-
7. [Module 5 — Rapport
|
| 18 |
-
8. [Module 6 — Interface
|
| 19 |
-
9. [
|
| 20 |
-
10. [
|
| 21 |
-
11. [
|
|
|
|
| 22 |
|
| 23 |
---
|
| 24 |
|
| 25 |
-
## 1. Vision
|
| 26 |
|
| 27 |
### 1.1 Problématique
|
| 28 |
|
| 29 |
-
Les équipes OCR/HTR travaillant sur des fonds patrimoniaux
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|---|---|
|
| 49 |
-
| Ingénieur OCR/ML | Pipeline programmatique, métriques fines, export JSON
|
| 50 |
-
| Chargé de numérisation | Rapport
|
| 51 |
-
| Responsable de projet | Vue agrégée
|
| 52 |
-
| Chercheur en humanités numériques | Métriques
|
| 53 |
-
| Paléographe | Diff visuel
|
| 54 |
-
|
| 55 |
-
### 1.4 Proposition de valeur unique
|
| 56 |
-
|
| 57 |
-
Picarones est le seul outil combinant :
|
| 58 |
-
1. **Métriques adaptées aux documents historiques** (glyphes, ligatures, diacritiques, abréviations, normalisation diplomatique)
|
| 59 |
-
2. **Évaluation des pipelines OCR+LLM** avec mesure du delta de qualité
|
| 60 |
-
3. **Intégration native des standards bibliothéconomiques** (IIIF, ALTO, PAGE XML, HTR-United, eScriptorium, Gallica)
|
| 61 |
-
4. **Rapport interactif auto-contenu** exploitable sans compétences techniques
|
| 62 |
|
| 63 |
---
|
| 64 |
|
| 65 |
-
## 2. Architecture
|
| 66 |
-
|
| 67 |
-
### 2.1 Vue d'ensemble
|
| 68 |
|
| 69 |
```
|
| 70 |
-
|
| 71 |
-
│
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
│ ▲ │ │ │
|
| 78 |
-
│ IIIF / Gallica ┌──────▼──────┐ HTML self-contained │
|
| 79 |
-
│ HTR-United │ Moteurs │ Export PDF/CSV/ALTO │
|
| 80 |
-
│ HuggingFace │ OCR │ │
|
| 81 |
-
│ eScriptorium └──────┬──────┘ │
|
| 82 |
-
│ Dossier local │ │
|
| 83 |
-
│ ┌──────▼──────┐ │
|
| 84 |
-
│ │ Couche │ │
|
| 85 |
-
│ │ LLM │ ◀── optionnelle │
|
| 86 |
-
│ │ (optionel) │ │
|
| 87 |
-
│ └─────────────┘ │
|
| 88 |
-
└──────────────────────────────────────────────────────────────────────────┘
|
| 89 |
```
|
| 90 |
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
-
|
| 105 |
-
|
| 106 |
-
-
|
| 107 |
-
|
| 108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
|
| 110 |
---
|
| 111 |
|
| 112 |
-
## 3. Module 1 —
|
| 113 |
|
| 114 |
### 3.1 Formats de vérité terrain acceptés
|
| 115 |
|
| 116 |
-
| Format | Extension | Usage typique |
|
| 117 |
-
|---|---|---|
|
| 118 |
-
| Texte brut
|
| 119 |
-
| ALTO XML | `.alto.xml` | Standard bibliothèques nationales, eScriptorium export |
|
| 120 |
-
| PAGE XML | `.page.xml` | Transkribus, OCRopus |
|
| 121 |
-
|
|
| 122 |
-
|
|
| 123 |
-
| CSV simple | `image,texte_gt` | Exports maison, tableaux Callico |
|
| 124 |
-
|
| 125 |
-
### 3.2 Sources d'import
|
| 126 |
-
|
| 127 |
-
#### 3.2.1 Dossier local
|
| 128 |
-
Import d'un dossier contenant des paires image/GT. Détection automatique du format. Prévisualisation du corpus avant lancement (nombre de documents, longueur moyenne de GT, aperçu des images).
|
| 129 |
-
|
| 130 |
-
#### 3.2.2 Import IIIF — fonctionnalité clé
|
| 131 |
-
|
| 132 |
-
L'intégration IIIF est la fonctionnalité d'import la plus stratégique pour le contexte patrimonial. Elle permet d'accéder directement aux fonds numérisés de toutes les grandes bibliothèques sans téléchargement manuel.
|
| 133 |
-
|
| 134 |
-
- Import par URL de manifeste IIIF v2 et v3
|
| 135 |
-
- Sélection des canvas (pages) via interface de sélection visuelle
|
| 136 |
-
- Récupération des annotations de transcription si le manifeste les contient
|
| 137 |
-
- Compatibilité : Gallica (BnF), Bodleian, BL, BSB, e-codices, Europeana et tout entrepôt IIIF-compliant
|
| 138 |
-
- Résolution configurable des images
|
| 139 |
-
|
| 140 |
-
> **Exemple :** coller l'URL du manifeste Gallica d'un incunable, sélectionner 50 pages, lancer le benchmark. La GT est fournie séparément ou issue d'un export eScriptorium.
|
| 141 |
-
|
| 142 |
-
#### 3.2.3 Import HuggingFace Datasets
|
| 143 |
-
- Recherche et prévisualisation de datasets OCR/HTR
|
| 144 |
-
- Filtrage par langue, type de script, époque, institution
|
| 145 |
-
- Datasets patrimoniaux pré-référencés : IAM, RIMES, READ-BAD, Esposalles, Bozen-Baptism, datasets HTR-United
|
| 146 |
-
- Import partiel : sous-ensemble aléatoire ou filtré
|
| 147 |
-
- Cache local avec gestion des versions
|
| 148 |
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
- Lecture des métadonnées : langue, script, institution, époque, nombre de lignes
|
| 153 |
|
| 154 |
-
###
|
| 155 |
-
- Recherche dans Gallica par cote, titre, auteur, date
|
| 156 |
-
- Récupération des images via API IIIF Gallica
|
| 157 |
-
- Récupération de l'OCR Gallica existant comme moteur de référence ou GT partielle
|
| 158 |
|
| 159 |
-
####
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
|
| 164 |
### 3.3 Gestion des corpus
|
| 165 |
|
| 166 |
-
- Corpus nommés et versionnés avec métadonnées descriptives
|
| 167 |
-
- Tags : type de script
|
| 168 |
-
|
| 169 |
-
-
|
| 170 |
-
|
|
|
|
| 171 |
|
| 172 |
---
|
| 173 |
|
| 174 |
-
## 4. Module 2 — Adaptateurs
|
| 175 |
|
| 176 |
### 4.1 Architecture des adaptateurs
|
| 177 |
|
| 178 |
-
Chaque moteur OCR est
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
|
| 180 |
-
|
|
|
|
|
|
|
| 181 |
|
| 182 |
-
|
| 183 |
-
|---|---|---|---|
|
| 184 |
-
| Tesseract 5 | Local CLI | v1.0 | `pytesseract`, multi-langues, LSTM |
|
| 185 |
-
| Pero OCR | Local Python | v1.0 | Excellent sur documents historiques |
|
| 186 |
-
| Kraken | Local Python | v1.0 | Référence HTR manuscrits, compatible eScriptorium |
|
| 187 |
-
| Mistral OCR | API REST | v1.0 | Mistral OCR 3, multimodal |
|
| 188 |
-
| Google Vision | API REST | v1.1 | Document AI, bonne couverture unicode |
|
| 189 |
-
| AWS Textract | API REST | v1.1 | Détection layout avancée |
|
| 190 |
-
| Azure Document Intelligence | API REST | v1.1 | Anciennement Form Recognizer |
|
| 191 |
-
| Calamari | Local Python | v1.1 | Basé TF, modèles pré-entraînés HTR |
|
| 192 |
-
| OCRopus4 | Local Python | v1.2 | Historique, utile pour comparaison |
|
| 193 |
-
| Moteur custom | CLI/API YAML | v1.0 | Déclaration YAML, aucun code requis |
|
| 194 |
-
|
| 195 |
-
### 4.3 Configuration d'un moteur (YAML)
|
| 196 |
-
|
| 197 |
-
```yaml
|
| 198 |
-
# Moteur custom via CLI
|
| 199 |
-
name: mon_ocr_interne
|
| 200 |
-
type: cli
|
| 201 |
-
command: "mon_ocr {input_image} --output {output_file} --lang fra"
|
| 202 |
-
output_format: txt
|
| 203 |
-
version_command: "mon_ocr --version"
|
| 204 |
-
|
| 205 |
-
# Moteur via API REST
|
| 206 |
-
name: api_ocr_bnf
|
| 207 |
-
type: api
|
| 208 |
-
endpoint: http://localhost:8080/ocr
|
| 209 |
-
method: POST
|
| 210 |
-
image_field: file
|
| 211 |
-
response_path: $.result.text
|
| 212 |
-
```
|
| 213 |
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
|
| 223 |
---
|
| 224 |
|
| 225 |
-
## 5. Module 3 — Pipelines OCR+LLM
|
| 226 |
-
|
| 227 |
-
> Ce module est la fonctionnalité la plus originale de Picarones. Il permet de tester l'apport réel d'une couche de correction LLM sur une sortie OCR, et de comparer des pipelines complets entre eux.
|
| 228 |
|
| 229 |
-
### 5.1
|
| 230 |
|
| 231 |
-
|
|
|
|
|
|
|
| 232 |
|
| 233 |
-
|
|
| 234 |
|---|---|---|
|
| 235 |
-
|
|
| 236 |
-
|
|
| 237 |
-
| OCR → LLM
|
| 238 |
-
| OCR → LLM (image + texte) | Le LLM reçoit image ET sortie OCR | `pero_ocr → gpt-4o` |
|
| 239 |
-
| OCR → LLM → LLM | Chaîne de correction en deux passes | `tesseract → llm1 → llm2` |
|
| 240 |
|
| 241 |
-
|
|
|
|
|
|
|
| 242 |
|
| 243 |
-
### 5.2
|
| 244 |
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
| Gemma / Phi (via Ollama) | Local | texte seul | v1.1 |
|
| 252 |
-
| LLM custom | API REST YAML | configurable | v1.0 |
|
| 253 |
-
|
| 254 |
-
### 5.3 Modes de correction LLM
|
| 255 |
-
|
| 256 |
-
#### Mode 1 — Post-correction texte brut
|
| 257 |
-
Le LLM reçoit uniquement la sortie OCR textuelle et un prompt de correction. Le plus rapide.
|
| 258 |
|
| 259 |
-
```
|
| 260 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 261 |
```
|
| 262 |
|
| 263 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 264 |
|
| 265 |
-
|
| 266 |
-
Le LLM reçoit l'image originale ET la sortie OCR. Permet au LLM de vérifier visuellement les passages ambigus.
|
| 267 |
|
| 268 |
-
|
| 269 |
-
[Image] ──────────────┐
|
| 270 |
-
▼
|
| 271 |
-
[Sortie OCR brute] ──▶ [LLM multimodal + prompt] ──▶ [Texte corrigé]
|
| 272 |
-
```
|
| 273 |
|
| 274 |
-
|
| 275 |
|
| 276 |
-
|
| 277 |
-
|
|
|
|
|
|
|
|
|
|
| 278 |
|
| 279 |
-
|
| 280 |
-
[Image] ──▶ [LLM multimodal + prompt] ──▶ [Transcription]
|
| 281 |
-
```
|
| 282 |
|
| 283 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 284 |
|
| 285 |
-
###
|
| 286 |
|
| 287 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 288 |
|
| 289 |
-
|
| 290 |
-
# Configuration d'un concurrent OCR+LLM
|
| 291 |
-
name: tesseract_gpt4o_correction
|
| 292 |
-
type: pipeline
|
| 293 |
-
steps:
|
| 294 |
-
- engine: tesseract
|
| 295 |
-
config:
|
| 296 |
-
lang: fra
|
| 297 |
-
psm: 6
|
| 298 |
-
- llm: gpt-4o
|
| 299 |
-
mode: text_and_image # text_only | text_and_image | zero_shot
|
| 300 |
-
prompt: prompts/correction_medieval_french.txt
|
| 301 |
-
temperature: 0.0
|
| 302 |
-
max_tokens: 4096
|
| 303 |
-
```
|
| 304 |
|
| 305 |
-
|
| 306 |
-
# prompts/correction_medieval_french.txt
|
| 307 |
-
Tu es un expert en paléographie et en transcription de documents en français médiéval.
|
| 308 |
-
On te fournit la sortie brute d'un moteur OCR et l'image originale du document.
|
| 309 |
-
Ta tâche est de corriger les erreurs de transcription en te basant sur :
|
| 310 |
-
- Le contexte linguistique (français médiéval, XVe siècle)
|
| 311 |
-
- Les confusions visuelles typiques de l'OCR (rn/m, l/1, u/n, ſ/f...)
|
| 312 |
-
- Les abréviations et ligatures médiévales visibles sur l'image
|
| 313 |
-
|
| 314 |
-
Retourne UNIQUEMENT le texte corrigé, sans commentaire ni explication.
|
| 315 |
-
Conserve fidèlement la graphie originale (ne modernise pas l'orthographe).
|
| 316 |
-
|
| 317 |
-
OCR BRUT :
|
| 318 |
-
{ocr_output}
|
| 319 |
-
```
|
| 320 |
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
| 324 |
|
| 325 |
-
###
|
| 326 |
|
| 327 |
-
|
| 328 |
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 336 |
|
| 337 |
-
|
| 338 |
|
| 339 |
-
|
|
|
|
|
|
|
|
|
|
| 340 |
|
| 341 |
-
|
| 342 |
|
| 343 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 344 |
|
| 345 |
-
####
|
| 346 |
-
- CER brut (distance d'édition caractère / longueur GT)
|
| 347 |
-
- CER avec normalisation Unicode NFC
|
| 348 |
-
- CER sans distinction de casse
|
| 349 |
-
- CER diplomatique : avec table de correspondances historiques (ſ=s, u=v, i=j...)
|
| 350 |
-
- CER par ligne : distribution, médiane, percentiles P90/P95
|
| 351 |
-
- Intervalles de confiance à 95% par bootstrap (1000 itérations)
|
| 352 |
|
| 353 |
-
|
| 354 |
-
-
|
| 355 |
-
|
| 356 |
-
- Match Error Rate (MER) et Word Information Lost (WIL)
|
| 357 |
|
| 358 |
-
####
|
| 359 |
-
- Précision et rappel au niveau caractère, mot, ligne
|
| 360 |
-
- F1-score global et par classe de caractère
|
| 361 |
|
| 362 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 363 |
|
| 364 |
-
####
|
| 365 |
-
- **Matrice de confusion unicode** : quels caractères GT sont transcrits par quels caractères OCR — fingerprint de chaque moteur
|
| 366 |
-
- **CER par bloc Unicode** : Latin de Base / Latin Étendu A & B / Diacritiques combinants / Formes de présentation latines
|
| 367 |
-
- **Score ligatures** : fi, fl, ff, ffi, ffl, st, ct, œ, æ, ꝑ, ꝓ...
|
| 368 |
-
- **Score abréviations** : taux de restitution correcte des formes abrégées
|
| 369 |
-
- **Précision diacritiques** : taux de conservation des accents, cédilles, trémas
|
| 370 |
-
- **Précision chiffres romains et arabes** séparément
|
| 371 |
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
- **Conservation des sauts de paragraphe et de section**
|
| 376 |
-
- **Détection des transpositions de blocs**
|
| 377 |
-
- **Score de mise en page** (si bounding boxes disponibles) : IoU entre zones détectées et zones GT
|
| 378 |
|
| 379 |
-
###
|
| 380 |
-
Catégorisation automatique de chaque erreur :
|
| 381 |
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
|
| 387 |
-
|
| 388 |
-
|
| 389 |
-
|
| 390 |
-
|
| 391 |
-
| 8 — Hors-vocabulaire | Caractère absent du modèle du moteur |
|
| 392 |
-
| 9 — Lacune | Zone non transcrite |
|
| 393 |
-
| 10 — Sur-normalisation LLM | Le LLM a modernisé à tort la graphie (spécifique pipelines LLM) |
|
| 394 |
-
|
| 395 |
-
#### Métriques sur entités et contenus critiques
|
| 396 |
-
- Précision sur les entités nommées (NER via spaCy multilingue) : personnes, lieux, dates
|
| 397 |
-
- Précision sur les séquences numériques (foliotation, pagination, montants)
|
| 398 |
-
- Taux de conservation de la ponctuation
|
| 399 |
-
|
| 400 |
-
### 6.3 Analyse qualité image et corrélations
|
| 401 |
-
|
| 402 |
-
#### Métriques de qualité image automatiques
|
| 403 |
-
- Score de netteté (variance du Laplacien)
|
| 404 |
-
- Niveau de bruit (écart-type sur région homogène)
|
| 405 |
-
- Détection du biais/rotation résiduel (transformée de Hough)
|
| 406 |
-
- Score de contraste (ratio Michelson encre/fond)
|
| 407 |
-
- Détection du show-through (transparence verso)
|
| 408 |
-
- Score de déformation géométrique (courbure de page)
|
| 409 |
-
- Détection des dégradations chimiques (taches, foxing)
|
| 410 |
-
|
| 411 |
-
#### Corrélations image ↔ performance
|
| 412 |
-
- Scatter plots interactifs : qualité image (X) vs CER (Y) par concurrent
|
| 413 |
-
- Corrélation de Pearson et Spearman, avec test de significativité
|
| 414 |
-
- Identification des concurrents robustes aux dégradations vs sensibles
|
| 415 |
-
- Segmentation du corpus en terciles qualité (bonne/moyenne/mauvaise)
|
| 416 |
-
|
| 417 |
-
### 6.4 Analyses statistiques et agrégées
|
| 418 |
-
|
| 419 |
-
#### Score de difficulté intrinsèque
|
| 420 |
-
Indicateur calculé indépendamment des moteurs, combinant :
|
| 421 |
-
- Variance du CER entre tous les concurrents (si tous ratent → document difficile)
|
| 422 |
-
- Métriques de qualité image
|
| 423 |
-
- Densité de caractères spéciaux (ligatures, abréviations, diacritiques)
|
| 424 |
-
- Longueur des lignes et densité du texte
|
| 425 |
-
|
| 426 |
-
**Valeur :** séparer deux questions distinctes — *est-ce que ce moteur est mauvais ?* vs *est-ce que ce document est objectivement difficile ?*
|
| 427 |
-
|
| 428 |
-
#### Tests statistiques
|
| 429 |
-
- Test de Wilcoxon (non-paramétrique) pour comparer deux concurrents
|
| 430 |
-
- Correction de Bonferroni pour comparaisons multiples (>2 concurrents)
|
| 431 |
-
- Intervalles de confiance à 95% par bootstrap sur toutes les métriques
|
| 432 |
-
- Test de Student apparié pour grands corpus
|
| 433 |
-
|
| 434 |
-
#### Analyse des séquences et clustering
|
| 435 |
-
- Longueur moyenne des séquences correctes entre deux erreurs
|
| 436 |
-
- Distribution des longueurs d'erreurs (erreurs isolées vs blocs)
|
| 437 |
-
- Clustering automatique des patterns d'erreurs (k-means) avec exemples représentatifs
|
| 438 |
-
- Export des clusters pour cibler le fine-tuning
|
| 439 |
-
|
| 440 |
-
#### Analyse inter-concurrents
|
| 441 |
-
- Score de consensus : vote majoritaire, souvent meilleur que n'importe quel moteur seul
|
| 442 |
-
- Carte d'accord : zones de consensus vs désaccord sur le corpus
|
| 443 |
-
- Complémentarité : quels concurrents ont des erreurs différentes (bons candidats pour ensemble) ?
|
| 444 |
-
- Analyse de dominance : pour quels types de documents le concurrent A bat-il systématiquement B ?
|
| 445 |
|
| 446 |
-
|
| 447 |
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
Le rapport est un **fichier HTML unique auto-contenu**, lisible hors-ligne, embarquant toutes les données et visualisations. C'est la livrable principale de Picarones.
|
| 451 |
-
|
| 452 |
-
### 7.1 Structure du rapport
|
| 453 |
-
|
| 454 |
-
#### Page d'accueil — Tableau de bord exécutif
|
| 455 |
-
- Résumé de l'expérience : concurrents testés, corpus, date, paramètres de normalisation
|
| 456 |
-
- **Tableau de classement** des concurrents : CER, WER, score ligatures, score diacritiques — trié par colonne au clic
|
| 457 |
-
- **Graphique radar (spider chart)** : CER / WER / Précision diacritiques / Précision ligatures / Score mise en page — snapshot visuel des forces/faiblesses
|
| 458 |
-
- Histogrammes de distribution CER côte-à-côte
|
| 459 |
-
- Alertes : concurrents avec CER > seuil, tests statistiques non-significatifs
|
| 460 |
-
- Recommandation automatique : quel concurrent pour quel usage (manuscrits anciens, imprimés, grand volume...)
|
| 461 |
-
|
| 462 |
-
#### Vue Galerie — exploration du corpus
|
| 463 |
-
- Toutes les images en grille de vignettes avec badge CER par concurrent (code couleur vert→rouge)
|
| 464 |
-
- Filtres dynamiques : CER > X%, score qualité image, type de script, longueur GT, concurrent gagnant
|
| 465 |
-
- Tri multi-critères : CER, difficulté intrinsèque, longueur, date
|
| 466 |
-
- Vue **"Worst cases"** : top N documents les plus difficiles par concurrent, avec explication automatique
|
| 467 |
-
- Vue **"Consensus"** : documents où tous les concurrents s'accordent — les plus fiables
|
| 468 |
-
- Vue **"LLM gagne"** / **"LLM dégrade"** : documents où la couche LLM améliore vs détériore la sortie OCR
|
| 469 |
-
|
| 470 |
-
#### Vue Document — analyse détaillée
|
| 471 |
-
- Image originale zoomable (panneau gauche) avec superposition des zones en erreur si bounding boxes disponibles
|
| 472 |
-
- **Affichage N-way synchronisé** : GT + sortie de chaque concurrent en colonnes parallèles avec scroll synchronisé
|
| 473 |
-
- **Diff token coloré** façon GitHub : insertions (vert), suppressions (rouge), substitutions (orange)
|
| 474 |
-
- **Diff aligné sur l'image** : surlignage de la zone correspondante au survol d'une erreur (si bounding boxes)
|
| 475 |
-
- Bascule **"Diplomatique / Normalisé"** : diff exact vs diff avec normalisation configurée
|
| 476 |
-
- **Vue spécifique OCR+LLM** : trois colonnes — GT / Sortie OCR brute / Sortie après correction LLM — avec double diff pour voir exactement ce que le LLM a modifié
|
| 477 |
-
- Détail des métriques pour ce document
|
| 478 |
-
|
| 479 |
-
#### Vue Analyse — graphiques et statistiques
|
| 480 |
-
- Distribution complète des CER (histogramme + courbe de densité)
|
| 481 |
-
- Scatter plots interactifs : qualité image vs CER, colorés par type de script
|
| 482 |
-
- Courbes de fiabilité : pour les X% documents les plus faciles, quel CER ?
|
| 483 |
-
- **Heatmap de confusion de caractères** : cliquable — cliquer affiche tous les exemples
|
| 484 |
-
- Diagramme de Venn des erreurs (communes et exclusives entre concurrents)
|
| 485 |
-
- Visualisation des clusters d'erreurs avec exemples représentatifs
|
| 486 |
-
- Matrices de corrélation entre toutes les métriques
|
| 487 |
-
- Graphiques de significativité (p-values des tests de Wilcoxon)
|
| 488 |
-
- Analyse temporelle si métadonnées de date disponibles
|
| 489 |
-
|
| 490 |
-
#### Vue Caractères — analyse unicode
|
| 491 |
-
- Matrice de confusion unicode interactive, colorée par fréquence
|
| 492 |
-
- Tableau des caractères les plus souvent manqués par chaque concurrent
|
| 493 |
-
- CER par bloc unicode en diagramme à barres groupées
|
| 494 |
-
- Analyse des ligatures : taux de reconnaissance par ligature
|
| 495 |
-
- Caractères absents du vocabulaire d'un moteur
|
| 496 |
-
|
| 497 |
-
|
| 498 |
-
### 7.2 Fonctionnalités transversales
|
| 499 |
-
|
| 500 |
-
- Thème sombre / clair, interface responsive
|
| 501 |
-
- Recherche plein texte dans le corpus (GT et sorties de tous les concurrents)
|
| 502 |
-
- **URL stateful** : chaque vue filtrée accessible via URL — partager un cas précis avec un collègue
|
| 503 |
-
- **Mode présentation** : vue épurée pour contextes institutionnels
|
| 504 |
-
- **Annotations inline** : notes du paléographe exportées en JSON
|
| 505 |
-
- **Comparaison de rapports** : charger deux rapports (avant/après fine-tuning) et voir les deltas
|
| 506 |
-
|
| 507 |
-
### 7.3 Exports depuis le rapport
|
| 508 |
-
|
| 509 |
-
| Format | Contenu |
|
| 510 |
|---|---|
|
| 511 |
-
|
|
| 512 |
-
|
|
| 513 |
-
|
|
| 514 |
-
|
|
| 515 |
-
|
|
| 516 |
-
|
|
| 517 |
-
|
|
| 518 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 519 |
|
| 520 |
---
|
| 521 |
|
| 522 |
-
## 8. Module 6 — Interface
|
| 523 |
-
|
| 524 |
-
### 8.1 Interface web légère (FastAPI)
|
| 525 |
|
| 526 |
-
|
| 527 |
-
- Visualisation de l'avancement en temps réel avec log streamé
|
| 528 |
-
- Gestion des configurations enregistrées (profils)
|
| 529 |
-
- Accès aux rapports générés précédemment
|
| 530 |
-
- Configuration des adaptateurs moteurs et LLM via formulaire
|
| 531 |
|
| 532 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 533 |
|
| 534 |
-
|
| 535 |
-
# Lancer un benchmark
|
| 536 |
-
picarones run --corpus ./mes_gt/ --engines tesseract,pero_ocr,mistral --output ./rapport/
|
| 537 |
|
| 538 |
-
|
| 539 |
-
picarones run --corpus ./gt/ --config pipelines/medieval_correction.yaml
|
| 540 |
|
| 541 |
-
|
| 542 |
-
picarones
|
| 543 |
-
picarones
|
| 544 |
-
|
| 545 |
-
#
|
| 546 |
-
picarones
|
| 547 |
-
|
| 548 |
-
#
|
| 549 |
-
picarones
|
| 550 |
-
|
| 551 |
-
picarones
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 552 |
```
|
| 553 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 554 |
### 8.3 Intégration CI/CD
|
| 555 |
|
| 556 |
-
- Mode headless
|
| 557 |
-
- Output JSON machine-readable
|
| 558 |
-
-
|
| 559 |
-
-
|
|
|
|
| 560 |
|
| 561 |
---
|
| 562 |
|
| 563 |
-
## 9.
|
| 564 |
|
| 565 |
-
### 9.1
|
| 566 |
|
| 567 |
-
|
| 568 |
-
|
| 569 |
-
| Français médiéval (XIIe-XVe) | u/v, i/j, ſ/s, abréviations courantes |
|
| 570 |
-
| Français moderne (XVIe-XVIIIe) | ſ/s, ligatures fi/fl, esperluettes |
|
| 571 |
-
| Latin médiéval | Abréviations, contractions, ligatures spécifiques |
|
| 572 |
-
| Imprimés anciens (XVe-XVIIe) | Conventions typographiques, réclames |
|
| 573 |
-
| Personnalisé | Configurable et exportable |
|
| 574 |
|
| 575 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 576 |
|
| 577 |
-
|
| 578 |
-
-
|
| 579 |
-
|
| 580 |
-
- Humanistique / italique
|
| 581 |
-
- Imprimé romain / italique ancien
|
| 582 |
-
- Cursives administratives (XVIIe-XIXe)
|
| 583 |
|
| 584 |
-
### 9.
|
| 585 |
-
|
| 586 |
-
- Base de données des benchmarks historiques (SQLite optionnel)
|
| 587 |
-
- Courbes d'évolution : CER dans le temps pour un modèle en développement
|
| 588 |
-
- Détection automatique des régressions entre deux versions
|
| 589 |
-
- Comparaison avant/après fine-tuning
|
| 590 |
-
|
| 591 |
-
### 9.4 Analyse de robustesse
|
| 592 |
-
|
| 593 |
-
- Génération automatique de versions dégradées des images (bruit, flou, rotation, réduction de résolution, binarisation)
|
| 594 |
-
- Courbes de robustesse : CER en fonction du niveau de dégradation
|
| 595 |
-
- Identification du seuil de dégradation critique pour chaque concurrent
|
| 596 |
-
|
| 597 |
-
### 9.5 Évaluation par sous-région
|
| 598 |
-
|
| 599 |
-
Si bounding boxes disponibles dans la GT (ALTO/PAGE XML) :
|
| 600 |
-
- CER par zone : corps du texte / titres courants / marginalia / initiales / notes de bas de page
|
| 601 |
-
- Heatmap de densité d'erreur sur l'image
|
| 602 |
-
|
| 603 |
-
### 9.6 Détection de la sur-normalisation LLM
|
| 604 |
-
|
| 605 |
-
Risque spécifique aux pipelines OCR+LLM : le LLM "corrige" à tort des graphies médiévales légitimes en les modernisant. Picarones mesure :
|
| 606 |
-
- Taux de modification introduites par le LLM sur des passages déjà corrects
|
| 607 |
-
- Score de sur-normalisation : combien de transcriptions correctes le LLM a-t-il dégradées ?
|
| 608 |
-
- Liste des interventions LLM non souhaitées pour affiner le prompt
|
| 609 |
-
|
| 610 |
-
---
|
| 611 |
-
|
| 612 |
-
## 10. Plan de développement
|
| 613 |
-
|
| 614 |
-
| Sprint | Durée | Livrables |
|
| 615 |
-
|---|---|---|
|
| 616 |
-
| **Sprint 1** | 1-2 sem. | Structure du projet, adaptateurs Tesseract + Pero OCR, calcul CER/WER avec `jiwer`, export JSON, CLI de base |
|
| 617 |
-
| **Sprint 2** | 1-2 sem. | Rapport HTML v1 : galerie, vue document avec diff coloré, tableau de classement, graphiques de base |
|
| 618 |
-
| **Sprint 3** | 1-2 sem. | Pipelines OCR+LLM (modes text_only et text_and_image), adaptateurs GPT-4o et Claude |
|
| 619 |
-
| **Sprint 4** | 1-2 sem. | Adaptateurs API OCR (Mistral OCR, Google Vision), import IIIF, normalisation unicode, CER diplomatique |
|
| 620 |
-
| **Sprint 5** | 1-2 sem. | Métriques avancées : matrice confusion unicode, ligatures, structure, qualité image, taxonomie des erreurs |
|
| 621 |
-
| **Sprint 6** | 1-2 sem. | Interface web FastAPI, import HTR-United / HuggingFace, profils de normalisation, Ollama (LLMs locaux) |
|
| 622 |
-
| **Sprint 7** | 1-2 sem. | Rapport HTML v2 : vue Caractères, scatter plots, heatmaps, clustering |
|
| 623 |
-
| **Sprint 8** | 2 sem. | Intégration eScriptorium et Gallica API, suivi longitudinal, analyse de robustesse, prompts bibliothèque |
|
| 624 |
-
| **Sprint 9+** | Continu | Tests utilisateurs, documentation, packaging Docker, CI/CD, publication open-source |
|
| 625 |
|
| 626 |
-
--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 627 |
|
| 628 |
-
##
|
| 629 |
|
| 630 |
-
|
| 631 |
-
|
| 632 |
-
-
|
| 633 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 634 |
|
| 635 |
-
|
| 636 |
-
- Compatibilité Linux, macOS, Windows
|
| 637 |
-
- Docker fourni pour un déploiement reproductible
|
| 638 |
-
- API REST documentée (OpenAPI) pour intégration tierce
|
| 639 |
-
- Conformité IIIF, ALTO XML, PAGE XML, TEI
|
| 640 |
|
| 641 |
-
###
|
| 642 |
-
- Tests unitaires pour toutes les métriques (vérification sur cas connus)
|
| 643 |
-
- Tests d'intégration sur corpus de référence
|
| 644 |
-
- Documentation de chaque métrique (définition, formule, interprétation)
|
| 645 |
-
- Code open-source (licence Apache 2.0)
|
| 646 |
|
| 647 |
-
|
| 648 |
-
-
|
| 649 |
-
|
| 650 |
-
|
| 651 |
|
| 652 |
---
|
| 653 |
|
| 654 |
-
##
|
| 655 |
-
|
| 656 |
-
Cette section complète les spécifications initiales avec les fonctionnalités
|
| 657 |
-
ajoutées entre les Sprints 16 et 30. Le cœur du document ci-dessus reste
|
| 658 |
-
fidèle au cahier des charges originel ; cet addendum documente les briques
|
| 659 |
-
qui ont enrichi la plateforme depuis.
|
| 660 |
|
| 661 |
-
|
| 662 |
-
|
| 663 |
-
|
| 664 |
-
|
| 665 |
-
> évolué. Une refonte intégrale est planifiée en **Sprint A14** du plan
|
| 666 |
-
> de remédiation institutionnelle (cf.
|
| 667 |
-
> [`docs/audits/remediation-plan-2026-05.md`](docs/audits/remediation-plan-2026-05.md)).
|
| 668 |
-
>
|
| 669 |
-
> En attendant, les promesses suivantes mentionnées dans le présent
|
| 670 |
-
> document **ne sont pas livrées** et seront soit implémentées
|
| 671 |
-
> ultérieurement, soit explicitement abandonnées dans SPECS v2 :
|
| 672 |
|
| 673 |
<!-- specs-check: known-abandoned-start -->
|
| 674 |
|
| 675 |
-
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
|
| 685 |
-
|
| 686 |
-
|
| 687 |
-
utilisateur
|
| 688 |
-
|
| 689 |
-
|
| 690 |
-
|
| 691 |
-
|
| 692 |
-
|
| 693 |
-
- **
|
| 694 |
-
|
| 695 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 696 |
|
| 697 |
<!-- specs-check: known-abandoned-end -->
|
| 698 |
|
| 699 |
-
|
| 700 |
-
|
| 701 |
-
Le rapport HTML embarque en tête une **synthèse en langage naturel**
|
| 702 |
-
construite à partir de 12 détecteurs déterministes. Aucun LLM n'intervient :
|
| 703 |
-
chaque nombre ou nom apparaissant dans la synthèse est traçable à un
|
| 704 |
-
``payload`` de ``Fact`` qui provient lui-même du JSON d'entrée. Garantie
|
| 705 |
-
testée en CI (``test_sprint19_narrative_engine.py``).
|
| 706 |
-
|
| 707 |
-
Les 12 détecteurs couvrent : leader CER, ex-aequo statistique (Nemenyi),
|
| 708 |
-
écart significatif (Wilcoxon), gagnant et effondrement par strate, profil
|
| 709 |
-
d'erreurs atypique, hallucination LLM, fragilité robustesse, alternative
|
| 710 |
-
Pareto, gagnant en vitesse, coût aberrant, avertissement sur la fiabilité.
|
| 711 |
-
|
| 712 |
-
Politique éditoriale (ordre canonique) documentée dans
|
| 713 |
-
``docs/developer/narrative-engine.md`` et surchargeable via
|
| 714 |
-
``select_facts(..., type_order=...)``. Le registre Sprint 29 permet
|
| 715 |
-
d'ajouter un détecteur en touchant 2 fichiers (au lieu de 4 avant).
|
| 716 |
-
|
| 717 |
-
### Tests statistiques multi-moteurs (Sprint 18)
|
| 718 |
-
|
| 719 |
-
Friedman + post-hoc Nemenyi + **Critical Difference Diagram** (Demšar 2006)
|
| 720 |
-
rendu en SVG côté serveur, sans JavaScript. Table Nemenyi pour k = 2 à 50,
|
| 721 |
-
α ∈ {0,01 ; 0,05}. Fallback pur Python (Wilson-Hilferty pour le χ²) avec
|
| 722 |
-
support scipy optionnel via l'extra ``[stats]``.
|
| 723 |
-
|
| 724 |
-
### Modèle de coût et front Pareto (Sprint 20)
|
| 725 |
-
|
| 726 |
-
- ``picarones/core/pricing.py`` + ``picarones/data/pricing.yaml``.
|
| 727 |
-
- ``compute_pareto_front(points, objectives)`` — multi-objectifs, N dim.
|
| 728 |
-
- Vue Chart.js avec front Pareto en surbrillance et trois axes :
|
| 729 |
-
coût € / vitesse / empreinte carbone (étiqueté *expérimental*).
|
| 730 |
-
|
| 731 |
-
### Glossaire contextuel + panneau avancé (Sprint 21)
|
| 732 |
-
|
| 733 |
-
- 25 entrées bilingues dans ``picarones/report/glossary/{fr,en}.yaml``.
|
| 734 |
-
- Panneau *« ⚙ Mode avancé »* : choix de colonnes, filtres par strate,
|
| 735 |
-
score composite opt-in. État persisté en URL.
|
| 736 |
-
|
| 737 |
-
### Études de cas et documentation (Sprint 22)
|
| 738 |
-
|
| 739 |
-
``docs/case-studies/`` (deux cas explicitement étiquetés *« Cas d'école »*),
|
| 740 |
-
``docs/user/reading-a-report.md``, trois guides développeur dans
|
| 741 |
-
``docs/developer/``.
|
| 742 |
-
|
| 743 |
-
### Reproductibilité scientifique (Sprint 27)
|
| 744 |
-
|
| 745 |
-
Le rapport HTML embarque ``report_data["snapshots"]`` :
|
| 746 |
-
|
| 747 |
-
- **pricing** — YAML brut intégral de la table de prix ;
|
| 748 |
-
- **glossary** — entrées effectivement référencées ;
|
| 749 |
-
- **normalization** — profil sérialisé (``diplomatic_table``,
|
| 750 |
-
``exclude_chars``…) ;
|
| 751 |
-
- **environment** — version Picarones, Python, plateforme, commit git,
|
| 752 |
-
paquets installés.
|
| 753 |
-
|
| 754 |
-
Un lecteur peut rejouer la synthèse, le Pareto et le glossaire sans
|
| 755 |
-
accès au code source du moment où le rapport a été généré.
|
| 756 |
-
|
| 757 |
-
### Sécurité institutionnelle (Sprint 24)
|
| 758 |
|
| 759 |
-
|
| 760 |
|
| 761 |
-
|
| 762 |
-
mutualisés et les pipelines LLM facturés à la clef serveur.
|
| 763 |
-
- Validation Pillow systématique sur les images (CVE-2023-50447 et autres).
|
| 764 |
-
- Browse roots configurables via ``PICARONES_BROWSE_ROOTS``.
|
| 765 |
-
- Rate limiting par IP + sémaphore de jobs concurrents.
|
| 766 |
-
- CSP + en-têtes durcis.
|
| 767 |
|
| 768 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 769 |
|
| 770 |
-
|
| 771 |
-
``picarones/web/templates/`` + ``static/web-app.js``.
|
| 772 |
-
- Sprint 26 : ``picarones/core/jobs.py`` — ``JobStore`` SQLite (WAL,
|
| 773 |
-
thread-safe). Reprise SSE via ``Last-Event-ID``. Jobs orphelins
|
| 774 |
-
marqués ``interrupted`` au boot.
|
| 775 |
|
| 776 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 777 |
|
| 778 |
-
-
|
| 779 |
-
régression — branchable sur GitHub Actions).
|
| 780 |
-
- ``/api/config/save`` + ``/api/config/load`` : sérialisation/import
|
| 781 |
-
d'une configuration de benchmark.
|
| 782 |
-
- ``/api/benchmark/{id}/synthesis_preview`` : synthèse narrative sans
|
| 783 |
-
rouvrir le HTML.
|
| 784 |
-
- ``/api/history/regressions`` : surface de l'infra Sprint 8.
|
| 785 |
|
| 786 |
-
##
|
| 787 |
|
| 788 |
-
|
| 789 |
-
(
|
| 790 |
-
|
| 791 |
-
``○``) et un pattern de bordure différenciant à chaque tier — la
|
| 792 |
-
couleur n'est plus la seule information visuelle.
|
| 793 |
|
| 794 |
-
|
| 795 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 796 |
|
| 797 |
---
|
| 798 |
|
| 799 |
-
*Picarones est conçu pour devenir
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Picarones — Spécifications fonctionnelles et techniques
|
| 2 |
|
| 3 |
+
> **Plateforme de banc d'essai d'OCR / HTR / VLM et de pipelines de
|
| 4 |
+
> post-correction pour documents patrimoniaux.**
|
| 5 |
>
|
| 6 |
+
> Version **2.0** — Mai 2026. Refonte intégrale (Sprint A14 du plan
|
| 7 |
+
> de remédiation institutionnelle, item **B-12**).
|
| 8 |
+
|
| 9 |
+
> **Note de lecture** : ce document décrit ce que Picarones **fait
|
| 10 |
+
> aujourd'hui**, dans la version 1.x. Pour les **non-fonctionnalités
|
| 11 |
+
> assumées** (ce que Picarones *ne fait pas et ne fera pas* dans
|
| 12 |
+
> la v1.x — par exemple la recommandation prescriptive, l'export PDF,
|
| 13 |
+
> les adapters Kraken/AWS Textract), voir la section §10.
|
| 14 |
+
>
|
| 15 |
+
> Pour la cartographie technique du code et les règles de
|
| 16 |
+
> contribution interne, voir [`CLAUDE.md`](CLAUDE.md). SPECS.md
|
| 17 |
+
> reste tourné « public » (vocabulaire bibliothécaire, exemples
|
| 18 |
+
> patrimoniaux). Les deux documents sont complémentaires, pas
|
| 19 |
+
> redondants.
|
| 20 |
|
| 21 |
---
|
| 22 |
|
| 23 |
## Table des matières
|
| 24 |
|
| 25 |
+
1. [Vision et positionnement](#1-vision-et-positionnement)
|
| 26 |
+
2. [Architecture en 3 cercles](#2-architecture-en-3-cercles)
|
| 27 |
+
3. [Module 1 — Corpus et imports](#3-module-1--corpus-et-imports)
|
| 28 |
+
4. [Module 2 — Adaptateurs OCR / HTR](#4-module-2--adaptateurs-ocr--htr)
|
| 29 |
+
5. [Module 3 — Pipelines OCR+LLM et pipelines composables](#5-module-3--pipelines-ocrllm-et-pipelines-composables)
|
| 30 |
+
6. [Module 4 — Métriques et analyses](#6-module-4--métriques-et-analyses)
|
| 31 |
+
7. [Module 5 — Rapport HTML interactif](#7-module-5--rapport-html-interactif)
|
| 32 |
+
8. [Module 6 — Interface web et CLI](#8-module-6--interface-web-et-cli)
|
| 33 |
+
9. [Reproductibilité et sécurité](#9-reproductibilité-et-sécurité)
|
| 34 |
+
10. [Limites assumées et non-fonctionnalités](#10-limites-assumées-et-non-fonctionnalités)
|
| 35 |
+
11. [Roadmap d'évolution](#11-roadmap-dévolution)
|
| 36 |
+
12. [Migration v1 → v2 — annexe historique](#12-migration-v1--v2--annexe-historique)
|
| 37 |
|
| 38 |
---
|
| 39 |
|
| 40 |
+
## 1. Vision et positionnement
|
| 41 |
|
| 42 |
### 1.1 Problématique
|
| 43 |
|
| 44 |
+
Les équipes OCR/HTR travaillant sur des fonds patrimoniaux
|
| 45 |
+
(manuscrits, imprimés anciens, archives) disposent d'un paysage
|
| 46 |
+
hétérogène — moteurs locaux (Tesseract, Pero OCR), services cloud
|
| 47 |
+
(Mistral OCR, Google Vision, Azure Document Intelligence), modèles
|
| 48 |
+
fine-tunés maison, VLMs (GPT-4o, Claude, Mistral Large) — sans
|
| 49 |
+
outil unifié pour les comparer rigoureusement sur leurs propres
|
| 50 |
+
corpus.
|
| 51 |
+
|
| 52 |
+
Les outils existants (ocrevalUAtion, dinglehopper) sont soit
|
| 53 |
+
obsolètes, soit limités au CER/WER, soit non adaptés aux
|
| 54 |
+
spécificités des documents historiques : glyphes anciens,
|
| 55 |
+
ligatures, abréviations, graphies variables, pathologies d'image,
|
| 56 |
+
ordre de lecture multi-colonnes, structure ALTO/PAGE.
|
| 57 |
+
|
| 58 |
+
À cela s'ajoute une question de recherche émergente : **est-ce
|
| 59 |
+
qu'une couche de correction par LLM améliore réellement la sortie
|
| 60 |
+
OCR, de combien, sur quels types d'erreurs, et sans introduire
|
| 61 |
+
d'over-normalisation moderne ?** Aucun outil existant ne permet
|
| 62 |
+
de tester et mesurer cela rigoureusement.
|
| 63 |
+
|
| 64 |
+
### 1.2 Philosophie : un banc d'essai, pas un atelier
|
| 65 |
+
|
| 66 |
+
Picarones est conçu comme un **banc d'essai** :
|
| 67 |
+
|
| 68 |
+
- L'utilisateur amène son **golden dataset** annoté (paires image +
|
| 69 |
+
vérité terrain). Sans VT, pas de benchmark.
|
| 70 |
+
- Picarones exécute les IA candidates et **mesure** l'écart à la VT.
|
| 71 |
+
- Picarones **classe** les résultats avec rigueur statistique.
|
| 72 |
+
- Picarones **n'arbitre pas le débat éditorial**. Il ne dit pas si
|
| 73 |
+
un moteur diplomatique vaut mieux qu'un moteur modernisant —
|
| 74 |
+
il rapporte les chiffres et laisse le chercheur, l'archiviste
|
| 75 |
+
ou le paléographe trancher selon ses critères propres.
|
| 76 |
+
|
| 77 |
+
Cette philosophie est tenue jusque dans le moteur narratif
|
| 78 |
+
factuel : chaque phrase de la synthèse en tête du rapport est
|
| 79 |
+
traçable à un payload de `Fact` qui provient du JSON d'entrée
|
| 80 |
+
(garde-fou anti-hallucination prouvé par tests).
|
| 81 |
+
|
| 82 |
+
### 1.3 Contributions scientifiques
|
| 83 |
+
|
| 84 |
+
Au-delà de la simple agrégation de moteurs, Picarones apporte
|
| 85 |
+
plusieurs briques nouvelles dans l'écosystème OCR/HTR open-source :
|
| 86 |
+
|
| 87 |
+
- **Registre typé de métriques** (Sprint 34) : chaque métrique
|
| 88 |
+
est enregistrée pour une jonction de types `ArtifactType`
|
| 89 |
+
(TEXT/ALTO/PAGE/ENTITIES/READING_ORDER) ; un pipeline composé
|
| 90 |
+
peut alors calculer automatiquement la métrique adéquate à
|
| 91 |
+
chaque jonction de son DAG.
|
| 92 |
+
- **Interface BaseModule générique** (Sprint 33) : OCR, mappeur
|
| 93 |
+
VLM→ALTO, rewriter ALTO→ALTO, classifieur d'entités texte→entités
|
| 94 |
+
partagent la même API ; le runner les enchaîne sans privilégier
|
| 95 |
+
un type particulier.
|
| 96 |
+
- **GT multi-niveaux** (Sprint 32) : un document peut porter
|
| 97 |
+
simultanément une vérité terrain texte, ALTO, PAGE, entités,
|
| 98 |
+
et reading order — chacune calibrée à son niveau d'évaluation.
|
| 99 |
+
- **Moteur narratif factuel anti-hallucination** (Sprint 19+) :
|
| 100 |
+
20+ détecteurs déterministes produisent une synthèse en
|
| 101 |
+
langage naturel dont chaque chiffre est traçable au payload
|
| 102 |
+
d'un `Fact`. Aucune intervention LLM, garde-fou prouvé par
|
| 103 |
+
test (`test_sprint23_anti_hallucination`).
|
| 104 |
+
- **Test multi-moteurs Friedman + Nemenyi + Critical Difference
|
| 105 |
+
Diagram** (Sprint 18, Demšar 2006) : référence canonique pour
|
| 106 |
+
la comparaison statistique de classifieurs, transposée à l'OCR.
|
| 107 |
+
- **Pareto coût / vitesse / CO₂** (Sprint 20) : positionnement
|
| 108 |
+
tri-objectifs avec front explicite, table de pricing
|
| 109 |
+
surchargeable.
|
| 110 |
+
- **Métriques philologiques transversales** (Sprints 55–60) :
|
| 111 |
+
six modules couvrant l'imprimé ancien, le médiéval, les
|
| 112 |
+
archives modernes (XIXᵉ–XXᵉ), avec scores éditoriaux séparés
|
| 113 |
+
(préservation stricte vs équivalence diplomatique).
|
| 114 |
+
|
| 115 |
+
### 1.4 Utilisateurs cibles
|
| 116 |
+
|
| 117 |
+
| Profil | Cas d'usage typique |
|
| 118 |
|---|---|
|
| 119 |
+
| **Ingénieur OCR/ML** | Pipeline programmatique, métriques fines, export JSON, intégration CI/CD via `picarones run --fail-if-cer-above` |
|
| 120 |
+
| **Chargé de numérisation** | Rapport HTML autonome, comparaison A vs B, lecture du Pareto coût/qualité |
|
| 121 |
+
| **Responsable de projet** | Vue agrégée multi-corpus, analyse coût/bénéfice des APIs cloud, suivi longitudinal SQLite |
|
| 122 |
+
| **Chercheur en humanités numériques** | Métriques philologiques, corpus HTR-United, taxonomie d'erreurs en 10 classes, glossaire contextuel |
|
| 123 |
+
| **Paléographe / éditeur critique** | Diff visuel par document, bascule diplomatique / normalisé, profil philologique séparant strict et expansion |
|
| 124 |
+
| **DSI institutionnel** | Déploiement intranet derrière SSO, RGPD, observabilité (cf. `docs/operations/`) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
---
|
| 127 |
|
| 128 |
+
## 2. Architecture en 3 cercles
|
|
|
|
|
|
|
| 129 |
|
| 130 |
```
|
| 131 |
+
Cercle 3 (extras, report, cli, web)
|
| 132 |
+
│
|
| 133 |
+
▼
|
| 134 |
+
Cercle 2 (measurements, engines, llm, pipelines, modules)
|
| 135 |
+
│
|
| 136 |
+
▼
|
| 137 |
+
Cercle 1 (core)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
```
|
| 139 |
|
| 140 |
+
**Règle de dépendance** : les imports vont uniquement de
|
| 141 |
+
l'extérieur vers l'intérieur. Aucun shim — un module a un seul
|
| 142 |
+
emplacement. La règle est appliquée par
|
| 143 |
+
`tests/core/test_circle_dependencies.py` (Sprint A3) qui parse
|
| 144 |
+
l'AST de chaque fichier et bloque toute violation au merge.
|
| 145 |
+
|
| 146 |
+
### 2.1 Cercle 1 — abstractions pures
|
| 147 |
+
|
| 148 |
+
7 modules dans `picarones/core/` :
|
| 149 |
+
|
| 150 |
+
- `corpus.py` — `Document`, `Corpus`, `GTLevel.{TEXT,ALTO,PAGE,ENTITIES,READING_ORDER}`,
|
| 151 |
+
payloads typés, loader auto-détectant les fichiers `.gt.alto.xml`,
|
| 152 |
+
`.gt.page.xml`, `.gt.entities.json`, `.gt.reading_order.json`.
|
| 153 |
+
- `modules.py` — `BaseModule`, `ArtifactType`. Interface commune
|
| 154 |
+
à OCR, mappeurs, rewriters, classifieurs.
|
| 155 |
+
- `metric_registry.py` — `MetricSpec`, `@register_metric`,
|
| 156 |
+
`select_metrics`, `compute_at_junction`. Sélection par signature
|
| 157 |
+
de types exacte (pas de coercion).
|
| 158 |
+
- `metric_hooks.py` — registre legacy compatible (Sprint 16-).
|
| 159 |
+
- `metrics.py` — `MetricsResult`, `aggregate_metrics`.
|
| 160 |
+
- `results.py` — `DocumentResult`, `EngineReport`, `BenchmarkResult`,
|
| 161 |
+
sérialisation JSON.
|
| 162 |
+
- `facts.py` — `Fact`, `FactType` (20 entrées), `FactImportance`,
|
| 163 |
+
`DetectorRegistry`. Modèle de données du moteur narratif.
|
| 164 |
+
- `diff_utils.py` — `compute_word_diff`, `compute_char_diff`,
|
| 165 |
+
`diff_stats` (déplacé Cercle 3 → Cercle 1 en A3).
|
| 166 |
+
- `pipeline.py` — `PipelineRunner`, `PipelineSpec`, `PipelineStep`.
|
| 167 |
+
- `xml_utils.py` — `safe_parse_xml` (defusedxml).
|
| 168 |
+
|
| 169 |
+
### 2.2 Cercle 2 — logique métier
|
| 170 |
+
|
| 171 |
+
5 sous-packages :
|
| 172 |
+
|
| 173 |
+
- `measurements/` — ~70 modules de calcul de métriques + le
|
| 174 |
+
moteur narratif (`narrative/` avec arbiter, registry, renderer,
|
| 175 |
+
20 détecteurs en 6 familles).
|
| 176 |
+
- `engines/` — adaptateurs OCR : Tesseract, Pero OCR, Mistral OCR,
|
| 177 |
+
Google Vision, Azure Document Intelligence (5 adapters).
|
| 178 |
+
- `llm/` — adaptateurs LLM : OpenAI, Anthropic, Mistral, Ollama
|
| 179 |
+
(4 adapters).
|
| 180 |
+
- `pipelines/` — orchestration OCR+LLM (3 modes historiques).
|
| 181 |
+
- `modules/` — modules `BaseModule` officiels (ALTO text→region
|
| 182 |
+
mappers).
|
| 183 |
+
|
| 184 |
+
### 2.3 Cercle 3 — entrées et rendu
|
| 185 |
+
|
| 186 |
+
- `report/` — générateur HTML, ~25 modules de rendu, vendor
|
| 187 |
+
Chart.js, templates Jinja2 (10 partials), i18n FR/EN, glossaire
|
| 188 |
+
contextuel (25 entrées bilingues).
|
| 189 |
+
- `cli/` — Click CLI (15 commandes) en package `picarones/cli/`.
|
| 190 |
+
- `web/` — FastAPI (app + 11 routers + sécurité + jobs SQLite +
|
| 191 |
+
maintenance auto-purge).
|
| 192 |
+
- `extras/` — plugins : importers (IIIF, Gallica, HTR-United, HF
|
| 193 |
+
Datasets, eScriptorium), modules historiques.
|
| 194 |
|
| 195 |
---
|
| 196 |
|
| 197 |
+
## 3. Module 1 — Corpus et imports
|
| 198 |
|
| 199 |
### 3.1 Formats de vérité terrain acceptés
|
| 200 |
|
| 201 |
+
| Format | Extension | Niveau GT | Usage typique |
|
| 202 |
+
|---|---|---|---|
|
| 203 |
+
| Texte brut | `image.gt.txt` | TEXT | Convention Tesseract, HTR-United |
|
| 204 |
+
| ALTO XML v4 | `.gt.alto.xml` | ALTO | Standard bibliothèques nationales, eScriptorium export |
|
| 205 |
+
| PAGE XML 2019 | `.gt.page.xml` | PAGE | Transkribus, OCRopus |
|
| 206 |
+
| Entités nommées | `.gt.entities.json` | ENTITIES | Format HIPE simplifié |
|
| 207 |
+
| Reading order | `.gt.reading_order.json` | READING_ORDER | Liste ordonnée de region IDs |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 208 |
|
| 209 |
+
Le loader (`load_corpus_from_directory`) détecte automatiquement
|
| 210 |
+
chacun de ces niveaux à côté de l'image. Un même document peut
|
| 211 |
+
porter plusieurs niveaux simultanément (Sprint 32).
|
|
|
|
| 212 |
|
| 213 |
+
### 3.2 Sources d'import
|
|
|
|
|
|
|
|
|
|
| 214 |
|
| 215 |
+
#### Local
|
| 216 |
+
Import d'un dossier de paires image / GT. Détection automatique
|
| 217 |
+
du format. Filtrage des fichiers macOS `._*`.
|
| 218 |
+
|
| 219 |
+
#### IIIF
|
| 220 |
+
Import par URL de manifeste IIIF v2 et v3. Compatible Gallica
|
| 221 |
+
(BnF), Bodleian, BL, Vatican, e-codices, Europeana, et tout
|
| 222 |
+
entrepôt IIIF-compliant. Sélection par range de canvas.
|
| 223 |
+
|
| 224 |
+
#### HuggingFace Datasets
|
| 225 |
+
Recherche par filtre langue/script/époque/institution. Datasets
|
| 226 |
+
patrimoniaux pré-référencés (IAM, RIMES, READ-BAD, Esposalles,
|
| 227 |
+
HTR-United datasets). Statut : module
|
| 228 |
+
`extras/importers/huggingface.py` marqué expérimental
|
| 229 |
+
(`UserWarning` à l'import).
|
| 230 |
+
|
| 231 |
+
#### HTR-United
|
| 232 |
+
Listing du catalogue distant + import direct. Lecture des
|
| 233 |
+
métadonnées (langue, script, institution, époque). En cas
|
| 234 |
+
d'échec réseau ou parsing, fallback sur catalogue de démo +
|
| 235 |
+
émission d'un `Fact` `IMPORTER_FALLBACK_TRIGGERED` (Sprint A3).
|
| 236 |
+
|
| 237 |
+
#### Gallica (API BnF)
|
| 238 |
+
Recherche par cote, titre, auteur, date. Récupération des
|
| 239 |
+
images via API IIIF Gallica.
|
| 240 |
+
|
| 241 |
+
#### eScriptorium
|
| 242 |
+
Connexion à une instance distante via API. Statut
|
| 243 |
+
expérimental.
|
| 244 |
+
|
| 245 |
+
#### Upload ZIP via navigateur
|
| 246 |
+
Endpoint `POST /api/corpus/upload`. Validation Pillow
|
| 247 |
+
(décompression bombs), zip-slip prévenu, taille plafonnée
|
| 248 |
+
(`PICARONES_MAX_UPLOAD_MB`).
|
| 249 |
|
| 250 |
### 3.3 Gestion des corpus
|
| 251 |
|
| 252 |
+
- Corpus nommés et versionnés avec métadonnées descriptives.
|
| 253 |
+
- Tags : type de script, langue, siècle, institution, état de
|
| 254 |
+
conservation.
|
| 255 |
+
- Stratification par `script_type` (Sprint 45-46) — vue stratifiée
|
| 256 |
+
dans le rapport, détecteur narratif `STRATIFICATION_RECOMMENDED`
|
| 257 |
+
qui invite l'utilisateur quand le corpus est hétérogène.
|
| 258 |
|
| 259 |
---
|
| 260 |
|
| 261 |
+
## 4. Module 2 — Adaptateurs OCR / HTR
|
| 262 |
|
| 263 |
### 4.1 Architecture des adaptateurs
|
| 264 |
|
| 265 |
+
Chaque moteur OCR est une classe Python qui hérite de
|
| 266 |
+
`BaseOCREngine` (`picarones/engines/base.py`), elle-même héritière
|
| 267 |
+
de `BaseModule` (Sprint 33). Une instance déclare son
|
| 268 |
+
`execution_mode` (`"io"` ou `"cpu"`) que le runner utilise pour
|
| 269 |
+
choisir entre `ThreadPoolExecutor` (cloud APIs) et
|
| 270 |
+
`ProcessPoolExecutor` (Tesseract, Pero).
|
| 271 |
|
| 272 |
+
Ajouter un nouveau moteur = créer une classe Python de ~50 lignes
|
| 273 |
+
qui implémente `_run_ocr(image_path) -> str` et déclare son
|
| 274 |
+
`execution_mode`.
|
| 275 |
|
| 276 |
+
### 4.2 Moteurs OCR livrés
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 277 |
|
| 278 |
+
| Moteur | Type | Mode d'exécution | Confidence native exposée ? |
|
| 279 |
+
|---|---|---|---|
|
| 280 |
+
| **Tesseract 5** | Local CLI | CPU (ProcessPool) | ✅ Sprint 47 (`image_to_data`) |
|
| 281 |
+
| **Pero OCR** | Local Python | CPU (ProcessPool) | ✅ Sprint 48 (`transcription_confidence` ligne) |
|
| 282 |
+
| **Mistral OCR** | Cloud API | IO (ThreadPool) | ✅ Sprint 49 (quand disponible côté API) |
|
| 283 |
+
| **Google Vision** | Cloud API | IO (ThreadPool) | ✅ Sprint 50 (`Word.confidence` en mode `DOCUMENT_TEXT_DETECTION`) |
|
| 284 |
+
| **Azure Doc Intelligence** | Cloud API | IO (ThreadPool) | ✅ Sprint 51 (`Word.confidence`) |
|
| 285 |
+
|
| 286 |
+
Quand un moteur expose ses confidences natives, le runner calcule
|
| 287 |
+
automatiquement les métriques de calibration (ECE, MCE, reliability
|
| 288 |
+
diagram — Sprint 39-43).
|
| 289 |
+
|
| 290 |
+
### 4.3 Robustesse runtime
|
| 291 |
+
|
| 292 |
+
- **Erreurs HTTP cloud** (4xx/5xx, timeout, body mal formé) :
|
| 293 |
+
remontées dans `EngineResult.error` avec le code HTTP, jamais
|
| 294 |
+
avalées silencieusement (Sprint A5 / m-10, 19 cas testés).
|
| 295 |
+
- **Crash isolé d'un document** : le runner continue avec les
|
| 296 |
+
autres documents. Le doc en échec a `engine_error` rempli.
|
| 297 |
+
- **Cancel mid-run** : `cancel_event.set()` interrompt proprement.
|
| 298 |
+
- **Timeout par document** : configurable via paramètre
|
| 299 |
+
`timeout_seconds`.
|
| 300 |
|
| 301 |
---
|
| 302 |
|
| 303 |
+
## 5. Module 3 — Pipelines OCR+LLM et pipelines composables
|
|
|
|
|
|
|
| 304 |
|
| 305 |
+
### 5.1 Pipelines OCR+LLM historiques (Sprint 3+)
|
| 306 |
|
| 307 |
+
L'unité de comparaison est le **concurrent** — pas forcément un
|
| 308 |
+
moteur seul, mais une chaîne produisant du texte à partir d'une
|
| 309 |
+
image.
|
| 310 |
|
| 311 |
+
| Mode | Description | Usage typique |
|
| 312 |
|---|---|---|
|
| 313 |
+
| `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 |
|
| 314 |
+
| `post_correction_texte` | OCR → texte brut → LLM corrige le texte | LLM non multimodal (Llama local), grand volume |
|
| 315 |
+
| `post_correction_image_texte` | OCR → LLM reçoit image ET texte brut | Meilleure qualité ; le LLM voit le contexte visuel |
|
|
|
|
|
|
|
| 316 |
|
| 317 |
+
Les prompts sont **versionnés** dans `picarones/prompts/` (8 fichiers
|
| 318 |
+
FR + EN), embarqués dans le snapshot du rapport pour
|
| 319 |
+
reproductibilité.
|
| 320 |
|
| 321 |
+
### 5.2 Pipelines composables (Sprint 63+)
|
| 322 |
|
| 323 |
+
Au-delà des 3 modes historiques, Picarones livre une infrastructure
|
| 324 |
+
générique : un pipeline est une **liste d'étapes `BaseModule`**
|
| 325 |
+
qui produit un artefact à chaque étape (TEXT, ALTO, PAGE,
|
| 326 |
+
ENTITIES…) ; à chaque jonction, le runner calcule
|
| 327 |
+
**automatiquement** la métrique adéquate via `compute_at_junction`
|
| 328 |
+
(registre typé Sprint 34).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 329 |
|
| 330 |
+
```yaml
|
| 331 |
+
# Spec YAML chargée par picarones pipeline run
|
| 332 |
+
name: ocr_then_corrector
|
| 333 |
+
steps:
|
| 334 |
+
- name: ocr
|
| 335 |
+
module: picarones.engines.tesseract.TesseractEngine
|
| 336 |
+
args: { lang: "fra", psm: 6 }
|
| 337 |
+
- name: post_correction
|
| 338 |
+
module: my_module.MyLLMCorrector
|
| 339 |
+
args: { model: "gpt-4o" }
|
| 340 |
```
|
| 341 |
|
| 342 |
+
`picarones pipeline compare specs.yaml --corpus ./scans --output rapport.html`
|
| 343 |
+
exécute N pipelines sur le même corpus et produit un rapport
|
| 344 |
+
comparatif. Conçu pour qu'un mainteneur tiers puisse contribuer
|
| 345 |
+
ses propres modules sans toucher au cœur de Picarones (cf.
|
| 346 |
+
`docs/developer/module-policy.md`, Sprint 97).
|
| 347 |
+
|
| 348 |
+
### 5.3 Détection d'over-normalisation LLM
|
| 349 |
+
|
| 350 |
+
Risque spécifique aux pipelines OCR+LLM : le LLM modernise à tort
|
| 351 |
+
des graphies historiques légitimes. Picarones mesure :
|
| 352 |
+
|
| 353 |
+
- **Modernisation lexicale** (Sprint 80) : top-N tokens GT
|
| 354 |
+
systématiquement remplacés (`maistre → maître` dans 100 % des
|
| 355 |
+
cas → signal exploitable).
|
| 356 |
+
- **Score d'absorption d'erreur** (Sprint 94) : à chaque jonction
|
| 357 |
+
OCR→LLM, calcule le **taux de correction** (parmi les erreurs
|
| 358 |
+
avant, combien corrigées) **et** le **taux d'introduction**
|
| 359 |
+
(parmi les erreurs après, combien nouvelles). Distingue un
|
| 360 |
+
module qui *corrige* d'un module qui *écrase*.
|
| 361 |
+
- **Delta Flesch** (Sprint 52) : sur les langues prises en
|
| 362 |
+
charge, signale les LLM qui rendent le texte « trop moderne »
|
| 363 |
+
par rapport à la GT.
|
| 364 |
+
- **Score d'ancrage** (Sprint 10) : proportion des trigrammes
|
| 365 |
+
produits par le LLM qui s'ancrent dans la GT — score bas =
|
| 366 |
+
hallucination probable.
|
| 367 |
|
| 368 |
+
---
|
|
|
|
| 369 |
|
| 370 |
+
## 6. Module 4 — Métriques et analyses
|
|
|
|
|
|
|
|
|
|
|
|
|
| 371 |
|
| 372 |
+
### 6.1 Catalogue exhaustif des métriques
|
| 373 |
|
| 374 |
+
Picarones livre **plus de 30 métriques** organisées en familles.
|
| 375 |
+
Pour chaque métrique : son nom, sa jonction de types, sa source,
|
| 376 |
+
ses limites — voir le **glossaire contextuel** intégré au rapport
|
| 377 |
+
HTML (25 entrées bilingues, ouvre via le `?` à côté du nom de
|
| 378 |
+
colonne) et `picarones/report/glossary/{fr,en}.yaml`.
|
| 379 |
|
| 380 |
+
#### Classique OCR/HTR
|
|
|
|
|
|
|
| 381 |
|
| 382 |
+
| Métrique | Jonction | Source primaire |
|
| 383 |
+
|---|---|---|
|
| 384 |
+
| CER (raw, NFC, caseless, diplomatique) | `(TEXT, TEXT)` | Levenshtein character / [jiwer](https://github.com/jitsi/jiwer) |
|
| 385 |
+
| WER, MER, WIL | `(TEXT, TEXT)` | jiwer |
|
| 386 |
+
| Bootstrap CI 95 % | dérivé | Efron (1979) |
|
| 387 |
+
| Distribution CER par ligne, Gini | dérivé | Sprint 10 |
|
| 388 |
+
| Détection hallucinations VLM (anchor score, length ratio) | dérivé | Sprint 10 |
|
| 389 |
|
| 390 |
+
#### Philologique (Sprints 52-60, 80, 84-85, 92-94)
|
| 391 |
|
| 392 |
+
| Métrique | Jonction | Cible patrimoniale |
|
| 393 |
+
|---|---|---|
|
| 394 |
+
| Couverture MUFI | `(TEXT, TEXT)` | Manuscrits médiévaux |
|
| 395 |
+
| Score d'expansion d'abréviations Capelli | `(TEXT, TEXT)` | Médiéval |
|
| 396 |
+
| Précision par bloc Unicode | `(TEXT, TEXT)` | Imprimés anciens / médiéval |
|
| 397 |
+
| Préservation des marqueurs typographiques de l'imprimé ancien (long-s, ligatures, tildes nasaux) | `(TEXT, TEXT)` | XVIᵉ-XVIIIᵉ |
|
| 398 |
+
| Marqueurs des archives modernes (titres, ordinaux, monnaies, état civil…) | `(TEXT, TEXT)` | XIXᵉ-XXᵉ |
|
| 399 |
+
| Préservation des numéraux romains (5 statuts) | `(TEXT, TEXT)` | Toutes périodes |
|
| 400 |
+
| Recherchabilité fuzzy (Levenshtein distance ≤ 2) | `(TEXT, TEXT)` | Indexation Elastic / full-text |
|
| 401 |
+
| Précision sur séquences numériques (dates, foliotation, monnaies) | `(TEXT, TEXT)` | Archives, économie historique |
|
| 402 |
+
| Modernisation lexicale (top-N tokens GT modernisés) | `(TEXT, TEXT)` | Pipelines OCR+LLM |
|
| 403 |
+
| Delta Flesch (FR + EN) | `(TEXT, TEXT)` | Repère VLM hallucinant du français moderne |
|
| 404 |
+
| Score d'absorption d'erreur par jonction | `(TEXT, TEXT)` | Pipelines composées |
|
| 405 |
+
| Précision sur entités nommées (HIPE) | `(ENTITIES, ENTITIES)` | Indexation prosopographique |
|
| 406 |
+
| Reading order F1 (ICDAR 2015) | `(READING_ORDER, READING_ORDER)` | Manuscrits glosés, journaux multi-colonnes |
|
| 407 |
+
| Layout F1 par type de région (IoU 0.5) | `(ALTO, ALTO)` | Texte/glose/marginalia |
|
| 408 |
+
|
| 409 |
+
#### Comparaison & décision (Sprints 18, 20, 35-37, 81, 89-92, 96)
|
| 410 |
+
|
| 411 |
+
| Métrique | Source primaire |
|
| 412 |
+
|---|---|
|
| 413 |
+
| Test multi-moteurs Friedman + post-hoc Nemenyi + CDD | Demšar (2006) |
|
| 414 |
+
| Test pairé Wilcoxon | Wilcoxon (1945) |
|
| 415 |
+
| Pareto coût / vitesse / CO₂ (multi-objectifs N dim) | Pareto (1896) |
|
| 416 |
+
| Divergence taxonomique inter-moteurs (Jensen-Shannon) | Lin (1991) |
|
| 417 |
+
| Oracle complementarity (recall borné supérieur) | Sprint 35 |
|
| 418 |
+
| Score de spécialisation inter-moteurs | Sprint 89 |
|
| 419 |
+
| Stabilité multi-runs (CV CER, accord identique) | Sprint 83 |
|
| 420 |
+
| Accord inter-annotateurs (Cohen κ, Krippendorff α) | Cohen (1960), Krippendorff (1970) |
|
| 421 |
+
| Tendance longitudinale + change-point Pettitt | Sprint 92 |
|
| 422 |
+
| Throughput effectif (pages/h après correction humaine 5s/erreur) | Sprint 91, HTR-United |
|
| 423 |
+
| Coût marginal par erreur évitée | Sprint 91 |
|
| 424 |
+
| Comparaison incrémentale ANOVA-like par slot | Sprint 96 |
|
| 425 |
+
|
| 426 |
+
**Note de traçabilité** : les références primaires (Demšar 2006,
|
| 427 |
+
Wilcoxon 1945, Efron 1979, etc.) sont citées dans les docstrings
|
| 428 |
+
de chaque fonction de `picarones/measurements/statistics.py`.
|
| 429 |
+
Le glossaire contextuel relie chaque métrique à sa publication
|
| 430 |
+
canonique (champ `reference`).
|
| 431 |
+
|
| 432 |
+
### 6.2 Profils de normalisation
|
| 433 |
+
|
| 434 |
+
11 profils livrés (`picarones/measurements/normalization.py`,
|
| 435 |
+
exposés via `/api/normalization/profiles`) : `nfc`, `caseless`,
|
| 436 |
+
`minimal`, `medieval_french`, `early_modern_french`,
|
| 437 |
+
`medieval_latin`, `medieval_english`, `early_modern_english`,
|
| 438 |
+
`secretary_hand`, `sans_ponctuation`, `sans_apostrophes`.
|
| 439 |
+
|
| 440 |
+
Chaque profil applique un ensemble d'équivalences diplomatiques
|
| 441 |
+
(ſ=s, u=v, i=j, ꝑ=per, þ=th, etc.). Un profil custom peut être
|
| 442 |
+
chargé depuis YAML.
|
| 443 |
+
|
| 444 |
+
**Traçabilité aux standards éditoriaux** (MUFI v4.0, TEI P5
|
| 445 |
+
Unicode chapter 3.4, DEAF) : prévue Sprint A12 (item B-6 du
|
| 446 |
+
plan de remédiation institutionnelle).
|
| 447 |
+
|
| 448 |
+
### 6.3 Taxonomie des erreurs en 10 classes
|
| 449 |
+
|
| 450 |
+
Catégorisation automatique de chaque erreur (Sprint 5) :
|
| 451 |
+
|
| 452 |
+
1. Confusion visuelle (rn/m, l/1, O/0, u/n…)
|
| 453 |
+
2. Erreur diacritique
|
| 454 |
+
3. Erreur de casse
|
| 455 |
+
4. Ligature non résolue
|
| 456 |
+
5. Abréviation non développée
|
| 457 |
+
6. Hapax (mot absent du lexique)
|
| 458 |
+
7. Segmentation (fusion / fragmentation)
|
| 459 |
+
8. Hors-vocabulaire
|
| 460 |
+
9. Lacune (texte présent en GT, absent en OCR)
|
| 461 |
+
10. Sur-normalisation LLM
|
| 462 |
+
|
| 463 |
+
### 6.4 Score de difficulté intrinsèque
|
| 464 |
+
|
| 465 |
+
Indicateur calculé **indépendamment des moteurs** (Sprint 7) :
|
| 466 |
+
|
| 467 |
+
- variance du CER entre tous les concurrents (si tous ratent →
|
| 468 |
+
document objectivement difficile),
|
| 469 |
+
- métriques de qualité image,
|
| 470 |
+
- densité de caractères spéciaux (ligatures, abréviations,
|
| 471 |
+
diacritiques),
|
| 472 |
+
- longueur et densité du texte.
|
| 473 |
+
|
| 474 |
+
Sépare deux questions distinctes : *« est-ce que ce moteur est
|
| 475 |
+
mauvais ? »* vs *« est-ce que ce document est objectivement
|
| 476 |
+
difficile ? »*.
|
| 477 |
|
| 478 |
+
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 479 |
|
| 480 |
+
## 7. Module 5 — Rapport HTML interactif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 481 |
|
| 482 |
+
Le rapport est un **fichier HTML auto-portant** (Jinja2 server-side,
|
| 483 |
+
Chart.js vendoré inline), lisible hors-ligne, embarquant toutes
|
| 484 |
+
les données et visualisations.
|
| 485 |
|
| 486 |
+
### 7.1 Cinq vues + sections globales
|
| 487 |
|
| 488 |
+
#### Sections globales (en tête)
|
| 489 |
|
| 490 |
+
- **Synthèse narrative factuelle** (Sprint 19+) : 3-5 phrases
|
| 491 |
+
produites par 20+ détecteurs déterministes. Chaque chiffre
|
| 492 |
+
rendu est traçable au payload du `Fact` correspondant
|
| 493 |
+
(anti-hallucination prouvé par test).
|
| 494 |
+
- **Critical Difference Diagram** (Sprint 18) : SVG server-side,
|
| 495 |
+
Friedman + post-hoc Nemenyi.
|
| 496 |
+
- **Section inter-moteurs** (Sprint 37) : matrice de divergence
|
| 497 |
+
taxonomique + encart oracle complementarity.
|
| 498 |
+
- **Front Pareto** (Sprint 20) : coût / vitesse / CO₂ avec
|
| 499 |
+
toggles d'axes.
|
| 500 |
+
- **Section leviers d'amélioration** (Sprint 51-82) : 5 leviers
|
| 501 |
+
factuels (taxonomie récupérable, concentration Pareto,
|
| 502 |
+
complémentarité, modernisation lexicale, déficit projeté de
|
| 503 |
+
robustesse).
|
| 504 |
|
| 505 |
+
#### Vue Classement (Ranking)
|
| 506 |
|
| 507 |
+
Tableau triable : CER (médiane par défaut depuis Sprint 44),
|
| 508 |
+
WER, MER, WIL, scores ligatures et diacritiques, Gini, score
|
| 509 |
+
d'ancrage, sur-normalisation, etc. Vue stratifiée optionnelle
|
| 510 |
+
par `script_type` (Sprint 45-46).
|
| 511 |
|
| 512 |
+
#### Vue Galerie (Gallery)
|
| 513 |
|
| 514 |
+
Grille de vignettes avec badge CER coloré. Filtres dynamiques
|
| 515 |
+
(CER > X, qualité image, type de script, longueur GT). Tri
|
| 516 |
+
multi-critères. Vue **« Worst lines globale »** (Sprint 72)
|
| 517 |
+
qui transcende les documents et liste les lignes individuelles
|
| 518 |
+
les plus mal transcrites.
|
| 519 |
|
| 520 |
+
#### Vue Document
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 521 |
|
| 522 |
+
Image originale + diff token coloré façon GitHub par moteur,
|
| 523 |
+
scroll synchronisé N-way. Vue spécifique OCR+LLM : triple diff
|
| 524 |
+
GT / sortie OCR brute / sortie après LLM.
|
|
|
|
| 525 |
|
| 526 |
+
#### Vue Analyses
|
|
|
|
|
|
|
| 527 |
|
| 528 |
+
Distribution CER (histogramme + densité), scatter plots
|
| 529 |
+
qualité image vs CER, heatmap de confusion de caractères,
|
| 530 |
+
diagrammes de fiabilité (calibration ECE/MCE — Sprint 43),
|
| 531 |
+
graphiques de bootstrap CI 95 %, profil philologique par moteur
|
| 532 |
+
(Sprint 62), throughput effectif (Sprint 91), tendances
|
| 533 |
+
longitudinales (Sprint 92), DAG de pipeline composée (Sprint 95),
|
| 534 |
+
etc.
|
| 535 |
|
| 536 |
+
#### Vue Caractères
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 537 |
|
| 538 |
+
Matrice de confusion Unicode interactive, tableau des
|
| 539 |
+
caractères les plus souvent manqués par chaque moteur, CER par
|
| 540 |
+
bloc Unicode (Sprint 55), analyse des ligatures.
|
|
|
|
|
|
|
|
|
|
| 541 |
|
| 542 |
+
### 7.2 Panneaux latéraux
|
|
|
|
| 543 |
|
| 544 |
+
- **Glossaire contextuel** (Sprint 21) : `?` à côté de chaque
|
| 545 |
+
en-tête de colonne ; clic ouvre un panneau avec définition,
|
| 546 |
+
ce qu'on mesure, usage, limites, référence primaire (25
|
| 547 |
+
entrées bilingues).
|
| 548 |
+
- **Mode avancé** (Sprint 21) : choix de colonnes visibles,
|
| 549 |
+
filtres par strate, opt-in score composite personnel
|
| 550 |
+
(curseurs à 0 par défaut, formule visible, warning explicite
|
| 551 |
+
« il n'existe pas de pondération universellement valide »),
|
| 552 |
+
toggle palette daltonien-friendly (Sprint A7), URL stateful.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 553 |
|
| 554 |
+
### 7.3 Exports
|
| 555 |
|
| 556 |
+
| Format | Statut |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 557 |
|---|---|
|
| 558 |
+
| HTML autonome | ✅ Livré |
|
| 559 |
+
| CSV (vue courante avec filtres) | ✅ Livré |
|
| 560 |
+
| JSON (BenchmarkResult complet) | ✅ Livré |
|
| 561 |
+
| Snapshot reproductibilité (versions, commit, lock) | ✅ Sprint 27 |
|
| 562 |
+
| Lazy images (rapport HTML + dossier `report-assets/`) | ✅ Sprint A5 / M-16 |
|
| 563 |
+
| PDF | ❌ Non livré (cf. §10) |
|
| 564 |
+
| ALTO XML / PAGE XML / images annotées | ❌ Non livré (cf. §10) |
|
| 565 |
+
|
| 566 |
+
### 7.4 Accessibilité
|
| 567 |
+
|
| 568 |
+
Conformité WCAG 2.1 niveau AA (cf.
|
| 569 |
+
[`ACCESSIBILITY.md`](ACCESSIBILITY.md)) :
|
| 570 |
+
|
| 571 |
+
- Skip-to-content link (WCAG 2.4.1).
|
| 572 |
+
- `role="img"` + `aria-label` + table de données jumelle
|
| 573 |
+
pour chaque graphique Chart.js (WCAG 1.1.1).
|
| 574 |
+
- `scope="col"` sur tous les `<th>`.
|
| 575 |
+
- Palette par défaut Okabe-Ito (daltonien-friendly), toggle vers
|
| 576 |
+
l'ancienne palette via panneau Avancé ou `?palette=classic`.
|
| 577 |
+
- Bilinguisme intégral (skip-link, ARIA labels, captions des
|
| 578 |
+
tables jumelles).
|
| 579 |
+
- Audit RGAA externe planifié Sprint A15.
|
| 580 |
|
| 581 |
---
|
| 582 |
|
| 583 |
+
## 8. Module 6 — Interface web et CLI
|
|
|
|
|
|
|
| 584 |
|
| 585 |
+
### 8.1 Interface web FastAPI
|
|
|
|
|
|
|
|
|
|
|
|
|
| 586 |
|
| 587 |
+
- Configuration de benchmark : sélection corpus, moteurs,
|
| 588 |
+
normalisation.
|
| 589 |
+
- Streaming SSE de la progression en temps réel (`Last-Event-ID`
|
| 590 |
+
reconnexion supportée — Sprint 26).
|
| 591 |
+
- Persistance des jobs en SQLite (mode WAL, thread-safe), reprise
|
| 592 |
+
des jobs orphelins au boot.
|
| 593 |
+
- Upload ZIP depuis le navigateur.
|
| 594 |
+
- Imports HTR-United / HuggingFace via formulaire.
|
| 595 |
+
- Bilingue FR/EN.
|
| 596 |
+
- Healthcheck minimal `/health` (Sprint A4 / M-3).
|
| 597 |
+
- Token CSRF (`/api/csrf/token`) + middleware (Sprint A4 / B-11)
|
| 598 |
+
activable via `PICARONES_CSRF_REQUIRED=1` pour les déploiements
|
| 599 |
+
institutionnels derrière SSO.
|
| 600 |
|
| 601 |
+
### 8.2 Interface en ligne de commande (Click)
|
|
|
|
|
|
|
| 602 |
|
| 603 |
+
15 commandes :
|
|
|
|
| 604 |
|
| 605 |
+
```bash
|
| 606 |
+
picarones run # benchmark
|
| 607 |
+
picarones report # rapport HTML depuis JSON
|
| 608 |
+
picarones demo # rapport démo synthétique
|
| 609 |
+
picarones compare # compare deux runs JSON, exit-code 2 si régression
|
| 610 |
+
picarones diagnose # workflow bench + leviers + recommandations factuelles
|
| 611 |
+
picarones economics # workflow bench + throughput + coût projeté
|
| 612 |
+
picarones edition # workflow bench + métriques philologiques
|
| 613 |
+
picarones pipeline # run/compare pipelines composées YAML
|
| 614 |
+
picarones import # IIIF / HF / HTR-United
|
| 615 |
+
picarones serve # interface web locale
|
| 616 |
+
picarones history # historique longitudinal SQLite
|
| 617 |
+
picarones robustness # courbes CER vs dégradation
|
| 618 |
+
picarones engines # liste les moteurs disponibles
|
| 619 |
+
picarones metrics # CER/WER entre deux fichiers texte
|
| 620 |
+
picarones info # version + system info
|
| 621 |
```
|
| 622 |
|
| 623 |
+
Toutes les commandes supportent `--help`. Workflows pré-câblés
|
| 624 |
+
(`diagnose`, `economics`, `edition`) sont des combinaisons
|
| 625 |
+
canoniques pour les profils utilisateurs typiques.
|
| 626 |
+
|
| 627 |
### 8.3 Intégration CI/CD
|
| 628 |
|
| 629 |
+
- Mode headless (`--no-progress`).
|
| 630 |
+
- Output JSON machine-readable.
|
| 631 |
+
- Exit code 2 sur `picarones compare` si régression CER détectée.
|
| 632 |
+
- Workflow GitHub Actions `perf_regression.yml` (Sprint A5 /
|
| 633 |
+
M-14) — cron hebdomadaire + sur PR touchant le runner.
|
| 634 |
|
| 635 |
---
|
| 636 |
|
| 637 |
+
## 9. Reproductibilité et sécurité
|
| 638 |
|
| 639 |
+
### 9.1 Snapshots de reproductibilité (Sprint 27)
|
| 640 |
|
| 641 |
+
Chaque rapport HTML embarque un dict `report_data["snapshots"]`
|
| 642 |
+
qui contient :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 643 |
|
| 644 |
+
- **pricing** — YAML brut intégral de `picarones/data/pricing.yaml`
|
| 645 |
+
utilisé.
|
| 646 |
+
- **glossary** — entrées du glossaire effectivement référencées.
|
| 647 |
+
- **normalization** — profil sérialisé.
|
| 648 |
+
- **environment** — version Picarones, Python, plateforme, commit
|
| 649 |
+
git, paquets installés (top 200).
|
| 650 |
|
| 651 |
+
Procédure complète de re-jeu d'un benchmark à 5 ans d'écart :
|
| 652 |
+
[`docs/reproducibility-snapshots.md`](docs/reproducibility-snapshots.md)
|
| 653 |
+
(Sprint A8 / M-12).
|
|
|
|
|
|
|
|
|
|
| 654 |
|
| 655 |
+
### 9.2 Reproductibilité des builds
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 656 |
|
| 657 |
+
- Lock files `requirements.lock` + `requirements-dev.lock`
|
| 658 |
+
générés via `uv pip compile` (Sprint A8).
|
| 659 |
+
- Image Docker épinglée à un patch précis via `ARG PYTHON_BASE_IMAGE`
|
| 660 |
+
(rotation trimestrielle).
|
| 661 |
+
- Release pipeline GitHub Actions (Sprint A9) : tag `v*.*.*` →
|
| 662 |
+
PyPI via OIDC trust + ghcr.io multi-arch + GitHub Release auto.
|
| 663 |
|
| 664 |
+
### 9.3 Sécurité institutionnelle
|
| 665 |
|
| 666 |
+
- **Mode public** (`PICARONES_PUBLIC_MODE=1`) : refuse les moteurs
|
| 667 |
+
cloud mutualisés et les pipelines LLM facturés à la clef serveur.
|
| 668 |
+
- **CSRF** double-submit (`PICARONES_CSRF_REQUIRED=1`) — Sprint A4.
|
| 669 |
+
- **XML défendu** par `defusedxml` partout (XXE / Billion Laughs).
|
| 670 |
+
- **Zip-slip prévenu** par `Path(member.filename).name`.
|
| 671 |
+
- **Validation Pillow** systématique (CVE bombes de
|
| 672 |
+
décompression).
|
| 673 |
+
- **Rate limiting** par IP + sémaphore de jobs concurrents.
|
| 674 |
+
- **CSP + en-têtes durcis** (X-Content-Type-Options,
|
| 675 |
+
Referrer-Policy).
|
| 676 |
|
| 677 |
+
Voir [`SECURITY.md`](SECURITY.md) pour la procédure complète.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 678 |
|
| 679 |
+
### 9.4 RGPD et rétention
|
|
|
|
|
|
|
|
|
|
|
|
|
| 680 |
|
| 681 |
+
Politique documentée dans
|
| 682 |
+
[`docs/operations/data-retention-rgpd.md`](docs/operations/data-retention-rgpd.md)
|
| 683 |
+
(Sprint A11 / M-8). Purge automatique des uploads anciens
|
| 684 |
+
configurable via `PICARONES_UPLOAD_RETENTION_DAYS=7` par défaut.
|
| 685 |
|
| 686 |
---
|
| 687 |
|
| 688 |
+
## 10. Limites assumées et non-fonctionnalités
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 689 |
|
| 690 |
+
Cette section décrit explicitement **ce que Picarones ne fait pas
|
| 691 |
+
et ne fera pas dans la v1.x**. Plusieurs items étaient promis dans
|
| 692 |
+
la SPECS v1 (Mars 2025) — leur abandon est un choix éditorial
|
| 693 |
+
documenté ci-dessous, pas un oubli.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 694 |
|
| 695 |
<!-- specs-check: known-abandoned-start -->
|
| 696 |
|
| 697 |
+
> Toutes les fonctionnalités listées ci-dessous étaient promises ou
|
| 698 |
+
> évoquées dans SPECS v1 et sont **explicitement abandonnées,
|
| 699 |
+
> non implémentées ou reportées** dans la v2.0 de ce document.
|
| 700 |
+
> Le test ``tests/docs/test_specs_consistency.py`` (Sprint A2)
|
| 701 |
+
> détecte cette section comme la déclaration officielle des
|
| 702 |
+
> non-fonctionnalités du projet.
|
| 703 |
+
|
| 704 |
+
### 10.1 Adapters OCR non livrés
|
| 705 |
+
|
| 706 |
+
- **Kraken** : prévu v1.0 dans SPECS v1, jamais implémenté. Choix :
|
| 707 |
+
ouverture en plugins externes via la politique de modules
|
| 708 |
+
contribués (Sprint 97), pas un adapter intégré au cœur. Un
|
| 709 |
+
utilisateur peut écrire son `KrakenEngine(BaseOCREngine)` et
|
| 710 |
+
l'exécuter via les pipelines composables.
|
| 711 |
+
- **AWS Textract** : prévu v1.1, abandonné. Pas de DPA Amazon
|
| 712 |
+
signé, et le périmètre patrimonial est mieux servi par les
|
| 713 |
+
trois clouds déjà intégrés (Mistral OCR, Google Vision, Azure
|
| 714 |
+
DI).
|
| 715 |
+
- **Calamari** : prévu v1.1, abandonné. Maintenance d'un adapter
|
| 716 |
+
par moteur ≈ 50 PJ/an ; mieux vaut concentrer sur les 5 adapters
|
| 717 |
+
livrés et ouvrir Calamari en plugin externe.
|
| 718 |
+
- **OCRopus4** : prévu v1.2, abandonné — projet historique en
|
| 719 |
+
fin de vie.
|
| 720 |
+
- **Moteur custom YAML** (`type: cli` / `type: api`) : prévu en
|
| 721 |
+
SPECS v1.0, abandonné. **Refondu en pipelines composables**
|
| 722 |
+
(Sprint 63-70) qui permettent de brancher n'importe quel module
|
| 723 |
+
via une spec YAML — plus puissant que la déclaration d'engine
|
| 724 |
+
custom imaginée à l'origine.
|
| 725 |
+
|
| 726 |
+
### 10.2 Exports non livrés
|
| 727 |
+
|
| 728 |
+
- **Export PDF** du rapport. CSV + JSON + HTML autonome couvrent
|
| 729 |
+
les usages observés. Reportable sur demande utilisateur si
|
| 730 |
+
besoin tracé.
|
| 731 |
+
- **Export ALTO XML** des sorties OCR.
|
| 732 |
+
- **Export PAGE XML** des sorties OCR.
|
| 733 |
+
- **Export images annotées** (PNG avec zones d'erreur surlignées).
|
| 734 |
+
|
| 735 |
+
### 10.3 Fonctionnalités explicitement abandonnées
|
| 736 |
+
|
| 737 |
+
- **Recommandation automatique** « quel concurrent pour quel
|
| 738 |
+
usage ». Promise dans SPECS v1 §7.1, **abandonnée** au profit
|
| 739 |
+
du moteur narratif factuel (Sprint 19) et de la philosophie
|
| 740 |
+
« Picarones mesure et classe — il ne tranche pas ». Les leviers
|
| 741 |
+
d'amélioration (Sprint 51-82) restent factuels.
|
| 742 |
+
- **Score de consensus / vote majoritaire / ensemble** : Picarones
|
| 743 |
+
livre l'**oracle borné supérieur** (Sprint 35) et le score de
|
| 744 |
+
spécialisation inter-moteurs (Sprint 89) — observations
|
| 745 |
+
factuelles. Pas de mécanisme de vote actif intégré ; au
|
| 746 |
+
chercheur de combiner les sorties s'il le décide.
|
| 747 |
+
- **Clustering automatique k-means des erreurs**. Remplacé par
|
| 748 |
+
la taxonomie discrète (Sprint 5) + co-occurrence Jaccard
|
| 749 |
+
(Sprint 75) + heatmap intra-doc (Sprint 76).
|
| 750 |
+
- **Annotations inline du paléographe exportées en JSON**. Non
|
| 751 |
+
implémentées.
|
| 752 |
+
- **Badge SVG de qualité OCR pour CI**. `picarones compare` avec
|
| 753 |
+
exit code 2 sur régression couvre l'usage CI ; un badge SVG
|
| 754 |
+
reste nice-to-have, non priorisé.
|
| 755 |
+
- **Dataset de référence embarqué de 100 documents
|
| 756 |
+
patrimoniaux**. Picarones est volontairement un **banc d'essai
|
| 757 |
+
sur votre golden dataset** — le 100-doc corpus de référence
|
| 758 |
+
imaginé en SPECS v1 §3.3 entrerait en concurrence avec les
|
| 759 |
+
corpus institutionnels existants (HTR-United, Esposalles,
|
| 760 |
+
IAM, RIMES, READ-BAD) et en fragmenterait l'écosystème. Les
|
| 761 |
+
5 documents synthétiques de Sprint A5 (`tests/fixtures/reference_corpus/`)
|
| 762 |
+
servent uniquement à l'anti-régression CER en CI, pas à la
|
| 763 |
+
valeur scientifique.
|
| 764 |
+
|
| 765 |
+
### 10.4 Fonctionnalités scientifiques planifiées
|
| 766 |
+
|
| 767 |
+
À livrer dans des sprints futurs :
|
| 768 |
+
|
| 769 |
+
- **CITATION.cff + DOI Zenodo + papier JOSS** (Sprint A12 du
|
| 770 |
+
plan institutionnel) — débloque la citation académique propre.
|
| 771 |
+
- **Traçabilité des profils de normalisation aux standards
|
| 772 |
+
éditoriaux** (MUFI v4.0, TEI P5, DEAF) — Sprint A12.
|
| 773 |
+
- **Citations primaires des méthodes statistiques** dans les
|
| 774 |
+
docstrings (Demšar 2006, Wilcoxon 1945, Efron 1979) —
|
| 775 |
+
Sprint A12.
|
| 776 |
|
| 777 |
<!-- specs-check: known-abandoned-end -->
|
| 778 |
|
| 779 |
+
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 780 |
|
| 781 |
+
## 11. Roadmap d'évolution
|
| 782 |
|
| 783 |
+
Trois documents complémentaires pilotent l'évolution :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 784 |
|
| 785 |
+
- [`CHANGELOG.md`](CHANGELOG.md) — historique sprint par sprint,
|
| 786 |
+
format Keep a Changelog.
|
| 787 |
+
- [`docs/roadmap/evolution-2026.md`](docs/roadmap/evolution-2026.md) —
|
| 788 |
+
roadmap technique 2026+ (axes A et B : nouvelles métriques et
|
| 789 |
+
pipelines composables).
|
| 790 |
+
- [`docs/audits/`](docs/audits/) — audits institutionnels et
|
| 791 |
+
plans de remédiation (sprints A1 à A15 du plan en cours).
|
| 792 |
|
| 793 |
+
L'**état du plan institutionnel** au 2 mai 2026 :
|
|
|
|
|
|
|
|
|
|
|
|
|
| 794 |
|
| 795 |
+
| Phase | Sprints | Statut |
|
| 796 |
+
|---|---|---|
|
| 797 |
+
| Phase 0 — Garde-fous CI | A1, A2 | ✅ Terminée |
|
| 798 |
+
| Phase 1 — Hygiène architecturale | A3 | ✅ Terminée |
|
| 799 |
+
| Phase 2 — Robustesse runtime | A4, A5 | ✅ Terminée |
|
| 800 |
+
| Phase 3 — Accessibilité | A6, A7 | ✅ Terminée |
|
| 801 |
+
| Phase 4 — Reproductibilité ops | A8, A9 | ✅ Terminée |
|
| 802 |
+
| Phase 5 — Gouvernance | A10, A11 | ✅ Terminée |
|
| 803 |
+
| Phase 7 — Refonte doc produit | A13, **A14 (ce document)** | ✅ Terminée |
|
| 804 |
+
| Phase 6 — Publication scientifique | A12 | ⏳ Planifiée |
|
| 805 |
+
| Phase 8 — Validation externe | A15 | ⏳ Planifiée (calendrier externe) |
|
| 806 |
|
| 807 |
+
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 808 |
|
| 809 |
+
## 12. Migration v1 → v2 — annexe historique
|
| 810 |
|
| 811 |
+
Pour les lecteurs qui avaient pris connaissance de SPECS v1.0
|
| 812 |
+
(mars 2025) ou de l'addendum Sprints 16-30, voici la table de
|
| 813 |
+
migration des promesses changées :
|
|
|
|
|
|
|
| 814 |
|
| 815 |
+
| SPECS v1 disait | SPECS v2 documente | Raison |
|
| 816 |
+
|---|---|---|
|
| 817 |
+
| Adapter Kraken (priorité v1.0) | Ouvert en plugin externe | Politique modules contribués Sprint 97 ; concentration sur 5 adapters cœur. |
|
| 818 |
+
| Adapter AWS Textract (v1.1) | Abandonné | Pas de DPA, périmètre couvert par 3 clouds existants. |
|
| 819 |
+
| Adapter Calamari (v1.1) | Abandonné | Maintenance par adapter ≈ 50 PJ/an ; mieux servi en plugin externe. |
|
| 820 |
+
| Adapter OCRopus4 (v1.2) | Abandonné | Projet historique en fin de vie. |
|
| 821 |
+
| Moteur custom YAML | Refondu en pipelines composables | Sprint 63-70 livre une infrastructure plus puissante. |
|
| 822 |
+
| Recommandation automatique | Remplacée par moteur narratif factuel | Pivot philosophique vers la neutralité éditoriale. |
|
| 823 |
+
| Export PDF | Abandonné | CSV + JSON + HTML couvrent les usages. |
|
| 824 |
+
| Export ALTO/PAGE/images annotées | Abandonné | Idem. |
|
| 825 |
+
| `picarones estimate` (preview coût) | Remplacé par vue Pareto post hoc | Sprint 20 livre la même information dans le rapport. |
|
| 826 |
+
| Score consensus / k-means | Remplacé par oracle borné + taxonomie discrète + Jaccard | Sprint 35, 5, 75 — équivalence fonctionnelle, formalisme différent. |
|
| 827 |
+
| Annotations inline JSON | Abandonné | Pas de demande utilisateur observée. |
|
| 828 |
+
| Badge SVG qualité OCR | Abandonné | `picarones compare` exit code 2 couvre la CI. |
|
| 829 |
+
| Dataset 100 docs embarqué | Abandonné | Banc d'essai sur votre golden dataset, pas un dataset de référence. |
|
| 830 |
+
| Prompt latin | Pas livré | Reportable sur demande. |
|
| 831 |
+
|
| 832 |
+
À l'inverse, **~25 modules majeurs ajoutés depuis Sprint 30** sont
|
| 833 |
+
documentés dans la nouvelle SPECS aux §6 (NER, reading order F1,
|
| 834 |
+
layout F1, recherchabilité fuzzy, séquences numériques, 6 modules
|
| 835 |
+
philologiques transversaux, narrative engine, Friedman+Nemenyi+CDD,
|
| 836 |
+
Pareto, glossaire, métriques inter-moteurs, absorption d'erreur,
|
| 837 |
+
pipelines composables, registre typé, audit modules, comparaison
|
| 838 |
+
de runs, stratification, calibration, longitudinal, throughput
|
| 839 |
+
effectif, etc.) — invisibles dans SPECS v1.
|
| 840 |
|
| 841 |
---
|
| 842 |
|
| 843 |
+
*Picarones est conçu pour devenir une référence open-source
|
| 844 |
+
d'évaluation OCR/HTR dans le champ patrimonial — métriques
|
| 845 |
+
adaptées aux documents historiques, pipelines composables,
|
| 846 |
+
intégration des standards bibliothéconomiques (IIIF, ALTO XML,
|
| 847 |
+
PAGE XML, HTR-United, eScriptorium, Gallica), rapport interactif
|
| 848 |
+
exportable, snapshot de reproductibilité.*
|
| 849 |
+
|
| 850 |
+
*Dernière mise à jour : 2 mai 2026 (Sprint A14, refonte v2.0).*
|