File size: 2,746 Bytes
3baa772
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
"""Configuration settings for the RAG engine.

Loads environment variables from .env or uses sensible defaults.
All settings can be customized via environment variables.
"""

import os
from pathlib import Path
from dotenv import load_dotenv

ROOT = Path(__file__).resolve().parent.parent
load_dotenv(ROOT / ".env")


class Settings:
    """Central configuration for paths, models, and retrieval hyperparameters."""

    def __init__(self):
        # LLM configuration
        self.user_llm_api_key = os.getenv("USER_LLM_API_KEY", "").strip()
        self.user_llm_base_url = os.getenv("USER_LLM_BASE_URL", "")
        self.user_llm_model = os.getenv("USER_LLM_MODEL", "gpt-4o-mini")
        self.llm_temperature = float(os.getenv("LLM_TEMPERATURE", "0.1"))
        self.llm_max_tokens = int(os.getenv("LLM_MAX_TOKENS", "1000"))

        # Embeddings & Vector Store
        # HashEmbeddings = 100% offline, zero-dependency token hashing for demo/testing
        self.use_hash_embeddings = os.getenv("USE_HASH_EMBEDDINGS", "true").lower() == "true"
        self.embedding_model = os.getenv("EMBEDDING_MODEL", "all-MiniLM-L6-v2")
        self.collection_name = "rag_engine_docs"

        # Chunking parameters
        self.chunk_size = int(os.getenv("CHUNK_SIZE", "400"))
        self.chunk_overlap = int(os.getenv("CHUNK_OVERLAP", "50"))
        self.parent_chunk_size = int(os.getenv("PARENT_CHUNK_SIZE", "1500"))

        # Retrieval hyperparameters
        self.dense_top_k = int(os.getenv("DENSE_TOP_K", "10"))
        self.bm25_top_k = int(os.getenv("BM25_TOP_K", "10"))
        self.final_top_k = int(os.getenv("FINAL_TOP_K", "4"))
        self.dense_weight = float(os.getenv("DENSE_WEIGHT", "0.6"))
        self.bm25_weight = float(os.getenv("BM25_WEIGHT", "0.4"))

        # Storage paths
        self.data_dir = ROOT / "data"
        self.documents_file = self.data_dir / "documents.jsonl"
        self.chroma_dir = self.data_dir / "chroma"
        self.bm25_file = self.data_dir / "bm25_index.pkl"
        self.parent_store_file = self.data_dir / "parents.jsonl"

        # Ensure base directories exist
        self.ensure_dirs()

    def ensure_dirs(self):
        """Create necessary data storage directories."""
        self.data_dir.mkdir(parents=True, exist_ok=True)
        self.chroma_dir.mkdir(parents=True, exist_ok=True)

    def has_llm_key(self):
        """Check if a valid LLM API key has been provided."""
        return bool(self.user_llm_api_key) and self.user_llm_api_key != "your-api-key-here"


_cached_settings = None


def get_settings():
    """Returns a singleton Settings instance."""
    global _cached_settings
    if _cached_settings is None:
        _cached_settings = Settings()
    return _cached_settings