""" Global configuration for Core Code API """ from pydantic_settings import BaseSettings from functools import lru_cache # Import infrastructure credentials from gitignored module try: from src.credentials import ( PORTAINER_URL, PORTAINER_API_KEY, NPM_URL, NPM_EMAIL, NPM_PASSWORD, KUMA_URL, KUMA_USERNAME, KUMA_PASSWORD, KUMA_API_KEY, BRAVE_SEARCH_API_KEY, GOOGLE_SEARCH_API_KEY, GOOGLE_SEARCH_ENGINE_ID ) except ImportError: # Fallback to empty strings if credentials.py doesn't exist # (e.g., fresh clone before credentials setup) PORTAINER_URL = "http://localhost:8001" PORTAINER_API_KEY = "" NPM_URL = "http://localhost:81" NPM_EMAIL = "" NPM_PASSWORD = "" KUMA_URL = "http://localhost:3001" KUMA_USERNAME = "" KUMA_PASSWORD = "" KUMA_API_KEY = "" BRAVE_SEARCH_API_KEY = "" GOOGLE_SEARCH_API_KEY = "" GOOGLE_SEARCH_ENGINE_ID = "" class Settings(BaseSettings): """Global application settings""" # Application app_name: str = "Core Code API" app_version: str = "1.0.0" debug: bool = False # Server host: str = "0.0.0.0" port: int = 8083 # CORS cors_origins: list[str] = ["*"] cors_credentials: bool = True cors_methods: list[str] = ["*"] cors_headers: list[str] = ["*"] # Logging log_level: str = "DEBUG" # Ollama Configuration (for AI orchestration) ollama_base_url: str = "http://ollama:11434" ollama_timeout: int = 300 # 5 minutes # Model Configuration default_model: str = "mistral-tools:7b" agent_model: str = "gemma2:9b-instruct-q5_K_M" # Must support tool calling with ADK (~4GB VRAM) lightweight_models: str = "gemma3-tools:1b,phi3:mini" heavy_models: str = "mistral:7b,gemma2:9b,gemma3:12b,mixtral:8x7b" code_models: str = "codestral:latest,codegemma:latest" # Previous config (gemma3:12b used ~10GB VRAM) # default_model: str = "gemma3:12b" # agent_model: str = "gemma3:12b" # System Prompt Variant (for A/B testing) # Options: v1_verbose, v2_concise, v3_imperative, v4_minimal, v4_gemini_suggestion, v5_adk_optimized, v7_adk_best_practice, v8_holistic system_prompt_variant: str = "v8_holistic" # Agent Configuration agent_fallback_enabled: bool = True # Model Aliases (OpenAI → Local) alias_gpt35: str = "gemma:7b" alias_gpt4: str = "mistral:7b" alias_gpt4_turbo: str = "mixtral:8x7b" alias_gpt4_code: str = "codestral:latest" # Memory Configuration memory_tier1_max_turns: int = 10 memory_consolidation_threshold: int = 10 # Qdrant Configuration qdrant_host: str = "qdrant" qdrant_port: int = 6333 qdrant_collection_conversations: str = "core_api_conversations" qdrant_collection_documents: str = "core_api_documents" qdrant_collection_user_facts: str = "core_api_user_facts" # Embeddings (using Ollama - no local models needed) embedding_model: str = "nomic-embed-text" # Ollama embedding model embedding_dimension: int = 768 # nomic-embed-text dimension embedding_batch_size: int = 32 # Search Configuration search_provider: str = "google" # Options: google, brave, searxng, duckduckgo searxng_url: str = "http://searxng:8080" # For future self-hosted SearxNG # Search API Keys (from credentials.py) brave_search_api_key: str = BRAVE_SEARCH_API_KEY # https://brave.com/search/api/ google_search_api_key: str = GOOGLE_SEARCH_API_KEY # https://console.cloud.google.com/ google_search_engine_id: str = GOOGLE_SEARCH_ENGINE_ID # Custom Search Engine ID # Infrastructure Management (from credentials.py) portainer_url: str = PORTAINER_URL portainer_api_key: str = PORTAINER_API_KEY npm_url: str = NPM_URL npm_email: str = NPM_EMAIL npm_password: str = NPM_PASSWORD kuma_url: str = KUMA_URL kuma_username: str = KUMA_USERNAME kuma_password: str = KUMA_PASSWORD kuma_api_key: str = KUMA_API_KEY # Core-AI Service (AI performance metrics) core_ai_base_url: str = "http://core-ai:8086" # OIDC Authentication (Authentik) oidc_enabled: bool = False # Set to True to require authentication oidc_issuer: str = "https://auth.schweitz.net/application/o/core-api/" oidc_audience: str = "core-api" @property def model_aliases(self) -> dict: """Computed property for model aliases""" return { "gpt-3.5-turbo": self.alias_gpt35, "gpt-4": self.alias_gpt4, "gpt-4-turbo": self.alias_gpt4_turbo, "gpt-4-code": self.alias_gpt4_code, } def get_lightweight_models(self) -> list[str]: """Parse comma-separated lightweight models""" return [m.strip().strip('"').strip("'") for m in self.lightweight_models.split(",") if m.strip()] def get_heavy_models(self) -> list[str]: """Parse comma-separated heavy models""" return [m.strip().strip('"').strip("'") for m in self.heavy_models.split(",") if m.strip()] def get_code_models(self) -> list[str]: """Parse comma-separated code models""" return [m.strip().strip('"').strip("'") for m in self.code_models.split(",") if m.strip()] class Config: env_file = ".env" case_sensitive = False @lru_cache() def get_settings() -> Settings: """Cached settings instance""" return Settings()