File size: 4,067 Bytes
99ad1af
 
dd38857
 
 
99ad1af
 
 
dd38857
99ad1af
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dd38857
 
 
 
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
# AltoView — fidélité documentaire ALTO

`AltoView` est la deuxième vue canonique.  Elle répond à la
question : **"quel pipeline produit le meilleur ALTO
exploitable ?"**

## Distinct de TextView

| Aspect | TextView | AltoView |
|---|---|---|
| Question | "meilleur texte final ?" | "meilleur ALTO exploitable ?" |
| Types acceptés | RAW_TEXT, CORRECTED_TEXT, ALTO, PAGE, CANONICAL | ALTO_XML uniquement |
| Projection | tout → RAW_TEXT | aucune (compare ALTO direct) |
| Mesure | qualité linguistique | fidélité structurelle |
| Métriques | CER, WER, MER, WIL | alto_validity, line_count_ratio, word_box_coverage |

Un même pipeline peut être évalué dans les deux vues.  Le rapport
HTML (S22) présentera les deux côte-à-côte pour qu'un lecteur
comprenne pourquoi deux pipelines avec le même CER peuvent
produire des ALTO de qualités différentes.

## Pattern d'omission explicite

Un pipeline qui ne produit pas d'`ALTO_XML` (exemple : Tesseract
texte brut sans ALTO) ne peut **pas** être évalué dans `AltoView`.
Le caller (typiquement un service applicatif au S19) doit
**omettre** ce pipeline du résultat, plutôt que de lui attribuer
un score factice à 0.

```python
from picarones.evaluation.views import build_alto_view

view = build_alto_view()

pipelines = [
    ("tesseract",       ArtifactType.RAW_TEXT),       # PAS d'ALTO
    ("ocr_llm_alto",    ArtifactType.ALTO_XML),       # ALTO ✓
    ("vlm_alto",        ArtifactType.ALTO_XML),       # ALTO ✓
]

eligible = [(n, t) for n, t in pipelines if view.accepts(t)]
omitted  = [(n, t) for n, t in pipelines if not view.accepts(t)]

# eligible: [("ocr_llm_alto", ALTO_XML), ("vlm_alto", ALTO_XML)]
# omitted: [("tesseract", RAW_TEXT)]
```

Le caller affichera dans le rapport : *"Tesseract n'est pas
évalué dans AltoView (ne produit pas d'ALTO)."*  Pas de score
factice à 0 qui ferait passer Tesseract pour un mauvais ALTO,
alors qu'il n'a juste pas pris part à la compétition.

## Métriques par défaut

### `alto_validity`

L'hypothèse a-t-elle une structure ALTO cohérente ?  ≥ 1 page ET
≥ 1 bloc ET ≥ 1 ligne.  Détecte les ALTO vides, tronqués, ou
produits par un reconstructeur défaillant.

- 1.0 = structure cohérente
- 0.0 = vide ou tronqué

### `alto_line_count_ratio`

Ratio min/max du nombre de lignes : `min(n_hyp, n_ref) / max(n_hyp,
n_ref)` ∈ [0, 1].  1.0 = même nombre de lignes.

Permet de détecter un reconstructeur qui invente ou perd des
lignes.  Ne dit rien sur l'**alignement spatial** — c'est
`textline_alignment` (post-livraison) qui mesurera cette
dimension.

### `alto_word_box_coverage`

Fraction des `AltoString` de l'hypothèse qui ont une `bbox`
définie (HPOS, VPOS, WIDTH, HEIGHT).  1.0 = tous les mots ont
une boîte (cas idéal pour un reconstructeur ALTO).

Un VLM qui produit du markdown puis le reconstruit en ALTO sans
coordonnées aura un `word_box_coverage` proche de 0.

## Garde-fou méthodologique

Le `ViewResult` produit par `AltoView` porte un `warnings`
explicite :

> Cette vue mesure la fidélité STRUCTURELLE de l'ALTO produit
> (validité, nombre de lignes, bbox).  La qualité TEXTUELLE de
> ce qui est dans cet ALTO est mesurée par TextView ; les deux
> doivent être lues ensemble pour juger un pipeline.
>
> Les pipelines qui ne produisent pas d'ALTO sont OMIS de cette
> vue.  Aucun score factice n'est attribué à un pipeline absent.

## Limites assumées

Reportées à des sprints suivants :

- **`textline_alignment`** (IoU des bbox de lignes) — exige un
  algorithme d'alignement bipartite par bbox.
- **`reading_order_consistency`** (Kendall tau sur les IDs de
  lignes) — exige un mapping ID → position.
- **`layout_f1` (ICDAR 2015)** — déjà implémenté dans
  `evaluation/metrics/layout.py` (migré au S10) sur des `Region`
  génériques ; un wrapper ALTO peut être ajouté plus tard.

## Statut

- ✅ `AltoView` (3 métriques + pattern d'omission)
- ✅ `SearchView` (recherchabilité fuzzy)
- ⏳ Intégration runner + RunManifest
- ⏳ Tests E2E sur le cas BnF central