From 2b0ca79dca55d57a5b1a7354dc4d2d388b6a8125 Mon Sep 17 00:00:00 2001 From: dschlueter Date: Mon, 15 Jun 2026 05:26:58 +0200 Subject: [PATCH] refactor: Modell- und Container-Alias auf coding_model vereinheitlicht MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Statt modell-spezifischer Namen (qwen3.5-single, qwen36-27b-single) wird überall der semantisch neutrale Bezeichner coding_model verwendet. Dadurch kann das Modell bei Bedarf ausgetauscht werden, ohne Konfiguration, Skripte oder Tests anpassen zu müssen. Geändert: models.json, settings.json, start-single.sh, stop-servers.sh, status.sh, pi-coder-judge-extension.ts, tests/, README.md, BEDIENUNGSANLEITUNG.md Co-Authored-By: Claude Sonnet 4.6 --- BEDIENUNGSANLEITUNG.md | 4 ++-- README.md | 14 +++++++------- models.json | 2 +- pi-coder-judge-extension.ts | 26 +++++++++++++------------- settings.json | 4 ++-- start-single.sh | 4 ++-- status.sh | 2 +- stop-servers.sh | 2 +- tests/config.test.mjs | 12 ++++++------ tests/scripts.test.mjs | 8 ++++---- 10 files changed, 39 insertions(+), 39 deletions(-) diff --git a/BEDIENUNGSANLEITUNG.md b/BEDIENUNGSANLEITUNG.md index f56f927..dc26e24 100644 --- a/BEDIENUNGSANLEITUNG.md +++ b/BEDIENUNGSANLEITUNG.md @@ -73,7 +73,7 @@ prüfen beim Start die VRAM-Verfügbarkeit, was zusätzliche Zeit kostet). ``` === LLaMA-Server Status === -qwen36-27b-single (Port 8001): Container=RUNNING HTTP=OK +coding_model (Port 8001): Container=RUNNING HTTP=OK ``` ### pi agent öffnen @@ -869,7 +869,7 @@ HF_HOME=/korrekter/pfad ./start-single.sh 1. Zu wenig VRAM — Container bricht beim Laden ab: ```bash - docker logs qwen36-27b-single | tail -50 + docker logs coding_model | tail -50 # Suche nach: "CUDA out of memory" oder "failed to allocate" ``` → Kontext reduzieren: `-c 65536` statt `-c 262144` in `start-single.sh` diff --git a/README.md b/README.md index 9f54073..8236080 100644 --- a/README.md +++ b/README.md @@ -13,19 +13,19 @@ Programm Produktionsreife hat. Nutzer gibt Auftrag │ ▼ - /coder → qwen3.5-single (:8001, Coder-Persona) → Implementierung + git commit + /coder → coding_model (:8001, Coder-Persona) → Implementierung + git commit │ ▼ - /judge → qwen3.5-single (:8001, Judge-Persona) → Review: PASS / FAIL + Blocker + /judge → coding_model (:8001, Judge-Persona) → Review: PASS / FAIL + Blocker │ FAIL? ▼ - /fix → qwen3.5-single (:8001, Coder-Persona) → Fixes + git commit + /fix → coding_model (:8001, Coder-Persona) → Fixes + git commit │ PASS WITH CONCERNS? ▼ │ (ohne --approve-concerns: wie FAIL → weiterer Fix-Zyklus) │ PASS? ▼ - /shipit → qwen3.5-single (:8001, Judge-Persona) → Finale Freigabe: SHIP / NO-SHIP + /shipit → coding_model (:8001, Judge-Persona) → Finale Freigabe: SHIP / NO-SHIP (nur bei "PASS WITH CONCERNS" --approve-concerns; klares PASS → direkt SHIP) /optimize = Coder→Judge→Fix-Schleife automatisch (bis PASS oder max. N Runden) @@ -43,7 +43,7 @@ nur die Persona im System-Prompt ändert sich. | Rolle | Modell | Port | Container | Alias | GPU | |----------------|---------------------------------------------------|------|--------------------|----------------|----------| -| Coder + Judge | Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS | 8001 | qwen36-27b-single | qwen3.5-single | device=1 | +| Coder + Judge | Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS | 8001 | coding_model | coding_model | device=1 | Coder- und Judge-Rollen werden durch verschiedene System-Prompts realisiert — dasselbe Modell, derselbe Container, unterschiedliche Persona. @@ -91,7 +91,7 @@ cd ~/pi_coder Das Install-Skript sichert eine vorhandene `~/.pi/agent/settings.json` als `.bak` und kopiert dann `settings.json` aus dem Repo. Damit ist der korrekte Default-Provider -(`llama-cpp-single/qwen3.5-single`) automatisch konfiguriert. +(`llama-cpp-single/coding_model`) automatisch konfiguriert. Nach späteren Änderungen an `pi-coder-judge-extension.ts` oder `models.json`: ```bash @@ -161,7 +161,7 @@ Ein einzelner Container bedient beide Rollen sequenziell: ``` GPU 0 NVIDIA T600 → Display / Monitor (nicht für KI genutzt) -GPU 1 RTX 3090 (24 GB) → qwen36-27b-single (Port 8001, Coder + Judge) +GPU 1 RTX 3090 (24 GB) → coding_model (Port 8001, Coder + Judge) ``` Da Coder und Judge nicht gleichzeitig inferieren, gibt es keinen VRAM-Konflikt. diff --git a/models.json b/models.json index 25ed185..8f08ae0 100644 --- a/models.json +++ b/models.json @@ -28,7 +28,7 @@ }, "models": [ { - "id": "qwen3.5-single", + "id": "coding_model", "name": "Qwen3.6 27B Single-Server (llama.cpp :8001)", "reasoning": true, "input": ["text"], diff --git a/pi-coder-judge-extension.ts b/pi-coder-judge-extension.ts index 837755f..b170b35 100644 --- a/pi-coder-judge-extension.ts +++ b/pi-coder-judge-extension.ts @@ -1,6 +1,6 @@ // pi-coder-judge-extension.ts // Automatisierter Coder-Judge-Fix-Workflow für AI-Coding-Assistenten -// Ein Modell (qwen3.5-single) auf Single-Server (Port 8001); Rollen Coder/Judge via System-Prompt +// Ein Modell (coding_model) auf Single-Server (Port 8001); Rollen Coder/Judge via System-Prompt import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent"; import { Type } from "typebox"; @@ -432,13 +432,13 @@ async function tickTaskMdStatus( ); } -// Single-Server: genau ein Modell (qwen3.5-single auf :8001) für beide Rollen. +// Single-Server: genau ein Modell (coding_model auf :8001) für beide Rollen. // Der Rollenwechsel Coder/Judge erfolgt NICHT mehr über den Modellwechsel, sondern // über den System-Prompt (siehe before_agent_start-Hook + currentRole). Diese Funktion // stellt nur sicher, dass das eine Single-Modell aktiv ist; nach dem ersten Aufruf // ist der Wechsel via currentModelKey gecacht und damit ein No-op. const SINGLE_PROVIDER = "llama-cpp-single"; -const SINGLE_MODEL_ID = "qwen3.5-single"; +const SINGLE_MODEL_ID = "coding_model"; async function ensureSingleModel( pi: ExtensionAPI, @@ -1071,7 +1071,7 @@ export default function (pi: ExtensionAPI) { ctx.ui.notify("Benutzung: /coder ", "error"); return; } - if (!await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-single")) { + if (!await waitUntilModelReady(pi, ctx, 8001, "coding_model")) { ctx.ui.notify("Server nicht bereit (Port 8001) — start-single.sh ausführen", "error"); return; } @@ -1085,7 +1085,7 @@ export default function (pi: ExtensionAPI) { pi.registerCommand("judge", { description: "Review gegen TASK.md + git show HEAD → Judge-Rolle (:8001).", handler: async function (args: string, ctx: ExtensionCommandContext) { - if (!await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-single")) { + if (!await waitUntilModelReady(pi, ctx, 8001, "coding_model")) { ctx.ui.notify("Server nicht bereit (Port 8001) — start-single.sh ausführen", "error"); return; } @@ -1098,7 +1098,7 @@ export default function (pi: ExtensionAPI) { pi.registerCommand("fix", { description: "Fixt Judge-Kritik, committet Ergebnis → Coder-Rolle (:8001).", handler: async function (args: string, ctx: ExtensionCommandContext) { - if (!await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-single")) { + if (!await waitUntilModelReady(pi, ctx, 8001, "coding_model")) { ctx.ui.notify("Server nicht bereit (Port 8001) — start-single.sh ausführen", "error"); return; } @@ -1111,7 +1111,7 @@ export default function (pi: ExtensionAPI) { pi.registerCommand("shipit", { description: "Finale Freigabe gegen TASK.md + git log → Judge-Rolle (:8001).", handler: async function (args: string, ctx: ExtensionCommandContext) { - if (!await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-single")) { + if (!await waitUntilModelReady(pi, ctx, 8001, "coding_model")) { ctx.ui.notify("Server nicht bereit (Port 8001) — start-single.sh ausführen", "error"); return; } @@ -1176,7 +1176,7 @@ export default function (pi: ExtensionAPI) { // Im --continue-Modus: Single-Server prüfen (Port 8001 — Coder + Judge in einem). ctx.ui.setStatus("optimize", "Single-Server wird geprüft (Port 8001)…"); - const serverReady = await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-single"); + const serverReady = await waitUntilModelReady(pi, ctx, 8001, "coding_model"); if (!serverReady) { finalNotify(ctx, "⛔ Server nicht erreichbar", "Port 8001 — kein HTTP 200 nach 3 min. start-single.sh ausführen"); return; @@ -1202,7 +1202,7 @@ export default function (pi: ExtensionAPI) { // GPU-Ladevorgangs und ist kein verlässliches Signal. Nur HTTP 200 auf einen // echten Completion-Request bedeutet: Modell ist im VRAM und bereit. ctx.ui.setStatus("optimize", "Single-Server wird geprüft…"); - if (!await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-single")) { + if (!await waitUntilModelReady(pi, ctx, 8001, "coding_model")) { finalNotify(ctx, "⛔ Server nicht erreichbar", "Port 8001 — kein HTTP 200 nach 3 min. start-single.sh ausführen"); return; } @@ -1408,7 +1408,7 @@ export default function (pi: ExtensionAPI) { ctx.ui.notify("Benutzung: /patch ", "error"); return; } - if (!await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-single")) { + if (!await waitUntilModelReady(pi, ctx, 8001, "coding_model")) { ctx.ui.notify("Server nicht bereit (Port 8001) — start-single.sh ausführen", "error"); return; } @@ -1421,7 +1421,7 @@ export default function (pi: ExtensionAPI) { pi.registerCommand("quick_check", { description: "Schnelle OK/PROBLEM-Prüfung einer kleinen Codeänderung → Judge-Rolle (:8001).", handler: async function (args: string, ctx: ExtensionCommandContext) { - if (!await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-single")) { + if (!await waitUntilModelReady(pi, ctx, 8001, "coding_model")) { ctx.ui.notify("Server nicht bereit (Port 8001) — start-single.sh ausführen", "error"); return; } @@ -1489,7 +1489,7 @@ export default function (pi: ExtensionAPI) { ctx.ui.notify("Benutzung: /plan ", "error"); return; } - if (!await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-single")) { + if (!await waitUntilModelReady(pi, ctx, 8001, "coding_model")) { ctx.ui.notify("Server nicht bereit (Port 8001) — start-single.sh ausführen", "error"); return; } @@ -1571,7 +1571,7 @@ export default function (pi: ExtensionAPI) { } // Standard-Verhalten: unterbrochenen Prozess wieder aufnehmen - if (!await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-single")) { + if (!await waitUntilModelReady(pi, ctx, 8001, "coding_model")) { ctx.ui.notify("Server nicht bereit (Port 8001) — start-single.sh ausführen", "error"); return; } diff --git a/settings.json b/settings.json index 1c394e6..da6d0ea 100644 --- a/settings.json +++ b/settings.json @@ -1,9 +1,9 @@ { "lastChangelogVersion": "0.79.3", "defaultProvider": "llama-cpp-single", - "defaultModel": "qwen3.5-single", + "defaultModel": "coding_model", "enabledModels": [ - "llama-cpp-single/qwen3.5-single" + "llama-cpp-single/coding_model" ], "defaultThinkingLevel": "high", "packages": [ diff --git a/start-single.sh b/start-single.sh index 553b14d..9668f31 100755 --- a/start-single.sh +++ b/start-single.sh @@ -4,10 +4,10 @@ set -euo pipefail HF_HOME="${HF_HOME:-/home/dschlueter/nvme2n1p7_home/huggingface}" MODEL_REL_PATH="models/qwen3/Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS.gguf" IMAGE="ghcr.io/ggml-org/llama.cpp:server-cuda" -CONTAINER_NAME="qwen36-27b-single" +CONTAINER_NAME="coding_model" HOST_PORT=8001 CONTAINER_PORT=8000 -MODEL_ALIAS="qwen3.5-single" +MODEL_ALIAS="coding_model" GPU_DEVICE="${GPU_DEVICE:-1}" echo "[*] Verwende HF_HOME = $HF_HOME" diff --git a/status.sh b/status.sh index fe734ca..513b793 100755 --- a/status.sh +++ b/status.sh @@ -30,4 +30,4 @@ check_server() { } echo "=== LLaMA-Server Status ===" -check_server "qwen36-27b-single" 8001 "qwen3.5-single" +check_server "coding_model" 8001 "coding_model" diff --git a/stop-servers.sh b/stop-servers.sh index 1321287..5c27e49 100755 --- a/stop-servers.sh +++ b/stop-servers.sh @@ -2,7 +2,7 @@ set -euo pipefail # Single-GPU-Architektur: nur noch ein Container (Coder + Judge in einem). -SINGLE="qwen36-27b-single" +SINGLE="coding_model" if docker ps -a --format '{{.Names}}' | grep -q "^${SINGLE}\$"; then docker rm -f "$SINGLE" >/dev/null diff --git a/tests/config.test.mjs b/tests/config.test.mjs index 261adac..258c489 100644 --- a/tests/config.test.mjs +++ b/tests/config.test.mjs @@ -8,11 +8,11 @@ import { readJson, readRepoFile } from "./helpers.mjs"; const models = readJson("models.json"); const settings = readJson("settings.json"); -test("models.json: Provider llama-cpp-single hat genau ein Modell qwen3.5-single auf Port 8001", () => { +test("models.json: Provider llama-cpp-single hat genau ein Modell coding_model auf Port 8001", () => { const p = models.providers["llama-cpp-single"]; assert.ok(p, "Provider llama-cpp-single fehlt"); assert.match(p.baseUrl, /:8001\//, "llama-cpp-single muss auf Port 8001 zeigen"); - assert.deepEqual(p.models.map((m) => m.id), ["qwen3.5-single"]); + assert.deepEqual(p.models.map((m) => m.id), ["coding_model"]); }); test("models.json: tote Dual-/Alt-Provider sind entfernt", () => { @@ -27,8 +27,8 @@ test("models.json: kein Verweis mehr auf den toten Port 8002", () => { test("settings.json: Default zeigt auf den Single-Server (nicht Port 8002)", () => { assert.equal(settings.defaultProvider, "llama-cpp-single"); - assert.equal(settings.defaultModel, "qwen3.5-single"); - assert.deepEqual(settings.enabledModels, ["llama-cpp-single/qwen3.5-single"]); + assert.equal(settings.defaultModel, "coding_model"); + assert.deepEqual(settings.enabledModels, ["llama-cpp-single/coding_model"]); }); test("settings.json: defaultProvider/defaultModel existieren in models.json", () => { @@ -61,7 +61,7 @@ test("settings.json ist valides JSON ohne überraschende Felder", () => { test("Konsistenz: Extension und settings.json nennen denselben Provider/dasselbe Modell", () => { const ext = readRepoFile("pi-coder-judge-extension.ts"); assert.match(ext, /SINGLE_PROVIDER = "llama-cpp-single"/); - assert.match(ext, /SINGLE_MODEL_ID = "qwen3.5-single"/); + assert.match(ext, /SINGLE_MODEL_ID = "coding_model"/); assert.equal(settings.defaultProvider, "llama-cpp-single"); - assert.equal(settings.defaultModel, "qwen3.5-single"); + assert.equal(settings.defaultModel, "coding_model"); }); diff --git a/tests/scripts.test.mjs b/tests/scripts.test.mjs index b904a5f..df450d9 100644 --- a/tests/scripts.test.mjs +++ b/tests/scripts.test.mjs @@ -22,19 +22,19 @@ test("Dual-GPU-Skripte sind entfernt", () => { } }); -test("start-single.sh nutzt eine GPU und registriert Alias qwen3.5-single", () => { +test("start-single.sh nutzt eine GPU und registriert Alias coding_model", () => { const s = readRepoFile("start-single.sh"); assert.match(s, /--alias\s+"\$\{MODEL_ALIAS\}"/); - assert.match(s, /MODEL_ALIAS="qwen3\.5-single"/); + assert.match(s, /MODEL_ALIAS="coding_model"/); assert.match(s, /device=\$\{GPU_DEVICE\}/, "GPU muss konfigurierbar/einzeln sein"); }); test("stop-servers.sh stoppt den Single-Container", () => { - assert.match(readRepoFile("stop-servers.sh"), /qwen36-27b-single/); + assert.match(readRepoFile("stop-servers.sh"), /coding_model/); }); test("status.sh prüft den Single-Container", () => { - assert.match(readRepoFile("status.sh"), /qwen36-27b-single/); + assert.match(readRepoFile("status.sh"), /coding_model/); }); test("install-Skript deployt settings.json mit vorherigem Backup", () => {