diff --git a/recipes.py b/recipes.py index 91a17d3..6364426 100644 --- a/recipes.py +++ b/recipes.py @@ -1,59 +1,66 @@ """ Kuratierte Use-Case-„Setups" (Stacks) fuers Cookbook 2.0. Stand: Juni 2026. -Daten, kein Code (KISS/SoC). Pro Modell nur Repo + Groesse/Quant — die konkrete GGUF-Datei wird -beim Installieren dynamisch aus dem Repo aufgeloest (robust gegen Datei-Umbenennungen). Hardware-Fit -+ optimaler Kontext kommen zur Laufzeit aus hw_math. +Best-in-class je Use-Case — bewusst herstelleruebergreifend (Qwen, Google Gemma, Mistral, DeepSeek), +nicht alles Qwen. Pro Modell nur Repo + Groesse/Quant; die GGUF-Datei wird beim Installieren dynamisch +aufgeloest (robust). Fit + optimaler Kontext kommen zur Laufzeit aus hw_math. """ -# Aktuelle, lokal gut laufende GGUF-Repos (Juni 2026). Bevorzugt unsloth (zuverlaessige Quants). RECIPES = [ { "id": "coding", "title": "Coden & Programmieren", "icon": "code", "desc": "Aktueller Top-Coder (MoE, nur 3B aktiv → schnell), ein flinker Helfer und Vision für Screenshots.", "models": [ {"role": "coder", "name": "Qwen3-Coder 30B-A3B", "repo": "unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF", - "params_b": 30, "quant": "Q4_K_M", "why": "Aktuelles Top-Coder-Modell — versteht große Codebasen, läuft dank MoE flott."}, + "params_b": 30, "quant": "Q4_K_M", "why": "Bestes lokales Coder-Modell — versteht große Codebasen, läuft dank MoE flott."}, {"role": "coder-fast", "name": "Qwen3 8B", "repo": "unsloth/Qwen3-8B-GGUF", "params_b": 8, "quant": "Q4_K_M", "why": "Schneller Helfer für einfache Edits & Autovervollständigung."}, - {"role": "vision", "name": "Qwen2.5-VL 7B", "repo": "unsloth/Qwen2.5-VL-7B-Instruct-GGUF", - "params_b": 7, "quant": "Q4_K_M", "why": "Liest Screenshots & Fehlerbilder für die Analyse."}, + {"role": "vision", "name": "Qwen3-VL 8B", "repo": "Qwen/Qwen3-VL-8B-Instruct-GGUF", + "params_b": 8, "quant": "Q4_K_M", "why": "Liest Screenshots & Fehlerbilder für die Analyse."}, ], }, { "id": "vision", "title": "Bilder verstehen", "icon": "eye", "desc": "Ein multimodales Modell, das Bilder und Text gemeinsam versteht.", "models": [ - {"role": "vision", "name": "Qwen2.5-VL 7B", "repo": "unsloth/Qwen2.5-VL-7B-Instruct-GGUF", - "params_b": 7, "quant": "Q4_K_M", "why": "Beschreibt Bilder, liest Diagramme, analysiert Screenshots."}, + {"role": "vision", "name": "Qwen3-VL 8B", "repo": "Qwen/Qwen3-VL-8B-Instruct-GGUF", + "params_b": 8, "quant": "Q4_K_M", "why": "Aktuelles Vision-Modell — beschreibt Bilder, liest Diagramme & Screenshots."}, ], }, { "id": "chat", "title": "Allrounder & Chat", "icon": "compass", - "desc": "Vielseitige Modelle für Alltag, Texte und Brainstorming.", + "desc": "Vielseitig für Alltag, Texte und Brainstorming — Googles Gemma als starke Alternative zu Qwen.", "models": [ - {"role": "scout", "name": "Qwen3 8B", "repo": "unsloth/Qwen3-8B-GGUF", - "params_b": 8, "quant": "Q4_K_M", "why": "Schneller, kluger Allrounder — guter Standard."}, - {"role": "scout-pro", "name": "Qwen3 30B-A3B", "repo": "unsloth/Qwen3-30B-A3B-Instruct-2507-GGUF", - "params_b": 30, "quant": "Q4_K_M", "why": "Mehr Tiefe (MoE), wenn die Antworten besser sein sollen."}, + {"role": "scout", "name": "Gemma 3 27B", "repo": "unsloth/gemma-3-27b-it-GGUF", + "params_b": 27, "quant": "Q4_K_M", "why": "Googles Allrounder — exzellent bei Sprache, Wissen und langem Kontext."}, + {"role": "scout-fast", "name": "Qwen3 8B", "repo": "unsloth/Qwen3-8B-GGUF", + "params_b": 8, "quant": "Q4_K_M", "why": "Schnelle Alternative für kurze Fragen."}, + ], + }, + { + "id": "reasoning", "title": "Nachdenken & Logik", "icon": "pulse", + "desc": "Ein Reasoning-Modell, das Schritt für Schritt denkt — für Mathe, Logik, knifflige Probleme.", + "models": [ + {"role": "thinker", "name": "DeepSeek-R1 Distill 7B", "repo": "unsloth/DeepSeek-R1-Distill-Qwen-7B-GGUF", + "params_b": 7, "quant": "Q4_K_M", "why": "DeepSeeks Reasoning-Ansatz — denkt laut mit, stark bei Logik & Mathe."}, ], }, { "id": "longdoc", "title": "Lange Dokumente", "icon": "file", "desc": "Großes Modell mit großem Kontext — für lange Texte, Verträge, Bücher.", "models": [ - {"role": "reader", "name": "Qwen3 30B-A3B", "repo": "unsloth/Qwen3-30B-A3B-Instruct-2507-GGUF", - "params_b": 30, "quant": "Q4_K_M", "why": "Starke Qualität bei großem Kontextfenster (auto-optimiert)."}, + {"role": "reader", "name": "Gemma 3 27B", "repo": "unsloth/gemma-3-27b-it-GGUF", + "params_b": 27, "quant": "Q4_K_M", "why": "Starke Qualität bei sehr großem Kontextfenster (auto-optimiert)."}, ], }, { "id": "agents", "title": "Agenten & Tool-Use", "icon": "layers", - "desc": "Modelle, die gut mit Werkzeugen/Funktionen umgehen — für autonome Agenten (MCP).", + "desc": "Modelle, die gut mit Werkzeugen/Funktionen umgehen (MCP) — Mistral als Tool-Use-Spezialist.", "models": [ - {"role": "agent", "name": "Qwen3 30B-A3B", "repo": "unsloth/Qwen3-30B-A3B-Instruct-2507-GGUF", - "params_b": 30, "quant": "Q4_K_M", "why": "Stark im Function-Calling und mehrstufigem Denken."}, - {"role": "agent-fast", "name": "Qwen3 8B", "repo": "unsloth/Qwen3-8B-GGUF", - "params_b": 8, "quant": "Q4_K_M", "why": "Schneller Helfer für einfache Tool-Schritte."}, + {"role": "agent", "name": "Mistral Small 3.2 24B", "repo": "unsloth/Mistral-Small-3.2-24B-Instruct-2506-GGUF", + "params_b": 24, "quant": "Q4_K_M", "why": "Mistrals Stärke: zuverlässiges Function-Calling für Agenten."}, + {"role": "agent-think", "name": "Qwen3 30B-A3B", "repo": "unsloth/Qwen3-30B-A3B-Instruct-2507-GGUF", + "params_b": 30, "quant": "Q4_K_M", "why": "Starkes mehrstufiges Denken (MoE) als Backup-Hirn."}, ], }, { @@ -62,21 +69,21 @@ RECIPES = [ "models": [ {"role": "mini", "name": "Qwen3 4B", "repo": "Qwen/Qwen3-4B-GGUF", "params_b": 4, "quant": "Q4_K_M", "why": "Winzig & sehr schnell für einfache Aufgaben."}, - {"role": "scout", "name": "Qwen3 8B", "repo": "unsloth/Qwen3-8B-GGUF", + {"role": "scout-fast", "name": "Qwen3 8B", "repo": "unsloth/Qwen3-8B-GGUF", "params_b": 8, "quant": "Q4_K_M", "why": "Etwas mehr Können, immer noch flott."}, ], }, ] -# Upgrade-Map (Phase 3.2): wenn der Nutzer ein „altes" Modell hat, schlagen wir das neue vor. +# Upgrade-Map: hat der Nutzer ein „altes" Modell, schlagen wir das aktuelle vor. UPGRADES = [ {"match": ["qwen2.5-coder", "qwen2_5-coder"], "name": "Qwen3-Coder 30B-A3B", "repo": "unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF", "params_b": 30, "quant": "Q4_K_M", "why": "Nachfolger deines Coders: MoE mit nur 3B aktiven Parametern → schneller und stärker auf SWE-bench."}, - {"match": ["qwen2.5-7b", "qwen2_5-7b", "qwen2.5-instruct"], "name": "Qwen3 8B", + {"match": ["qwen2.5-7b", "qwen2_5-7b", "qwen2.5-instruct", "llama-3.1-8b", "llama-3-8b"], "name": "Qwen3 8B", "repo": "unsloth/Qwen3-8B-GGUF", "params_b": 8, "quant": "Q4_K_M", "why": "Neuere Generation deines Allrounders — besser im Reasoning und bei Tool-Use."}, - {"match": ["llama-3.2-11b-vision", "llama3.2", "llama-3.2-vision"], "name": "Qwen2.5-VL 7B", - "repo": "unsloth/Qwen2.5-VL-7B-Instruct-GGUF", "params_b": 7, "quant": "Q4_K_M", - "why": "Modernes Vision-Modell — kleiner und meist treffsicherer beim Bildverständnis."}, + {"match": ["llama-3.2-11b-vision", "llama-3.2-vision", "qwen2.5-vl"], "name": "Qwen3-VL 8B", + "repo": "Qwen/Qwen3-VL-8B-Instruct-GGUF", "params_b": 8, "quant": "Q4_K_M", + "why": "Modernes Vision-Modell — kleiner und treffsicherer beim Bildverständnis."}, ] diff --git a/routers/cookbook.py b/routers/cookbook.py index 3b39600..6f26e54 100644 --- a/routers/cookbook.py +++ b/routers/cookbook.py @@ -134,7 +134,10 @@ def recipes(): if _FIT_ORDER[fit["level"]] > _FIT_ORDER[worst]: worst = fit["level"] out.append({**r, "models": models, "fit_level": worst}) - return {"recipes": out, "sys_ram_gb": round(ram_gb, 1)} + # „Beste Wahl": das reichste Setup, das komplett auf die Hardware passt. + fitting = [r for r in out if r["fit_level"] != "too_tight"] + rec = max(fitting, key=lambda r: len(r["models"]), default=None) if fitting else None + return {"recipes": out, "sys_ram_gb": round(ram_gb, 1), "recommended_id": rec["id"] if rec else None} @router.post("/install-recipe") diff --git a/static/css/components.css b/static/css/components.css index 11a0f5e..da6f5b4 100644 --- a/static/css/components.css +++ b/static/css/components.css @@ -216,5 +216,7 @@ button:disabled{opacity:.5;cursor:not-allowed} border-radius:var(--radius);padding:var(--sp-3) var(--sp-4);cursor:pointer;transition:border-color .15s,background .15s; color:var(--tx);font-family:var(--sans)} .card-btn:hover,.card-btn:focus{border-color:var(--accent);background:var(--bg2);outline:none} +.card-btn.cb-best{border:2px solid var(--accent);background:rgba(45,212,191,.05)} +.cb-best-tag{display:inline-block;font-size:11px;color:var(--accent-ink);background:var(--accent);border-radius:6px;padding:2px 9px;margin-bottom:8px;font-weight:500} .card-btn h3{margin:0;font-size:var(--text-lg);font-weight:500} .card-btn p{margin:var(--sp-2) 0 0;font-size:var(--text-sm);color:var(--mut)} diff --git a/static/js/panels/cookbook.js b/static/js/panels/cookbook.js index 72f1e0b..08a84a7 100644 --- a/static/js/panels/cookbook.js +++ b/static/js/panels/cookbook.js @@ -17,6 +17,7 @@ let currentResults = []; let currentAnalysis = null; let activeFilter = ""; let RECIPES = []; +let RECOMMENDED = null; const fitCls = lvl => lvl === "perfect" ? "ok" : lvl === "marginal" ? "warn" : "bad"; const fitWord = lvl => lvl === "perfect" ? "Passt locker" : lvl === "marginal" ? "Wird knapp" : "Zu groß"; @@ -117,6 +118,7 @@ async function loadRecipes() { try { const d = await api("/api/cookbook/recipes"); RECIPES = d.recipes || []; + RECOMMENDED = d.recommended_id || null; renderRecipes(); } catch (e) { $("#cb-recipes").innerHTML = `
Setups nicht ladbar: ${esc(e.message)}
`; @@ -124,8 +126,10 @@ async function loadRecipes() { } function renderRecipes() { - $("#cb-recipes").innerHTML = RECIPES.map(r => ` - `).join(""); + `; + }).join(""); $("#cb-recipes").querySelectorAll("[data-recipe]").forEach(b => b.addEventListener("click", () => openRecipe(b.getAttribute("data-recipe")))); }