"""Configuration management for Mem0 Interface POC.""" import os import json from typing import List, Optional, Dict from pydantic import Field, AliasChoices from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): """Application settings loaded from environment variables.""" model_config = SettingsConfigDict( env_file=".env", case_sensitive=False, extra="ignore" ) # API Configuration # Accept both OPENAI_API_KEY (from docker-compose) and OPENAI_COMPAT_API_KEY (from direct .env) openai_api_key: str = Field( validation_alias=AliasChoices( "OPENAI_API_KEY", "OPENAI_COMPAT_API_KEY", "openai_api_key" ) ) openai_base_url: str = Field( validation_alias=AliasChoices( "OPENAI_BASE_URL", "OPENAI_COMPAT_BASE_URL", "openai_base_url" ) ) cohere_api_key: str = Field( validation_alias=AliasChoices("COHERE_API_KEY", "cohere_api_key") ) # Database Configuration qdrant_host: str = Field( default="localhost", validation_alias=AliasChoices("QDRANT_HOST", "qdrant_host") ) qdrant_port: int = Field( default=6333, validation_alias=AliasChoices("QDRANT_PORT", "qdrant_port") ) qdrant_collection_name: str = Field( default="mem0", validation_alias=AliasChoices( "QDRANT_COLLECTION_NAME", "qdrant_collection_name" ), ) # Neo4j Configuration neo4j_uri: str = Field( default="bolt://localhost:7687", validation_alias=AliasChoices("NEO4J_URI", "neo4j_uri"), ) neo4j_username: str = Field( default="neo4j", validation_alias=AliasChoices("NEO4J_USERNAME", "neo4j_username"), ) neo4j_password: str = Field( default="mem0_neo4j_password", validation_alias=AliasChoices("NEO4J_PASSWORD", "neo4j_password"), ) # Application Configuration log_level: str = Field( default="INFO", validation_alias=AliasChoices("LOG_LEVEL", "log_level") ) cors_origins: str = Field( default="http://localhost:3000", validation_alias=AliasChoices("CORS_ORIGINS", "cors_origins"), ) # Model Configuration - Ultra-minimal (single model) default_model: str = Field( default="claude-sonnet-4", validation_alias=AliasChoices("DEFAULT_MODEL", "default_model"), ) # Embedder Configuration ollama_base_url: str = Field( default="http://host.docker.internal:11434", validation_alias=AliasChoices("OLLAMA_BASE_URL", "ollama_base_url"), ) embedding_model: str = Field( default="qwen3-embedding:4b-q8_0", validation_alias=AliasChoices("EMBEDDING_MODEL", "embedding_model"), ) embedding_dims: int = Field( default=2560, validation_alias=AliasChoices("EMBEDDING_DIMS", "embedding_dims") ) # Authentication Configuration # Format: JSON string mapping API keys to user IDs # Example: {"api_key_123": "alice", "api_key_456": "bob"} api_keys: str = Field( default="{}", validation_alias=AliasChoices("API_KEYS", "api_keys") ) @property def cors_origins_list(self) -> List[str]: """Convert CORS origins string to list.""" return [origin.strip() for origin in self.cors_origins.split(",")] @property def api_key_mapping(self) -> Dict[str, str]: """Parse and return API key to user_id mapping.""" try: mapping = json.loads(self.api_keys) if not isinstance(mapping, dict): raise ValueError("API_KEYS must be a JSON object/dict") return mapping except json.JSONDecodeError as e: raise ValueError(f"Invalid API_KEYS JSON format: {e}") # Global settings instance settings = Settings()