Refactor: Agent-Hirn-Info zeigt real genutztes Modell (NousResearch-Update-Logik raus)
hermes_brain_info() suchte das role==hermes-Modell + verglich gegen NousResearch-Hermes- Releases. Da das Hirn jetzt ein beliebiges Modell ist (fast = Qwen3.6 via Alias), war das irrefuehrend. Neu: _active_brain_name() liest Hermes' model.default und loest den Alias/Namen auf das installierte Modell auf; recommended/update_available entfallen; Budget-Check bleibt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+27
-53
@@ -25,63 +25,43 @@ def _hermes_version(name: str) -> float | None:
|
|||||||
return float(m.group(1)) if m else None
|
return float(m.group(1)) if m else None
|
||||||
|
|
||||||
|
|
||||||
|
def _active_brain_name() -> str:
|
||||||
|
"""Aktives Agent-Hirn aus Hermes' Config: model.default (sonst model.model)."""
|
||||||
|
try:
|
||||||
|
from ruamel.yaml import YAML
|
||||||
|
p = HERMES_HOME / "config.yaml"
|
||||||
|
if p.exists():
|
||||||
|
with p.open(encoding="utf-8") as f:
|
||||||
|
cfg = YAML().load(f) or {}
|
||||||
|
m = (cfg.get("model") or {}) if isinstance(cfg, dict) else {}
|
||||||
|
return str(m.get("default") or m.get("model") or "auto")
|
||||||
|
except Exception:
|
||||||
|
log.debug("_active_brain_name: Lesefehler", exc_info=True)
|
||||||
|
return "auto"
|
||||||
|
|
||||||
|
|
||||||
def hermes_brain_info() -> dict:
|
def hermes_brain_info() -> dict:
|
||||||
"""Aktuelles Agent-Hirn (hermes-Rolle) + bestes verfügbares NousResearch-Hermes-Modell,
|
"""Aktuelles Agent-Hirn = Modell/Alias, das Hermes laut Config nutzt (model.default),
|
||||||
das auf diese Hardware passt. Für den Modell-Manager: Brain sichtbar + updatebar,
|
plus Budget-Check. Zeigt das REAL genutzte Hirn — unabhängig von einer 'hermes'-Rolle."""
|
||||||
sobald NousResearch eine neuere Hermes-Generation veröffentlicht."""
|
from services import llamaswap
|
||||||
from services import discover, llamaswap
|
|
||||||
from services.fit import evaluate_fit, extract_params_b
|
|
||||||
|
|
||||||
models = llamaswap.list_models()
|
models = llamaswap.list_models()
|
||||||
cur = next((m for m in models if m.get("role") == "hermes"), None)
|
brain = _active_brain_name() # z.B. "fast" (Alias) oder ein Modellname
|
||||||
cur_ver = _hermes_version(cur["name"]) if cur else None
|
bl = brain.lower()
|
||||||
|
cur = next((m for m in models if (m.get("role") or "").lower() == bl), None) \
|
||||||
|
or next((m for m in models if bl in (m["name"] or "").lower()), None)
|
||||||
cur_params = (cur.get("capabilities") or {}).get("params_b") if cur else None
|
cur_params = (cur.get("capabilities") or {}).get("params_b") if cur else None
|
||||||
current = None
|
current = None
|
||||||
if cur:
|
if cur:
|
||||||
current = {"name": cur["name"], "filename": cur.get("filename"),
|
current = {"name": cur["name"], "alias": brain, "filename": cur.get("filename"),
|
||||||
"params_b": cur_params, "quant": cur.get("quant"),
|
"params_b": cur_params, "quant": cur.get("quant"),
|
||||||
"size_bytes": cur.get("size_bytes"), "version": cur_ver,
|
"size_bytes": cur.get("size_bytes"),
|
||||||
"gguf_path": cur.get("gguf_path"), "incomplete": cur.get("incomplete")}
|
"gguf_path": cur.get("gguf_path"), "incomplete": cur.get("incomplete")}
|
||||||
|
|
||||||
ram = psutil.virtual_memory().total / (1024 ** 3)
|
# Fit-Check: passt das (immer warme) Hirn + das größte on-demand-Modell zusammen ins Budget?
|
||||||
best = None
|
|
||||||
try:
|
|
||||||
cands = []
|
|
||||||
for r in discover._fetch_author_models("NousResearch"):
|
|
||||||
rid = r.get("id", "")
|
|
||||||
if "hermes" not in rid.lower():
|
|
||||||
continue
|
|
||||||
pb = extract_params_b(rid)
|
|
||||||
fit = evaluate_fit(pb, "Q4_K_M", 8192, ram, name=rid)
|
|
||||||
if fit["level"] == "too_tight":
|
|
||||||
continue
|
|
||||||
cands.append({"repo": rid, "name": rid.split("/")[-1],
|
|
||||||
"version": _hermes_version(rid) or 0.0, "params_b": pb,
|
|
||||||
"downloads": int(r.get("downloads") or 0), "fit": fit})
|
|
||||||
# neueste Hermes-Version zuerst, dann größer/fähiger, dann beliebter
|
|
||||||
cands.sort(key=lambda c: (c["version"], c["params_b"], c["downloads"]), reverse=True)
|
|
||||||
best = cands[0] if cands else None
|
|
||||||
except Exception:
|
|
||||||
log.debug("hermes_brain_info: HF-Abfrage fehlgeschlagen", exc_info=True)
|
|
||||||
|
|
||||||
update = False
|
|
||||||
if best is not None:
|
|
||||||
if cur_ver is None:
|
|
||||||
update = True
|
|
||||||
elif best["version"] > cur_ver:
|
|
||||||
update = True
|
|
||||||
elif best["version"] == cur_ver and best["params_b"] > (cur_params or 0) * 1.05:
|
|
||||||
update = True
|
|
||||||
# gleiche Datei schon installiert? dann kein Update
|
|
||||||
if current and best["repo"].split("/")[-1].lower() in (current["name"] or "").lower():
|
|
||||||
update = False
|
|
||||||
|
|
||||||
# Fit-Check: passt das EMPFOHLENE Brain als Always-On noch ins Budget, sodass das
|
|
||||||
# größte on-demand-Modell daneben lädt? (Brain muss immer resident sein.)
|
|
||||||
budget = None
|
budget = None
|
||||||
try:
|
try:
|
||||||
from services.budget import footprint_gb, gtt_budget_gb
|
from services.budget import footprint_gb, gtt_budget_gb
|
||||||
from services.fit import estimate_memory_gb
|
|
||||||
groups = llamaswap.list_groups()
|
groups = llamaswap.list_groups()
|
||||||
persist = set()
|
persist = set()
|
||||||
for g in groups.values():
|
for g in groups.values():
|
||||||
@@ -89,13 +69,7 @@ def hermes_brain_info() -> dict:
|
|||||||
persist.update(g.get("members") or [])
|
persist.update(g.get("members") or [])
|
||||||
|
|
||||||
cur_name = cur["name"] if cur else None
|
cur_name = cur["name"] if cur else None
|
||||||
brain_ctx = int((cur.get("ctx") if cur else None) or 32768)
|
brain_gb = footprint_gb(cur) if cur else 0.0
|
||||||
if best:
|
|
||||||
brain_gb = estimate_memory_gb(float(best["params_b"]), "Q4_K_M", brain_ctx)
|
|
||||||
elif cur:
|
|
||||||
brain_gb = footprint_gb(cur)
|
|
||||||
else:
|
|
||||||
brain_gb = 0.0
|
|
||||||
# voller Always-Warm-Footprint (alle persist, Brain=Empfehlung) — nur Info
|
# voller Always-Warm-Footprint (alle persist, Brain=Empfehlung) — nur Info
|
||||||
warm = brain_gb + sum(footprint_gb(m) for m in models
|
warm = brain_gb + sum(footprint_gb(m) for m in models
|
||||||
if m["name"] in persist and m["name"] != cur_name)
|
if m["name"] in persist and m["name"] != cur_name)
|
||||||
@@ -114,7 +88,7 @@ def hermes_brain_info() -> dict:
|
|||||||
except Exception:
|
except Exception:
|
||||||
log.debug("hermes_brain_info: Budget-Berechnung fehlgeschlagen", exc_info=True)
|
log.debug("hermes_brain_info: Budget-Berechnung fehlgeschlagen", exc_info=True)
|
||||||
|
|
||||||
return {"current": current, "recommended": best, "update_available": update, "budget": budget}
|
return {"current": current, "recommended": None, "update_available": False, "budget": budget}
|
||||||
|
|
||||||
|
|
||||||
def _reach(url: str, path: str = "") -> bool:
|
def _reach(url: str, path: str = "") -> bool:
|
||||||
|
|||||||
Reference in New Issue
Block a user