"""Pydantic Schemas for API Request/Response Validation. Matches exact hackathon requirements: - Request: language, audioFormat, audioBase64 - Response: status, language, classification, confidenceScore, explanation """ from pydantic import BaseModel, Field, field_validator from typing import List, Optional, Dict import base64 # ============== REQUEST SCHEMAS ============== class VoiceDetectionRequest(BaseModel): """Request schema matching hackathon requirements exactly.""" language: str = Field( ..., description="Language of the audio: Tamil, English, Hindi, Malayalam, Telugu" ) audioFormat: str = Field( default="mp3", description="Audio format (always mp3 per requirements)" ) audioBase64: str = Field( ..., description="Base64 encoded MP3 audio file", min_length=100 ) @field_validator('audioBase64') @classmethod def validate_base64(cls, v: str) -> str: """Validate that audio is valid Base64.""" try: decoded = base64.b64decode(v) if len(decoded) < 100: raise ValueError("Audio data too small") return v except Exception as e: raise ValueError(f"Invalid Base64 encoding: {str(e)}") @field_validator('language') @classmethod def validate_language(cls, v: str) -> str: """Validate language is supported (case-insensitive).""" valid_languages = ['tamil', 'english', 'hindi', 'malayalam', 'telugu'] v_lower = v.lower() if v_lower not in valid_languages: raise ValueError(f"Language must be one of: Tamil, English, Hindi, Malayalam, Telugu") return v_lower @field_validator('audioFormat') @classmethod def validate_audio_format(cls, v: str) -> str: """Validate audio format is mp3.""" if v.lower() != "mp3": raise ValueError("audioFormat must be 'mp3'") return v.lower() class Config: json_schema_extra = { "example": { "language": "Tamil", "audioFormat": "mp3", "audioBase64": "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU2LjM2LjEwMAAAAAAA..." } } # ============== RESPONSE SCHEMAS ============== class VoiceDetectionResponse(BaseModel): """Success response matching hackathon requirements exactly.""" status: str = Field( default="success", description="Response status: success or error" ) language: str = Field( ..., description="Language of the audio" ) classification: str = Field( ..., description="AI_GENERATED or HUMAN" ) confidenceScore: float = Field( ..., ge=0, le=1, description="Confidence score between 0.0 and 1.0" ) explanation: str = Field( ..., description="Short reason for the decision" ) class Config: json_schema_extra = { "example": { "status": "success", "language": "Tamil", "classification": "AI_GENERATED", "confidenceScore": 0.91, "explanation": "Unnatural pitch consistency and robotic speech patterns detected" } } class ErrorResponse(BaseModel): """Error response matching hackathon requirements exactly.""" status: str = Field( default="error", description="Response status: error" ) message: str = Field( ..., description="Error message" ) class Config: json_schema_extra = { "example": { "status": "error", "message": "Invalid API key or malformed request" } } # ============== HEALTH CHECK SCHEMA (bonus, not required) ============== class HealthResponse(BaseModel): """Health check response.""" status: str = Field(default="healthy", description="Service health status") model_loaded: bool = Field(..., description="Whether ML model is loaded") version: str = Field(default="1.0.0", description="API version")