refactor: Modell- und Container-Alias auf coding_model vereinheitlicht
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 <noreply@anthropic.com>
This commit is contained in:
parent
485ab30265
commit
2b0ca79dca
10 changed files with 39 additions and 39 deletions
|
|
@ -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`
|
||||
|
|
|
|||
14
README.md
14
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.
|
||||
|
|
|
|||
|
|
@ -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"],
|
||||
|
|
|
|||
|
|
@ -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 <auftrag>", "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 <beschreibung der änderung>", "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 <auftrag>", "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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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": [
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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", () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue