docs: umfassende README + BEDIENUNGSANLEITUNG mit llama.cpp-Parametern und Beispielen

This commit is contained in:
Dieter Schlüter 2026-05-19 21:22:02 +02:00
commit 120f223c9b
2 changed files with 889 additions and 30 deletions

678
BEDIENUNGSANLEITUNG.md Normal file
View file

@ -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: 13 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 <pfad>
```
### 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 <auftrag>
```
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 <auftrag> [--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 <beschreibung der änderung>
```
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 <pfad>` im Terminal:
```bash
cd <pfad>
pi
```

241
README.md
View file

@ -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 <repo-url> ~/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 13 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.40.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 <auftrag>` | 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 <auftrag> [--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 <pfad>` | 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.00.1` | Maximale Reproduzierbarkeit. Gut für Judge/Review. |
| `0.10.3` | Guter Kompromiss für Coding. **Empfohlen für Coder.** |
| `0.40.6` | Kreativere Lösungen, mehr Varianz. Sinnvoll für Prototyping. |
| `0.71.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 <auftrag>` | 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 <auftrag> [--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 <pfad>` | — | Neues Projektverzeichnis + git init |
Ausführliche Beschreibung aller Kommandos mit Beispielen: siehe **BEDIENUNGSANLEITUNG.md**.