150 lines
4.8 KiB
Markdown
150 lines
4.8 KiB
Markdown
|
|
# Plan: pi_coder_v2 — Single-Server (Option B)
|
||
|
|
|
||
|
|
## Kontext
|
||
|
|
|
||
|
|
pi_coder verwendet zwei llama.cpp-Server für Coder (GPU 1) und Judge (GPU 2),
|
||
|
|
die aber dasselbe GGUF-Modell ausführen. Die Rollentrennung entsteht ausschließlich
|
||
|
|
durch System-Prompts. Wenn nur eine GPU verfügbar ist, kann ein einziger Server
|
||
|
|
beide Rollen übernehmen — Rollenwechsel per Prompt statt per Server-Neustart.
|
||
|
|
|
||
|
|
**pi_coder bleibt unverändert.** Die Umsetzung erfolgt im neuen Verzeichnis `~/pi_coder_v2`.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Schritt 1: Verzeichnis anlegen und Dateien kopieren
|
||
|
|
|
||
|
|
```bash
|
||
|
|
mkdir ~/pi_coder_v2
|
||
|
|
cp ~/pi_coder/pi-coder-judge-extension.ts ~/pi_coder_v2/
|
||
|
|
cp ~/pi_coder/models.json ~/pi_coder_v2/
|
||
|
|
cp ~/pi_coder/start-coder.sh ~/pi_coder_v2/
|
||
|
|
cp ~/pi_coder/start-judge.sh ~/pi_coder_v2/
|
||
|
|
cp ~/pi_coder/start-servers.sh ~/pi_coder_v2/
|
||
|
|
cp ~/pi_coder/stop-servers.sh ~/pi_coder_v2/
|
||
|
|
cp ~/pi_coder/status.sh ~/pi_coder_v2/
|
||
|
|
cp ~/pi_coder/install_servers_and_pi_coder_extension.sh ~/pi_coder_v2/
|
||
|
|
cp ~/pi_coder/README.md ~/pi_coder_v2/
|
||
|
|
cp ~/pi_coder/BEDIENUNGSANLEITUNG.md ~/pi_coder_v2/
|
||
|
|
cp ~/pi_coder/CLAUDE.md ~/pi_coder_v2/
|
||
|
|
# Plan-Datei ebenfalls kopieren
|
||
|
|
cp <dieser-plan> ~/pi_coder_v2/SINGLE_SERVER_PLAN.md
|
||
|
|
# git init
|
||
|
|
cd ~/pi_coder_v2 && git init && git add -A && git commit -m "init: kopiert aus pi_coder"
|
||
|
|
```
|
||
|
|
|
||
|
|
Nicht kopieren: `run-tests.sh`, `test-utils.ts`, `examples/` (nicht relevant für Kernfunktion).
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Schritt 2: `start-single.sh` anlegen
|
||
|
|
|
||
|
|
Basiert auf `start-coder.sh` mit folgenden Änderungen:
|
||
|
|
|
||
|
|
| Parameter | Alt (coder) | Neu (single) |
|
||
|
|
|---|---|---|
|
||
|
|
| `CONTAINER_NAME` | `qwen36-27b-coder` | `qwen36-27b-single` |
|
||
|
|
| `HOST_PORT` | 8001 | 8001 |
|
||
|
|
| `MODEL_ALIAS` | `qwen3.5-coder` | `qwen3.5-single` |
|
||
|
|
| `--temp` | 0.6 | 0.65 (Kompromiss) |
|
||
|
|
| `--gpus` | `"device=1"` | `"device=1"` (oder konfigurierbar) |
|
||
|
|
|
||
|
|
Der Server registriert sich unter dem Alias `qwen3.5-single`.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Schritt 3: `models.json` anpassen
|
||
|
|
|
||
|
|
Neuen Provider `llama-cpp-single` hinzufügen mit **beiden** Modell-IDs auf Port 8001:
|
||
|
|
|
||
|
|
```json
|
||
|
|
"llama-cpp-single": {
|
||
|
|
"baseUrl": "http://127.0.0.1:8001/v1",
|
||
|
|
"api": "openai-completions",
|
||
|
|
"apiKey": "none",
|
||
|
|
"compat": {
|
||
|
|
"supportsDeveloperRole": false,
|
||
|
|
"supportsReasoningEffort": false,
|
||
|
|
"maxTokensField": "max_tokens",
|
||
|
|
"thinkingFormat": "qwen-chat-template"
|
||
|
|
},
|
||
|
|
"models": [
|
||
|
|
{
|
||
|
|
"id": "qwen3.5-coder",
|
||
|
|
"name": "Qwen3.6 27B Single-Server Coder (llama.cpp :8001)",
|
||
|
|
"reasoning": true,
|
||
|
|
"input": ["text"],
|
||
|
|
"contextWindow": 262144,
|
||
|
|
"maxTokens": 16384,
|
||
|
|
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "qwen3.5-judge",
|
||
|
|
"name": "Qwen3.6 27B Single-Server Judge (llama.cpp :8001)",
|
||
|
|
"reasoning": true,
|
||
|
|
"input": ["text"],
|
||
|
|
"contextWindow": 262144,
|
||
|
|
"maxTokens": 16384,
|
||
|
|
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
|
||
|
|
}
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Die bestehenden Provider `llama-cpp-coder` und `llama-cpp-judge` bleiben erhalten
|
||
|
|
(für Kompatibilität), werden aber nicht aktiv genutzt.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Schritt 4: `pi-coder-judge-extension.ts` — switchModel-Aufrufe
|
||
|
|
|
||
|
|
Alle Aufrufe von `switchModel(pi, ctx, "llama-cpp-coder", "qwen3.5-coder")`
|
||
|
|
und `switchModel(pi, ctx, "llama-cpp-judge", "qwen3.5-judge")` werden auf
|
||
|
|
`"llama-cpp-single"` umgestellt. Der Modell-ID-Parameter (`"qwen3.5-coder"` /
|
||
|
|
`"qwen3.5-judge"`) bleibt unverändert — so bleiben die Registry-Wechsel erhalten,
|
||
|
|
sind aber sofort (kein Server-Neustart).
|
||
|
|
|
||
|
|
Betroffene Stellen (ca. 8):
|
||
|
|
- `/coder` handler
|
||
|
|
- `/judge` handler
|
||
|
|
- `/fix` handler
|
||
|
|
- `/shipit` handler
|
||
|
|
- `/optimize` loop (Coder-Kickoff, Judge-Phase, Fix-Phase, ShipIt-Phase)
|
||
|
|
- `/patch` handler
|
||
|
|
- `/quick_check` handler
|
||
|
|
- `/plan` handler
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Schritt 5: `install_servers_and_pi_coder_extension.sh` anpassen
|
||
|
|
|
||
|
|
Pfade auf `pi_coder_v2` anpassen (falls nötig — Skript referenziert vermutlich `$REPO`
|
||
|
|
als relatives Verzeichnis, was automatisch korrekt ist).
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Schritt 6: `waitUntilModelReady` im `--continue`-Modus
|
||
|
|
|
||
|
|
Im `--continue`-Modus prüft die Extension beide Server parallel:
|
||
|
|
```typescript
|
||
|
|
const [coderReady, judgeReady] = await Promise.all([
|
||
|
|
waitUntilModelReady(pi, ctx, 8001, "qwen3.5-coder"),
|
||
|
|
waitUntilModelReady(pi, ctx, 8002, "qwen3.5-judge"),
|
||
|
|
]);
|
||
|
|
```
|
||
|
|
|
||
|
|
Dies muss auf einen einzigen Check umgestellt werden:
|
||
|
|
```typescript
|
||
|
|
const ready = await waitUntilModelReady(pi, ctx, 8001, "qwen3.5-single");
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Verifikation
|
||
|
|
|
||
|
|
1. `cd ~/pi_coder_v2 && ./start-single.sh` → Server startet auf Port 8001
|
||
|
|
2. `nvidia-smi` → nur eine GPU belegt, ~20 GB VRAM
|
||
|
|
3. `./install_servers_and_pi_coder_extension.sh` → Extension in `~/.pi/agent/` deployen
|
||
|
|
4. In pi: `/reload` → Extension neu laden
|
||
|
|
5. `/optimize <kleiner Testauftrag>` → Loop läuft durch
|
||
|
|
6. In der Statuszeile: `switchModel` wechselt ohne spürbare Pause
|
||
|
|
7. Qualitätscheck: Judge-Urteil und Coder-Fix verhalten sich wie erwartet
|