Claude commited on
Commit
1acc64c
·
unverified ·
1 Parent(s): c0f7ba9

docs(architecture): manifeste 3 cercles avec règle de dépendance stricte

Browse files

Réécriture du manifeste pour clarifier la frontière entre cercles :

- Cercle 1 (`core/`) : abstractions pures, pas de logique métier.
Liste exhaustive : modules, corpus, results, metric_registry,
metric_hooks, pipeline, facts.
- Cercle 2 (`measurements/`, `engines/`, `llm/`, `pipelines/`,
`modules/`) : implémentations officielles distribuées.
- Cercle 3 (`extras/`, `report/`, `cli/`, `web/`) : extensions et
présentation.

Règle de dépendance : les flèches d'import vont uniquement de
l'extérieur vers l'intérieur. Pas de shim — un module a un seul
emplacement physique.

https://claude.ai/code/session_01Hsd7kL8yeCbXn1mA7GQK9L

Files changed (1) hide show
  1. docs/architecture.md +132 -170
docs/architecture.md CHANGED
@@ -1,181 +1,143 @@
1
- # Architecture Picarones — vue d'ensemble post-chantiers
2
-
3
- Ce document décrit l'architecture du projet **après les chantiers 1-5**
4
- du plan d'évolution post-Sprint 97. Il complète le `CLAUDE.md`
5
- historique (qui reste l'historique chronologique des sprints) en
6
- donnant une **vue thématique** de l'organisation actuelle du code.
7
-
8
- ## Vue d'ensemble
9
 
10
  Picarones est un **banc d'essai** pour pipelines OCR/HTR sur documents
11
- patrimoniaux. Le projet livre :
12
-
13
- 1. **Engines OCR** (5 adapters : Tesseract, Pero OCR, Mistral OCR,
14
- Google Vision, Azure Document Intelligence).
15
- 2. **Adapters LLM** (4 providers : OpenAI, Anthropic, Mistral, Ollama)
16
- pour les pipelines OCR+LLM (zero-shot, post-correction…).
17
- 3. **Modules de référence** (chantier 1) : `TextToAltoMonoRegion`
18
- pour démonstrer l'extension `BaseModule` (image+texte → ALTO).
19
- 4. **Runner** orchestrateur multi-moteurs avec parallélisation
20
- ProcessPool (CPU-bound) ou ThreadPool (IO-bound).
21
- 5. **Rapport HTML** auto-suffisant (Chart.js embarqué) avec 5+ vues
22
- thématiques composables.
23
- 6. **Interface web FastAPI** + **CLI Click** (15 sous-commandes).
24
-
25
- ## Structure des packages
26
 
27
  ```
28
- picarones/
29
- ├── cli/ (chantier 5) Package CLI Click
30
- ├── __init__.py Groupe `cli` + helpers + commandes simples
31
- ├── _workflows.py run, diagnose, economics, edition, compare
32
- ├── _pipeline.py pipeline run, pipeline compare
33
- ├── _imports.py import iiif (+ futurs)
34
- ├── _serve.py serve (FastAPI launcher)
35
- │ ├── _history.py history (consultation SQLite)
36
- │ └── _robustness.py analyse robustesse
37
-
38
- ├── core/
39
- │ ├── corpus.py Document, Corpus, GTLevel multi-niveaux
40
- │ ├── modules.py BaseModule + ArtifactType (Sprint 33)
41
- │ ├── metric_registry.py Registre typé (Sprint 34)
42
- │ ├── builtin_metrics.py Métriques scalaires natives
43
- │ ├── alto_metrics.py (chantier 1) Métriques (ALTO, ALTO)
44
- │ ├── metric_hooks.py (chantier 2) Profils + registre de hooks
45
- │ ├── builtin_hooks.py (chantier 2) 12 hooks doc + 12 agrégateurs
46
- │ ├── runner.py Orchestrateur multi-moteurs
47
- │ ├── pipeline_runner.py Banc d'essai de pipelines composées
48
- │ ├── narrative/
49
- │ │ ├── facts.py Modèle Fact + 18+ FactType
50
- │ │ ├── registry.py Registre déclaratif
51
- │ │ ├── arbiter.py Arbitrage des Facts (anti-redondance)
52
- │ │ ├── renderer.py Rendu i18n YAML → str.format_map
53
- │ │ └── detectors/ (chantier 5) 6 sous-modules thématiques
54
- │ │ ├── ranking.py
55
- │ │ ├── pareto.py
56
- │ │ ├── stratum.py
57
- │ │ ├── quality.py
58
- │ │ ├── history.py
59
- │ │ └── ensemble.py
60
- │ └── ... (~60 modules métriques philologiques, statistiques, etc.)
61
-
62
- ├── engines/
63
- │ ├── base.py (chantier 1) BaseOCREngine factorisée
64
- │ │ avec hooks _run_with_native +
65
- │ │ _extract_raw_confidences
66
- │ ├── tesseract.py
67
- │ ├── pero_ocr.py
68
- │ ├── mistral_ocr.py
69
- │ ├── google_vision.py
70
- │ └── azure_doc_intel.py
71
-
72
- ├── llm/
73
- │ ├── base.py (chantier 4) Helpers normalize_llm_content +
74
- │ │ log_http_error factorisés
75
- │ ├── mistral_adapter.py
76
- │ ├── openai_adapter.py
77
- │ ├── anthropic_adapter.py
78
- │ └── ollama_adapter.py
79
-
80
- ├── modules/ (chantier 1) Modules BaseModule de référence
81
- │ └── alto_text_to_mono_region.py
82
-
83
- ├── importers/
84
- │ ├── _http.py (chantier 4) Helpers HTTP factorisés
85
- │ ├── iiif.py
86
- │ ├── htr_united.py
87
- │ ├── gallica.py (chantier 4) Délègue à _http
88
- │ ├── huggingface.py
89
- │ └── escriptorium.py
90
-
91
- ├── pipelines/ Pipelines OCR+LLM (zero_shot, post_correction)
92
-
93
- ├── prompts/ 8 templates .txt FR+EN
94
-
95
- ├── report/ Rapport HTML
96
- │ ├── generator.py Orchestrateur Jinja2
97
- │ ├── views/ (chantier 3) 5 vues thématiques composables
98
- │ │ ├── economics.py throughput + cost projection
99
- │ │ ├── advanced_taxonomy.py taxonomy comparison + lexical_modernization
100
- │ │ ├── diagnostics.py levers + image_predictive + baseline + worst_lines
101
- │ │ ├── pipeline.py DAG + error_absorption + incremental + audit
102
- │ │ └── robustness.py robustness projection
103
- │ ├── *_render.py 26 renderers atomiques
104
- │ ├── templates/ Jinja2 (10 vues HTML + partials)
105
- │ ├── i18n/{fr,en}.json 410 clés
106
- │ ├── glossary/ 25 entrées YAML bilingues
107
- │ └── vendor/ Chart.js embarqué
108
-
109
- └── web/
110
- ├── app.py FastAPI (2065 lignes — découpage reporté)
111
- ├── security.py
112
- ├── templates/, static/
113
- └── ...
114
  ```
115
 
116
- ## Fluxes principaux
117
 
118
- ### Bench OCR classique
 
119
 
120
- ```
121
- CLI: picarones run --corpus DIR --engines tess,pero --profile standard
122
-
123
- load_corpus_from_directory(DIR) Corpus
124
- _engine_from_name("tess") → TesseractEngine (BaseOCREngine)
125
- (chantier 1 : refondu sur _run_with_native
126
- + _extract_raw_confidences)
127
-
128
- run_benchmark(corpus, engines, profile="standard")
129
- ↓ (profil active 12 hooks doc + 12 agrégateurs via builtin_hooks)
130
- ProcessPoolExecutor / ThreadPoolExecutor
131
-
132
- _compute_document_result(doc, profile)
133
- ↓ (run_document_hooks itère sur les hooks actifs du profil)
134
- DocumentResult (avec confusion, taxonomy, calibration, …)
135
- ↓ (run_corpus_aggregators)
136
- EngineReport (avec aggregated_*)
137
-
138
- BenchmarkResult
139
-
140
- ReportGenerator.generate()
141
- ↓ (build_economics_view_html + build_advanced_taxonomy_view_html
142
- + build_diagnostics_view_html selon profil)
143
- report.html (autonome, ~450 Ko)
144
- ```
145
 
146
- ### Bench pipeline composée (axe B, chantier 1 livré bout-en-bout)
 
147
 
148
- ```
149
- CLI: picarones pipeline run examples/pipelines/ocr_to_alto.yaml --corpus DIR
150
-
151
- load_pipeline_spec_from_yaml()
152
-
153
- PipelineSpec :
154
- step "ocr" : TesseractEngine (IMAGE TEXT)
155
- step "alto" : TextToAltoMonoRegion (IMAGE+TEXT → ALTO)
156
-
157
- PipelineRunner.run(spec, document)
158
- (compute_at_junction((TEXT,TEXT)) cer/wer/mer/wil)
159
- (compute_at_junction((ALTO,ALTO)) alto_text_cer/wer/...)
160
- PipelineResult avec junction_metrics par étape
161
-
162
- build_pipeline_report_html() (rapport pipeline composée autonome)
163
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
 
165
- ## Documents complémentaires
166
-
167
- - [`docs/profiles.md`](profiles.md) — les 7 profils de calcul du chantier 2.
168
- - [`docs/cli-workflows.md`](cli-workflows.md) — les 15 commandes CLI.
169
- - [`docs/views.md`](views.md) — les vues HTML disponibles dans le rapport.
170
- - [`docs/user/reading-a-report.md`](user/reading-a-report.md) — guide
171
- utilisateur pour lire un rapport.
172
- - [`docs/user/writing-a-pipeline-module.md`](user/writing-a-pipeline-module.md)
173
- — guide pour brancher un module tiers (`BaseModule`).
174
- - [`docs/developer/narrative-engine.md`](developer/narrative-engine.md)
175
- — détecteurs narratifs : architecture, comment en ajouter.
176
- - [`docs/developer/module-policy.md`](developer/module-policy.md) — manifest
177
- + audit pour modules contribués (Sprint 97).
178
- - [`docs/case-studies/`](case-studies/) — 2 cas d'école (registres
179
- paroissiaux, édition critique).
180
- - [`docs/roadmap/evolution-2026.md`](roadmap/evolution-2026.md) — plan
181
- d'évolution (axe A métrique + axe B pipelines composées).
 
1
+ # Architecture Picarones — manifeste
 
 
 
 
 
 
 
2
 
3
  Picarones est un **banc d'essai** pour pipelines OCR/HTR sur documents
4
+ patrimoniaux. Le code est organisé en **3 cercles concentriques** avec
5
+ une règle de dépendance stricte : les flèches d'import vont uniquement
6
+ de l'extérieur vers l'intérieur.
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  ```
9
+ Cercle 3 (extras, report, cli, web)
10
+
11
+
12
+ Cercle 2 (measurements, engines, llm, pipelines, modules)
13
+
14
+
15
+ Cercle 1 (core)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  ```
17
 
18
+ ## Cercle 1 — `picarones/core/` : abstractions de domaine
19
 
20
+ Pas de logique métier, pas d'I/O. Uniquement des **contrats** que les
21
+ cercles supérieurs implémentent.
22
 
23
+ | Module | Contenu |
24
+ |---|---|
25
+ | `modules.py` | `BaseModule`, `ArtifactType`, `validate_inputs`/`validate_outputs` |
26
+ | `corpus.py` | `Document`, `Corpus`, `GTLevel`, payloads typés (`TextGT`, `AltoGT`, `PageGT`, `EntitiesGT`, `ReadingOrderGT`) |
27
+ | `results.py` | `DocumentResult`, `EngineReport`, `BenchmarkResult` |
28
+ | `metric_registry.py` | `MetricSpec`, `register_metric`, `select_metrics`, `compute_at_junction` |
29
+ | `metric_hooks.py` | `register_document_metric`, `register_corpus_aggregator`, profils de calcul |
30
+ | `pipeline.py` | `PipelineRunner`, `PipelineSpec`, `PipelineStep` (DAG de modules) |
31
+ | `facts.py` | `Fact`, `FactType`, `FactImportance`, `DetectorRegistry` |
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
+ **Règle** : un module du cercle 1 peut importer un autre module du
34
+ cercle 1. Il ne peut **rien** importer des cercles 2 ou 3.
35
 
36
+ ## Cercle 2 — implémentations officielles
37
+
38
+ Les implémentations distribuées par défaut dans le package `picarones`.
39
+
40
+ ### `picarones/measurements/` — métriques (~50 modules)
41
+
42
+ | Catégorie | Modules |
43
+ |---|---|
44
+ | Coeur | `metrics.py`, `statistics.py`, `runner.py`, `builtin_hooks.py`, `builtin_metrics.py`, `normalization.py` |
45
+ | Erreurs | `confusion.py`, `taxonomy.py`, `taxonomy_comparison.py`, `taxonomy_cooccurrence.py`, `taxonomy_intra_doc.py` |
46
+ | Lignes/structure | `line_metrics.py`, `structure.py`, `worst_lines.py`, `char_scores.py` |
47
+ | Calibration/fiabilité | `calibration.py`, `reliability.py`, `hallucination.py` |
48
+ | Image | `image_quality.py`, `image_predictive.py`, `difficulty.py` |
49
+ | Robustesse | `robustness.py`, `robustness_projection.py` |
50
+ | Inter-moteurs | `inter_engine.py`, `specialization.py` |
51
+ | Statistique avancée | `baseline_comparison.py`, `longitudinal.py`, `incremental_comparison.py` |
52
+ | Contenu | `searchability.py`, `numerical_sequences.py`, `rare_tokens.py`, `readability.py` |
53
+ | Structure ALTO | `layout.py`, `reading_order.py`, `ner.py`, `ner_backends.py`, `error_absorption.py` |
54
+ | Économie | `cost_projection.py`, `marginal_cost.py`, `pricing.py`, `throughput.py` |
55
+ | Philologie historique | `mufi.py`, `abbreviations.py`, `unicode_blocks.py`, `early_modern_typography.py`, `modern_archives.py`, `roman_numerals.py`, `lexical_modernization.py`, `philological_runner.py` |
56
+ | Pipelines composées | `pipeline_benchmark.py`, `pipeline_comparison.py`, `pipeline_spec_loader.py`, `alto_metrics.py` |
57
+ | Divers | `equivalence_profile.py`, `levers.py`, `module_policy.py`, `history.py` |
58
+ | Runners adaptifs | `readability_runner.py`, `searchability_runner.py`, `numerical_sequences_runner.py` |
59
+ | Narratif | `narrative/` (arbiter, renderer, registry, 18 détecteurs en 6 familles) |
60
+
61
+ ### `picarones/engines/` — adapters OCR (5)
62
+
63
+ `tesseract.py`, `pero_ocr.py`, `mistral_ocr.py`, `google_vision.py`,
64
+ `azure_doc_intel.py`. Tous héritent de `picarones.core.engine.BaseOCREngine`
65
+ (qui vit dans `engines/base.py` pour la lisibilité).
66
+
67
+ ### `picarones/llm/` — adapters LLM (4)
68
+
69
+ `mistral_adapter.py`, `openai_adapter.py`, `anthropic_adapter.py`,
70
+ `ollama_adapter.py`. Interface commune dans `base.py`.
71
+
72
+ ### `picarones/pipelines/` — pipelines OCR+LLM intégrés
73
+
74
+ `base.py` (`OCRLLMPipeline`, qui hérite de `BaseOCREngine`),
75
+ `over_normalization.py`.
76
+
77
+ ### `picarones/modules/` — modules `BaseModule` officiels
78
+
79
+ Démonstrateurs qui prouvent l'axe B du plan d'évolution :
80
+ `alto_text_to_mono_region.py`.
81
+
82
+ ## Cercle 3 — extensions et présentation
83
+
84
+ ### `picarones/extras/importers/` — connecteurs corpus
85
+
86
+ `iiif.py`, `gallica.py`, `htr_united.py`, `huggingface.py`,
87
+ `escriptorium.py`, `_http.py`. Plugins pluggable, certains expérimentaux.
88
+
89
+ ### `picarones/report/` — rendu HTML
90
+
91
+ | Sous-dossier | Contenu |
92
+ |---|---|
93
+ | `generator.py` | Orchestration Jinja2 |
94
+ | `views/` | 5 vues thématiques (economics, advanced_taxonomy, diagnostics, pipeline, robustness) |
95
+ | `templates/` | Jinja2 (base, header, footer, vues, partials) |
96
+ | `i18n/` | FR/EN |
97
+ | `glossary/` | 25 entrées bilingues |
98
+ | `vendor/` | Chart.js |
99
+ | `*_render.py` | ~22 renderers (calibration, NER, Pareto, Sankey, etc.) |
100
+
101
+ Pas de sous-dossier `extras/render/` — tout le rendu est ici.
102
+
103
+ ### `picarones/cli/` — Click (7 fichiers)
104
+
105
+ Point d'entrée `picarones.cli:cli` (référencé dans `pyproject.toml`).
106
+ 15 sous-commandes : `run`, `diagnose`, `economics`, `edition`,
107
+ `compare`, `metrics`, `engines`, `info`, `report`, `demo`, `serve`,
108
+ `history`, `robustness`, `pipeline run/compare`, `import`.
109
+
110
+ ### `picarones/web/` — FastAPI
111
+
112
+ Interface web (`app.py`).
113
+
114
+ ## Données
115
+
116
+ | Dossier | Rôle |
117
+ |---|---|
118
+ | `picarones/prompts/` | Prompts LLM versionnés (8 fichiers, FR + EN) |
119
+ | `picarones/data/` | Tables indicatives (pricing, etc.) |
120
+ | `picarones/fixtures.py` | Corpus de démonstration |
121
+
122
+ ## Règles de migration
123
+
124
+ 1. **Pas de shim** : un module a un seul emplacement physique. Les
125
+ imports pointent directement vers la vraie source.
126
+ 2. **Pas de double API** : une fonction a un seul nom canonique. Les
127
+ alias historiques sont supprimés et les tests mis à jour.
128
+ 3. **Frontières strictes** : si un module Y du cercle N importe le
129
+ module X, alors le cercle de X est ≤ N. Une exception
130
+ pragmatique : `engines/base.py` est conceptuellement cercle 1
131
+ mais physiquement dans `engines/` pour rester avec ses
132
+ implémentations.
133
+ 4. **Les dépendances optionnelles** (`scipy`, `spacy`, etc.) sont
134
+ gérées par try/except à l'import — pas par shim.
135
+
136
+ ## Tests
137
+
138
+ Organisés par cercle : `tests/core/`, `tests/measurements/`,
139
+ `tests/engines/`, `tests/extras/`, `tests/report/`,
140
+ `tests/integration/` (tests E2E croisant plusieurs cercles).
141
 
142
+ Un test du cercle N **n'importe pas** les implémentations des
143
+ cercles > N (sauf `tests/integration/`).