from typing import Dict, Any, Optional from pydantic import BaseModel, Field from pydantic_settings import BaseSettings, SettingsConfigDict from dotenv import load_dotenv load_dotenv() class LLMConfig(BaseModel): """Configuration for a specific LLM node.""" provider: str = "openai" model: str = "gpt-5-mini" temperature: float = 0.0 max_tokens: Optional[int] = None provider_specific: Dict[str, Any] = Field(default_factory=dict) class Settings(BaseSettings): """Global application settings.""" data_dir: str = "data" data_state: str = "new_jersey" log_level: str = Field(default="INFO", alias="LOG_LEVEL") dev_mode: bool = Field(default=False, alias="DEV_MODE") frontend_url: str = Field(default="http://localhost:5173", alias="FRONTEND_URL") api_v1_str: str = "/api/v1" # Voter Database configuration db_host: str = Field(default="localhost", alias="DB_HOST") db_port: int = Field(default=5432, alias="DB_PORT") db_name: str = Field(default="blockdata", alias="DB_NAME") db_user: str = Field(default="user", alias="DB_USER") db_pswd: str = Field(default="password", alias="DB_PSWD") db_table: str = Field(default="rd_gc_voters_nj", alias="DB_TABLE") # Application/History Database history_db_url: str = Field(default="postgresql://user:password@localhost:5433/ea_history", alias="HISTORY_DB_URL") # JWT Configuration secret_key: str = Field(default="change-me-in-production", alias="SECRET_KEY") algorithm: str = Field(default="HS256", alias="ALGORITHM") access_token_expire_minutes: int = Field(default=30, alias="ACCESS_TOKEN_EXPIRE_MINUTES") refresh_token_expire_days: int = Field(default=7, alias="REFRESH_TOKEN_EXPIRE_DAYS") # OIDC Configuration oidc_client_id: Optional[str] = Field(default=None, alias="OIDC_CLIENT_ID") oidc_client_secret: Optional[str] = Field(default=None, alias="OIDC_CLIENT_SECRET") oidc_server_metadata_url: Optional[str] = Field(default=None, alias="OIDC_SERVER_METADATA_URL") oidc_redirect_uri: str = Field(default="http://localhost:8000/api/v1/auth/oidc/callback", alias="OIDC_REDIRECT_URI") # Default configurations for each node query_analyzer_llm: LLMConfig = Field(default_factory=lambda: LLMConfig(model="gpt-5-mini", temperature=0.0)) planner_llm: LLMConfig = Field(default_factory=lambda: LLMConfig(model="gpt-5-mini", temperature=0.0)) coder_llm: LLMConfig = Field(default_factory=lambda: LLMConfig(model="gpt-5-mini", temperature=0.0)) summarizer_llm: LLMConfig = Field(default_factory=lambda: LLMConfig(model="gpt-5-mini", temperature=0.0)) researcher_llm: LLMConfig = Field(default_factory=lambda: LLMConfig(model="gpt-5-mini", temperature=0.0)) # Allow nested env vars like QUERY_ANALYZER_LLM__MODEL model_config = SettingsConfigDict(env_nested_delimiter='__', env_prefix='')