| from __future__ import annotations |
|
|
| from pathlib import Path |
| from typing import Optional |
|
|
| import os |
| import yaml |
| from fastapi import FastAPI, HTTPException, APIRouter, UploadFile, File, Query |
| from fastapi.middleware.cors import CORSMiddleware |
| from pydantic import BaseModel, Field |
|
|
| from refinement.multiagent_refinement import ( |
| execute_refinement, |
| execute_refinement_for_video, |
| _load_refinement_flags, |
| ) |
|
|
|
|
|
|
| |
|
|
| ROOT = Path(__file__).resolve().parent |
| CONFIG_PATH = "config.yaml" |
| router = APIRouter(prefix="/refinement", tags=["Refinement Process"]) |
|
|
|
|
| def _load_engine_token() -> Optional[str]: |
| """Carga el token compartido del engine desde config.yaml o variables de entorno. |
| |
| Sigue la misma convención que engine/api.py: usa API_SHARED_TOKEN si está |
| definido por entorno; en caso contrario, intenta leer demo/config.yaml. |
| """ |
|
|
| env_token = os.getenv("API_SHARED_TOKEN") |
| if env_token: |
| return env_token |
|
|
| |
| try: |
| repo_root = ROOT |
| |
| demo_cfg = repo_root / "demo" / "config.yaml" |
| if demo_cfg.exists(): |
| with demo_cfg.open("r", encoding="utf-8") as f: |
| cfg = yaml.safe_load(f) or {} |
| api_cfg = cfg.get("api", {}) or {} |
| token = api_cfg.get("token") |
| if token and isinstance(token, str): |
| |
| |
| if "${" in token and "}" in token: |
| return None |
| return token |
| except Exception: |
| pass |
|
|
| return None |
|
|
|
|
| ENGINE_TOKEN = _load_engine_token() |
|
|
|
|
| def _assert_valid_token(token: str | None) -> None: |
| expected = ENGINE_TOKEN |
| if not expected: |
| |
| return |
| if not token or token != expected: |
| raise HTTPException(status_code=401, detail="Invalid or missing engine token") |
|
|
|
|
| |
|
|
|
|
| class ApplyRefinementRequest(BaseModel): |
| token: Optional[str] = Field(None, description="Engine shared token") |
| srt_content: Optional[str] = Field( |
| None, |
| description=( |
| "Contenido del SRT a refinar. Opcional si se proporciona sha1sum+version, " |
| "en cuyo caso se leerá el SRT desde audiodescriptions.db." |
| ), |
| ) |
| sha1sum: Optional[str] = Field( |
| None, |
| description=( |
| "Identificador sha1sum del vídeo. Si se proporciona junto con version, " |
| "se utilizará el pipeline basat en BDs (audiodescriptions.db, casting.db, scenarios.db)." |
| ), |
| ) |
| version: Optional[str] = Field( |
| None, |
| description=( |
| "Versió de l'audiodescripció (p.ex. 'MoE', 'Salamandra', 'HITL'). " |
| "Necessària si s'especifica sha1sum per utilitzar el pipeline de vídeo." |
| ), |
| ) |
| reflection_enabled: bool = Field(True, description="Activar paso de reflection") |
| reflexion_enabled: bool = Field(False, description="Activar paso de reflexion") |
| introspection_enabled: bool = Field(False, description="Activar paso de introspection") |
|
|
|
|
| class ApplyRefinementResponse(BaseModel): |
| refined_srt: str |
|
|
|
|
| class TrainMultiagentRefinementRequest(BaseModel): |
| audiodescriptions_db_path: str = Field(..., description="Ruta a la base de datos tipo audiodescriptions.db") |
| videos_db_path: str = Field(..., description="Ruta a la base de datos tipo videos.db") |
| casting_db_path: str = Field(..., description="Ruta a la base de datos tipo casting.db") |
| scenarios_db_path: str = Field(..., description="Ruta a la base de datos tipo scenarios.db") |
| system_to_train: str = Field(..., pattern="^(reflexion|introspection)$", description="Sistema a entrenar: 'reflexion' o 'introspection'") |
|
|
|
|
| class TrainMultiagentRefinementResponse(BaseModel): |
| ok: bool |
| detail: str |
|
|
|
|
| |
|
|
|
|
| @router.post("/apply_refinement", tags=["Refinement Process"], response_model=ApplyRefinementResponse) |
| def apply_refinement(payload: ApplyRefinementRequest) -> ApplyRefinementResponse: |
| """Aplica el pipeline multi‑agente de refinamiento sobre un SRT. |
| |
| - Valida el token del engine. |
| - Aplica los pasos reflection/reflexion/introspection según los flags |
| recibidos en la petición. |
| - Devuelve el SRT refinado. |
| """ |
|
|
| _assert_valid_token(payload.token) |
|
|
| |
| |
| flags = _load_refinement_flags() |
| flags["reflection_enabled"] = bool(payload.reflection_enabled) |
| flags["reflexion_enabled"] = bool(payload.reflexion_enabled) |
| flags["introspection_enabled"] = bool(payload.introspection_enabled) |
|
|
| |
| |
| |
| |
| |
|
|
| |
| repo_root = ROOT |
| demo_cfg = repo_root / "demo" / "config.yaml" |
| if not demo_cfg.exists(): |
| raise HTTPException(status_code=500, detail="demo/config.yaml not found") |
|
|
| original_yaml = demo_cfg.read_text(encoding="utf-8") |
| try: |
| cfg = yaml.safe_load(original_yaml) or {} |
| ref_cfg = cfg.get("refinement", {}) or {} |
| ref_cfg["reflection_enabled"] = flags["reflection_enabled"] |
| ref_cfg["reflexion_enabled"] = flags["reflexion_enabled"] |
| ref_cfg["introspection_enabled"] = flags["introspection_enabled"] |
| cfg["refinement"] = ref_cfg |
| demo_cfg.write_text(yaml.safe_dump(cfg, allow_unicode=True), encoding="utf-8") |
|
|
| |
| if payload.sha1sum and payload.version: |
| refined = execute_refinement_for_video( |
| payload.sha1sum, |
| payload.version, |
| config_path=demo_cfg, |
| ) |
| else: |
| if not payload.srt_content: |
| raise HTTPException( |
| status_code=400, |
| detail=( |
| "Cal proporcionar o bé sha1sum+version, o bé srt_content " |
| "per poder aplicar el refinament." |
| ), |
| ) |
| refined = execute_refinement(payload.srt_content, config_path=demo_cfg) |
| finally: |
| |
| demo_cfg.write_text(original_yaml, encoding="utf-8") |
|
|
| return ApplyRefinementResponse(refined_srt=refined) |
|
|
|
|
| @router.post("/train_multiagent_refinement", tags=["Refinement Process"], response_model=TrainMultiagentRefinementResponse) |
| def train_multiagent_refinement(payload: TrainMultiagentRefinementRequest) -> TrainMultiagentRefinementResponse: |
| """Endpoint placeholder para entrenar els sistemes de reflexion / introspection. |
| |
| De moment no implementa cap lògica; simplement valida la càrrega i retorna |
| un missatge indicant que és un stub. |
| """ |
|
|
| |
| |
|
|
| return TrainMultiagentRefinementResponse( |
| ok=True, |
| detail=( |
| "train_multiagent_refinement està definit com a stub; encara no s'ha " |
| "implementat la lògica d'entrenament per als sistemes 'reflexion' o 'introspection'." |
| ), |
| ) |
|
|