"""`POST /v1/train` — appelé par `apps/api` (`IntentServiceClient.train`, `TechStepClassifierService._train`) une fois par locale à chaque warm-up serveur, avec l'intégralité de `TECH_STEP_TRAINING_DATA` filtrée pour cette locale. Voir `LocalePipeline.train` pour ce que "reconstruit à neuf" signifie concrètement. """ from fastapi import APIRouter, Depends, HTTPException, status from ..locale_pipeline import TrainEntry, UnsupportedLocaleError from ..pipeline_registry import registry from ..schemas import TrainRequest, TrainResponse from ..security import require_valid_secret router = APIRouter(dependencies=[Depends(require_valid_secret)]) @router.post("/v1/train", response_model=TrainResponse) def train(request: TrainRequest) -> TrainResponse: entries = [ TrainEntry(uid=entry.uid, synonyms=entry.synonyms, utterances=entry.utterances) for entry in request.entries ] try: label_count, utterance_count, synonym_count = registry.train(request.locale, entries) except UnsupportedLocaleError as err: # 422, pas 500 : une locale non supportée dans une requête de # `apps/api` est une erreur de configuration/version-skew entre les # deux services (voir le contrat documenté dans le plan de # migration), pas un échec inattendu du service lui-même. raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(err)) from err return TrainResponse( locale=request.locale, label_count=label_count, utterance_count=utterance_count, synonym_count=synonym_count, )