kadiirgok
Add RAG chatbot app (Gradio interface)
9ad23a2
Raw History Blame Contribute Delete
4.31 kB
# -*- coding: utf-8 -*-
"""Çalışma zamanı ayarları.
Tüm yapılandırma tek yerde toplanır: LLM sağlayıcıları (DeepSeek/Groq), embedding modeli,
ChromaDB klasörü, GitHub token'ı ve eşikler. Değer önceliği: açık parametre >
ortam değişkeni > .env > varsayılan.
"""
import os
from dataclasses import dataclass
from pathlib import Path
# Proje kökü: github_rag/ klasörünün bir üstü
PROJECT_ROOT = Path(__file__).resolve().parent.parent
DEFAULT_CHROMA_DIR = PROJECT_ROOT / "chroma_db"
# Çok dilli embedding: Türkçe soru -> İngilizce README eşleşmesini de destekler
DEFAULT_EMBEDDING_MODEL = "paraphrase-multilingual-MiniLM-L12-v2"
# Cosine mesafe eşiği (1 - kosinüs benzerliği). Küçük = daha alakalı.
DEFAULT_DISTANCE_THRESHOLD = 0.4
def _load_dotenv(path: Path | None = None) -> dict[str, str]:
"""Proje kökündeki .env dosyasını (varsa) KEY=VALUE biçiminde okur."""
p = path or (PROJECT_ROOT / ".env")
out: dict[str, str] = {}
if not p.is_file():
return out
for line in p.read_text(encoding="utf-8").splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
k, v = line.split("=", 1)
out[k.strip()] = v.strip().strip('"').strip("'")
return out
def _ensure_env_file() -> None:
""".env yoksa .env.example'dan kopyalar (ilk çalıştırma deneyimini kolaylaştırır)."""
env_path = PROJECT_ROOT / ".env"
example_path = PROJECT_ROOT / ".env.example"
if not env_path.is_file() and example_path.is_file():
try:
env_path.write_text(example_path.read_text(encoding="utf-8"), encoding="utf-8")
except OSError:
pass
@dataclass
class Config:
embedding_model: str = DEFAULT_EMBEDDING_MODEL
chroma_dir: str = str(DEFAULT_CHROMA_DIR)
github_token: str = ""
# LLM sağlayıcıları (OpenAI-uyumlu): DeepSeek (birincil) -> Groq (yedek).
deepseek_api_key: str = ""
deepseek_model: str = "deepseek-chat"
groq_api_key: str = ""
groq_model: str = "openai/gpt-oss-20b"
llm_timeout: int = 120
llm_retries: int = 1
distance_threshold: float = DEFAULT_DISTANCE_THRESHOLD
top_k: int = 4
max_tokens: int = 512
code_max_files: int = 200 # kod okumada en fazla dosya sayısı
code_max_size: int = 1_500_000 # kod okumada toplam byte sınırı (~1.5 MB)
code_distance_threshold: float = 0.7 # kod retrieval eşiği (kod mesafeleri daha yüksek çıkar)
code_top_k: int = 12 # kod retrieval'da dönen chunk sayısı (betimleme için daha geniş)
def _int_env(env: dict, key: str) -> int | None:
try:
return int(env[key])
except (KeyError, ValueError):
return None
def load_config() -> Config:
"""Ortam değişkenlerinden ve .env dosyasından Config üretir.
Öncelik: gerçek ortam değişkenleri (örn. HF Spaces Secrets) > .env > varsayılan.
.env yalnızca yerel geliştirme kolaylığıdır; ortamda ayarlı bir değer varsa o kazanır.
"""
_ensure_env_file()
env = _load_dotenv()
env.update(os.environ)
cfg = Config()
if env.get("GITHUB_RAG_EMBEDDING_MODEL"):
cfg.embedding_model = env["GITHUB_RAG_EMBEDDING_MODEL"]
if env.get("GITHUB_RAG_CHROMA_DIR"):
cfg.chroma_dir = env["GITHUB_RAG_CHROMA_DIR"]
if env.get("GITHUB_TOKEN"):
cfg.github_token = env["GITHUB_TOKEN"]
if env.get("DEEPSEEK_API_KEY"):
cfg.deepseek_api_key = env["DEEPSEEK_API_KEY"]
if env.get("DEEPSEEK_MODEL"):
cfg.deepseek_model = env["DEEPSEEK_MODEL"]
if env.get("GROQ_API_KEY"):
cfg.groq_api_key = env["GROQ_API_KEY"]
if env.get("GROQ_MODEL"):
cfg.groq_model = env["GROQ_MODEL"]
if (t := _int_env(env, "GITHUB_RAG_LLM_TIMEOUT")) is not None:
cfg.llm_timeout = t
if (r := _int_env(env, "GITHUB_RAG_LLM_RETRIES")) is not None:
cfg.llm_retries = r
try:
if env.get("GITHUB_RAG_MAX_TOKENS"):
cfg.max_tokens = int(env["GITHUB_RAG_MAX_TOKENS"])
except ValueError:
pass
try:
if env.get("GITHUB_RAG_THRESHOLD"):
cfg.distance_threshold = float(env["GITHUB_RAG_THRESHOLD"])
except ValueError:
pass
return cfg