""" Central configuration for the DSA RAG Chatbot. No magic numbers should be hardcoded anywhere else in the codebase — import from here. """ import os from dotenv import load_dotenv load_dotenv() BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # --------------------------------------------------------------------------- # Flask / App # --------------------------------------------------------------------------- SECRET_KEY = os.getenv("SECRET_KEY", "dev-secret-key-change-me") SESSION_COOKIE_NAME = "dsa_chatbot_session" SESSION_LIFETIME_MINUTES = int(os.getenv("SESSION_LIFETIME_MINUTES", 60 * 24 * 7)) # 7 days # --------------------------------------------------------------------------- # Database (SQLite via SQLAlchemy) # --------------------------------------------------------------------------- DATABASE_PATH = os.path.join(BASE_DIR, "database", "app.db") SQLALCHEMY_DATABASE_URI = f"sqlite:///{DATABASE_PATH}" SQLALCHEMY_TRACK_MODIFICATIONS = False # --------------------------------------------------------------------------- # RAG / Knowledge base # --------------------------------------------------------------------------- KNOWLEDGE_BASE_DIR = os.path.join(BASE_DIR, "rag", "knowledge_base") TOPIC_METADATA_PATH = os.path.join(BASE_DIR, "rag", "knowledge_base", "topic_metadata.json") CHROMA_DB_DIR = os.path.join(BASE_DIR, "rag", "chroma_db") CHROMA_COLLECTION_NAME = "dsa_knowledge_base" EMBEDDING_MODEL_NAME = "all-MiniLM-L6-v2" # Sections expected inside each knowledge-base .txt file. Used by the chunker # to split on structure rather than arbitrary fixed-size windows. KB_SECTION_HEADERS = [ "DEFINITION", "TIME_COMPLEXITY", "SPACE_COMPLEXITY", "USE_WHEN", "EXAMPLE", ] # --------------------------------------------------------------------------- # Retrieval pipeline # --------------------------------------------------------------------------- INITIAL_RETRIEVAL_K = int(os.getenv("INITIAL_RETRIEVAL_K", 15)) TOP_K = int(os.getenv("TOP_K", 5)) SIMILARITY_THRESHOLD = float(os.getenv("SIMILARITY_THRESHOLD", 0.45)) # --------------------------------------------------------------------------- # Memory (mem0) # --------------------------------------------------------------------------- USE_MEM0 = os.getenv("USE_MEM0", "True") == "True" MEM0_LOCAL_STORAGE_DIR = os.path.join(BASE_DIR, "memory", "mem0_store") # --------------------------------------------------------------------------- # History / conversation # --------------------------------------------------------------------------- MAX_RECENT_HISTORY_MESSAGES = int(os.getenv("MAX_RECENT_HISTORY_MESSAGES", 6)) # --------------------------------------------------------------------------- # LLM Provider # --------------------------------------------------------------------------- # "local" -> Mistral-7B-Instruct-v0.2 via transformers/bitsandbytes # "groq" -> future Groq-hosted provider # "openai"-> future OpenAI provider # LLM_PROVIDER = os.getenv("LLM_PROVIDER", "local") LLM_PROVIDER = os.getenv("LLM_PROVIDER", "groq") LOCAL_MODEL_NAME = os.getenv("LOCAL_MODEL_NAME", "mistralai/Mistral-7B-Instruct-v0.2") LOCAL_MODEL_MAX_NEW_TOKENS = int(os.getenv("LOCAL_MODEL_MAX_NEW_TOKENS", 512)) LOCAL_MODEL_TEMPERATURE = float(os.getenv("LOCAL_MODEL_TEMPERATURE", 0.3)) LOCAL_MODEL_LOAD_IN_4BIT = os.getenv("LOCAL_MODEL_LOAD_IN_4BIT", "True") == "True" GROQ_API_KEY = os.getenv("GROQ_API_KEY") GROQ_MAX_TOKENS = int(os.getenv("GROQ_MAX_TOKENS", 1024)) GROQ_MODEL_NAME = os.getenv("GROQ_MODEL_NAME", "llama-3.3-70b-versatile") OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "") OPENAI_MODEL_NAME = os.getenv("OPENAI_MODEL_NAME", "") # --------------------------------------------------------------------------- # Logging # --------------------------------------------------------------------------- LOG_DIR = os.path.join(BASE_DIR, "logs") LOG_FILE_PATH = os.path.join(LOG_DIR, "app.log") LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")