""" Global application configuration. Following best practice of splitting config across domains. """ from enum import Enum from functools import lru_cache from pydantic import Field, HttpUrl from pydantic_settings import BaseSettings, SettingsConfigDict class Environment(str, Enum): """Application environment.""" DEVELOPMENT = "development" PRODUCTION = "production" TESTING = "testing" class Config(BaseSettings): """ Global application configuration. Loads from environment variables and .env file. Domain-specific configs should be in their respective modules. """ model_config = SettingsConfigDict( env_file=".env", env_file_encoding="utf-8", case_sensitive=True, extra="ignore", ) # Application APP_NAME: str = "OpenAI-Compatible API" APP_VERSION: str = "0.2.5" ENVIRONMENT: Environment = Environment.DEVELOPMENT DEBUG: bool = Field(default=False, description="Debug mode") # API Configuration API_HOST: str = Field(default="0.0.0.0", description="API host") API_PORT: int = Field(default=8000, description="API port") API_PREFIX: str = Field(default="/v1", description="API route prefix") # Ollama Configuration OLLAMA_HOST: HttpUrl = Field( default="http://localhost:11434", description="Ollama server URL" ) OLLAMA_DEFAULT_MODEL: str = Field( default="mistral-nemo:latest", description="Default Ollama model" ) OLLAMA_TIMEOUT: int = Field( default=120, description="Ollama request timeout in seconds" ) STREAM_TIMEOUT: int = Field( default=20, description="Timeout for each streaming turn in seconds" ) # SearXNG Configuration SEARXNG_HOST: HttpUrl = Field( default="http://localhost:8087", description="SearXNG server URL" ) SEARXNG_TIMEOUT: int = Field( default=30, description="SearXNG request timeout in seconds" ) # Redis Configuration REDIS_HOST: str = Field( default="localhost", description="Redis server host" ) REDIS_PORT: int = Field( default=6379, description="Redis server port" ) REDIS_DB: int = Field( default=1, description="Redis database number" ) REDIS_TIMEOUT: int = Field( default=5, description="Redis connection timeout in seconds" ) # Logging LOG_LEVEL: str = Field(default="INFO", description="Logging level") ENABLE_BENCHMARKS: bool = Field(default=True, description="Enable performance benchmarking") # CORS CORS_ORIGINS: list[str] = Field( default=["*"], description="Allowed CORS origins" ) CORS_ALLOW_CREDENTIALS: bool = True CORS_ALLOW_METHODS: list[str] = ["*"] CORS_ALLOW_HEADERS: list[str] = ["*"] @property def redis_url(self) -> str: """Construct Redis connection URL.""" return f"redis://{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB}" @property def log_format(self) -> str: """ Determine log format based on environment. - production: JSON format for machine parsing - development/testing: Console format for human readability """ return "json" if self.ENVIRONMENT == Environment.PRODUCTION else "console" @lru_cache def get_config() -> Config: """ Get cached configuration instance. Uses lru_cache to ensure config is loaded once and reused. """ return Config() # Global config instance config = get_config()