pi_coder/README.md
dschlueter 3f7ffe60c2 feat: GPU-Split, Phase-Timer, llama.cpp-Update-Fixes
GPU-Setup:
- Coder → GPU 1 (device=1), Judge → GPU 2 (device=2), kein --tensor-split
- --chat-template-kwargs deprecated → --reasoning on (neue llama.cpp-API)
- Smoke-Test-Timeout 180s → 300s (neue fitting-Phase beim Start)

Fortschrittsanzeige:
- Phase-Timer [MM:SS] in Statuszeile während LLM-Inference (sendAndWait)
- currentActivity in Fix-Phase zeigt konkreten Blocker statt generischem Text

Dokumentation:
- README: GPU-Tabelle, VRAM-Abschätzung, --reasoning on, Timer-Beispiele
- BEDIENUNGSANLEITUNG: Ladezeit, Fortschrittsanzeige mit Timer-Beispielen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:19:23 +02:00

330 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# pi_coder — Automatisierter Coder/Judge-Workflow für pi agent
Dieses Repository enthält die Konfiguration und Skripte für einen automatisierten
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
```
Nutzer gibt Auftrag
/coder → qwen3.5-coder (:8001) → Implementierung + git commit
/judge → qwen3.5-judge (:8002) → Review: PASS / FAIL + Blocker
FAIL? ▼
/fix → qwen3.5-coder (:8001) → Fixes + git commit
PASS? ▼
/shipit → qwen3.5-judge (:8002) → Finale Freigabe: SHIP / NO-SHIP
(nur bei "PASS WITH CONCERNS" — klares PASS → direkt SHIP)
/optimize = Coder→Judge→Fix-Schleife automatisch (bis PASS oder max. N Runden)
--interactive: pausiert nach PASS für menschlichen Checkpoint + optionale Zusatzaufträge
```
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 | Alias | GPU |
|--------|---------------------------------------------------|------|------------------|----------------|----------|
| Coder | Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS | 8001 | qwen36-27b-coder | qwen3.5-coder | device=1 |
| Judge | Qwen3.6-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS | 8002 | qwen36-27b-judge | qwen3.5-judge | device=2 |
Beide Container verwenden dasselbe GGUF-Datei, aber mit unterschiedlichen
Serverparametern (Kontext, Temperatur, Parallelität).
---
## Voraussetzungen
- 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
```
- NVIDIA-GPUs: empfohlen 2 × RTX 3090 (je 24 GB VRAM) für Coder und Judge parallel.
Bei 3 GPUs: GPU 0 für Display reservieren, GPU 1 → Coder, GPU 2 → Judge.
- 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/`)
---
## Installation
```bash
# 1. Repository klonen
git clone https://kitux.de/forgejo/dschlueter/pi_coder.git ~/pi_coder
cd ~/pi_coder
# 2. Extension und Modell-Config nach ~/.pi/agent/ deployen
./install_servers_and_pi_coder_extension.sh
# 3. pi agent neu laden (in der pi-Oberfläche)
# /reload
# 4. Server starten
./start-servers.sh
```
Nach späteren Änderungen an `pi-coder-judge-extension.ts` oder `models.json`:
```bash
./install_servers_and_pi_coder_extension.sh # kopiert nach ~/.pi/agent/
# dann /reload in pi agent
```
---
## Server starten / stoppen / status
```bash
# Beide Server parallel starten (empfohlen — dauert 13 Minuten)
./start-servers.sh
# Einzeln starten (z.B. nur einen neu starten)
./start-coder.sh # Port 8001
./start-judge.sh # Port 8002
# Beide stoppen
./stop-servers.sh
# Status beider Server prüfen
./status.sh
```
`start-servers.sh` startet beide Container gleichzeitig und wartet bis beide
HTTP-ready sind (max. 5 Minuten — die neue llama.cpp-Version prüft beim Start, ob
Modell + KV-Cache in den VRAM passen, was zusätzliche Zeit kostet). 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. |
| `--reasoning on` | — | Aktiviert das interne Thinking-Budget des Modells (Qwen3-spezifisch). Ersetzt das frühere `--chat-template-kwargs '{"enable_thinking":true}'`. |
| `--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 20` | — | Nur die 20 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 q4_0` | — | KV-Cache Keys in 4-Bit quantisiert. Spart ~75 % VRAM gegenüber fp16 — nötig für 256K Kontext auf einer 24-GB-GPU. |
| `--cache-type-v q4_0` | — | KV-Cache Values ebenfalls 4-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 des Containers) für Nicht-Tensor-Operationen. |
| `--gpus '"device=1"'` (Coder) | — | Docker: nur GPU 1 dem Coder-Container zuweisen. |
| `--gpus '"device=2"'` (Judge) | — | Docker: nur GPU 2 dem Judge-Container zuweisen. |
### Coder-Server (Port 8001) — optimiert für Coding-Aufgaben
| Parameter | Wert | Erklärung / Wirkung |
|---|---|---|
| `-c 262144` | 256K Tokens | Sehr großes Kontextfenster: gesamte Codebasis + langer Gesprächsverlauf passt rein. **Sehr 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 262144` | 256K Tokens | Großes Kontextfenster: nötig bei langen /optimize-Runden, wo der Gesprächsverlauf stark anwächst. |
| `-n 16384` | 16K Tokens | Lange Reviews und Begründungen passen vollständig in die Ausgabe. |
| `--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. |
---
## GPU-Konfiguration und VRAM
### Aktuelles Setup (1 GPU pro Server)
Jeder Server bekommt eine dedizierte GPU — dadurch kein VRAM-Konflikt:
```
GPU 0 NVIDIA T600 → Display / Monitor (nicht für KI genutzt)
GPU 1 RTX 3090 (24 GB) → qwen36-27b-coder (Port 8001)
GPU 2 RTX 3090 (24 GB) → qwen36-27b-judge (Port 8002)
```
Die Skripte verwenden `--gpus '"device=1"'` (Coder) bzw. `'"device=2"'` (Judge).
Innerhalb des Containers ist dies stets `CUDA:0`, daher `--main-gpu 0` ohne `--tensor-split`.
### VRAM-Abschätzung für das 27B IQ4_XS-Modell (eine GPU)
| Komponente | Größe (ca.) |
|---|---|
| Modell-Gewichte (IQ4_XS, 27B) | ~14 GB |
| KV-Cache bei 262 144 Tokens (q4_0) | ~810 GB |
| KV-Cache bei 131 072 Tokens (q4_0) | ~45 GB |
| KV-Cache bei 65 536 Tokens (q4_0) | ~23 GB |
| **Summe (262k Kontext)** | **~2224 GB** |
Bei einer **24-GB-GPU** ist 262k Kontext knapp kalkuliert. Wichtig: keine anderen Prozesse
dürfen nennenswert VRAM belegen (z. B. TTS-Dienste, Ollama). Prüfen mit:
```bash
nvidia-smi --query-gpu=index,memory.used,memory.free --format=csv
```
Falls der VRAM nicht reicht: Kontext in den Startskripten auf `131072` oder `65536` reduzieren.
### Anpassung für andere GPU-Konfigurationen
```bash
# 2 GPUs (beide für KI, keine Display-GPU):
--gpus '"device=0"' # Coder
--gpus '"device=1"' # Judge
# 1 GPU (beide Server auf gleicher GPU — nicht empfohlen, VRAM-Konflikt):
--gpus '"device=0"' # beide Server
--tensor-split 0.5,0.5 # Modell hälftig aufteilen
-c 65536 # Kontext stark reduzieren
# 2 GPUs für einen Server (wenn sehr großer Kontext nötig):
--gpus '"device=0,1"' \
--tensor-split 0.5,0.5 \
--main-gpu 0 \
-c 262144
```
Bei einer **16-GB-GPU** ist die Modellgröße allein schon grenzwertig.
Entweder ein kleineres Modell verwenden oder die Quantisierung erhöhen (IQ3_XS, Q4_K_M).
---
## 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 (q4_0) | Empfehlung |
|---|---|---|
| 32 768 | ~1,9 GB | 1 × 16-GB-GPU |
| 65 536 | ~3,7 GB | 1 × 24-GB-GPU |
| 131 072 | ~7,5 GB | 2 × 16-GB-GPU |
| 262 144 | ~810 GB | 1 × 24-GB-GPU (q4_0) — **aktuell gesetzt** |
### KV-Cache-Quantisierung
| `--cache-type-k/v` | VRAM | Qualität |
|---|---|---|
| `f16` | 100 % (Basis) | Referenz |
| `q8_0` | ~50 % | Kaum merklich schlechter |
| `q4_0` | ~25 % | Merklicher Qualitätsverlust bei langen Kontexten — aber nötig für 256K Kontext auf 2× 24 GB. **Aktuell gesetzt.** |
### 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
| Datei | Zweck |
|---|---|
| `pi-coder-judge-extension.ts` | pi agent Extension (Kommandos, Tools, Hooks) |
| `models.json` | Provider- und Modell-Konfiguration für pi agent |
| `test-utils.ts` | Unit-Tests für Hilfsfunktionen der Extension |
| `run-tests.sh` | Unit-Tests ausführen (TypeScript-Stripping + node) |
| `start-servers.sh` | Beide Server parallel starten (empfohlen) |
| `start-coder.sh` | Nur Coder-Container starten (Port 8001) |
| `start-judge.sh` | Nur Judge-Container starten (Port 8002) |
| `stop-servers.sh` | Beide Container stoppen |
| `status.sh` | Laufstatus beider Server anzeigen |
| `install_servers_and_pi_coder_extension.sh` | Extension + models.json nach `~/.pi/agent/` kopieren |
| `examples/` | Demo-Projekte (Python, Rust, Go, C, Bash, HTML/JS) für Live-Demos |
| `examples/restore-all.sh` | Examples nach Demo-Lauf in Ausgangszustand zurücksetzen |
---
## 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] [--continue] [--interactive]` | beide | Vollautomatische Schleife bis PASS (Standard: 2 Runden, Runde 1: Quick-Judge) |
| `/optimize ... [--no-tests] [--approve-concerns] [--test-cmd "cmd"] [--test-timeout N]` | beide | Test-Erkennung überspringen / PASS WITH CONCERNS direkt shippern |
| `/patch <änderung>` | Coder | Gezielte Minimaländerung ohne Review |
| `/quick_check [was]` | Judge | Schnelle Prüfung der letzten Änderung |
| `/version` | — | Versionsnummer erhöhen (SemVer + Git-Tag) |
| `/update_doku` | Coder | Code kommentieren + README + Bedienungsanleitung |
| `/plan <auftrag>` | Coder | Implementierungsplan in PLAN.md (kein Code) |
| `/continue` | Coder | Unterbrochenen Prozess fortsetzen |
| `/cancel` | — | Laufenden Loop nach aktuellem Schritt abbrechen |
| `/new_project <pfad>` | — | Neues Projektverzeichnis + git init |
Ausführliche Beschreibung aller Kommandos mit Beispielen: siehe **BEDIENUNGSANLEITUNG.md**.
---
## Live-Aktivitätsstatus
Während der Ausführung zeigt pi_coder in der Statuszeile, was gerade passiert —
inklusive eines laufenden `[MM:SS]`-Timers während jeder LLM-Inference-Phase:
| Situation | Anzeige |
|---|---|
| Coder implementiert | `◉ Coder implementiert: Login-Flow mit JWT [01:23]` |
| edit-Tool aktiv | `Editiere src/main.py…` |
| git commit | `Git-Commit…` |
| Judge (Quick-Check, Runde 1) | `◉○ Runde 1/2: Quick-Check [00:47]` |
| Judge (voller Review, Runde 2) | `●◉ Runde 2/2: Judge — TASK.md + letzter Commit + Tests [02:15]` |
| Tests laufen | `●○ Runde 1/2: Tests laufen (pytest, max. 120s)…` |
| Fix-Phase | `●◉ Runde 2/2: Coder fixt — fehlendes Null-Check [01:05]` |
| ShipIt | `●●◉ ShipIt — finale Freigabe [00:33]` |
| Interactive-Pause (--interactive) | `⏸ PASS warte auf /continue…` |
Der Timer beweist, dass die LLM tatsächlich arbeitet. Steht er still, hängt der Prozess.