Claude
refactor(api): renommer PipelineConfig.ocr_engine → engine_name (Phase 5b)
bc96a54 unverified
Raw
History Blame
6.59 kB
"""Modèles Pydantic partagés par les routers FastAPI.
Ces schémas décrivent les payloads des requêtes ``POST`` consommées
par plusieurs endpoints du serveur web. Les sortir d'``app.py``
permet à chaque routeur de les importer sans dépendance vers
l'application elle-même.
Validation stricte
------------------
Tous les champs ``str`` ont une borne ``max_length`` proportionnée
à leur usage attendu (chemin filesystem, identifiant HuggingFace,
nom de rapport…) pour empêcher qu'un payload géant n'épuise la
mémoire avant validation. Les énumérations finies (langue OCR,
langue de rapport) sont typées en ``Literal[...]`` pour rejeter au
plus tôt les valeurs invalides.
"""
from __future__ import annotations
from typing import Literal
from pydantic import BaseModel, Field
# Bornes éditoriales — ajustées au plus large raisonnable, pas plus.
_MAX_PATH = 1024
"""Longueur max d'un chemin filesystem (limite POSIX généralement 4096)."""
_MAX_NAME = 256
"""Longueur max d'un identifiant ou nom court (rapport, label, dataset)."""
_MAX_PROMPT_FILENAME = 256
"""Nom de fichier prompt — ``"correction_medieval_french.txt"`` etc."""
_MAX_CHAR_EXCLUDE = 256
"""Liste de caractères à exclure (séparés par virgules)."""
_MAX_ENGINE_LIST = 32
"""Nombre max de moteurs OCR par requête legacy."""
_MAX_COMPETITORS = 32
"""Nombre max de concurrents composés par benchmark/run."""
# Codes ISO Tesseract acceptés pour le paramètre ``lang`` de
# ``BenchmarkRequest``. Liste explicite plutôt que ``str`` ouvert
# pour rejeter au plus tôt une valeur fantaisiste qui transiterait
# vers ``pytesseract`` en pure perte.
TesseractLang = Literal[
"fra", "lat", "eng", "deu", "ita", "spa", "por", "nld", "cat",
"rum", "ell", "ara", "heb", "rus", "ukr", "pol", "ces", "swe",
]
ReportLang = Literal["fr", "en"]
"""Langue du rapport HTML."""
NormalizationProfileId = Literal[
"nfc", "caseless", "minimal",
"medieval_french", "early_modern_french",
"medieval_latin",
"early_modern_english", "medieval_english",
"secretary_hand",
"sans_ponctuation", "sans_apostrophes",
]
"""Identifiants des profils de normalisation Unicode disponibles.
Liste alignée sur ``measurements.normalization.NORMALIZATION_PROFILES``
(11 profils). Toute addition côté ``normalization.py`` doit être
répercutée ici sous peine de rejet Pydantic au niveau API web.
Sprint A14-S1 — alignement README ↔ web models ↔ runtime."""
PipelineMode = Literal["text_only", "text_and_image", "zero_shot"]
"""Modes de pipeline OCR+LLM acceptés par ``PipelineConfig``.
Aligné sur :class:`picarones.pipeline.llm_pipeline_config.OCRLLMMode` —
toute valeur hors de ces 3 littéraux est rejetée 422 par Pydantic.
Sémantique :
- ``text_only`` — l'OCR amont produit un texte brut, le LLM le corrige
sans voir l'image (post-correction texte).
- ``text_and_image`` — l'OCR amont produit un texte ; le VLM le corrige
en s'appuyant sur l'image (post-correction multimodale).
- ``zero_shot`` — pas d'OCR amont ; un VLM transcrit l'image directement.
Phase 2 du chantier post-rewrite : suppression du fallback silencieux
``mode_map.get(comp.pipeline_mode, 'text_only')`` qui acceptait toute
chaîne arbitraire et la mappait sur ``text_only``."""
class BenchmarkRequest(BaseModel):
corpus_path: str = Field(min_length=1, max_length=_MAX_PATH)
engines: list[str] = Field(default=["tesseract"], max_length=_MAX_ENGINE_LIST)
normalization_profile: NormalizationProfileId = "nfc"
char_exclude: str = Field(default="", max_length=_MAX_CHAR_EXCLUDE)
"""Caractères à ignorer (séparés par virgule, ex: ``"',–"``)."""
output_dir: str = Field(default="./rapports/", max_length=_MAX_PATH)
report_name: str = Field(default="", max_length=_MAX_NAME)
lang: TesseractLang = "fra"
report_lang: ReportLang = "fr"
"""Langue du rapport HTML : ``fr`` ou ``en``."""
class HTRUnitedImportRequest(BaseModel):
entry_id: str = Field(min_length=1, max_length=_MAX_NAME)
output_dir: str = Field(default="./corpus/", max_length=_MAX_PATH)
max_samples: int = Field(default=100, ge=1, le=10_000)
class HuggingFaceImportRequest(BaseModel):
dataset_id: str = Field(min_length=1, max_length=_MAX_NAME)
output_dir: str = Field(default="./corpus/", max_length=_MAX_PATH)
split: str = Field(default="train", max_length=_MAX_NAME)
max_samples: int = Field(default=100, ge=1, le=10_000)
class PipelineConfig(BaseModel):
name: str = Field(default="", max_length=_MAX_NAME)
engine_name: str = Field(default="", max_length=_MAX_NAME)
"""Identifiant du moteur de transcription : ``tesseract``,
``mistral_ocr``, ``kraken``, ``calamari``, … ou ``corpus`` pour
utiliser l'OCR pré-calculé. Vide (``""``) pour un pipeline LLM
seul (zero-shot VLM).
Phase 5b du chantier post-rewrite : renommé depuis ``ocr_engine``
car le field accepte aussi des VLMs (zero_shot) et des sources
pré-calculées (``corpus``) — le préfixe ``ocr_`` était trompeur.
Rupture API : les clients qui envoyaient ``ocr_engine`` reçoivent
désormais 422.
"""
ocr_model: str = Field(default="", max_length=_MAX_NAME)
llm_provider: str = Field(default="", max_length=_MAX_NAME)
llm_model: str = Field(default="", max_length=_MAX_NAME)
pipeline_mode: PipelineMode | Literal[""] = ""
"""Mode du pipeline OCR+LLM — vide si pas de pipeline LLM (OCR seul).
Typage strict (Phase 2 chantier post-rewrite) : Pydantic rejette
en 422 toute valeur hors de la matrice canonique au lieu d'aliaser
silencieusement sur ``text_only``. La chaîne vide (``""``) reste
autorisée pour indiquer qu'aucun LLM n'est attaché au moteur OCR.
"""
prompt_file: str = Field(default="", max_length=_MAX_PROMPT_FILENAME)
class BenchmarkRunRequest(BaseModel):
corpus_path: str = Field(min_length=1, max_length=_MAX_PATH)
competitors: list[PipelineConfig] = Field(
min_length=1, max_length=_MAX_COMPETITORS,
)
normalization_profile: NormalizationProfileId = "nfc"
char_exclude: str = Field(default="", max_length=_MAX_CHAR_EXCLUDE)
output_dir: str = Field(default="./rapports/", max_length=_MAX_PATH)
report_name: str = Field(default="", max_length=_MAX_NAME)
report_lang: ReportLang = "fr"
__all__ = [
"TesseractLang",
"ReportLang",
"NormalizationProfileId",
"PipelineMode",
"BenchmarkRequest",
"HTRUnitedImportRequest",
"HuggingFaceImportRequest",
"PipelineConfig",
"BenchmarkRunRequest",
]