""" Routing-Gateway-Service: liest/schreibt die LiteLLM-Config und prüft die Erreichbarkeit. MC verwaltet damit die Modell-Zuordnung (welcher llama-swap-Alias ist fast/heavy/vision/coder) und die Routing-Regeln. """ import httpx from config import GATEWAY_CONFIG_PATH, GATEWAY_URL, yaml def read_gateway_config() -> dict: if not GATEWAY_CONFIG_PATH.exists(): return {"model_list": [], "litellm_settings": {}, "router_settings": {}} with GATEWAY_CONFIG_PATH.open("r", encoding="utf-8") as f: return yaml.load(f) or {} def write_gateway_config(cfg: dict) -> None: import os GATEWAY_CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True) tmp = GATEWAY_CONFIG_PATH.with_name(GATEWAY_CONFIG_PATH.name + ".tmp") with tmp.open("w", encoding="utf-8") as f: yaml.dump(cfg, f) os.replace(tmp, GATEWAY_CONFIG_PATH) def routing_summary() -> dict: """Kompakte Sicht für die UI: welcher Backend-Alias steckt hinter welchem Gateway-Modellnamen + die Fallback-Ketten.""" cfg = read_gateway_config() routes = [] for entry in cfg.get("model_list") or []: params = entry.get("litellm_params") or {} routes.append({ "name": entry.get("model_name"), "target": str(params.get("model", "")), "api_base": params.get("api_base"), }) settings = cfg.get("litellm_settings") or {} return { "routes": routes, "fallbacks": settings.get("fallbacks") or [], "context_window_fallbacks": settings.get("context_window_fallbacks") or [], } def set_route(name: str, target_alias: str, api_base: str = "http://127.0.0.1:8080/v1") -> None: """Einen Gateway-Modellnamen (z.B. 'fast') auf einen llama-swap-Alias mappen.""" cfg = read_gateway_config() ml = cfg.setdefault("model_list", []) params = {"model": f"openai/{target_alias}", "api_base": api_base, "api_key": "sk-noauth"} for entry in ml: if entry.get("model_name") == name: entry["litellm_params"] = params break else: ml.append({"model_name": name, "litellm_params": params}) write_gateway_config(cfg) def gateway_reachable() -> bool: try: with httpx.Client(timeout=3.0) as c: # LiteLLM hat /health/liveliness; /v1/models tut's auch. r = c.get(f"{GATEWAY_URL}/v1/models") return r.status_code in (200, 401) except Exception: return False