Spaces:
Sleeping
Sleeping
| """Pydantic models for API request/response schemas.""" | |
| from pydantic import BaseModel, Field | |
| from typing import Optional, List, Dict, Union | |
| from enum import Enum | |
| class PredictionLabel(str, Enum): | |
| """Possible prediction outcomes.""" | |
| AI_GENERATED = "AI Generated" | |
| HUMAN = "Human" | |
| UNCERTAIN = "Uncertain" | |
| class MetricDetail(BaseModel): | |
| score: int | |
| confidence: str | |
| reason: str | |
| class ForensicMetrics(BaseModel): | |
| voice_naturalness: Union[int, MetricDetail] | |
| audio_quality: Union[int, MetricDetail] | |
| characteristics: List[str] | |
| advanced: Dict[str, str] | |
| class TimelineSegment(BaseModel): | |
| start: float | |
| end: float | |
| label: str | |
| human_probability: float | |
| ai_probability: float | |
| class AnalysisResponse(BaseModel): | |
| """Response schema for the /analyze endpoint.""" | |
| id: str = Field(..., description="Unique analysis ID") | |
| filename: str = Field(..., description="Original uploaded filename") | |
| duration_seconds: float = Field(..., description="Audio duration in seconds") | |
| file_size_bytes: int = Field(..., description="File size in bytes") | |
| # DL Preprocessing Data | |
| sample_rate: int = Field(..., description="Audio sample rate in Hz") | |
| channels: int = Field(..., description="Number of audio channels (1 for mono)") | |
| peak_amplitude: float = Field(..., description="Peak amplitude after normalization") | |
| waveform: list[float] = Field(..., description="Downsampled waveform array (max 500 points)") | |
| spectrogram_image: str = Field(..., description="Base64 encoded PNG of the Mel Spectrogram") | |
| processed_audio_path: str = Field(..., description="Path to the cached processed WAV file") | |
| # Prediction | |
| prediction: str = Field(..., description="Prediction label: 'AI Generated', 'Human', or 'Uncertain'") | |
| confidence: float = Field(..., ge=0.0, le=1.0, description="Confidence score between 0 and 1") | |
| human_probability: float = Field(..., description="Human probability") | |
| ai_probability: float = Field(..., description="AI probability") | |
| # Forensics | |
| forensics: ForensicMetrics = Field(..., description="Simplified forensics metrics") | |
| timeline: List[TimelineSegment] = Field(..., description="1-second chunk analysis") | |
| model_config = { | |
| "json_schema_extra": { | |
| "examples": [ | |
| { | |
| "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", | |
| "filename": "suspicious_call.wav", | |
| "duration_seconds": 12.5, | |
| "file_size_bytes": 1024000, | |
| "sample_rate": 16000, | |
| "channels": 1, | |
| "peak_amplitude": 0.85, | |
| "waveform": [0.12, -0.23, 0.45], | |
| "spectrogram_image": "data:image/png;base64,iVBORw0KGgo...", | |
| "processed_audio_path": "backend/cache/a1b2c3d4_processed.wav", | |
| "prediction": "AI Generated", | |
| "confidence": 0.92, | |
| "human_probability": 0.08, | |
| "ai_probability": 0.92, | |
| "forensics": { | |
| "voice_naturalness": 40, | |
| "audio_quality": 85, | |
| "speech_stability": 92, | |
| "characteristics": ["⚠ Limited voice variation detected"], | |
| "advanced": {"Mean Pitch (Hz)": "120.5"} | |
| }, | |
| "timeline": [ | |
| {"start": 0.0, "end": 1.0, "label": "Suspicious", "human_probability": 0.1, "ai_probability": 0.9} | |
| ] | |
| } | |
| ] | |
| } | |
| } | |
| class HealthResponse(BaseModel): | |
| """Response schema for the /health endpoint.""" | |
| status: str | |
| service: str | |
| version: str | |
| uptime_seconds: float | |
| class ErrorResponse(BaseModel): | |
| """Standard error response schema.""" | |
| error: str = Field(..., description="Error type identifier") | |
| detail: str = Field(..., description="Human-readable error description") | |
| status_code: int = Field(..., description="HTTP status code") | |