CoolFace
Apppublic

nifty-coder/stemsplit-backend

sourceHugging Faceupdated 8mo agoView on Hugging Face
0likes
models.py309 linesDownload Raw Back to voice_control
1"""2Core data models for the voice control optimization system.3 4This module defines all the data structures used throughout the voice control5system, including provider configurations, transcription results, usage statistics,6and monitoring data.7"""8 9from dataclasses import dataclass, field10from typing import Dict, List, Optional, Any, Union11from datetime import datetime, timezone12from enum import Enum13 14 15class ProviderType(Enum):16    """Enumeration of supported STT provider types."""17    WEB_SPEECH_API = "web_speech_api"18    GOOGLE_SPEECH = "google_speech"19    AZURE_SPEECH = "azure_speech"20    ASSEMBLY_AI = "assembly_ai"21    DEEPGRAM = "deepgram"22 23 24class QuotaType(Enum):25    """Types of quota limits that can be enforced."""26    REQUESTS_PER_MINUTE = "requests_per_minute"27    REQUESTS_PER_HOUR = "requests_per_hour"28    REQUESTS_PER_DAY = "requests_per_day"29    AUDIO_MINUTES_PER_DAY = "audio_minutes_per_day"30    AUDIO_MINUTES_PER_MONTH = "audio_minutes_per_month"31 32 33@dataclass34class ProviderConfig:35    """Configuration for a speech-to-text provider."""36    name: str37    provider_type: ProviderType38    enabled: bool39    priority: int  # Lower number = higher priority40    free_tier_limits: Dict[str, Any]41    rate_limits: Dict[str, int]42    supported_formats: List[str]43    supported_languages: List[str]44    cost_per_minute: float45    api_credentials: Dict[str, str]46    endpoint_url: Optional[str] = None47    timeout_seconds: int = 3048    max_retries: int = 349    50    def __post_init__(self):51        """Validate configuration after initialization."""52        if self.priority < 0:53            raise ValueError("Priority must be non-negative")54        if self.cost_per_minute < 0:55            raise ValueError("Cost per minute must be non-negative")56        if not self.supported_formats:57            raise ValueError("At least one supported format must be specified")58 59 60@dataclass61class WordTimestamp:62    """Timestamp information for a transcribed word."""63    word: str64    start_time: float65    end_time: float66    confidence: float67 68 69@dataclass70class TranscriptionResult:71    """Result of a speech-to-text transcription operation."""72    text: str73    confidence: float74    provider: str75    processing_time: float76    audio_duration: float77    language: str78    alternatives: List[str] = field(default_factory=list)79    word_timestamps: Optional[List[WordTimestamp]] = None80    is_final: bool = True81    session_id: Optional[str] = None82    created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))83    84    def __post_init__(self):85        """Validate transcription result after initialization."""86        if self.confidence < 0 or self.confidence > 1:87            raise ValueError("Confidence must be between 0 and 1")88        if self.processing_time < 0:89            raise ValueError("Processing time must be non-negative")90        if self.audio_duration < 0:91            raise ValueError("Audio duration must be non-negative")92 93 94@dataclass95class UsageStats:96    """Usage statistics for a provider within a time window."""97    provider: str98    requests_count: int99    audio_minutes: float100    estimated_cost: float101    success_rate: float102    average_latency: float103    time_window: str104    window_start: datetime105    window_end: datetime106    107    def __post_init__(self):108        """Validate usage statistics after initialization."""109        if self.requests_count < 0:110            raise ValueError("Request count must be non-negative")111        if self.audio_minutes < 0:112            raise ValueError("Audio minutes must be non-negative")113        if self.estimated_cost < 0:114            raise ValueError("Estimated cost must be non-negative")115        if self.success_rate < 0 or self.success_rate > 1:116            raise ValueError("Success rate must be between 0 and 1")117        if self.average_latency < 0:118            raise ValueError("Average latency must be non-negative")119 120 121@dataclass122class ProviderStatus:123    """Current status and health information for a provider."""124    name: str125    available: bool126    current_load: float127    quota_remaining: Dict[str, float]128    last_error: Optional[str]129    response_time_avg: float130    last_health_check: datetime = field(default_factory=datetime.utcnow)131    circuit_breaker_state: str = "CLOSED"  # CLOSED, OPEN, HALF_OPEN132    consecutive_failures: int = 0133    134    def __post_init__(self):135        """Validate provider status after initialization."""136        if self.current_load < 0:137            raise ValueError("Current load must be non-negative")138        if self.response_time_avg < 0:139            raise ValueError("Response time average must be non-negative")140        if self.consecutive_failures < 0:141            raise ValueError("Consecutive failures must be non-negative")142 143 144@dataclass145class AudioSegment:146    """Represents a segment of audio data."""147    data: bytes148    start_time: float149    end_time: float150    sample_rate: int151    channels: int152    format: str153    154    @property155    def duration(self) -> float:156        """Calculate the duration of the audio segment."""157        return self.end_time - self.start_time158    159    def __post_init__(self):160        """Validate audio segment after initialization."""161        if self.start_time < 0:162            raise ValueError("Start time must be non-negative")163        if self.end_time <= self.start_time:164            raise ValueError("End time must be greater than start time")165        if self.sample_rate <= 0:166            raise ValueError("Sample rate must be positive")167        if self.channels <= 0:168            raise ValueError("Channels must be positive")169 170 171@dataclass172class ProcessedAudio:173    """Audio data that has been processed and optimized for a provider."""174    data: bytes175    format: str176    sample_rate: int177    channels: int178    duration: float179    provider: str180    compression_ratio: float = 1.0181    noise_reduced: bool = False182    silence_removed: bool = False183    184    def __post_init__(self):185        """Validate processed audio after initialization."""186        if self.duration <= 0:187            raise ValueError("Duration must be positive")188        if self.sample_rate <= 0:189            raise ValueError("Sample rate must be positive")190        if self.channels <= 0:191            raise ValueError("Channels must be positive")192        if self.compression_ratio <= 0:193            raise ValueError("Compression ratio must be positive")194 195 196@dataclass197class QuotaStatus:198    """Status of quota usage for a provider."""199    provider: str200    quota_type: QuotaType201    current_usage: float202    limit: float203    remaining: float204    reset_time: datetime205    percentage_used: float206    207    @property208    def is_exceeded(self) -> bool:209        """Check if quota is exceeded."""210        return self.current_usage >= self.limit211    212    def is_near_limit(self, threshold: float = 0.8) -> bool:213        """Check if quota is near the limit."""214        return self.percentage_used >= threshold215    216    def __post_init__(self):217        """Calculate derived fields and validate."""218        if self.limit > 0:219            self.percentage_used = min(self.current_usage / self.limit, 1.0)220            self.remaining = max(self.limit - self.current_usage, 0)221        else:222            self.percentage_used = 0.0223            self.remaining = 0.0224        225        if self.current_usage < 0:226            raise ValueError("Current usage must be non-negative")227        if self.limit < 0:228            raise ValueError("Limit must be non-negative")229 230 231@dataclass232class CacheStats:233    """Statistics about cache performance."""234    total_requests: int235    cache_hits: int236    cache_misses: int237    hit_rate: float238    total_size_bytes: int239    entry_count: int240    evictions: int241    242    @property243    def miss_rate(self) -> float:244        """Calculate cache miss rate."""245        return 1.0 - self.hit_rate246    247    def __post_init__(self):248        """Calculate hit rate and validate."""249        if self.total_requests > 0:250            self.hit_rate = self.cache_hits / self.total_requests251        else:252            self.hit_rate = 0.0253        254        if self.cache_hits < 0 or self.cache_misses < 0:255            raise ValueError("Cache hits and misses must be non-negative")256        if self.total_requests != self.cache_hits + self.cache_misses:257            raise ValueError("Total requests must equal hits plus misses")258 259 260@dataclass261class CostSummary:262    """Summary of costs across providers for a time period."""263    time_period: str264    start_date: datetime265    end_date: datetime266    total_cost: float267    provider_costs: Dict[str, float]268    total_requests: int269    total_audio_minutes: float270    average_cost_per_minute: float271    272    def __post_init__(self):273        """Validate cost summary after initialization."""274        if self.total_cost < 0:275            raise ValueError("Total cost must be non-negative")276        if self.total_requests < 0:277            raise ValueError("Total requests must be non-negative")278        if self.total_audio_minutes < 0:279            raise ValueError("Total audio minutes must be non-negative")280        if self.average_cost_per_minute < 0:281            raise ValueError("Average cost per minute must be non-negative")282 283 284@dataclass285class BudgetAlert:286    """Alert when budget thresholds are exceeded."""287    alert_id: str288    provider: str289    alert_type: str  # "threshold_warning", "threshold_exceeded", "quota_exceeded"290    message: str291    current_cost: float292    threshold: float293    time_period: str294    created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))295    acknowledged: bool = False296    297    def __post_init__(self):298        """Validate budget alert after initialization."""299        if self.current_cost < 0:300            raise ValueError("Current cost must be non-negative")301        if self.threshold < 0:302            raise ValueError("Threshold must be non-negative")303 304 305# Type aliases for common data structures306ProviderMetrics = Dict[str, Union[float, int, str]]307ConfigurationDict = Dict[str, Any]308AudioFingerprint = str309CacheKey = str