"""Konfiguration des PV RAG Agent (alle Werte per Umgebungsvariable übersteuerbar).""" from __future__ import annotations import os from dataclasses import dataclass def _env_str(name: str, default: str) -> str: v = os.environ.get(name) return v if v not in (None, "") else default def _env_int(name: str, default: int) -> int: try: return int(os.environ.get(name, default)) except (TypeError, ValueError): return default def _env_float(name: str, default: float) -> float: try: return float(os.environ.get(name, default)) except (TypeError, ValueError): return default def _env_bool(name: str, default: bool) -> bool: v = os.environ.get(name) if v is None: return default return v.strip().lower() in ("1", "true", "yes", "on") @dataclass class Config: # Pfade (relativ zum Repo-Root, sofern nicht absolut) kb_dir: str = "wissensbasis" db_path: str = "data/index.db" # Ollama (Custom-Port 11435 — nicht "korrigieren", s. Skill) ollama_url: str = "http://100.183.83.12:11435" embed_model: str = "bge-m3" answer_model: str = "qwen3.8:27b" # provisorisch bis Bake-off (M3) # Generierung temperature: float = 0.1 num_ctx: int = 16384 num_predict: int = 1024 think: bool = False # Thinking per Request abschalten (Latenz) chat_timeout_s: float = 300.0 embed_timeout_s: float = 240.0 # Retrieval embed_off: bool = False # True = BM25-only (ohne Dense-Index/-Suche) candidate_pool: int = 50 # Kandidaten je Liste vor der Fusion context_blocks: int = 8 # Kontext-Blöcke im Prompt cross_ref_expand: int = 3 # Top-Einträge, deren cross_refs ergänzt werden cross_ref_max_extra: int = 6 # Obergrenze der Ergänzungen rrf_k: int = 60 recency_boost: float = 0.005 # additiv auf RRF-Score, gewichtet nach Stand # Service port: int = 8080 @classmethod def from_env(cls) -> "Config": d = cls() return cls( kb_dir=_env_str("PV_KB_DIR", d.kb_dir), db_path=_env_str("PV_DB_PATH", d.db_path), ollama_url=_env_str("OLLAMA_URL", d.ollama_url), embed_model=_env_str("PV_EMBED_MODEL", d.embed_model), answer_model=_env_str("PV_ANSWER_MODEL", d.answer_model), temperature=_env_float("PV_TEMPERATURE", d.temperature), num_ctx=_env_int("PV_NUM_CTX", d.num_ctx), num_predict=_env_int("PV_NUM_PREDICT", d.num_predict), think=_env_bool("PV_THINK", d.think), chat_timeout_s=_env_float("PV_CHAT_TIMEOUT_S", d.chat_timeout_s), embed_timeout_s=_env_float("PV_EMBED_TIMEOUT_S", d.embed_timeout_s), embed_off=_env_bool("PV_EMBED_OFF", d.embed_off), candidate_pool=_env_int("PV_CANDIDATE_POOL", d.candidate_pool), context_blocks=_env_int("PV_CONTEXT_BLOCKS", d.context_blocks), cross_ref_expand=_env_int("PV_CROSS_REF_EXPAND", d.cross_ref_expand), cross_ref_max_extra=_env_int("PV_CROSS_REF_MAX_EXTRA", d.cross_ref_max_extra), recency_boost=_env_float("PV_RECENCY_BOOST", d.recency_boost), port=_env_int("PV_PORT", d.port), )