File size: 4,273 Bytes
32c3118
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# Écrire un module pour le banc d'essai

Ce tutoriel montre **par l'exemple** comment écrire un module
Picarones qui peut être chargé dans une pipeline composée, audité,
et inclus dans un rapport. Pour la **politique normative complète**
(contrat d'interface, métadonnées obligatoires, règles d'audit),
voir [`developer/module-policy.md`](../developer/module-policy.md).

---

## Cas d'usage

Vous avez écrit un script qui post-corrige du texte OCR avec une
heuristique métier (par exemple : règles de normalisation propres
à un fonds d'archives donné). Vous voulez le brancher dans
Picarones pour mesurer son apport vs un baseline.

C'est exactement le cas que cible l'axe B (banc d'essai de
pipelines composées).

---

## Module minimal

Un module Picarones est une **classe Python** qui hérite de
`BaseModule` et implémente `run(...)`.

```python
# my_corrector.py
from picarones.domain.module_protocol import BaseModule
from picarones.domain.artifacts import ArtifactType, Artifact


class MyCorrector(BaseModule):
    """Post-corrige le texte OCR avec une règle métier."""

    input_types = (ArtifactType.TEXT,)
    output_types = (ArtifactType.TEXT,)

    def run(self, artifact: Artifact) -> Artifact:
        text = artifact.payload
        # Votre logique métier ici.
        corrected = text.replace(" l'", " l'").replace("  ", " ")
        return Artifact(
            type=ArtifactType.TEXT,
            payload=corrected,
        )
```

Quatre points à retenir :

1. `input_types` et `output_types` doivent être déclarés au niveau
   classe (le planner les lit avant exécution).
2. `run` prend un `Artifact` et en retourne un. Pas d'effet de
   bord, pas de mutation.
3. Le type de sortie peut différer du type d'entrée (par exemple
   `IMAGE → TEXT` pour un OCR).
4. La classe ne doit rien savoir de Picarones au-delà de
   `BaseModule` — c'est du Python ordinaire.

---

## Manifeste

Pour être chargé, le module doit déclarer un manifeste avec
**5 champs obligatoires** :

```python
from picarones.domain.module_protocol import ModuleManifest

MANIFEST = ModuleManifest(
    name="my-corrector",
    version="0.1.0",
    author="Vous <vous@institution.fr>",
    license="MIT",
    description="Post-correction par règles métier.",
)
```

Le manifeste sert à tracer **qui** est responsable du module dans
le rapport et à versionner les comparaisons longitudinales.

---

## Audit

Avant exécution, le module passe un audit statique :

```python
from picarones.evaluation.metrics.module_policy import audit_module

issues = audit_module(MyCorrector, MANIFEST)
assert not issues, f"Module non conforme : {issues}"
```

Si l'audit échoue, le module n'est **pas chargé** dans la pipeline
— pas d'exception silencieuse en production. Les règles d'audit
sont énumérées dans
[`developer/module-policy.md`](../developer/module-policy.md).

---

## Brancher dans une pipeline

Une pipeline est décrite par un `PipelineSpec`. Le module est
référencé par son chemin Python :

```python
from picarones.domain.pipeline_spec import PipelineSpec, PipelineStep

spec = PipelineSpec(
    name="ocr-puis-correction",
    steps=[
        PipelineStep(
            name="ocr",
            module="picarones.adapters.ocr.tesseract:TesseractAdapter",
        ),
        PipelineStep(
            name="post-correction",
            module="my_corrector:MyCorrector",
        ),
    ],
)
```

Lancez le benchmark avec ce pipeline :

```bash
picarones run \
  --corpus mon_corpus/ \
  --pipeline ocr-puis-correction.yaml \
  --output rapport.html
```

Le rapport présente alors **la pipeline complète** comme un
« moteur » à part entière, comparable aux autres dans le tableau
récapitulatif et le diagramme CD.

---

## Étapes suivantes

- Politique normative et règles d'audit :
  [`developer/module-policy.md`](../developer/module-policy.md)
- Étendre le moteur narratif pour commenter votre module :
  [`developer/extending-i18n.md`](../developer/extending-i18n.md)
- Reproductibilité de la comparaison :
  [`reference/reproducibility-snapshots.md`](../reference/reproducibility-snapshots.md)
- Architecture en cercles (où se branche un module) :
  [`explanation/architecture.md`](../explanation/architecture.md)