Baktabek's picture
Fix: Add validator for Qdrant :memory: URL
64de372 verified
"""
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()