# 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 | |--------|---------------------------------------------------|------|------------------|----------------| | 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 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 ``` - 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/`) --- ## 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.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.sh # kopiert nach ~/.pi/agent/ # dann /reload in pi agent ``` --- ## Server starten / stoppen / status ```bash # Beide Server parallel starten (empfohlen — dauert 1–3 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. 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 q4_0` | — | KV-Cache Keys in 4-Bit quantisiert. Spart ~75 % VRAM gegenüber fp16 — nötig für 256K Kontext auf 2× 24 GB. | | `--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 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 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.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 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. | --- ## 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`: ```bash # 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 ``` ### VRAM-Abschätzung für das 27B IQ4_XS-Modell | Komponente | Größe (ca.) | |---|---| | 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 131072 ``` 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 (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 | ~15 GB | 2 × 24-GB-GPU — **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.sh` | Extension + models.json nach `~/.pi/agent/` kopieren | | `examples/` | Demo-Projekte (Python, Rust, Go, C) für Live-Demos | | `examples/restore-all.sh` | Examples nach Demo-Lauf in Ausgangszustand zurücksetzen | --- ## 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] [--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 ` | 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**. --- ## Live-Aktivitätsstatus Während der Ausführung zeigt pi_coder in der Statuszeile, was gerade passiert: | Situation | Anzeige | |---|---| | Coder implementiert | `Coder implementiert…` | | edit-Tool aktiv | `Editiere src/main.py…` | | git commit | `Git-Commit…` | | Judge reviewt (Runde 2/2) | `Judge reviewt (Runde 2/2)…` | | Tests laufen | `Tests laufen…` | | Fix-Phase | `Coder fixt Blocker…` | | Interactive-Pause (--interactive) | `⏸ PASS – warte auf /continue…` | So ist jederzeit erkennbar, in welcher Phase sich der automatische Loop befindet.