Picarones / docs /reference /api-stable.md
Claude
docs: Phase 2 — vérité documentaire (compteurs, fantômes, legacy refs)
2c2bc0f unverified
# API publique stable de Picarones
> **Statut v2.0 (mai 2026)** : la migration vers l'architecture
> 8 couches canoniques est terminée. Tous les paquets legacy
> top-level (`picarones.core`, `picarones.measurements`,
> `picarones.engines`, `picarones.modules`, `picarones.report`,
> `picarones.llm`, `picarones.pipelines`, `picarones.cli`,
> `picarones.web`, `picarones.extras`) ainsi que les sous-paquets
> transitoires (`adapters/legacy_engines/`, `adapters/legacy_pipelines/`,
> `interfaces/{cli,web}/_legacy/`) ont été **supprimés**. Plus aucun
> shim, plus aucun `DeprecationWarning` rétrocompat.
>
> **Architecture canonique (cf.
> [`docs/explanation/architecture.md`](../explanation/architecture.md))** :
> `domain → formats → evaluation → pipeline → adapters → app →
> reports → interfaces`.
>
> **Chantier post-rewrite (mai 2026, branche
> `claude/fix-module-rewiring-MHssX`)** : réconciliation des
> contrats UI/API/runner après la migration. Ruptures API
> visibles côté consommateur :
>
> - `CompetitorConfig` → `PipelineConfig`.
> - `PipelineConfig.ocr_engine` → `PipelineConfig.engine_name`
> (le field accepte aussi `corpus` et des VLMs zero-shot — le
> préfixe `ocr_` était trompeur).
> - `PipelineConfig.pipeline_mode` typé `Literal["text_only",
> "text_and_image", "zero_shot"]` ; toute autre valeur (y compris
> les anciens alias `post_correction_text` /
> `post_correction_image`) est rejetée en 422.
## Définition
L'API publique stable de Picarones est constituée des classes,
fonctions, constantes et types listés ci-dessous, exportés depuis
l'arborescence canonique 8 couches.
Ce qui n'est pas dans cette liste peut évoluer à tout moment
sans bump majeur — utiliser ces points d'entrée pour une intégration
durable.
## Test automatique
Le test `tests/test_public_api.py` vérifie que tous les noms listés
ici existent et restent accessibles. Il échoue si un nom disparaît
ou change de forme.
## Liste exhaustive
### `picarones.evaluation.corpus`
```python
class GTLevel(str, Enum):
TEXT, ALTO, PAGE, ENTITIES, READING_ORDER
class TextGT: # GT texte plat
class AltoGT: # GT ALTO XML
class PageGT: # GT PAGE XML
class EntitiesGT: # GT entités nommées (NER)
class ReadingOrderGT: # GT ordre de lecture des régions
GTPayload = Union[...] # type alias
class Document: # un document du corpus (image + GT multi-niveaux)
class Corpus: # collection de Documents
GT_SUFFIXES: dict[GTLevel, str] # mapping niveau → suffixe fichier
def load_corpus_from_directory(path) -> Corpus
```
### `picarones.domain.artifacts`
```python
class ArtifactType(str, Enum):
IMAGE, RAW_TEXT, CORRECTED_TEXT, ALTO_XML, PAGE_XML,
CANONICAL_DOCUMENT, ENTITIES, READING_ORDER, ALIGNMENT, CONFIDENCES
# Aliases legacy pour rétrocompat : TEXT, ALTO, PAGE
```
### `picarones.domain.module_protocol`
```python
class BaseModule(ABC):
input_types: tuple[ArtifactType, ...]
output_types: tuple[ArtifactType, ...]
execution_mode: "io" | "cpu"
@property name
@abstractmethod process(inputs)
metadata() -> dict
validate_inputs(inputs)
validate_outputs(outputs)
ExecutionMode = Literal["io", "cpu"]
```
### `picarones.evaluation.benchmark_result`
```python
class DocumentResult: # résultat moteur sur un doc (CER, métriques, taxonomy…)
class EngineReport: # agrégat moteur sur tout le corpus
class BenchmarkResult: # résultat global multi-moteurs
```
### `picarones.evaluation.metrics.text_metrics`
```python
class MetricsResult: # CER, WER, MER, WIL + variantes diplomatique/caseless
def compute_metrics(reference, hypothesis, char_exclude=None) -> MetricsResult
def aggregate_metrics(results: list) -> dict
```
### `picarones.app.services.benchmark_runner`
```python
def run_benchmark_via_service(
corpus, engines,
output_json=None,
show_progress=True,
progress_callback=None,
char_exclude=None,
max_workers=4,
timeout_seconds=60.0,
partial_dir=None,
cancel_event=None,
entity_extractor=None,
profile="standard",
normalization_profile=None,
) -> BenchmarkResult
```
Sprint D du plan v2.0 — adapter de compatibilité qui présente
l'API mono-call historique de
``measurements.runner.run_benchmark`` (supprimé en D.6.b) en
s'appuyant en interne sur ``BenchmarkService`` (rewrite).
Prouvé numériquement équivalent en D.1.e.
### `picarones.evaluation.metric_registry`
```python
class MetricSpec: # frozen dataclass : name, func, input_types, ...
def register_metric(*, name, input_types, ...) -> Callable
def get_metric(name) -> MetricSpec
def all_metrics() -> list[MetricSpec]
def select_metrics(input_types) -> list[MetricSpec]
def compute_at_junction(reference, hypothesis, input_types, *, skip_on_error=True) -> dict
```
### `picarones.evaluation.metric_hooks`
```python
# Profils — constantes
PROFILE_MINIMAL = "minimal"
PROFILE_STANDARD = "standard"
PROFILE_PHILOLOGICAL = "philological"
PROFILE_DIAGNOSTICS = "diagnostics"
PROFILE_ECONOMICS = "economics"
PROFILE_PIPELINE = "pipeline"
PROFILE_FULL = "full"
KNOWN_PROFILES: frozenset[str]
# Modèles
class DocumentMetricHook: # frozen dataclass
class CorpusMetricAggregator:
# API
def validate_profile(profile)
def register_document_metric(*, name, attribute, profiles, ...) -> Callable
def register_corpus_aggregator(*, name, attribute, profiles) -> Callable
def select_document_hooks(profile) -> list[DocumentMetricHook]
def select_corpus_aggregators(profile) -> list[CorpusMetricAggregator]
def run_document_hooks(profile, *, ground_truth, hypothesis, image_path, corpus_lang, ocr_result) -> dict
def run_corpus_aggregators(profile, document_results) -> dict
```
### `picarones.evaluation.metrics.builtin_metrics`
Métriques scalaires natives, enregistrées dans le registre typé :
```python
def cer(reference, hypothesis) -> float
def wer(reference, hypothesis) -> float
def mer(reference, hypothesis) -> float
def wil(reference, hypothesis) -> float
# Stub démonstrateur
def text_preservation_after_reconstruction(reference_text, hypothesis_alto) -> float
```
### `picarones.evaluation.metrics.alto_metrics`
Métriques (ALTO, ALTO) + helper :
```python
def extract_text_from_alto(payload) -> str
def alto_text_cer(reference_alto, hypothesis_alto) -> float
def alto_text_wer(reference_alto, hypothesis_alto) -> float
def alto_text_mer(reference_alto, hypothesis_alto) -> float
def alto_text_wil(reference_alto, hypothesis_alto) -> float
```
### `picarones.interfaces.web.jobs`
Persistance des jobs benchmark (utilisé par l'interface web) :
```python
class JobStore:
def get_default_store() -> JobStore
def reset_default_store(...)
```
## Politique de stabilité
### Ce que nous garantissons
- **Existence** : aucun nom listé ne disparaît entre `1.x.0` et
`1.y.0` (pour `y > x`).
- **Signatures** : aucun argument requis ajouté à une fonction
publique. Les nouveaux arguments sont keyword avec valeur par
défaut.
- **Types de retour** : compatibles entre versions mineures (un
`dict` peut gagner des clés mais pas en perdre).
- **Sémantique** : un nom listé garde le même comportement
fonctionnel. Les corrections de bug sont permises.
### Ce que nous ne garantissons pas
- **Modules `picarones.evaluation.metrics/`** : peuvent évoluer librement.
Quand ils changent, les shims rétrocompat dans `picarones.domain/`
reflètent ces changements.
- **Modules `picarones.evaluation.metrics/`** : statut variable selon le
sous-package (academic / governance / historical / importers).
Voir `docs/explanation/architecture.md`.
- **Comportement des renderers HTML** : la structure des fichiers HTML
peut évoluer entre versions mineures. Nous gardons les noms des
vues principales.
- **Internes des modules canoniques** : les noms commençant par `_`
ne font pas partie de l'API publique. Les tests Sprints
historiques qui les importent (Sprint 13/42) sont préservés mais
par effort, pas par contrat.
### Bump majeur (`2.0.0`)
Un bump majeur sera nécessaire pour :
- Supprimer un nom de cette liste.
- Changer la signature d'une fonction publique de manière non
rétrocompatible.
- Casser le format de sérialisation du `BenchmarkResult.to_json()`.
- Renommer un module de l'arborescence canonique.
## Chemins canoniques par couche
L'arborescence v2.0 expose des points d'entrée stables organisés par
couche. Toutes les intégrations doivent passer par ces chemins —
plus de path legacy disponible.
### Couche 3 — `picarones.evaluation`
```python
# Métriques (CER/WER + métriques avancées)
from picarones.evaluation.metrics.confusion import build_confusion_matrix
from picarones.evaluation.metrics.taxonomy import classify_errors
from picarones.evaluation.metrics.calibration import compute_calibration_metrics
# Moteur narratif (Cercle 7 → reports/, mais le contrat est en
# couche 3 pour rester accessible aux consommateurs externes)
from picarones.reports.narrative import build_synthesis
from picarones.domain.facts import Fact, FactType, FactImportance
# Modules philologiques (Sprints 55-60)
from picarones.evaluation.metrics.unicode_blocks import compute_unicode_block_accuracy
from picarones.evaluation.metrics.module_policy import ModuleManifest
```
### Couche 5 — `picarones.adapters`
```python
# OCR (factory canonique)
from picarones.adapters.ocr import ocr_adapter_from_name
from picarones.adapters.ocr import (
TesseractAdapter, PeroOCRAdapter, KrakenAdapter, CalamariAdapter,
MistralOCRAdapter, GoogleVisionAdapter, AzureDocIntelAdapter,
PrecomputedTextAdapter,
)
# LLM
from picarones.adapters.llm.openai_adapter import OpenAIAdapter
from picarones.adapters.llm.anthropic_adapter import AnthropicAdapter
from picarones.adapters.llm.mistral_adapter import MistralAdapter
from picarones.adapters.llm.ollama_adapter import OllamaAdapter
# Importers de corpus distants
from picarones.adapters.corpus.iiif import IIIFImporter
from picarones.adapters.corpus.htr_united import HTRUnitedCatalogue
from picarones.adapters.corpus.huggingface import HuggingFaceImporter
```
### Couche 6 — `picarones.app.services`
```python
# Orchestration benchmark
from picarones.app.services.benchmark_runner import run_benchmark_via_service
from picarones.app.services.corpus_service import CorpusService
from picarones.app.services.path_security import (
WorkspaceManager,
validated_path,
safe_report_name,
validated_prompt_filename,
)
from picarones.app.services.partial_store import (
compute_run_fingerprint,
partial_path_for_engine,
)
```
### Couche 7 — `picarones.reports.html`
```python
from picarones.reports.html.generator import ReportGenerator
```
### Couche 8 — `picarones.interfaces`
```python
# CLI : exposée comme entry point ``picarones`` (cf. pyproject.toml).
# Pas d'API Python stable — l'invocation est ``picarones run/diagnose/…``.
# Web : FastAPI app (intégration via ASGI).
from picarones.interfaces.web.app import app
from picarones.interfaces.web.models import (
PipelineConfig, PipelineMode,
BenchmarkRequest, BenchmarkRunRequest,
NormalizationProfileId, TesseractLang, ReportLang,
)
```
## Voir aussi
- [`docs/explanation/architecture.md`](architecture.md) — cartographie
des 3 cercles + critères d'assignation.
- [`docs/explanation/architecture.md`](architecture.md) — vue d'ensemble post-chantiers.
- [`tests/test_public_api.py`](../tests/test_public_api.py) — test
automatique qui échoue si un nom listé ici disparaît.