docs: umfassende README + BEDIENUNGSANLEITUNG mit llama.cpp-Parametern und Beispielen
This commit is contained in:
parent
8dddd0eabd
commit
120f223c9b
2 changed files with 889 additions and 30 deletions
678
BEDIENUNGSANLEITUNG.md
Normal file
678
BEDIENUNGSANLEITUNG.md
Normal 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: 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 <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
241
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 <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 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 <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.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 <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**.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue