From 902867be3f644c6a5589eef46caf37142c09adc3 Mon Sep 17 00:00:00 2001 From: Hitonabi Date: Wed, 24 Jun 2026 21:02:40 +0200 Subject: [PATCH] fix(v9): Auto-Setup "agent"-Slot via Tool-Capability statt Name-Kategorie Der agent-Slot zog bisher aus der duennen Name-Keyword-Kategorie und blieb oft leer. Jetzt poolt build_dynamic_recipes fuer role==agent ueber ALLE discover-Kategorien und filtert via model_caps.capabilities (HF-Tags) auf tool-faehige Modelle. Co-Authored-By: Claude Opus 4.8 --- routers/cookbook.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/routers/cookbook.py b/routers/cookbook.py index f4d9853..5479e1d 100644 --- a/routers/cookbook.py +++ b/routers/cookbook.py @@ -52,6 +52,13 @@ def _is_moe(name: str) -> bool: or "mixtral" in low or bool(re.search(r"\d+x\d+\.?\d*b", low))) +def _tool_capable(m: dict) -> bool: + """Tool-Fähigkeit eines (noch nicht installierten) Modells aus Name + HF-Tags.""" + from model_caps import capabilities + c = capabilities(name=m.get("repo", ""), hf={"tags": m.get("tags", [])}) + return c["tools"] != "no" + + def _safe_discover(ram_gb: float) -> dict | None: """discover-Daten aus Cache (oder live), ohne zu werfen — None wenn nichts da.""" cached = _load_discover() @@ -68,15 +75,20 @@ def build_dynamic_recipes(disc: dict) -> list: Pro Slot das beste passende Modell (perfect>marginal, MoE bevorzugt fuer APU, dann Beliebtheit); dedupe ueber Slots; leere Slots werden still ausgelassen.""" cats = {c["role"]: c for c in (disc.get("categories") or [])} + all_models = [m for c in cats.values() for m in (c.get("models") or [])] out = [] for tpl in RECIPE_TEMPLATES: used: set[str] = set() models = [] for role in tpl["slots"]: - cat = cats.get(role) - if not cat: - continue - cands = [m for m in cat["models"] + # "agent" = bestes TOOL-FÄHIGES Modell (kategorieübergreifend, via caps), + # nicht die dünne Name-Keyword-Kategorie. Sonst: Modelle der Rolle. + if role == "agent": + pool = [m for m in all_models if _tool_capable(m)] + else: + cat = cats.get(role) + pool = (cat.get("models") if cat else []) or [] + cands = [m for m in pool if m["fit"]["level"] != "too_tight" and m["repo"] not in used] if not cands: continue