File size: 2,311 Bytes
fcf8749 | 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 | """
Application configuration using Pydantic Settings.
Loads from environment variables and .env file.
"""
from functools import lru_cache
from typing import Optional
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""Application settings loaded from environment variables."""
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=False,
)
# Database (must be set via DATABASE_URL env var in production)
database_url: str = ""
# Application
app_env: str = "production"
debug: bool = False
app_title: str = "Fair Dispatch System"
app_version: str = "1.0.0"
api_prefix: str = "/api/v1"
# CORS - comma-separated allowed origins
cors_origins: str = "https://fairrelay.vercel.app,https://fairrelay-dashboard.vercel.app"
# Workload Score Weights
workload_weight_a: float = 1.0 # num_packages weight
workload_weight_b: float = 0.5 # total_weight_kg weight
workload_weight_c: float = 10.0 # route_difficulty_score weight
workload_weight_d: float = 0.2 # estimated_time_minutes weight
# Clustering Settings
target_packages_per_route: int = 20
# Route Difficulty Weights
difficulty_weight_per_kg: float = 0.01
difficulty_weight_per_stop: float = 0.1
difficulty_base: float = 1.0
# Time Estimation (minutes)
time_per_package: float = 5.0
time_per_stop: float = 3.0
base_route_time: float = 30.0
# LangGraph / LangSmith (optional)
langchain_tracing_v2: bool = False
langchain_api_key: Optional[str] = None
langchain_project: str = "fair-dispatch-dev"
# Gemini API (optional)
google_api_key: Optional[str] = None
enable_gemini_explain: bool = False
@property
def is_production(self) -> bool:
return self.app_env == "production"
@property
def cors_origin_list(self) -> list[str]:
origins = [o.strip() for o in self.cors_origins.split(",") if o.strip()]
if not self.is_production:
origins.extend(["http://localhost:5173", "http://localhost:3000", "http://localhost:8000"])
return origins
@lru_cache()
def get_settings() -> Settings:
"""Get cached settings instance."""
return Settings()
|