| """ |
| config.py β Centralized configuration for SmartRAG. |
| All hyperparameters, paths, and model choices live here. |
| """ |
|
|
| from dataclasses import dataclass, field |
| from pathlib import Path |
|
|
| |
| ROOT = Path(__file__).parent |
|
|
|
|
| |
| @dataclass |
| class ModelConfig: |
| |
| base_model_id: str = "microsoft/phi-2" |
|
|
| |
| output_dir: str = str(ROOT / "artifacts" / "finetuned_model") |
|
|
| |
| embedding_model_id: str = "BAAI/bge-base-en-v1.5" |
|
|
| |
| max_seq_length: int = 2048 |
| max_new_tokens: int = 512 |
|
|
|
|
| |
| @dataclass |
| class LoRAConfig: |
| r: int = 16 |
| lora_alpha: int = 32 |
| target_modules: list = field( |
| default_factory=lambda: [ |
| "q_proj", "k_proj", "v_proj", "o_proj", |
| "gate_proj", "up_proj", "down_proj" |
| ] |
| ) |
| lora_dropout: float = 0.05 |
| bias: str = "none" |
| task_type: str = "CAUSAL_LM" |
|
|
|
|
| |
| @dataclass |
| class TrainingConfig: |
| num_train_epochs: int = 3 |
| per_device_train_batch_size: int = 2 |
| gradient_accumulation_steps: int = 4 |
| learning_rate: float = 2e-4 |
| warmup_ratio: float = 0.03 |
| lr_scheduler_type: str = "cosine" |
| fp16: bool = True |
| logging_steps: int = 10 |
| save_steps: int = 100 |
| eval_steps: int = 100 |
| load_best_model_at_end: bool = True |
| report_to: str = "mlflow" |
|
|
|
|
| |
| @dataclass |
| class RAGConfig: |
| |
| chroma_persist_dir: str = str(ROOT / "artifacts" / "chroma_db") |
| collection_name: str = "smartrag_docs" |
|
|
| |
| top_k: int = 4 |
| chunk_size: int = 512 |
| chunk_overlap: int = 64 |
|
|
| |
| similarity_threshold: float = 0.3 |
|
|
|
|
| |
| @dataclass |
| class DataConfig: |
| |
| |
| dataset_name: str = "medalpaca/medical_meadow_wikidoc" |
| dataset_split: str = "train" |
|
|
| |
| raw_data_dir: str = str(ROOT / "artifacts" / "raw_data") |
| processed_data_dir: str = str(ROOT / "artifacts" / "processed_data") |
|
|
| |
| val_size: float = 0.1 |
| seed: int = 42 |
|
|
|
|
| |
| @dataclass |
| class EvalConfig: |
| mlflow_experiment_name: str = "smartrag-evaluation" |
| results_dir: str = str(ROOT / "artifacts" / "eval_results") |
|
|
| |
| metrics: list = field( |
| default_factory=lambda: [ |
| "faithfulness", |
| "answer_relevancy", |
| "context_precision", |
| "context_recall", |
| ] |
| ) |
|
|
|
|
| |
| @dataclass |
| class UseCaseConfig: |
| """ |
| SmartRAG is focused on: AI Assistant for Programmers. |
| Helps developers query codebases, docs, Stack Overflow Q&A, |
| debug errors, and understand APIs β all grounded in real sources. |
| """ |
| name: str = "AI Assistant for Programmers" |
| domain: str = "software_engineering" |
|
|
| |
| finetune_dataset: str = "iamtarun/python_code_instructions_18k_alpaca" |
|
|
| |
| default_doc_sources: list = field(default_factory=lambda: [ |
| "https://docs.python.org/3/", |
| "https://fastapi.tiangolo.com/", |
| ]) |
|
|
| |
| system_prompt: str = ( |
| "You are an expert programming assistant. " |
| "Answer questions about code, APIs, debugging, and software architecture " |
| "using ONLY the provided context. Show code examples where helpful. " |
| "If unsure, say so β never hallucinate function names or APIs." |
| ) |
|
|
|
|
| |
| @dataclass |
| class HybridSearchConfig: |
| """BM25 (keyword) + Dense (embedding) hybrid retrieval.""" |
| enabled: bool = True |
|
|
| |
| alpha: float = 0.7 |
|
|
| |
| bm25_k1: float = 1.5 |
| bm25_b: float = 0.75 |
|
|
| |
| dense_candidates: int = 20 |
| bm25_candidates: int = 20 |
|
|
| |
| top_k_after_blend: int = 10 |
|
|
|
|
| |
| @dataclass |
| class RerankerConfig: |
| """Cross-encoder reranking on top of hybrid retrieval.""" |
| enabled: bool = True |
|
|
| |
| model_id: str = "cross-encoder/ms-marco-MiniLM-L-6-v2" |
|
|
| |
| top_k_final: int = 4 |
|
|
| |
| score_threshold: float = -5.0 |
|
|
| |
| batch_size: int = 16 |
|
|
|
|
| |
| @dataclass |
| class CacheConfig: |
| """ |
| Embedding cache to avoid re-computing vectors for repeated queries. |
| Cuts latency by 80β95% on cache hits. |
| """ |
| enabled: bool = True |
| backend: str = "memory" |
|
|
| |
| redis_host: str = "localhost" |
| redis_port: int = 6379 |
| redis_db: int = 0 |
| redis_ttl_seconds: int = 3600 |
|
|
| |
| max_memory_entries: int = 10_000 |
|
|
| |
| disk_cache_dir: str = str(ROOT / "artifacts" / "embedding_cache") |
|
|
|
|
| |
| @dataclass |
| class RateLimitConfig: |
| """Per-IP API rate limiting to prevent abuse and manage GPU cost.""" |
| enabled: bool = True |
|
|
| |
| requests_per_minute: int = 20 |
| requests_per_hour: int = 200 |
| requests_per_day: int = 1000 |
|
|
| |
| burst_multiplier: float = 1.5 |
|
|
| |
| backend: str = "memory" |
|
|
|
|
| |
| @dataclass |
| class AgentConfig: |
| """ |
| Multi-step reasoning agent with tool calling. |
| Agent decides WHEN to retrieve, WHEN to search the web, |
| WHEN to execute code β producing richer answers than single-pass RAG. |
| """ |
| enabled: bool = True |
| max_iterations: int = 5 |
| max_tokens_per_step: int = 256 |
|
|
| |
| tools: list = field(default_factory=lambda: [ |
| "vector_search", |
| "hybrid_search", |
| "web_search", |
| "code_executor", |
| "calculator", |
| ]) |
|
|
| |
| temperature: float = 0.05 |
|
|
|
|
| |
| @dataclass |
| class SystemConfig: |
| """ |
| Production system design parameters. |
| These control latency, throughput, and cost. |
| """ |
| |
| target_p50_latency_ms: int = 500 |
| target_p95_latency_ms: int = 2000 |
| target_p99_latency_ms: int = 5000 |
|
|
| |
| api_workers: int = 1 |
| max_concurrent_requests: int = 10 |
|
|
| |
| chroma_hnsw_ef: int = 100 |
| chroma_hnsw_m: int = 16 |
| chroma_batch_size: int = 512 |
|
|
| |
| embedding_batch_size: int = 32 |
| embedding_normalize: bool = True |
|
|
| |
| request_timeout_seconds: int = 60 |
| max_payload_size_mb: int = 10 |
|
|
|
|
| |
| class Config: |
| model = ModelConfig() |
| lora = LoRAConfig() |
| training = TrainingConfig() |
| rag = RAGConfig() |
| data = DataConfig() |
| eval = EvalConfig() |
| usecase = UseCaseConfig() |
| hybrid = HybridSearchConfig() |
| reranker = RerankerConfig() |
| cache = CacheConfig() |
| ratelimit = RateLimitConfig() |
| agent = AgentConfig() |
| system = SystemConfig() |
|
|
| @staticmethod |
| def ensure_dirs(): |
| """Create all artifact directories if they don't exist.""" |
| dirs = [ |
| Path(Config.model.output_dir), |
| Path(Config.rag.chroma_persist_dir), |
| Path(Config.data.raw_data_dir), |
| Path(Config.data.processed_data_dir), |
| Path(Config.eval.results_dir), |
| Path(Config.cache.disk_cache_dir), |
| ] |
| for d in dirs: |
| d.mkdir(parents=True, exist_ok=True) |
|
|
|
|
| cfg = Config() |
|
|