# pi_coder_2 — Automatisierter Coder/Judge-Workflow für pi agent Dieses Repository enthält die Konfiguration und Skripte für einen automatisierten Coding-Workflow mit einem lokalen Modell (Standard: Strata), das abwechselnd als Coder und Judge agiert — gesteuert über Pi Agent. Er dreht solange Optimierungsschleifen, bis das Programm Produktionsreife hat. --- ## Überblick ``` Nutzer gibt Auftrag │ ▼ /coder → Strata (:9090, Coder-Persona) → Implementierung + git commit │ ▼ /judge → Strata (:9090, Judge-Persona) → Review: PASS / FAIL + Blocker │ FAIL? ▼ /fix → Strata (:9090, Coder-Persona) → Fixes + git commit │ PASS WITH CONCERNS? ▼ │ (ohne --approve-concerns: wie FAIL → weiterer Fix-Zyklus) │ PASS? ▼ /shipit → Strata (:9090, 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) --interactive: pausiert nach PASS für menschlichen Checkpoint + optionale Zusatzaufträge ``` Ein **einzelner** llama.cpp-Docker-Container bedient beide Rollen. Die Rollenumschaltung (Coder ↔ Judge) erfolgt über unterschiedliche System-Prompts, die der `before_agent_start`-Hook der Extension vor jeder Inference injiziert. pi agent wechselt keine Server mehr — nur die Persona im System-Prompt ändert sich. --- ## Modelle | Rolle | Modell (`/`) | Port | Betrieb | GPU | |---|---|---|---|---| | Coder + Judge (Standard) | `strata/qwen3.8-flash-next-iq3_s` | 9090 | Strata-Server, `~/nvme2n1p7_home/strata-betrieb` | 1 und 2 | | Coder + Judge (Alternative) | `llama-cpp-single/coding_model` (Qwen3.6-27B IQ4_XS) | 8001 | Container `coding_model`, `start-coding-server.sh` | 1 | Coder- und Judge-Rollen werden durch verschiedene System-Prompts realisiert — dasselbe Modell, unterschiedliche Persona. Freie Eingaben in pi nutzen weiter pis eigenes Standardmodell. Strata lädt sein Modell bei der ersten Anfrage selbst, gibt vorher die GPUs frei und entlädt es nach 10 Minuten ohne Anfrage (eingerichtet in `strata-betrieb`). Ein anderes Modell für beide Rollen setzt `PI_CODER_MODEL=/`, siehe [BEDIENUNGSANLEITUNG.md](BEDIENUNGSANLEITUNG.md#anderes-modell-für-die-schleife). --- ## 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-GPU: empfohlen RTX 3090 (24 GB VRAM). Standard: GPU 1. Überschreibbar mit `GPU_DEVICE=0 ./start-coding-server.sh`. Bei 3 GPUs: GPU 0 für Display reservieren. - 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-coding-server.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, Modell-Config und settings.json nach ~/.pi/agent/ deployen ./deploy-pi-config.sh # 3. pi agent neu laden (in der pi-Oberfläche) # /reload # 4. Server starten ./start-coding-server.sh ``` 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/coding_model`) automatisch konfiguriert. Die Extension wird nicht kopiert, sondern verlinkt (`~/.pi/agent/extensions/pi-coding-extension.ts` → Repo). Änderungen an `pi-coding-extension.ts` gelten damit für jeden pi-Aufruf ab dem nächsten Start bzw. `/reload`, ohne erneutes Deploy. Das gilt auch für noch nicht committete Änderungen. Nach späteren Änderungen an `models.json` oder `settings.json`: ```bash ./deploy-pi-config.sh # verlinkt die Extension, kopiert models.json, settings.json (nur packages) # dann /reload in pi agent ``` --- ## Server starten / stoppen / status ```bash # Server starten (empfohlen — dauert 1–3 Minuten) ./start-coding-server.sh # Server auf anderer GPU starten GPU_DEVICE=0 ./start-coding-server.sh # Stoppen ./stop-coding-server.sh # Status prüfen ./status-coding-server.sh ``` `start-coding-server.sh` startet den Container und wartet bis HTTP-ready (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). Wenn der Server bereits läuft und du `start-coding-server.sh` aufrufst, wird der laufende Container zuerst per `docker rm -f` gestoppt und dann neu gestartet — ein laufender Inference-Request wird dabei abgebrochen. --- ## llama.cpp-Serverparameter im Detail ### Parameter des Single-Servers (Port 8001) | 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). | | `--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. | | `--top-k 20` | — | Nur die 20 wahrscheinlichsten nächsten Tokens. | | `--min-p 0.01` | — | Tokens mit Wahrscheinlichkeit < 1 % des wahrscheinlichsten Tokens werden ausgeschlossen. | | `-ngl 999` | — | Alle Layer auf die GPU laden. | | `-fa on` | — | Flash Attention. | | `--kv-unified` | — | Einheitlicher KV-Cache über alle Schichten. | | `--cache-type-k q4_0` | — | KV-Cache Keys 4-Bit quantisiert. 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. | | `-c 262144` | 256K | Großes Kontextfenster für langen Gesprächsverlauf im Optimize-Loop. | | `-n 16384` | 16K | Maximale Ausgabelänge. | | `--temp 0.2` | — | Deterministisch — Coder-Rolle. Der Judge-System-Prompt gleicht die etwas höhere Temperatur aus. | | `--parallel 2` | — | 2 Slots, damit pi agent Folgeanfragen schnell hintereinander stellen kann. | | `--gpus '"device=1"'` | — | Standard: GPU 1. Überschreibbar: `GPU_DEVICE=0 ./start-coding-server.sh`. | --- ## GPU-Konfiguration und VRAM ### Aktuelles Setup (1 GPU, 1 Server) Ein einzelner Container bedient beide Rollen sequenziell: ``` GPU 0 NVIDIA T600 → Display / Monitor (nicht für KI genutzt) GPU 1 RTX 3090 (24 GB) → coding_model (Port 8001, Coder + Judge) ``` Da Coder und Judge nicht gleichzeitig inferieren, gibt es keinen VRAM-Konflikt. Die Umschaltung zwischen den Rollen erfolgt ausschließlich über den System-Prompt — der Container läuft ohne Unterbrechung durch. ### VRAM-Abschätzung für das 27B IQ4_XS-Modell | Komponente | Größe (ca.) | |---|---| | Modell-Gewichte (IQ4_XS, 27B) | ~14 GB | | KV-Cache bei 262 144 Tokens (q4_0) | ~8–10 GB | | KV-Cache bei 131 072 Tokens (q4_0) | ~4–5 GB | | KV-Cache bei 65 536 Tokens (q4_0) | ~2–3 GB | | **Summe (262k Kontext)** | **~22–24 GB** | Bei einer **24-GB-GPU** ist 262k Kontext knapp kalkuliert. 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 `start-coding-server.sh` auf `131072` oder `65536` reduzieren. ### Anpassung für andere GPU-Konfigurationen ```bash # Andere GPU verwenden: GPU_DEVICE=0 ./start-coding-server.sh # 2 GPUs für einen Server (sehr großer Kontext): # start-coding-server.sh anpassen: --gpus '"device=0,1"' \ --tensor-split 0.5,0.5 \ --main-gpu 0 \ -c 262144 ``` --- ## Parameter-Tuning-Guide ### Temperatur (`--temp`) | Wert | Eignung | |---|---| | `0.0–0.1` | Maximale Reproduzierbarkeit. | | `0.1–0.3` | Guter Kompromiss für Coding. **Aktuell gesetzt: 0.2.** | | `0.4–0.6` | Kreativere Lösungen. | | `0.7–1.0` | Für Coding meist zu viel Rauschen. | ### Kontextgröße (`-c`) | Kontext | KV-Cache (q4_0) | Empfehlung | |---|---|---| | 32 768 | ~1,9 GB | 1 × 16-GB-GPU | | 65 536 | ~3,7 GB | 1 × 24-GB-GPU (konservativ) | | 131 072 | ~7,5 GB | 1 × 24-GB-GPU | | 262 144 | ~8–10 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 24 GB. **Aktuell gesetzt.** | --- ## Tests ausführen ```bash ./run-tests.sh ``` Keine npm-Installation nötig — nutzt den integrierten `node:test`-Runner und `--experimental-strip-types` für TypeScript. Testet Parsing-Logik, Konfigurationskonsistenz und Extension-Guards gegen Regressionen. --- ## Dateien | Datei / Verzeichnis | Zweck | |---|---| | `pi-coding-extension.ts` | pi agent Extension (Kommandos, Tools, Hooks, Rollen-Logik) | | `models.json` | Provider- und Modell-Konfiguration für pi agent | | `settings.json` | pi-agent-Settings (Default-Modell, aktivierte Modelle) — wird von Install-Skript deployt | | `run-tests.sh` | Tests ausführen | | `tests/` | Testdateien (pure-logic, config, extension-guards, scripts) | | `start-coding-server.sh` | Single-Server starten (Port 8001, Coder + Judge) | | `stop-coding-server.sh` | Container stoppen | | `status-coding-server.sh` | Laufstatus anzeigen | | `deploy-pi-config.sh` | Extension nach `~/.pi/agent/extensions/` verlinken, models.json + settings.json 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 | Persona | 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] [--continue] [--interactive]` | beide | Vollautomatische Schleife bis PASS (Standard: 2 Runden) | | `/optimize ... [--no-tests] [--approve-concerns] [--test-cmd "cmd"] [--test-timeout N]` | beide | Test-Erkennung überspringen / PASS WITH CONCERNS akzeptieren | | `/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 + LICENCE.md | | `/plan ` | Coder | Implementierungsplan in PLAN.md (kein Code) | | `/continue` | Coder | Unterbrochenen Prozess fortsetzen | | `/cancel` | — | Laufenden Loop nach aktuellem Schritt abbrechen | | `/new_project ` | — | Neues Projektverzeichnis + git init | Ausführliche Beschreibung aller Kommandos mit Beispielen: siehe **BEDIENUNGSANLEITUNG.md**. --- ## PASS WITH CONCERNS — Verhalten Im `/optimize`-Loop gilt `PASS WITH CONCERNS` **nicht** als bestanden — der Coder erhält einen weiteren Fix-Auftrag, genau wie bei `FAIL`. Erst sauberes `PASS` beendet die Schleife. Opt-out: `--approve-concerns` lässt `PASS WITH CONCERNS` als bestanden gelten. Wann der Judge welches Urteil gibt (Urteilsregeln, Abschnitt „Hinweise“): siehe [BEDIENUNGSANLEITUNG.md](BEDIENUNGSANLEITUNG.md), Judge-Persona. --- ## 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 (Runde 1) | `◉○ Runde 1/2: Judge — TASK.md + letzter Commit + Tests [00:47]` | | Judge (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 | `⏸ PASS – warte auf /continue…` | Der Timer beweist, dass die LLM tatsächlich arbeitet. Steht er still, hängt der Prozess.