""" Core - Configuration Management Handles application configuration using Pydantic Settings. """ from functools import lru_cache from typing import List from pydantic import Field, field_validator from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): """Application settings""" model_config = SettingsConfigDict(env_file=".env", case_sensitive=False) # Application app_name: str = Field(default="RAG Onboarding Backend") app_version: str = Field(default="1.0.0") environment: str = Field(default="development") debug: bool = Field(default=True) log_level: str = Field(default="INFO") # Server host: str = Field(default="0.0.0.0") port: int = Field(default=8000) workers: int = Field(default=4) # Database database_url: str = Field( default="postgresql+asyncpg://postgres:postgres@localhost:5432/rag_onboarding" ) database_pool_size: int = Field(default=20) database_max_overflow: int = Field(default=0) # Redis redis_url: str = Field(default="redis://localhost:6379/0") redis_cache_ttl: int = Field(default=3600) # Qdrant qdrant_url: str = Field(default="http://localhost:6333") qdrant_api_key: str = Field(default="") qdrant_collection_name: str = Field(default="onboarding_documents") qdrant_vector_size: int = Field(default=384) # RabbitMQ / Celery rabbitmq_url: str = Field(default="amqp://guest:guest@localhost:5672/") celery_broker_url: str = Field(default="redis://localhost:6379/1") celery_result_backend: str = Field(default="redis://localhost:6379/2") # Gemini gemini_api_key: str = Field(default="") gemini_model: str = Field(default="gemini-2.0-flash") gemini_temperature: float = Field(default=0.7) gemini_max_tokens: int = Field(default=2048) # OpenAI (fallback) openai_api_key: str = Field(default="") openai_model: str = Field(default="gpt-4-turbo-preview") # Embeddings embedding_model: str = Field(default="sentence-transformers/all-MiniLM-L6-v2") embedding_dimension: int = Field(default=384) embedding_batch_size: int = Field(default=32) # RAG Configuration rag_initial_k: int = Field(default=100) rag_final_k: int = Field(default=10) rag_min_score: float = Field(default=0.7) rag_search_type: str = Field(default="hybrid") rag_hybrid_alpha: float = Field(default=0.5) rag_max_context_tokens: int = Field(default=4000) # Reranking rerank_model: str = Field(default="cross-encoder/ms-marco-MiniLM-L-12-v2") use_reranking: bool = Field(default=True) # Caching enable_semantic_cache: bool = Field(default=True) cache_embedding_ttl: int = Field(default=86400) cache_retrieval_ttl: int = Field(default=3600) cache_generation_ttl: int = Field(default=1800) # Circuit Breaker circuit_breaker_failure_threshold: int = Field(default=5) circuit_breaker_recovery_timeout: int = Field(default=60) # Retry Policy retry_max_attempts: int = Field(default=3) retry_wait_exponential_multiplier: int = Field(default=1) retry_wait_exponential_max: int = Field(default=10) # Rate Limiting rate_limit_enabled: bool = Field(default=True) rate_limit_per_minute: int = Field(default=60) rate_limit_per_hour: int = Field(default=1000) # Monitoring prometheus_port: int = Field(default=9090) enable_tracing: bool = Field(default=True) jaeger_agent_host: str = Field(default="localhost") jaeger_agent_port: int = Field(default=6831) trace_sample_rate: float = Field(default=0.1) # CORS cors_origins: List[str] = Field( default=["http://localhost:3000", "http://localhost:8000"] ) cors_allow_credentials: bool = Field(default=True) # Security secret_key: str = Field(default="your-secret-key-change-in-production") algorithm: str = Field(default="HS256") access_token_expire_minutes: int = Field(default=30) @field_validator('qdrant_url', mode='before') @classmethod def validate_qdrant_url(cls, v): """Allow :memory: as a valid Qdrant URL""" if v == ":memory:" or v.startswith("memory://"): return v return v @lru_cache def get_settings() -> Settings: """Get cached settings instance""" return Settings()