itssKarthiii's picture
Upload 70 files
6b408d7 verified
"""
Application configuration using Pydantic Settings.
Loads configuration from environment variables and .env file.
"""
from functools import lru_cache
from typing import Literal
import torch
from pydantic import Field
from pydantic import field_validator
from pydantic_settings import BaseSettings
from pydantic_settings import SettingsConfigDict
class Settings(BaseSettings):
"""Application settings loaded from environment variables."""
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=False,
extra="ignore",
)
# -------------------------------------------------------------------------
# Application Settings
# -------------------------------------------------------------------------
APP_NAME: str = "VoiceAuth API"
APP_VERSION: str = "1.0.0"
DEBUG: bool = False
HOST: str = "0.0.0.0"
PORT: int = 8000
# -------------------------------------------------------------------------
# Security Settings
# -------------------------------------------------------------------------
API_KEYS: str = Field(
default="",
description="Comma-separated list of valid API keys",
)
CORS_ORIGINS: str = Field(
default="http://localhost:3000,http://localhost:8000",
description="Comma-separated list of allowed CORS origins",
)
RATE_LIMIT_REQUESTS: int = Field(default=100, ge=1)
RATE_LIMIT_PERIOD: int = Field(default=60, ge=1, description="Period in seconds")
# -------------------------------------------------------------------------
# ML Model Settings
# -------------------------------------------------------------------------
MODEL_NAME: str = "facebook/wav2vec2-base"
MODEL_PATH: str = ""
DEVICE: str = "auto"
MAX_AUDIO_DURATION: float = Field(default=30.0, ge=1.0)
MIN_AUDIO_DURATION: float = Field(default=0.5, ge=0.1)
SAMPLE_RATE: int = Field(default=16000, ge=8000, le=48000)
# -------------------------------------------------------------------------
# Redis Settings
# -------------------------------------------------------------------------
REDIS_URL: str = "redis://localhost:6379"
REDIS_DB: int = 0
# -------------------------------------------------------------------------
# Logging Settings
# -------------------------------------------------------------------------
LOG_LEVEL: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = "INFO"
LOG_FORMAT: Literal["json", "console"] = "json"
# -------------------------------------------------------------------------
# Computed Properties
# -------------------------------------------------------------------------
@property
def api_keys_list(self) -> list[str]:
"""Parse comma-separated API keys into a list."""
if not self.API_KEYS:
return []
return [key.strip() for key in self.API_KEYS.split(",") if key.strip()]
@property
def cors_origins_list(self) -> list[str]:
"""Parse comma-separated CORS origins into a list."""
if not self.CORS_ORIGINS:
return []
return [origin.strip() for origin in self.CORS_ORIGINS.split(",") if origin.strip()]
@property
def torch_device(self) -> str:
"""Determine the appropriate torch device."""
if self.DEVICE == "auto":
return "cuda" if torch.cuda.is_available() else "cpu"
return self.DEVICE
@property
def model_identifier(self) -> str:
"""Get the model path or name to load."""
return self.MODEL_PATH if self.MODEL_PATH else self.MODEL_NAME
# -------------------------------------------------------------------------
# Validators
# -------------------------------------------------------------------------
@field_validator("DEVICE")
@classmethod
def validate_device(cls, v: str) -> str:
"""Validate device configuration."""
valid_devices = {"auto", "cpu", "cuda", "mps"}
# Allow cuda:N format
if v.startswith("cuda:"):
return v
if v not in valid_devices:
raise ValueError(f"Device must be one of {valid_devices} or 'cuda:N' format")
return v
@lru_cache
def get_settings() -> Settings:
"""
Get cached settings instance.
Uses lru_cache to ensure settings are only loaded once.
"""
return Settings()