Spaces:
Sleeping
Sleeping
File size: 4,093 Bytes
96fd859 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | """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")
|