# backend/models.py from dataclasses import dataclass from typing import Any, Optional # Model name mapping for anonymization # Maps internal model names to display labels MODEL_NAME_MAP = { "xtts": "Model A", # Coqui XTTS -> Model A "csm": "Model B", # Sesame CSM -> Model B "orpheus": "Model C", # Orpheus -> Model C } def get_display_model_name(internal_name: str) -> str: """Convert internal model name to display label.""" return MODEL_NAME_MAP.get(internal_name, internal_name.upper()) def audio_to_base64_url(audio_data): """Return the audio data URL string as-is (no-op since audio_url is already a base64 data URL).""" return audio_data if isinstance(audio_data, str) else None # Data models @dataclass class Clip: id: str model: str speaker: str # male/female exercise: str exercise_id: str transcript: str audio_url: Any # Can be string URL or tuple (array, sample_rate) duration_s: Optional[float] = None @dataclass class MOSResponse: session_id: str clip_id: str clarity: int pronunciation: int prosody: int naturalness: int overall: int comment: str = "" gender_mismatch: bool = False # Flag for wrong gender voice @dataclass class ABResponse: session_id: str clip_a_id: str clip_b_id: str comparison_type: str # "model_vs_model" or "gender_vs_gender" choice: str # "A", "B", "tie" comment: str = "" gender_mismatch_a: bool = False # Flag for wrong gender voice in clip A gender_mismatch_b: bool = False # Flag for wrong gender voice in clip B