diff --git a/BEDIENUNGSANLEITUNG.md b/BEDIENUNGSANLEITUNG.md new file mode 100644 index 0000000..baede8c --- /dev/null +++ b/BEDIENUNGSANLEITUNG.md @@ -0,0 +1,678 @@ +# Bedienungsanleitung: pi_coder + +pi_coder ist ein Werkzeug, das zwei lokale KI-Modelle als **Coder** und **Judge** einsetzt, +um Software automatisch zu schreiben, zu prüfen und zu verbessern — alles gesteuert über +einfache Slash-Kommandos in der pi-Agent-Oberfläche. + +--- + +## Inhaltsverzeichnis + +1. [Konzept: Coder und Judge](#1-konzept-coder-und-judge) +2. [Vorbereitung](#2-vorbereitung) +3. [Server starten und stoppen](#3-server-starten-und-stoppen) +4. [Neues Projekt anlegen](#4-neues-projekt-anlegen) +5. [Manueller Workflow: /coder → /judge → /fix → /shipit](#5-manueller-workflow) +6. [Automatischer Workflow: /optimize](#6-automatischer-workflow-optimize) +7. [Kleine Änderungen: /patch und /quick_check](#7-kleine-änderungen-patch-und-quick_check) +8. [Dokumentation generieren: /update_doku](#8-dokumentation-generieren-update_doku) +9. [TASK.md verstehen und nutzen](#9-taskmd-verstehen-und-nutzen) +10. [Typische Anwendungsfälle](#10-typische-anwendungsfälle) +11. [Fehlermeldungen und Lösungen](#11-fehlermeldungen-und-lösungen) + +--- + +## 1. Konzept: Coder und Judge + +pi_coder verwendet zwei Rollen: + +**Coder** (Port 8001): Schreibt und repariert Code. Liest die Aufgabe aus `TASK.md`, +implementiert sie, führt Tests aus und erstellt Git-Commits. + +**Judge** (Port 8002): Überprüft den Code mit dem Blick eines skeptischen Senior-Entwicklers. +Prüft Korrektheit, Robustheit, Randfälle, Sicherheit und Produktionsreife. Gibt ein Urteil: +- `PASS` — Code ist in Ordnung +- `PASS WITH CONCERNS` — grundsätzlich akzeptabel, aber mit Anmerkungen +- `FAIL` — enthält Blocker, die behoben werden müssen + +Der Grundgedanke: Coder und Judge haben keine „Höflichkeitsschranke" zueinander — +der Judge kritisiert direkt und konkret, der Coder repariert ohne Widerspruch. + +--- + +## 2. Vorbereitung + +### Server starten + +```bash +cd ~/pi_coder +./start-servers.sh +``` + +Ausgabe bei Erfolg: +``` +[*] Starte beide Server parallel ... +[✓] Coder (:8001) bereit +[✓] Judge (:8002) bereit +``` + +Dauer: 1–3 Minuten (Modell wird in GPU-VRAM geladen). + +### Status prüfen + +```bash +./status.sh +``` + +``` +=== LLaMA-Server Status === +qwen36-27b-coder (Port 8001): Container=RUNNING HTTP=OK +qwen36-27b-judge (Port 8002): Container=RUNNING HTTP=OK +``` + +### pi agent öffnen + +pi agent im Projektverzeichnis starten — das ist das Verzeichnis, in dem dein Code liegt, +**nicht** `~/pi_coder`: + +```bash +cd ~/MeinProjekt +pi +``` + +--- + +## 3. Server starten und stoppen + +### Beide starten (empfohlen) + +```bash +./start-servers.sh +``` + +### Einzelnen Server neu starten + +Z.B. wenn nur der Coder-Server abgestürzt ist: + +```bash +./start-coder.sh +``` + +### Beide stoppen + +```bash +./stop-servers.sh +``` + +### Alternativer Modellpfad + +Falls die GGUF-Datei an einem anderen Ort liegt: + +```bash +HF_HOME=/mnt/daten/huggingface ./start-servers.sh +``` + +--- + +## 4. Neues Projekt anlegen + +### Kommando + +``` +/new_project +``` + +### Beispiel + +``` +/new_project ~/Python_Programs/mein_tool +``` + +Was passiert: +- Verzeichnis `~/Python_Programs/mein_tool` wird angelegt +- `git init` wird ausgeführt +- `.gitignore` wird mit Standardeinträgen angelegt und committed + +**Wichtig:** pi agent wechselt **nicht automatisch** in das neue Verzeichnis — +die Session bleibt im aktuellen Verzeichnis. Nach dem Anlegen: + +```bash +cd ~/Python_Programs/mein_tool +pi +``` + +Dann kannst du `/coder` oder `/optimize` mit dem neuen Projekt verwenden. + +--- + +## 5. Manueller Workflow + +Der manuelle Workflow gibt dir volle Kontrolle über jeden Schritt. + +### Schritt 1: /coder — Aufgabe übergeben + +``` +/coder +``` + +Der Coder: +1. Legt `TASK.md` im aktuellen Verzeichnis an (oder hängt an bestehende an) +2. Liest `TASK.md` und implementiert den Auftrag +3. Führt Tests oder Build-Checks aus +4. Erstellt einen Git-Commit + +**Beispiel:** + +``` +/coder Schreibe ein Python-Kommandozeilenprogramm 'textcount'. Es soll eine Textdatei als Argument nehmen und folgendes ausgeben: Anzahl Zeichen, Wörter, Zeilen und die 5 häufigsten Wörter (ohne Stoppwörter). +``` + +Typische Ausgabe des Coders: +``` +Implementierung abgeschlossen. +- src/textcount.py erstellt (Hauptprogramm) +- tests/test_textcount.py erstellt (Unit-Tests) +- requirements.txt angelegt (keine externen Abhängigkeiten) +- Alle 8 Tests bestanden +- Commit: feat: implement textcount CLI tool +Risiken: Stoppwortliste nur Deutsch/Englisch, keine Konfigurations-Option. +``` + +### Schritt 2: /judge — Code überprüfen lassen + +``` +/judge +``` + +Optionaler Fokus: +``` +/judge Besonderes Augenmerk auf Fehlerbehandlung und Edge Cases +``` + +Der Judge: +1. Liest `TASK.md` und prüft ob alle Anforderungen umgesetzt sind +2. Analysiert `git show HEAD` +3. Führt Tests aus +4. Gibt ein strukturiertes Urteil aus + +**Beispiel-Ausgabe PASS:** +``` +Urteil: PASS WITH CONCERNS + +Blocker: keine + +Major: +- Stoppwortliste ist hardcoded; große Projekte erwarten --stopwords-file Option + +Minor: +- Keine --version Flag +- Fehlermeldung bei nicht-existenter Datei gibt keinen Exit-Code 1 zurück + +Fehlende Tests: +- Test für leere Datei fehlt +- Test für Datei mit nur Leerzeichen fehlt + +Produktionsrisiken: +- Bei sehr großen Dateien (>1 GB) wird alles in den RAM geladen + +Konkrete Fix-Aufträge: +1. exit(1) bei FileNotFoundError +2. Test für leere Eingabedatei +``` + +**Beispiel-Ausgabe FAIL:** +``` +Urteil: FAIL + +Blocker: +- textcount.py importiert 'collections.Counter' aber das ist nicht installiert + (Counter ist stdlib, aber der Import-Fehler tritt bei Python < 3.9 auf) +- ./textcount.py existiert nicht — tests/test_textcount.py schlägt komplett fehl + +Major: ... +``` + +### Schritt 3: /fix — Kritik beheben + +``` +/fix +``` + +Optionaler Hinweis: +``` +/fix Den Major-Punkt mit der Stoppwortliste kannst du weglassen, das ist kein Produktionsprojekt +``` + +Der Coder arbeitet die Judge-Kritik ab (Blocker zuerst, dann Major, dann Minor) +und erstellt einen neuen Commit. + +### Schritt 4: /shipit — Finale Freigabe + +``` +/shipit +``` + +Der Judge gibt ein finales Urteil: +- `SHIP` — bereit für Produktion +- `NO-SHIP` — noch Probleme offen + +**Beispiel:** +``` +Urteil: SHIP + +Letzte Blocker: keine + +Restrisiken: +- Kein Streaming für sehr große Dateien (dokumentiert in README) + +Empfohlene Sofortmaßnahmen: keine +``` + +--- + +## 6. Automatischer Workflow: /optimize + +`/optimize` führt den gesamten Coder→Judge→Fix-Zyklus automatisch durch. + +### Syntax + +``` +/optimize [--rounds N] [--with-doku] +``` + +- `--rounds N` — maximale Anzahl Runden (Standard: 3) +- `--with-doku` — nach SHIP automatisch `/update_doku` ausführen + +### Beispiel: einfacher Auftrag + +``` +/optimize Schreibe ein Rust-Programm 'genpw' das sichere Passwörter generiert. Optionen: --length N (Standard 16), --count N (Standard 1), --no-symbols, --no-numbers. +``` + +Was im Hintergrund passiert: +``` +Phase 1: Coder implementiert... +Phase 2: Runde 1/3: Judge prüft... + → Urteil: FAIL (2 Blocker) +Phase 3: Runde 1/3: Coder fixt... +Phase 4: Runde 2/3: Judge prüft... + → Urteil: PASS WITH CONCERNS +✓ PASS WITH CONCERNS nach Runde 2 +Finale ShipIt-Prüfung... + → SHIP +``` + +### Beispiel: mehr Runden + +``` +/optimize Implementiere einen vollständigen REST-API-Client für die GitHub API in Python mit Rate-Limiting, Retry-Logic und Caching --rounds 5 +``` + +### Beispiel: mit automatischer Dokumentation + +``` +/optimize Schreibe ein Go-Tool 'logfilter' das Logdateien nach Regex-Muster filtert --with-doku +``` + +Nach SHIP werden automatisch ausgeführt: +1. Code-Kommentare einfügen +2. README.md schreiben +3. BEDIENUNGSANLEITUNG.md schreiben + +### Loop-Erkennung + +Wenn zweimal hintereinander genau dieselben Blocker auftreten, bricht `/optimize` ab: +``` +⚠ Derselbe Blocker tritt erneut auf – Schleife abgebrochen. Bitte manuell prüfen. +``` + +In diesem Fall: `/judge` manuell ausführen, Blocker lesen, mit `/fix` manuell eingreifen. + +### Max. Runden ohne PASS + +``` +⚠ 3 Runden durchlaufen ohne PASS. Bitte manuell prüfen. +``` + +Dann: `/judge` und `/fix` manuell für gezielte Eingriffe. + +--- + +## 7. Kleine Änderungen: /patch und /quick_check + +Für minimale Korrekturen — kein voller Review-Zyklus, keine TASK.md-Änderungen. + +### /patch — kleine Änderung umsetzen + +``` +/patch +``` + +Der Coder ändert **ausschließlich** das Beschriebene, prüft ob es noch kompiliert/startet +und erstellt einen Commit. + +**Beispiele:** + +``` +/patch Mindestpasswortlänge von 4 auf 8 Zeichen erhöhen +``` + +``` +/patch Fehlermeldung bei ungültigem Argument von stderr auf stdout umleiten +``` + +``` +/patch Versionsnummer in Cargo.toml von 0.1.0 auf 0.2.0 erhöhen +``` + +``` +/patch Die Funktion parse_args() soll bei fehlendem --input-Argument eine sinnvolle Hilfsnachricht ausgeben statt zu paniken +``` + +### /quick_check — Änderung schnell prüfen lassen + +``` +/quick_check [was geprüft werden soll] +``` + +Der Judge schaut sich `git show HEAD` an und gibt nur `OK` oder `PROBLEM` zurück. + +**Beispiele:** + +``` +/quick_check +``` + +``` +/quick_check Prüfe ob die Mindestlängen-Änderung korrekt umgesetzt ist und keine Randfälle fehlen +``` + +**Typische Ausgaben:** + +``` +Urteil: OK + +Die Änderung in src/main.rs Zeile 47 ist korrekt. Mindestlänge wird jetzt +sowohl bei --length als auch im Standardfall geprüft. +``` + +``` +Urteil: PROBLEM + +src/lib.rs Zeile 23: Der neue Mindestwert von 8 wird nur bei --length geprüft, +nicht beim Standardwert (16). Wenn jemand --length 6 übergibt, schlägt die +Validierung korrekt fehl, aber der Standardfall ist nicht abgedeckt. +Fix: Validierung in die Funktion generate_password() verschieben statt in parse_args(). +``` + +### Typischer /patch + /quick_check Workflow + +``` +/patch Timeout bei HTTP-Requests von 30 auf 10 Sekunden setzen +``` +*(Coder ändert, committet)* + +``` +/quick_check Prüfe ob der Timeout auch bei Retry-Versuchen korrekt gilt +``` +*(Judge gibt OK oder zeigt konkretes Problem)* + +--- + +## 8. Dokumentation generieren: /update_doku + +Nach Abschluss der Entwicklung (nach `/shipit` oder `/optimize`) erstellt `/update_doku` +drei Dinge automatisch: + +1. **Code-Kommentare** — erklärt das WARUM in den Quelldateien (Deutsch) +2. **README.md** — Entwicklerperspektive: Installation, Build, Verwendung +3. **BEDIENUNGSANLEITUNG.md** — Endnutzerperspektive: einfach, ohne Jargon + +``` +/update_doku +``` + +### Inkrementelles Update + +`/update_doku` merkt sich via Git-Tags welche Dateien seit dem letzten Lauf geändert wurden. +Nur geänderte Quelldateien werden neu kommentiert — unveränderte bleiben unangetastet. + +``` +Code-Kommentare: keine Änderungen seit letztem Lauf – übersprungen. +README.md: 2 Datei(en) geändert – wird geprüft +BEDIENUNGSANLEITUNG.md: 2 Datei(en) geändert – wird geprüft +``` + +### Zusammen mit /optimize + +``` +/optimize Implementiere Feature X --with-doku +``` + +Führt nach SHIP automatisch `/update_doku` aus. + +--- + +## 9. TASK.md verstehen und nutzen + +`TASK.md` ist die persistente Aufgabenbeschreibung im Projektverzeichnis. Sie wird von +allen Kommandos als Referenz gelesen. + +### Erstellt von /coder und /optimize + +Beim ersten `/coder`-Aufruf: +```markdown +# Aufgabe + +Schreibe ein Python-Kommandozeilenprogramm 'textcount'... + +## Erstellt +2026-05-19T14:30:00.000Z + +## Status +- [ ] Implementierung +- [x] Review bestanden (PASS) +- [ ] Produktionsreif (SHIP) +``` + +### Zusatzauftrag hinzufügen + +Wenn du später `/coder` mit einer neuen Aufgabe aufrufst, wird TASK.md erweitert statt überschrieben: + +``` +/coder Füge zusätzlich eine --csv-Option hinzu, die das Ergebnis als CSV ausgibt +``` + +```markdown +# Aufgabe + +[...ursprüngliche Aufgabe...] + +--- + +## Zusatzauftrag + +2026-05-19T15:45:00.000Z + +Füge zusätzlich eine --csv-Option hinzu... + +## Status +- [ ] Implementierung +- [ ] Review bestanden (PASS) +- [ ] Produktionsreif (SHIP) +``` + +### Status-Checkboxen + +Die Checkboxen werden automatisch abgehakt: +- `[x] Implementierung` — nach erfolgreichem `/coder` oder `Phase 1` von `/optimize` +- `[x] Review bestanden (PASS)` — nach PASS durch `/judge` oder in `/optimize` +- `[x] Produktionsreif (SHIP)` — nach SHIP durch `/shipit` oder `/update_doku` + +--- + +## 10. Typische Anwendungsfälle + +### Neues Rust-Programm von Null + +```bash +# 1. Verzeichnis anlegen +/new_project ~/Rust_Programs/mein_tool + +# 2. Terminal: in Verzeichnis wechseln und pi neu starten +# cd ~/Rust_Programs/mein_tool && pi + +# 3. In pi: vollautomatisch implementieren + dokumentieren +/optimize Schreibe ein Rust-CLI-Tool 'csvfilter' das CSV-Dateien zeilenweise filtert. Optionen: --column NAME, --value WERT, --regex. Ausgabe auf stdout. --with-doku +``` + +### Bestehendes Projekt verbessern + +```bash +# In pi, im Projektverzeichnis: +/coder Refaktoriere die Datenbankschicht: ersetze das raw-SQL durch sqlx mit typsicheren Queries. Alle Tests müssen danach noch laufen. +/judge +/fix +/shipit +``` + +### Schnelle Bugfixes + +```bash +/patch Die Funktion split_csv() schlägt bei Feldern mit eingebetteten Kommas fehl (RFC 4180 nicht implementiert) +/quick_check +``` + +### Kommentarlosen Legacy-Code dokumentieren + +```bash +# Nur Kommentare und Dokumentation, kein Code ändern: +/update_doku +``` + +### Schrittweise mit manuellem Review + +```bash +/coder Implementiere OAuth2-Login mit GitHub +# → Code lesen, verstehen +/judge Besonderes Augenmerk auf Token-Speicherung und CSRF-Schutz +# → Judge-Bericht lesen +/fix Ignoriere den Minor-Punkt mit der Logging-Verbosität, das ist Absicht +/shipit +``` + +### Experiment: mehrere Runden explizit + +```bash +/optimize Schreibe einen vollständigen Markdown-Parser mit AST in Python --rounds 5 +``` + +--- + +## 11. Fehlermeldungen und Lösungen + +### "Modell-Datei nicht gefunden" + +``` +[!] Modell-Datei nicht gefunden: /home/.../models/qwen3/Qwen3.6-27B-Uncensored-...gguf +``` + +**Ursache:** Die GGUF-Datei liegt nicht am erwarteten Ort. + +**Lösung:** +```bash +# Pfad prüfen: +ls $HF_HOME/models/qwen3/ + +# Oder mit explizitem Pfad starten: +HF_HOME=/korrekter/pfad ./start-servers.sh +``` + +### Server startet nicht / HTTP nicht erreichbar + +``` +[!] HTTP-Server wurde nicht rechtzeitig erreichbar. +``` + +**Ursachen und Lösungen:** + +1. Zu wenig VRAM — Container bricht beim Laden ab: + ```bash + docker logs qwen36-27b-coder | tail -50 + # Suche nach: "CUDA out of memory" oder "failed to allocate" + ``` + → Kontext reduzieren: `-c 32768` statt `-c 131072` + +2. GPU nicht verfügbar: + ```bash + nvidia-smi # GPUs sichtbar? + docker run --gpus '"device=1,2"' --rm nvidia/cuda:12.0-base nvidia-smi + ``` + +3. Port bereits belegt: + ```bash + ss -tlnp | grep 800[12] + docker ps -a # alter Container noch vorhanden? + ./stop-servers.sh + ./start-servers.sh + ``` + +### "Agent is already processing a prompt" + +**Ursache:** Ein Kommando wurde aufgerufen während pi agent noch auf eine Antwort wartet. + +**Lösung:** Warten bis die aktuelle Antwort fertig ist, dann das Kommando wiederholen. +Bei `/optimize` passiert das automatisch — der interne Mechanismus wartet auf `idle`. + +### "edits[n] ... oldText must match exactly" + +**Ursache:** Der interne pi-agent-Edit-Mechanismus hat beim Anwenden mehrerer Änderungen +an derselben Datei versagt. + +**Was pi_coder dagegen tut:** Ein `tool_call`-Hook in der Extension sortiert +Mehrfach-Edits automatisch von hinten nach vorne (Bottom-up-Reordering), sodass +frühere Edits spätere Positionen nicht verschieben. Zusätzlich steht das `apply_patch`-Tool +bereit, das GNU `patch -p1` mit Fuzzy-Matching nutzt. + +**Falls es trotzdem auftritt:** Das Modell manuell anweisen: +``` +Lies die Datei neu ein und wende die Änderungen als unified diff mit apply_patch an. +``` + +### "Drei Runden ohne PASS" / Loop-Erkennung schlägt an + +``` +⚠ Derselbe Blocker tritt erneut auf – Schleife abgebrochen. +``` + +**Ursache:** Der Coder kann einen bestimmten Blocker nicht beheben — z.B. weil die +Aufgabe einen Widerspruch enthält oder ein externes System fehlt. + +**Lösung:** Manuell eingreifen: +``` +/judge ← Judge-Bericht lesen +``` +Dann den Blocker analysieren und entweder: +- `/fix Ignoriere Blocker X, das ist nicht Teil dieser Aufgabe` +- Den Code selbst anpassen und dann `/fix` aufrufen +- Die Aufgabe in TASK.md präzisieren + +### Server läuft, aber pi wechselt nicht das Modell + +**Ursache:** `models.json` wurde nach einer Änderung nicht neu deployt. + +**Lösung:** +```bash +cd ~/pi_coder +./install.sh +# Dann /reload in pi agent +``` + +### "Neues Projekt" wechselt nicht das Verzeichnis + +Das ist gewollt — pi-Sessions sind an ihr Startverzeichnis gebunden. +Nach `/new_project ` im Terminal: +```bash +cd +pi +``` diff --git a/README.md b/README.md index 774318d..a09553a 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Dieses Repository enthält die Konfiguration und Skripte für einen automatisier Coding-Workflow mit zwei lokalen LLaMA-Modellen: ein Coder-Modell und ein Judge-Modell, gesteuert über [pi agent](https://github.com/earendil-works/pi). +--- + ## Überblick ``` @@ -24,45 +26,77 @@ Nutzer gibt Auftrag /optimize = Coder→Judge→Fix-Schleife automatisch (bis PASS oder max. N Runden) ``` +Beide Modelle laufen als **separate llama.cpp-Docker-Container** und sprechen eine +OpenAI-kompatible API (`/v1/chat/completions`). pi agent wechselt automatisch zwischen +den Endpunkten wenn du ein `/judge`-, `/fix`- oder `/coder`-Kommando aufrufst. + +--- + ## Modelle -| Rolle | Modell | Port | Container | -|---------|-------------------------------------------------|------|---------------------| -| Coder | Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS | 8001 | qwen36-27b-coder | -| Judge | Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS | 8002 | qwen36-27b-judge | +| Rolle | Modell | Port | Container | Alias | +|--------|---------------------------------------------------|------|------------------|----------------| +| Coder | Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS | 8001 | qwen36-27b-coder | qwen3.5-coder | +| Judge | Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS | 8002 | qwen36-27b-judge | qwen3.5-judge | -Beide Modelle laufen als separate llama.cpp-Docker-Container auf GPU 1 und 2 (tensor-split 0.5/0.5). +Beide Container verwenden dasselbe GGUF-Datei, aber mit unterschiedlichen +Serverparametern (Kontext, Temperatur, Parallelität). + +--- ## Voraussetzungen -- Docker mit NVIDIA-GPU-Support (`nvidia-container-toolkit`) -- GPU 1 und GPU 2 verfügbar (`nvidia-smi`) -- GGUF-Modell unter: `$HF_HOME/models/qwen3/Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS.gguf` - - Standard: `HF_HOME=/home/dschlueter/nvme2n1p7_home/huggingface` +- Docker mit NVIDIA-GPU-Support: + ```bash + # NVIDIA Container Toolkit installieren (falls nicht vorhanden) + distribution=$(. /etc/os-release; echo $ID$VERSION_ID) + curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - + curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list \ + | sudo tee /etc/apt/sources.list.d/nvidia-docker.list + sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit + sudo systemctl restart docker + ``` +- Mindestens eine NVIDIA-GPU (empfohlen: zwei GPUs mit je ≥ 16 GB VRAM) +- GGUF-Modell vorhanden unter: + `$HF_HOME/models/qwen3/Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS.gguf` + - Standard-Pfad: `HF_HOME=/home/dschlueter/nvme2n1p7_home/huggingface` + - Überschreibbar: `HF_HOME=/anderer/pfad ./start-servers.sh` - [pi agent](https://github.com/earendil-works/pi) installiert (`~/.pi/`) -## Setup +--- + +## Installation ```bash -# 1. Extension und Modell-Config nach ~/.pi/agent/ deployen +# 1. Repository klonen +git clone ~/pi_coder +cd ~/pi_coder + +# 2. Extension und Modell-Config nach ~/.pi/agent/ deployen ./install.sh -# 2. /reload in pi agent ausführen +# 3. pi agent neu laden (in der pi-Oberfläche) +# /reload + +# 4. Server starten +./start-servers.sh ``` -Nach Änderungen an `pi-coder-judge-extension.ts` oder `models.json`: +Nach späteren Änderungen an `pi-coder-judge-extension.ts` oder `models.json`: ```bash ./install.sh # kopiert nach ~/.pi/agent/ # dann /reload in pi agent ``` +--- + ## Server starten / stoppen / status ```bash -# Beide Server parallel starten (empfohlen) +# Beide Server parallel starten (empfohlen — dauert 1–3 Minuten) ./start-servers.sh -# Einzeln starten (z.B. nach Absturz eines Servers) +# Einzeln starten (z.B. nur einen neu starten) ./start-coder.sh # Port 8001 ./start-judge.sh # Port 8002 @@ -74,27 +108,156 @@ Nach Änderungen an `pi-coder-judge-extension.ts` oder `models.json`: ``` `start-servers.sh` startet beide Container gleichzeitig und wartet bis beide -HTTP-ready sind — schneller als sequenziell. Logs werden getrennt gesammelt -und nur bei Fehler ausgegeben. +HTTP-ready sind. Logs werden getrennt gesammelt und nur bei Fehler ausgegeben. + +Wenn Server bereits laufen und du `start-servers.sh` (oder ein Einzelskript) +aufrufst, werden die laufenden Container zuerst per `docker rm -f` gestoppt +und dann neu gestartet — ein laufender Inference-Request wird dabei abgebrochen. + +--- + +## llama.cpp-Serverparameter im Detail + +### Gemeinsame Parameter + +| Parameter | Wert | Bedeutung | +|---|---|---| +| `--jinja` | — | Verwendet das im GGUF eingebettete Jinja-Chat-Template (Qwen-Format). Notwendig für korrekte `<\|im_start\|>`-Tokens. | +| `--no-context-shift` | — | Kontextfenster wird **nicht** verschoben wenn es voll ist — stattdessen Fehler. Verhindert stille Datenverluste. | +| `--repeat-penalty 1.05` | — | Leichte Penalty für Wiederholungen. Wert > 1.0 unterdrückt Loops. | +| `--top-k 40` | — | Nur die 40 wahrscheinlichsten nächsten Tokens werden berücksichtigt. | +| `--min-p 0.01` | — | Tokens mit Wahrscheinlichkeit < 1 % des wahrscheinlichsten Tokens werden ausgeschlossen. | +| `-ngl 999` | — | Alle Layer auf die GPU laden (999 = „alle"). Bei zu wenig VRAM reduzieren. | +| `-fa on` | — | Flash Attention — schnellere Attention-Berechnung, weniger VRAM für den Attention-Pass. | +| `--kv-unified` | — | Einheitlicher KV-Cache über alle Schichten. Effizienter bei langen Kontexten. | +| `--cache-type-k q8_0` | — | KV-Cache Keys in 8-Bit quantisiert. Spart ~50 % VRAM gegenüber fp16, minimaler Qualitätsverlust. | +| `--cache-type-v q8_0` | — | KV-Cache Values ebenfalls 8-Bit quantisiert. | +| `--cont-batching` | — | Continuous Batching: neue Anfragen werden in laufende Batches eingefügt — höherer Durchsatz bei mehreren parallelen Anfragen. | +| `--main-gpu 0` | — | GPU-Index (0 = erste der übergebenen GPUs) für Nicht-Tensor-Operationen. | +| `--tensor-split 0.5,0.5` | — | Modell-Gewichte 50/50 auf zwei GPUs aufteilen. | +| `--gpus '"device=1,2"'` | — | Docker-Argument: GPU 1 und GPU 2 dem Container übergeben. | + +### Coder-Server (Port 8001) — optimiert für Coding-Aufgaben + +| Parameter | Wert | Erklärung / Wirkung | +|---|---|---| +| `-c 131072` | 128K Tokens | Großes Kontextfenster: gesamte Codebasis + Gesprächsverlauf passt rein. **Hoher VRAM-Bedarf.** Reduziere auf `65536` wenn VRAM knapp. | +| `-n 16384` | 16K Tokens | Maximale Ausgabelänge pro Anfrage. Für Kommentieraufgaben (`/update_doku`) nötig. | +| `--temp 0.2` | — | Niedrige Temperatur: deterministisch, konsistenter Code. Erhöhe auf `0.4–0.6` für kreativere Lösungsansätze. | +| `--top-p 0.95` | — | Nucleus Sampling: 95 % der Wahrscheinlichkeitsmasse. Passend zu temp 0.2. | +| `--batch-size 1024` | — | Prompt-Verarbeitungs-Batch. Größer = schnelleres Einlesen langer Dateien. | +| `--ubatch-size 512` | — | Micro-Batch für GPU-Kernel. Muss ≤ batch-size sein. | +| `--parallel 2` | — | 2 gleichzeitige Request-Slots. Nützlich wenn pi agent schnell Folgeanfragen schickt. | + +### Judge-Server (Port 8002) — optimiert für Reviews + +| Parameter | Wert | Erklärung / Wirkung | +|---|---|---| +| `-c 65536` | 64K Tokens | Mittleres Kontextfenster: reicht für Code-Review des letzten Commits + Konversationshistorie. | +| `-n 8192` | 8K Tokens | Reviews müssen nicht länger sein. Spart Inferenz-Zeit. | +| `--temp 0.1` | — | Sehr niedrige Temperatur: maximale Konsistenz und Reproduzierbarkeit der Urteile. | +| `--top-p 0.9` | — | Etwas enger als beim Coder — weniger Variation im Urteil gewünscht. | +| `--batch-size 512` | — | Kleiner als beim Coder — Judge bekommt selten sehr lange Prompts. | +| `--ubatch-size 256` | — | Entsprechend kleiner. | +| `--parallel 1` | — | Judge-Aufgaben sind immer sequenziell im Workflow, daher 1 Slot ausreichend. | + +--- + +## Anpassung für eine einzelne GPU + +Mit einer GPU läuft das Modell vollständig auf dieser GPU statt verteilt. +Anpassungen in `start-coder.sh` und `start-judge.sh`: -Umgebungsvariable für alternativen Modellpfad: ```bash -HF_HOME=/anderer/pfad ./start-servers.sh +# Vorher (2 GPUs, device 1 und 2): + --gpus '"device=1,2"' \ + --main-gpu 0 \ + --tensor-split 0.5,0.5 \ + +# Nachher (1 GPU, z.B. device 0): + --gpus '"device=0"' \ + --main-gpu 0 \ +# --tensor-split ← diese Zeile komplett entfernen ``` -## pi-Kommandos +### VRAM-Abschätzung für das 27B IQ4_XS-Modell -| Kommando | Beschreibung | +| Komponente | Größe (ca.) | |---|---| -| `/coder ` | TASK.md anlegen, Implementierung starten (Coder-Modell) | -| `/judge [fokus]` | Code-Review gegen TASK.md + letzten Commit (Judge-Modell) | -| `/fix [hinweis]` | Judge-Kritik beheben, committen (Coder-Modell) | -| `/shipit` | Finale Freigabeprüfung (Judge-Modell) | -| `/optimize [--rounds N] [--with-doku]` | Vollautomatische Schleife bis PASS | -| `/patch <änderung>` | Gezielte Minimaländerung ohne vollständigen Review | -| `/quick_check [was]` | Schnelle Prüfung der letzten Änderung (OK/PROBLEM) | -| `/update_doku` | Code kommentieren + README.md + BEDIENUNGSANLEITUNG.md | -| `/new_project ` | Neues Projektverzeichnis + git init anlegen | +| Modell-Gewichte (IQ4_XS, 27B) | ~14,5 GB | +| KV-Cache bei 128K Kontext (q8_0) | ~14 GB | +| KV-Cache bei 64K Kontext (q8_0) | ~7 GB | +| KV-Cache bei 32K Kontext (q8_0) | ~3,5 GB | + +Bei einer **24-GB-GPU** ist nur ein Server gleichzeitig sinnvoll betreibbar: +- Modell-Gewichte: ~14,5 GB +- KV-Cache bei 32K Kontext: ~3,5 GB +- Summe: ~18 GB → passt mit Puffer + +**Empfehlung für eine 24-GB-GPU:** +```bash +# Coder — Kontext reduzieren +-c 32768 # statt 131072 +-n 8192 # statt 16384 + +# Judge — Kontext reduzieren +-c 32768 # statt 65536 +``` + +Bei einer **16-GB-GPU** ist die Modellgröße allein schon grenzwertig. +Entweder ein kleineres Modell verwenden oder die Quantisierung weiter erhöhen (IQ3_XS, Q4_K_M). + +### Beide Server auf einer GPU betreiben + +Technisch möglich, aber beide Server laden das Modell gleichzeitig → doppelter VRAM-Bedarf. +Auf einer 24-GB-GPU daher **nicht empfohlen**. Alternativen: + +- Nur einen Server gleichzeitig starten (manuell umschalten) +- Kleinere Quantisierung wählen (IQ3_XS: ~11 GB) +- `ollama` als Alternative — lädt Modelle bei Bedarf und entlädt sie wieder + +--- + +## Parameter-Tuning-Guide + +### Temperatur (`--temp`) + +| Wert | Eignung | +|---|---| +| `0.0–0.1` | Maximale Reproduzierbarkeit. Gut für Judge/Review. | +| `0.1–0.3` | Guter Kompromiss für Coding. **Empfohlen für Coder.** | +| `0.4–0.6` | Kreativere Lösungen, mehr Varianz. Sinnvoll für Prototyping. | +| `0.7–1.0` | Kreativschreiben, Brainstorming. Für Coding meist zu viel Rauschen. | + +### Kontextgröße (`-c`) + +Je größer der Kontext, desto mehr VRAM braucht der KV-Cache. +Faustregel: KV-Cache ≈ `context_size × layers × head_dim × 2 × bytes_per_element`. +Bei q8_0 (1 Byte/Element) und Qwen3-27B (28 Schichten, 128 Head-Dim, 32 Heads): +KV-Cache ≈ `context_size × 28 × 128 × 32 × 2 × 1 Byte ≈ context_size × 0,23 MB` + +| Kontext | KV-Cache (q8_0) | Empfehlung | +|---|---|---| +| 32 768 | ~7,5 GB | 1 × 24-GB-GPU | +| 65 536 | ~15 GB | 2 × 16-GB-GPU | +| 131 072 | ~30 GB | 2 × 24-GB-GPU | + +### KV-Cache-Quantisierung + +| `--cache-type-k/v` | VRAM | Qualität | +|---|---|---| +| `f16` | 100 % (Basis) | Referenz | +| `q8_0` | ~50 % | Kaum merklich schlechter — **empfohlen** | +| `q4_0` | ~25 % | Sichtbarer Qualitätsverlust bei langen Kontexten | + +### Parallelität (`--parallel`) + +Mehr parallele Slots erhöhen den Durchsatz bei gleichzeitigen Anfragen, aber jeder Slot +reserviert Speicher im KV-Cache. Im pi-coder-Workflow sind echte Parallelaufrufe selten, +daher ist `--parallel 1` für den Judge ausreichend. Coder `--parallel 2` bietet Puffer +wenn pi agent Folgeanfragen schnell hintereinander schickt. + +--- ## Dateien @@ -108,3 +271,21 @@ HF_HOME=/anderer/pfad ./start-servers.sh | `stop-servers.sh` | Beide Container stoppen | | `status.sh` | Laufstatus beider Server anzeigen | | `install.sh` | Extension + models.json nach `~/.pi/agent/` kopieren | + +--- + +## pi-Kommandos (Kurzübersicht) + +| Kommando | Modell | Beschreibung | +|---|---|---| +| `/coder ` | Coder | TASK.md anlegen, Implementierung starten | +| `/judge [fokus]` | Judge | Code-Review gegen TASK.md + letzten Commit | +| `/fix [hinweis]` | Coder | Judge-Kritik beheben, committen | +| `/shipit` | Judge | Finale Freigabeprüfung | +| `/optimize [--rounds N] [--with-doku]` | beide | Vollautomatische Schleife bis PASS | +| `/patch <änderung>` | Coder | Gezielte Minimaländerung ohne Review | +| `/quick_check [was]` | Judge | Schnelle Prüfung der letzten Änderung | +| `/update_doku` | Coder | Code kommentieren + README + Bedienungsanleitung | +| `/new_project ` | — | Neues Projektverzeichnis + git init | + +Ausführliche Beschreibung aller Kommandos mit Beispielen: siehe **BEDIENUNGSANLEITUNG.md**.