""" Hält das Agent-Hirn (Rolle `hermes`) dauerhaft warm. Hintergrund: llama-swap ist EIN-Gruppen-resident — lädt ein on-demand-Modell außerhalb der `brains`-Gruppe, wird die ganze Gruppe (inkl. Hirn) verdrängt. `persist: true` verhindert nur Idle-Unload, NICHT die Gruppen-Verdrängung; neu vorgewärmt wird sonst erst beim nächsten llama-swap-(Re)Start. Dieser Wächter schließt die Lücke: ist die Box idle (nichts geladen), pingt er das Hirn vor. Während aktiver Last (irgendetwas geladen) hält er sich raus, verdrängt also nie ein gerade genutztes Modell. Abschaltbar/justierbar via Env: MC_REWARM_ENABLED=0, MC_REWARM_INTERVAL, MC_REWARM_MODEL. """ import asyncio import logging import os import httpx from config import LLAMA_SWAP_URL log = logging.getLogger(__name__) ENABLED = os.environ.get("MC_REWARM_ENABLED", "1") != "0" INTERVAL = int(os.environ.get("MC_REWARM_INTERVAL", "90")) # Sekunden zwischen Checks MODEL = os.environ.get("MC_REWARM_MODEL", "hermes") # Alias der Rolle START_DELAY = int(os.environ.get("MC_REWARM_START_DELAY", "25")) async def _running_empty() -> bool: async with httpx.AsyncClient(timeout=8.0) as c: r = await c.get(f"{LLAMA_SWAP_URL}/running") data = r.json() or {} return not (data.get("running") or []) async def _warm() -> None: async with httpx.AsyncClient(timeout=180.0) as c: await c.post(f"{LLAMA_SWAP_URL}/v1/chat/completions", json={ "model": MODEL, "max_tokens": 1, "messages": [{"role": "user", "content": "ping"}], }) async def rewarm_loop() -> None: """Endlos-Schleife (Hintergrund-Task): prüft periodisch, wärmt bei Idle vor.""" await asyncio.sleep(START_DELAY) # Box/Engine nach MC-Start setzen lassen while True: try: if await _running_empty(): log.info("rewarm: Box idle → Hirn '%s' wird vorgewärmt", MODEL) await _warm() except Exception: log.debug("rewarm: Tick fehlgeschlagen", exc_info=True) await asyncio.sleep(INTERVAL)