Spaces:
Sleeping
Sleeping
Claude
refactor(api): renommer PipelineConfig.ocr_engine → engine_name (Phase 5b)
bc96a54 unverified | """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", | |
| ] | |