Files
cluster-knaster/docs/PLAN.md
Robert RappandClaude Opus 5.5 e88e0ea46b sites: Inventar und Registry an echte Knoten (pve44–pve61) angepasst; ADR-0001/0002/0006 und PLAN §1.3/1.4/9 ergänzt
Inventar mit pve44–pve61 und den Ada-Rechnern gode-pc-05/06 (M4000 weiter
disabled). Registry-ops auf gpu-pve44/gpu-pve48/infra laut Placement, bei
den Ada-Slots entfallen pve_node und vmid (Worker-Registry v2, Task 6.4).
Tests: neuer test_site_knaster_matches_real_nodes, Konsistenztest auf
gpus-Liste umgestellt. ADR-Nachträge zu D1 (Variante B), D2 (eine GPU-VM
pro Knoten) und D3 (Ada bleibt Windows, vorgeschlagen).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:04:55 +02:00

338 lines
28 KiB
Markdown
Raw Permalink 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.
# embedd-everything – Architektur- und Betriebsplan
Stand: 2026-10-11 (überarbeitet: Netzwerk 1 GbE, verteilte SSDs, halbautomatischer Pflege-Agent)
Ziel: Ein starkes LLM (OpenRouter) erarbeitet neue Aufgaben einmalig und bricht sie in Skills herunter. Danach erledigen schwächere, selbst gehostete Modelle diese Aufgaben. Embedding-Modelle übernehmen Wiedererkennung, Routing und einfache Entscheidungen. Die Last verteilt sich auf CPU und GPU, RAM und VRAM.
---
## 0. Leitprinzipien
1. **Control Plane und Data Plane trennen.** n8n, Registry und Router *entscheiden*. vLLM, llama.cpp und die Embedding-Server *rechnen*. Fällt die Control Plane aus, läuft die Data Plane mit dem letzten Stand weiter.
2. **Slots statt Modellnamen.** n8n, Hermes und Skills sprechen nur abstrakte Slots an, etwa `tier1-general`, `verifier-small` oder `embed-default`. Welches Modell und welcher Adapter dahinterstehen, steht ausschließlich in der Registry. Ein Modellwechsel ist dann eine Datenänderung und kein Umbau.
3. **Daten sind das Asset, Gewichte sind Cache.** Verifizierte Fälle, Skills und Eval-Sets werden modellneutral gespeichert. Adapter und Quantisierungen lassen sich daraus jederzeit neu erzeugen.
4. **Alles deklarativ.** Gewünschter Zustand liegt in Git (IaC und Konfiguration), ein Reconcile-Prozess gleicht den Ist-Zustand ab. Das ist die Basis für Autohealing und Übertragbarkeit.
5. **Jede automatische Aktion ist begrenzt.** Autohealing hat Rate Limits und Eskalationsstufen und ruft ab Stufe X einen Menschen.
---
## 1. Proxmox-Einbindung
### 1.1 VM oder LXC?
| | VM mit PCI-Passthrough | LXC mit GPU-Durchreichung |
|---|---|---|
| Overhead | gering: CPU ~2–5 %, GPU praktisch nativ | minimal |
| RAM | **fest reserviert** (Passthrough pinnt den gesamten VM-RAM, kein Ballooning) | flexibel geteilt |
| Treiber/CUDA | **eigener pro VM**, unabhängig vom Host | an den Host-Treiber gekoppelt |
| GPU-Teilung | 1 GPU → 1 VM | mehrere Container pro GPU möglich |
| Isolation | stark (eigener Kernel) | schwächer |
| Snapshots/Backup | vollständig | ja, mit Einschränkungen bei Bind-Mounts |
**Empfehlung:**
- **GPU-Nodes als VM.** Grund: Die alten Karten (Maxwell M4000, Pascal P2000) brauchen fest gepinnte Treiber mit CUDA 12.x, die Ada-Karten profitieren von aktuellen Treibern. Mit VMs lebt beides sauber getrennt auf einem Cluster. Treiber-Updates werden per Snapshot rückrollbar.
- **CPU-Infrastruktur als LXC oder leichte VM** (n8n, Postgres, LiteLLM, Monitoring). Das spart RAM auf den i7-Nodes.
- Innerhalb der VMs bzw. LXCs läuft Docker Compose, ein Compose-Projekt pro Rolle.
### 1.2 Was Proxmox zusätzlich ermöglicht
- **Resource Mappings für PCI-Geräte.** GPUs werden clusterweit logisch benannt (z. B. `gpu-ada-1`). VM-Konfigurationen verweisen auf den Namen statt auf eine PCI-Adresse, wodurch sie zwischen Nodes mit gleicher Karte portabel werden.
- **Snapshots vor jedem riskanten Schritt** (Treiber-Update, Modellwechsel, vLLM-Upgrade). Schlägt die Eval fehl, folgt ein Rollback in Sekunden.
- **Templates und Cloud-Init.** Jede Rolle (`gpu-vllm`, `gpu-llamacpp`, `infra`) ist ein Template, damit neue Nodes reproduzierbar sind.
- **Staging durch Klonen.** Eine geklonte VM dient als Testumgebung für neue Modellversionen, ohne die Produktion anzufassen.
- **HA-Gruppen** für die zustandslosen und CPU-Dienste: automatischer Neustart auf einem anderen Node. GPU-VMs sind nicht live-migrierbar. Ein Neustart auf einem anderen Node geht nur, wenn dort eine gleich gemappte Karte steckt.
- **Proxmox Backup Server** für Postgres (Skills, Registry, Traces), Konfiguration und Datensätze. Modellgewichte nicht sichern, die lassen sich neu laden.
- **Energie.** Selten genutzte GPU-VMs (z. B. M4000) per API bedarfsgesteuert starten und stoppen. Für echte Stromersparnis ganze Hosts per Wake-on-LAN schlafen legen bzw. wecken.
- **API-Steuerung.** Alles oben Genannte ist über die Proxmox-API automatisierbar, aus n8n, Terraform/OpenTofu (Provider `bpg/proxmox`) oder dem Healer-Service.
### 1.3 Rollenverteilung (aktuelle Hardware)
Stand 12.10.2026, per SSH geprüft. Proxmox-Cluster `knaster` mit fünf Knoten:
| Knoten | IP | Hardware (Kerne/Threads, RAM) | GPUs |
|---|---|---|---|
| pve44 | 192.168.100.210 | ThinkStation P310, i7-6700 (4/8), 32 GB | Quadro M4000 (8 GB) + Quadro P2000 (5 GB) |
| pve46 | 192.168.100.209 | ThinkStation P310, i7-6700 (4/8), 32 GB | M4000 + P2000 |
| pve48 | 192.168.100.212 | ThinkStation P310, i7-6700 (4/8), 32 GB | M4000 + P2000 |
| pve52 | 192.168.100.207 | ThinkStation P320, i7-7700 (4/8), 32 GB | nur M4000 |
| pve61 | 192.168.100.214 | Surface Book, i5-8350U (4/8), 8 GB | keine NVIDIA (Intel UHD 620, Kiosk) |
Jeder GPU-Knoten hat **eine** GPU-VM mit allen Karten (`gpu-pve44`, `gpu-pve46`, `gpu-pve48`, `gpu-pve52`, ADR-0001 Nachtrag). Die beiden RTX 4000 Ada (20 GB) stecken nicht im Cluster, sondern je eine in den Windows-Arbeitsplätzen GODE-PC-05 und GODE-PC-06 (64 GB RAM, ADR-0006 Nachtrag). Die Zuordnung unten ist die Ausgabe von `knaster placement` mit `sites/knaster/inventory.yaml`.
| Rolle | Hardware | Ort | Engine | Aufgabe |
|---|---|---|---|---|
| `gpu-main` | RTX 4000 Ada (20 GB) | gode-pc-05 (Windows) | vLLM, Multi-LoRA; unter Windows vorerst llama-server (D3, vorgeschlagen) | Slot `tier1-general` plus Skill-Adapter |
| `gpu-flex` | RTX 4000 Ada (20 GB) | gode-pc-06 (Windows) | vLLM / Unsloth; unter Windows vorerst llama-server (D3, vorgeschlagen) | tagsüber zweiter Slot oder Reserve, nachts LoRA-Training |
| `gpu-embed` | 2× Quadro P2000 (5 GB) | `gpu-pve44`, `gpu-pve46` | llama.cpp (Embedding/Rerank) | `embed-default`, `rerank-default`, redundant auf zwei Knoten |
| `gpu-small` | Quadro P2000 (5 GB) | `gpu-pve48` | llama.cpp | `verifier-small`, `signature-extractor` (3–4B) |
| – | 4× Quadro M4000 (8 GB) | je eine in den vier GPU-VMs | – | **vorerst außer Betrieb** (ADR-0006), durchgereicht, aber `disabled`; nur nach Benchmark für llama.cpp-Rollen |
| `tts-hq` | teilt die Ada von `gpu-flex` | gode-pc-06 | PyTorch | `tts-de-hq`: Qwen3-TTS 1.7B (ADR-0006), unter Windows erst nach der WSL2-Entscheidung |
| `tts-cpu` | Infra-LXC (CPU) | `infra` | Piper (ONNX) | `tts-de`: schnelle Sprachausgabe, Fallback |
| `infra` | LXC, 4 Kerne, 8 GB | pve44 in `tank`, HA nach pve52/pve48 | Docker | n8n, Postgres+pgvector, Redis, Router, Healer, Langfuse, Prometheus/Grafana; LiteLLM auf appsrv08 (D4, vorgeschlagen) |
| `strong` | extern | – | OpenRouter | `tier0-strong` über den LiteLLM mit PSE auf appsrv08, Skill-Autor (Hermes) |
Das Placement schlägt für `infra` pve52 vor, weil es CPU-Rollen auf Knoten ohne aktive GPU-Rolle legt. Festgelegt ist pve44 (`sites/knaster/proxmox.yaml`), pve52 ist Replikations- und HA-Ziel.
Wichtig: Auf Maxwell und Pascal läuft kein vLLM (das braucht Compute Capability ≥ 7.0), und CUDA 13 unterstützt sie nicht mehr. Daher auf diesen Nodes Treiber und Images pinnen. Auch PyTorch hat dort keine Zukunft mehr (2.14 ist die letzte Version mit CUDA-12-Wheels). Deshalb laufen auf alten Karten nur llama.cpp-Workloads (ADR-0006).
### 1.4 Netzwerk und Storage (entschieden, siehe ADR-0002)
Ausgangslage: **1 GbE** zwischen den Knoten, flaches Netz `192.168.100.0/24` (Gateway `.1`, DNS `.120`, kein VLAN). Pro Knoten **eine oder zwei SSDs mit 256 GB**, pve48 zusätzlich eine leere 128-GB-SSD (Tabelle in 1.3).
- **Kein Ceph.** Ceph braucht für brauchbare Latenz und Rebuild-Zeiten mindestens 10 GbE und mehr Platz pro OSD. Mit 1 GbE und kleinen SSDs würde jeder Schreibvorgang über das Netz gebremst und ein Rebuild das Netz tagelang belegen.
- **System auf ext4/LVM-thin, ZFS auf der zweiten SSD** (D1 = Variante B, ADR-0002 Nachtrag). SSD 1 trägt das Proxmox-System mit `local` und `local-lvm`. Die zweite SSD ist auf pve44, pve48 und pve52 der ZFS-Pool `tank` (Einzel-SSD), abgesichert über Replikation. pve46 und pve61 haben nur eine Platte und bleiben ohne ZFS.
- **ZFS-Replikation** (Proxmox-Job, alle 15 Min.) nur zwischen pve44, pve48 und pve52: `infra` liegt auf pve44 in `tank` und wird nach pve52 und pve48 repliziert. Zusammen mit Proxmox HA startet der LXC nach einem Knotenausfall dort mit maximal 15 Min. altem Stand. Für Postgres wird das zusätzlich durch PBS-Backups und WAL-Archivierung abgefedert.
- **Modelle liegen lokal** auf der GPU-VM (auf `local-lvm`), in einem eigenen Disk-Image (`models`, nicht repliziert, nicht gesichert). Quelle ist Hugging Face oder ein optionaler **Modell-Mirror** auf einem Infra-Node (HTTP/NFS, nur lesend). 10 GB über 1 GbE dauern etwa 90 s, das ist für Modellwechsel unkritisch.
- **Proxmox Backup Server** als VM oder LXC auf dem Node mit dem meisten freien SSD-Platz, oder besser auf einer externen Platte bzw. einem NAS. Gesichert werden Postgres, Konfiguration und Datensätze, keine Modellgewichte.
- **IP-Adressen:** Die Knoten behalten .207–.214. Gäste bekommen vorerst DHCP-Adressen (D5 zurückgestellt); feste Gast-IPs müssen vor Phase 6 stehen, weil STT und die LiteLLM-Slots IP-Literale nutzen.
- **Netztrennung per VLAN** (Proxmox SDN) ist zurückgestellt, bis der Switch das zulässt: `mgmt` (Proxmox, PBS), `svc` (Dienste untereinander), `ext` (Zugriff von außen auf n8n und Router). Ohne Bandbreitengewinn, aber Replikation und Backups ließen sich zeitlich steuern, damit sie den Inferenz-Traffic nicht stören.
**Speicherbudget pro Rolle (Richtwerte):**
| Rolle | belegt | Inhalt |
|---|---|---|
| `gpu-main` / `gpu-flex` | 60–100 GB | aktives Basismodell (~9 GB bei 14B/AWQ), Kandidat (~9 GB), 4-Bit-Trainingsbasis (~9 GB), Adapter (je 50–200 MB), Checkpoints, Docker-Images (~15 GB) |
| `gpu-embed` / `gpu-small` | 15–25 GB | Embedding-, Rerank- und kleine GGUF-Modelle (je 0,5–3 GB), Images |
| `infra` | 40–80 GB | Postgres (Fälle, Traces), Prometheus (15 Tage Retention), Langfuse |
`gpu-main` und `gpu-flex` liegen auf den Windows-Rechnern. Eine GPU-VM hat 40 GB Systemplatte und 60 GB Modellplatte auf `local-lvm` (141 GB je Knoten), `infra` 60 GB in `tank` (238 GB). Die SSD-Verteilung steht in `sites/knaster/inventory.yaml`, die Gäste in `sites/knaster/proxmox.yaml`.
---
## 2. Betrieb und Pflege
### 2.1 Was gepflegt werden muss
| Objekt | Pflege | Automatisierbar? |
|---|---|---|
| Skill-Bibliothek | Duplikate zusammenführen, veraltete Skills stilllegen, Konflikte (zwei Skills fast gleich ähnlich) auflösen | großteils: Clustering plus Vorschlag, Freigabe durch Mensch |
| Eval-Sets (Golden Sets) | pro Skill wachsen lassen, Ausreißer prüfen, Leaks ins Training vermeiden | ja, mit Stichproben-Review |
| Registry | neue Modelle und Slots, Kalibrierungswerte | ja, über Kalibrierungs-Job (Abschnitt 7) |
| Adapter | Versionen, Rollback, Aufräumen alter Versionen | ja (Lifecycle-Pipeline) |
| Embedding-Index | Re-Embedding bei Wechsel des Embedding-Modells | ja, Blue/Green (Abschnitt 4.4) |
| Treiber, CUDA, Engines | Updates mit Snapshot, Eval, Rollback | halbautomatisch |
| OpenRouter-Kosten | Budget-Alarme, Anteil Stufe 0 beobachten | ja (LiteLLM-Budgets) |
| Backups | Restore-Test | ja, monatlich |
### 2.2 Wartungsrhythmus
- **Täglich, automatisch:** Health-Report (Pass-Rates pro Skill und Slot, Eskalationsquote, Kosten, Fehlerklassen). Er geht nur bei Auffälligkeiten an einen Menschen.
- **Nächtlich:** Graduierungs-Läufe, LoRA-Training für Cluster mit genug neuen Fällen, Re-Evals.
- **Wöchentlich, ca. 15–30 Min. Mensch:** Service-Routine mit dem Pflege-Agenten (Abschnitt 2.3): Freigaben, Merge-Vorschläge, Stichproben aus Eskalationen.
- **Monatlich:** Restore-Test, Kandidaten für Updates von Basismodell, Engine und Treiber prüfen.
### 2.3 Pflege-Agent mit Human-in-the-Loop (Service-Routine)
Die Pflege läuft **halbautomatisch**, geführt von einem Pflege-Agenten (siehe `docs/spec/SPEC-maintenance.md`):
1. **Service-Routine.** Wöchentlich per Zeitplan, jederzeit auch auf Zuruf („starte die Service-Routine“). Der Agent sammelt Befunde: Skills mit sinkender Pass-Rate, ähnliche Skills (Merge-Kandidaten), offene Kandidaten der Lifecycle-Pipeline, Slots im Zustand `degraded`, Häufungen von Kontext-Ausweichern und den Kostenstand.
2. Daraus erzeugt er **Vorschläge** (`P-<nr>`), jeweils mit Begründung, Risiko und erwarteter Wirkung.
3. Der Mensch antwortet **per Prompt** im Chat (n8n Chat oder Messenger): „genehmige P-3“, „lehne P-4 ab, weil …“, „alle mit Risiko niedrig genehmigen“, oder neue Aufträge wie „wechsle tier1-general auf qwen3-14b“ und „trainiere einen Adapter für den Cluster rechnungen“.
4. Aufträge des Menschen werden ebenfalls zu Vorschlägen. Der Agent zeigt, was passieren würde, und führt erst nach Bestätigung aus.
5. Eine **Freigabe-Richtlinie** (`config/policy.yaml`) legt fest, was ohne Rückfrage laufen darf. Standard: Schritte in die sichere Richtung (Skill zurückstufen, Slot als `degraded` markieren, Container-Neustart) laufen automatisch. Alles, was Qualität oder Kosten nach oben verändert (Skill freischalten, Adapter oder Basismodell tauschen, Host-Neustart, Löschen), braucht eine Freigabe.
Der Agent **entscheidet nicht über Infrastruktur**. Er schlägt vor, erklärt und führt Freigegebenes über dieselben deterministischen Aktionen aus wie der Healer. Freitext wird zuerst mit einer festen Befehlsgrammatik verstanden. Ein LLM wird nur verwendet, um unklare Formulierungen auf einen dieser Befehle abzubilden, und der Agent fragt dann zurück.
### 2.4 Observability (Voraussetzung für alles Weitere)
- **Langfuse:** Trace jeder Anfrage mit Slot, Skill, Adapter, Verifier-Ergebnis, Tokens, Latenz und Eskalation. Daraus entstehen Trainings- und Eval-Daten.
- **Prometheus + Grafana:** Metriken von vLLM (KV-Cache-Auslastung, wartende Requests, Preemptions), llama.cpp, LiteLLM, Router, `pve-exporter` (Proxmox) und `nvidia_gpu_exporter` (funktioniert auch auf alten Quadros).
- **Loki** für Logs, inkl. Kernel-Logs der GPU-VMs (NVIDIA-Xid-Fehler).
---
## 3. Autohealing – in Schichten
Jede Schicht fängt ab, was die darunterliegende nicht schafft. Jede Aktion hat einen Zähler, und nach N Versuchen wird an die nächste Schicht bzw. einen Menschen eskaliert.
| Schicht | Erkennt | Reaktion |
|---|---|---|
| **L1 Container** | Prozess hängt, Healthcheck schlägt fehl | Docker-Healthcheck plus `autoheal`-Container (Compose startet Container im Zustand *unhealthy* nicht selbst neu) |
| **L2 Modell-Endpunkt** | Endpunkt antwortet, aber falsch oder zu langsam | **Canary-Prompt** mit erwarteter Antwort statt nur HTTP 200; LiteLLM-Fallbacks und Cooldowns; Circuit Breaker im Router |
| **L3 VM / GPU** | GPU fällt vom Bus (Xid 79), CUDA-Fehler, OOM-Schleifen, Überhitzung | Healer startet VM über die Proxmox-API neu. Bei Wiederholung wird der Slot in der Registry als `degraded` markiert, der Router meidet ihn, und auf Wunsch wird ein Ersatz-Node gestartet |
| **L4 Node** | Host weg | Proxmox HA startet Infra-VMs woanders neu. GPU-Slots fallen per Registry auf andere Nodes oder Stufe 0 zurück |
| **L5 Qualität** | Pass-Rate eines Skills oder Adapters sinkt (Drift) | Skill automatisch auf Stufe 0 zurückstufen, Re-Destillation einreihen, Adapter auf Vorversion zurückrollen |
| **L6 Konfiguration** | Ist-Zustand weicht von Git ab | Reconcile (Ansible/OpenTofu) stellt den Sollzustand wieder her |
**Healer-Service:** Ein kleiner Dienst (oder n8n-Workflow mit Cron) wertet Prometheus-Alerts aus und führt die Aktionen nach einer festen Regeltabelle aus. Keine LLM-Entscheidung beim Heilen der Infrastruktur, das muss deterministisch sein. Später kann ein LLM *Diagnose-Berichte* schreiben, aber nicht handeln.
**Hinweis zu Passthrough:** Manche älteren Karten lassen sich nach einem Absturz nicht sauber zurücksetzen (fehlendes FLR) und brauchen einen Host-Neustart. Das gehört in die Regeltabelle (Eskalation „Host-Reboot“, nur mit Freigabe oder in einem Wartungsfenster).
---
## 4. Modellwechsel und Nachtrainieren = eine Pipeline
Basismodell-Wechsel, neuer Adapter, neue Quantisierung, neues Embedding-Modell und Engine-Update sind alle dasselbe: **ein Kandidat für einen Slot.** Deshalb gibt es genau eine Lifecycle-Pipeline.
### 4.1 Ablauf
```
Kandidat (Basis/Adapter/Quant/Engine)
→ Build (Download+Quantisierung oder LoRA-Training aus Datensatz)
→ Offline-Eval (Golden Sets aller betroffenen Skills + allgemeines Sanity-Set
+ Kontextlängen-Kalibrierung, s. Abschnitt 6)
→ Shadow (läuft parallel auf echtem Traffic mit, Antworten werden nur verglichen)
→ Canary (x % Traffic, Verifier-Pass-Rate vs. aktueller Version)
→ Promote (Registry-Eintrag des Slots umschalten)
→ Vorversion bleibt N Tage als Rollback-Ziel erhalten
```
n8n orchestriert die Schritte und holt die Freigaben ein. Die Arbeit selbst machen Jobs auf `gpu-flex`.
### 4.2 Basismodell-Wechsel
- Adapter sind **an das Basismodell gebunden**. In der Registry heißt ihr Schlüssel deshalb `(base_model_hash, skill_cluster, version)`.
- Wechsel = neue Basis als Kandidat plus **Batch-Neutraining aller Adapter** aus den gespeicherten Datensätzen. Das ist ein einziger nächtlicher Job.
- Vorher prüfen: Schafft die neue Basis die Skills **ohne Adapter** (nur Skill-Text)? Adapter werden nur für Cluster trainiert, in denen sie messbar etwas bringen. Das reduziert die Pflege.
### 4.3 Datensätze modellneutral halten
- Speichern als Nachrichtenliste (`system`/`user`/`assistant` plus Metadaten), **ohne** modellspezifisches Chat-Template. Das Template kommt erst beim Training dazu.
- Jeder Fall trägt Herkunft (Stufe, Modell), Verifier-Ergebnis, Skill-ID und Zeitstempel.
- Train/Eval-Split ist fest pro Fall, damit Eval-Fälle nie ins Training geraten.
### 4.4 Sonderfall Embedding-Modell
Neues Embedding-Modell bedeutet: Alle Vektoren sind ungültig. Deshalb **Blue/Green-Index**: zweite Collection mit dem neuen Modell befüllen, Routing-Qualität vergleichen (Recall auf historisch korrekt gerouteten Fällen), dann den Alias umschalten.
---
## 5. Finetuning-Strategie
### 5.1 Stufen (in dieser Reihenfolge ausreizen)
1. **Skill-Text und Beispiele im Kontext.** Kostenlos und sofort wirksam.
2. **LoRA pro Skill-Cluster.** Wird trainiert, sobald ein Cluster ≥ N verifizierte Fälle hat (Startwert ca. 200–500) *und* Stufe 1 dort unter dem Zielwert liegt.
3. **Präferenz-Training (DPO/ORPO).** Das System erzeugt automatisch Präferenzpaare: *Antwort des schwachen Modells (Verifier: falsch)* gegen *Korrektur des starken Modells (Verifier: richtig)* für dieselbe Eingabe. Das ist sehr wertvolles Trainingsmaterial, das hier nebenbei entsteht.
4. **Allgemeiner Domänen-Adapter** (mehrere Cluster zusammengeführt), wenn viele kleine Adapter unhandlich werden.
### 5.2 Technik auf der vorhandenen Hardware
- Training auf `gpu-flex` (RTX 4000 Ada, 20 GB) mit **QLoRA** über Unsloth oder Axolotl. 7–14B ist komfortabel, größere Modelle nur knapp oder gar nicht.
- Serving über vLLM mit `--enable-lora`. Begrenzungen (`max_loras`, `max_lora_rank`) setzen, sonst wird VRAM für den KV-Cache knapp.
- Während des Trainings ist `gpu-flex` in der Registry `unavailable`. Der Router weiß das, und ein Healer-Alarm wird dadurch nicht ausgelöst (Wartungsfenster).
### 5.3 Risiken
- **Overfitting auf selbst erzeugte Varianten.** Das Eval-Set muss echte Produktionsfälle enthalten.
- **Verifier als Flaschenhals.** Was der Verifier nicht prüft, lernt das Modell auch nicht sicher. Verifier-Qualität regelmäßig gegen das starke Modell stichprobenartig gegenprüfen.
- **Schleichende Selbstverstärkung.** Nur Fälle, die *unabhängig* verifiziert wurden, dürfen ins Training, nicht bloß solche, die das schwache Modell selbst für gut hält.
---
## 6. Problemerkennung (z. B. zu kleine Kontextlänge)
### 6.1 Vor dem Aufruf (präventiv, im Router)
- **Token-Budget berechnen** mit dem Tokenizer des Zielmodells: Eingabe + Skill + Beispiele + erwartete Ausgabelänge.
- Liegt die Summe über `effective_context` des Slots (nicht über `max_context`, siehe unten), reagiert der Router in dieser Reihenfolge:
1. kompaktere Skill-Variante bzw. weniger Beispiele laden
2. Slot mit größerem effektivem Kontext wählen
3. Aufgabe aufteilen (Map-Reduce, Chunking)
4. auf Stufe 0 eskalieren
- Jede dieser Ausweichreaktionen wird als Ereignis geloggt. Häufen sie sich bei einem Skill, ist das ein Signal für Pflege.
### 6.2 Effektiver vs. nomineller Kontext
Modelle werden oft deutlich vor ihrem offiziellen Kontextlimit schlechter. Deshalb **kalibrieren**: die Verifier-Pass-Rate pro Slot nach Eingabelänge in Klassen gruppieren (z. B. <2k, 2–8k, 8–16k, …). Die Länge, ab der die Pass-Rate unter den Zielwert fällt, wird als `effective_context` in der Registry gespeichert und automatisch nachgeführt.
### 6.3 Laufzeit-Signale und Fehlerklassen
| Signal | Bedeutung | Automatische Reaktion |
|---|---|---|
| `finish_reason = length` | Ausgabe abgeschnitten | `max_tokens` erhöhen bzw. Aufgabe teilen; bei Häufung `effective_context` senken |
| Kontext-Overflow-Fehler der Engine | Budget falsch berechnet | Tokenizer-Konfiguration prüfen, Anfrage neu routen |
| JSON/Schema ungültig | Formatproblem | ein Retry mit Fehlerhinweis, danach Eskalation; bei Häufung Kandidat für Adapter |
| Wiederholungsschleifen in der Ausgabe | Degeneration (oft Quantisierung oder zu langer Kontext) | Abbruch, Eskalation, Längen-Bucket markieren |
| Hohe Ähnlichkeit, aber Verifier schlägt fehl | **Fehlrouting** | Schwellwert des Skills anheben, Fall als Negativbeispiel für den Router |
| Zwei Skills fast gleichauf | Skill-Konflikt | Reranker entscheiden lassen, Merge-Vorschlag |
| KV-Cache voll, Preemptions | Überlast | Drosselung, Ausweichen auf zweiten Slot |
| Latenz-Ausreißer | Überhitzung, Swapping, Nachbar-Last | Node-Metriken prüfen, ggf. Slot `degraded` |
Alle Klassen landen mit Zählern in Grafana. Die Regeltabelle (Signal → Reaktion) ist dieselbe, die der Healer nutzt.
---
## 7. Übertragbarkeit auf andere Cluster
### 7.1 Hardware-Abstraktion
1. **Inventar-Agent** auf jedem Node: liest GPU-Modell, VRAM, Compute Capability, Treiber, CPU-Kerne, RAM und Speicher aus (`nvidia-smi`, `lscpu`, …) und meldet ein **Capability-Profil**.
2. **Modell-Katalog** mit Anforderungen pro Modell und Quantisierung: Mindest-VRAM, Mindest-Compute-Capability, unterstützte Engines, Kontext.
3. **Placement-Regeln** (anfangs deterministisch, keine Optimierung):
- Compute Capability ≥ 7.x und genug VRAM → vLLM-Rolle
- Compute Capability 5.x–6.x → llama.cpp-Rolle (Embedding, Rerank, kleine Modelle)
- keine GPU → CPU-Rollen (Infra, CPU-Embedding als Fallback)
4. **Kalibrierungslauf** nach dem Deployment: Benchmark pro Slot (Tokens/s, Latenz, effektiver Kontext) → Registry wird automatisch befüllt.
### 7.2 Konfigurationsschichten (Repo-Struktur)
```
core/ portabel: Python-Paket `knaster` (Router, Registry, Verifier, Healer,
Pflege-Agent, Lifecycle, Inventar/Placement) + Tests
config/ portable Standardwerte: Registry-Schema-Beispiel, Policy, Healer-Regeln
catalog/ Modell-Katalog mit Hardware-Anforderungen
skills/ SKILL.md-Bibliothek (Format kompatibel zu Hermes / agentskills)
deploy/ Docker-Compose pro Rolle, LiteLLM-, Prometheus-, Alertmanager-Konfiguration
n8n/ importierbare Workflows
platform/proxmox/ austauschbar: OpenTofu + Ansible; später ggf. platform/baremetal, platform/k8s
sites/<cluster>/ standortspezifisch: Inventar, Registry, Placement-Overrides, Secret-Referenzen
```
### 7.3 Was wandert mit, was nicht?
| Asset | Übertragbar? |
|---|---|
| Skills (Text), Eval-Sets, Trainingsdaten | **ja**, uneingeschränkt |
| Router-Schwellwerte | ja, aber nur wenn das Embedding-Modell gleich ist; sonst neu kalibrieren |
| LoRA-Adapter | nur bei identischem Basismodell; sonst neu trainieren (Pipeline aus Abschnitt 4) |
| Registry-Kalibrierung | nein, wird pro Cluster neu gemessen |
Die Portabilität beruht also auf den **Daten und der Pipeline**, nicht auf Gewichten oder Hardware-Annahmen.
---
## 8. Roadmap
> **Abgelöst** durch [superpowers/plans/2026-10-12-aufbau-cluster-knaster.md](superpowers/plans/2026-10-12-aufbau-cluster-knaster.md). Dort ist der chronologische Ablauf auf der echten Hardware beschrieben, mit den Entscheidungen D1–D5 und der Zuordnung zu Planner Epic 7. Die Tabelle unten bleibt nur zur Nachvollziehbarkeit stehen (Zuordnung: 0 → Phasen 0–5, 1 → 6, 2 → 7, 3–6 → 9).
| Phase | Inhalt | Fertig, wenn … |
|---|---|---|
| **0 Fundament** | Proxmox-Templates, Resource Mappings, OpenTofu/Ansible, Monitoring-Stack | eine GPU-VM lässt sich per Code neu erzeugen, Grafana zeigt GPU- und Proxmox-Metriken |
| **1 Data Plane** | LiteLLM, vLLM (Ada), llama.cpp (P2000/M4000), Postgres+pgvector | alle Slots per LiteLLM erreichbar, Canary-Checks grün |
| **2 Kernpfad** | Router (`/route`, `/escalate`), Registry, n8n-Hauptworkflow, Verifier v1, Langfuse | Anfrage läuft Ende-zu-Ende inkl. Eskalation nach OpenRouter |
| **3 Skills** | Hermes als Skill-Autor, SKILL.md-Bibliothek, Graduierungs-Workflow | erster Skill autonom erstellt, getestet und auf Stufe 1 freigegeben |
| **4 Robustheit** | Healer, Regeltabelle, Token-Budget, Kontext-Kalibrierung, Fehlerklassen | provozierter GPU- bzw. Container-Ausfall heilt ohne Eingriff |
| **5 Lifecycle** | Kandidaten-Pipeline, QLoRA-Training, Shadow/Canary, Rollback | Adapter automatisch trainiert, evaluiert, promoted und einmal zurückgerollt |
| **6 Portabilität** | Inventar-Agent, Katalog, Placement, Kalibrierungslauf | zweiter (ggf. simulierter) Cluster aus `sites/` aufgesetzt |
---
## 9. Entscheidungen
### Getroffen
- GPU-Nodes als VM, Infrastruktur als LXC bzw. leichte VM (ADR-0001)
- Netzwerk 1 GbE → kein Ceph, ZFS lokal plus Replikation, Modelle lokal (ADR-0002)
- Slots statt Modellnamen, eine Lifecycle-Pipeline für alle Wechsel (ADR-0003)
- Halbautomatische Pflege über einen Pflege-Agenten mit Freigabe per Prompt (ADR-0004)
- Infrastruktur heilt deterministisch, ohne LLM-Entscheidungen (ADR-0005)
- Alte GPUs nur llama.cpp, M4000 vorerst aus, TTS mit Piper (CPU) und Qwen3-TTS (Ada) (ADR-0006)
### Entscheidungen 2026-10
Aus dem [Aufbauplan](superpowers/plans/2026-10-12-aufbau-cluster-knaster.md), Abschnitt „Entscheidungen“:
- **D1 Speicher – umgesetzt (12.10.):** Variante B ohne Neuinstallation. System-SSD ext4/LVM-thin mit `local-lvm`, zweite SSD als ZFS-Pool `tank` auf pve44, pve48 und pve52. Replikation und HA nur zwischen diesen drei, pve46 und pve61 ohne ZFS (ADR-0002, Nachtrag).
- **D2 GPU als VM – entschieden (12.10.):** eine Ubuntu-24.04-VM pro GPU-Knoten mit allen Karten des Knotens (`gpu-pve44` 244, `gpu-pve46` 246, `gpu-pve48` 248, `gpu-pve52` 252), darin ein Docker-Container pro Rolle (ADR-0001, Nachtrag).
- **D3 Ada-Rechner – vorgeschlagen, Bestätigung offen:** GODE-PC-05/06 bleiben Windows und stellen ihre Leistung über die Worker-Registry v2 bereit (ADR-0006, Nachtrag; Umsetzung in Task 6.4).
- **D4 LiteLLM – vorgeschlagen, Bestätigung offen:** kein eigener LiteLLM im knaster-Infra. Der Router nutzt den LiteLLM mit PSE auf appsrv08, die lokalen Slots werden dort als Modelle eingetragen.
- **D5 IP-Plan – zurückgestellt (12.10.):** Knoten behalten .207–.214, Gäste vorerst per DHCP. Feste Gast-IPs (Vorschlag `.220–.239`) über Reservierungen bzw. einen Ausschluss im DHCP-Server, spätestens vor Phase 6.
### Offen
1. Erstes Basismodell für `tier1-general` (8–14B, gut quantisierbar, LoRA-freundlich, gutes Deutsch). Entscheidung per Kalibrierungslauf.
2. Kommen die M4000 zurück? `llama-bench` plus Strommessung am Deployment-Tag (bis dahin außer Betrieb, ADR-0006)
3. Verifier-Strategie pro Aufgabentyp: Code-Checks, Schema, kleines Judge-Modell, Stichproben durch das starke Modell
4. Schwellwerte: Graduierung (Start 90 %), Fallzahl fürs LoRA-Training (Start 300), Canary-Anteil (Start 10 %)
5. Kanal für den Pflege-Agenten: n8n Chat, Telegram oder Matrix
6. Standort des Proxmox Backup Servers (intern auf SSD oder extern)