From 64efe1850063fa9058dd44e78a8e501402d949d6 Mon Sep 17 00:00:00 2001 From: Hitonabi Date: Thu, 2 Jul 2026 10:30:12 +0200 Subject: [PATCH] Docs: Komplett-Review 2026-07-02 (IST live verifiziert + Roadmap P0-P3) + Session-Docs - REVIEW_2026-07-02.md: Latenz-Baseline (STT 2s dominant, LLM-TTFT 65ms), chat-Lane-Bug, SOLL-Recherche (Parakeet v3, Silero VAD v6, KV-Quant, MoE-Spec-Trap), Verdikte bestaetigt - Audit-/TTS-/ZeroClaw-/DR-Docs von main nachgezogen; launch.json Co-Authored-By: Claude Fable 5 --- .claude/launch.json | 9 + docs/AUDIT_KICKOFF.md | 75 +++++ docs/CLAUDE_CODE_BRIEF_lucy-brain-role.md | 106 +++++++ docs/DISASTER_RECOVERY.md | 326 ++++++++++++++++++++++ docs/LUCY_TTS_PLAN.md | 149 ++++++++++ docs/REVIEW_2026-07-02.md | 221 +++++++++++++++ docs/ZEROCLAW_POC_BRIEF.md | 83 ++++++ docs/ZEROCLAW_POC_RESULTS.md | 118 ++++++++ 8 files changed, 1087 insertions(+) create mode 100644 docs/AUDIT_KICKOFF.md create mode 100644 docs/CLAUDE_CODE_BRIEF_lucy-brain-role.md create mode 100644 docs/DISASTER_RECOVERY.md create mode 100644 docs/LUCY_TTS_PLAN.md create mode 100644 docs/REVIEW_2026-07-02.md create mode 100644 docs/ZEROCLAW_POC_BRIEF.md create mode 100644 docs/ZEROCLAW_POC_RESULTS.md diff --git a/.claude/launch.json b/.claude/launch.json index 292479f..46b3732 100644 --- a/.claude/launch.json +++ b/.claude/launch.json @@ -14,6 +14,15 @@ "9000" ], "port": 9000 + }, + { + "name": "frontend", + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "dev", "--", "--port", "5180", "--strictPort"], + "cwd": "F:\\Coding Stuff\\mission-control-2\\frontend", + "env": { "MC_API_TARGET": "http://192.168.178.151:9001" }, + "autoPort": false, + "port": 5180 } ] } diff --git a/docs/AUDIT_KICKOFF.md b/docs/AUDIT_KICKOFF.md new file mode 100644 index 0000000..4ec890f --- /dev/null +++ b/docs/AUDIT_KICKOFF.md @@ -0,0 +1,75 @@ +# Kickoff: Voll-Audit MC2 (Front+Backend) + Box-SSH + Optimierungsplan + +> Für eine **frische Claude-Code-Session mit echtem Terminal** (direkter SSH-Zugang zur Box). +> Aufgabe vom Nutzer: front/backend komplett scannen (IST-Zustand), via SSH auf die Box gehen +> (ausdrücklich erlaubt), und am Ende einen **sauberen, strukturierten Plan** liefern, wie es +> weitergeht — inkl. Optimierungen für ALLE LLM-Rollen und einem **neuen `scout`-Modell**. +> Erst auditieren/planen — keine destruktiven Änderungen ohne Plan-Freigabe. + +## Zugänge +- **Repo (Dev-PC):** `F:\Coding Stuff\mission-control-2` (Windows). Auf der Box: `~/mission-control-v2`. +- **Box:** `ssh hitonabi@192.168.178.151` (key-based, funktioniert non-interaktiv). Hostname + `tobisniceaiarbeitstier`, AMD Ryzen AI MAX+ 395 (Strix Halo), 122 GB RAM, GTT ~124 GB, Vulkan/RADV. +- **Wichtige Box-Pfade:** `/etc/llama-swap/config.yaml` (Engine, `-watch-config`), + `~/.hermes/config.yaml` (Hermes-Agent = Lucys Hirn), `/srv/models/` (GGUFs), + `/opt/llamacpp-vulkan/llama-server` (Engine v9843). +- **Dienste (systemd --user):** `hermes-gateway` (:8642), `hermes-webui` (:8787), llama-swap (:8080), + MC2-Gateway (:9001). Live-Logs: `journalctl --user -u hermes-gateway -f`. + +## Architektur (verifiziert 30.06.2026) +- **llama-swap** (:8080) lädt GGUFs; Rollen = llama-swap **`aliases`**; Warm-Bleiben über + `groups: { brains: { swap:false } }` + `ttl`. +- **MC2-Gateway** (:9001/v1, FastAPI) mit virtuellen Lanes `chat`(→fast/heavy) & `coding`(→coder_lite/coder). + Code: `backend/services/router_logic.py`, `routing_policy.py`, `roles.py`, `llamaswap.py`, `budget.py`, + `fit.py`; Router `backend/routers/{models,routing,voice}.py`. Frontend: `frontend/src/views/ModelsView.tsx`, + `components/models/*`, `SystemDrawer.tsx`. +- **Hermes-Agent** (:8642) = Lucys Hirn (`~/.hermes/config.yaml: model.default`), Delegation `heavy`. +- **Lucy-Client** (`client/lucy-desktop`, Electron) spawnt lokal pocket-tts (:8130); Persona+Umlaut-Logik + im Client (`renderer/src/config.ts`, `lib/voice/useVoiceAgent.ts`). +- **Features sind eigene Rollen** (hirn-unabhängig): Sehen=`Qwen3-VL-8B`, Hören=Whisper(`stt`), + Sprechen=pocket-tts, Embedding=`Qwen3-Embedding-0.6B`(ttl 0, immer warm), Gedächtnis=Mem0/MCP. + +## Modelle / Rollen (Stand jetzt) +| Rolle (alias) | Modell | aktiv | ctt/ttl | Notiz | +|---|---|---|---|---| +| fast | Qwen3.6-35B-A3B | 3B | ttl 0, --parallel 2, mmproj | chat-Lane Default | +| heavy | Qwen3.5-122B-A10B | 10B | ttl 600 | Delegation-Ziel | +| coder | Qwen3-Coder-Next | — | ttl 600, spec draft-simple (Qwen3-0.6B) | | +| coder_lite | Qwen3-Coder-30B-A3B | 3B | ttl 300 | coding-Lane Default | +| vision | Qwen3-VL-8B-Instruct | — | ttl 300 | Screen-Beschreibung | +| (embedding) | Qwen3-Embedding-0.6B | — | ttl 0 | immer warm | +| **brain (NEU, Lucy)** | **gemma-4-26B-A4B-it** | 4B | ttl 0, **noch Alias `scout`** | Hermes default seit 30.06. | + +## Bereits gemacht (30.06.) +- Lucys Hirn `fast` → **`gemma-4-26B-A4B-it`** (`~/.hermes/config.yaml model.default`, Backup + `~/.hermes/config.yaml.gemma-swap.bak`, hermes-gateway neu gestartet, verifiziert). +- Umlaut-Fix: Client-Stammliste erweitert (`useVoiceAgent.ts`) **und** Server-Netz `_fix_umlauts` + (`client/lucy-tts/pocket_server.py`). Hermes-System-Prompt fordert echte Umlaute (Client-Persona). +- pocket-tts getunt: A1 safetensors-Voice-Cache, A2 Referenz-Cleaning, B3 FP-Gate skip kurze Audios, + FAST_FIRST (kurzer 1. Chunk, TTFB ~1,3s), seriell (WORKERS=0) als Default. Details: `docs/LUCY_TTS_PLAN.md`. + +## Offene Probleme / Aufgaben +1. **Brain-Rolle fehlt als Konzept.** gemma läuft als Alias `scout`, ist NICHT in `brains: swap:false` + → unter Speicherdruck evakuierbar trotz ttl 0. Detail-Brief: **`docs/CLAUDE_CODE_BRIEF_lucy-brain-role.md`** + (Backend+Frontend-Umbau: erstklassige `brain`-Rolle, auto-warm/ko-resident, Hermes-Sync). +2. **`scout`-Rolle jetzt vakant** (gemma war scout, ist jetzt Hirn). **Neues scout-Modell suchen:** + multimodaler Allrounder, klein/MoE (schnell, KO-Residenz-freundlich), Tools wünschenswert. Tagesaktuell + recherchieren + Empfehlung. +3. **MTP-Speculative-Decoding für gemma** (1,5–2× Durchsatz, 0 Qualitätsverlust): Engine kann `draft-mtp` + ✓; MTP-Drafter `gemma-4-26B-A4B-it-assistant` (~0,4B) muss nach `/srv/models/`, gemma-cmd ergänzen + (`-md --spec-type draft-mtp --spec-draft-n-max/-n-min`; **alte** `--draft-max/-min` + sind entfernt!). MC2-UI/Backend kennt MTP-Drafter nicht (zeigte „Vocab ?") → erweitern. (Im Brain-Brief.) +4. **Optimierung ALLER Rollen prüfen:** je Modell ctx/quant/ttl/Warm-Gruppe/Parallelität/Spec-Decoding + (MTP für Gemma; Draft-Eignung für Qwen-Modelle) gegen das GTT-/RAM-Budget (~124 GB) und reale t/s + auf Strix Halo (bandbreitenlimitiert → MoE bevorzugt; dichte Modelle langsam). KO-Residenz-Set + sinnvoll definieren (was muss gleichzeitig warm sein für Lucy + IDE-Coding?). + +## Deliverable +Ein **strukturierter Plan** (z.B. `docs/OPTIMIZATION_PLAN.md`): IST-Zustand → konkrete Maßnahmen je Rolle +(mit Begründung/Zahlen) → Reihenfolge/Risiko/Revert → offene Entscheidungen. Erst Plan, dann Umsetzung +nach Freigabe. Alles reversibel (Config-Backups vor jeder Änderung). + +## Leitplanken +- Features (Sehen/Hören/Sprechen/Embedding/Gedächtnis) + IDE-Lanes dürfen NICHT brechen. +- Vor jeder Box-Config-Änderung Backup; llama-swap reloadt per `-watch-config`. +- Keine destruktiven Aktionen ohne Plan-Freigabe des Nutzers. diff --git a/docs/CLAUDE_CODE_BRIEF_lucy-brain-role.md b/docs/CLAUDE_CODE_BRIEF_lucy-brain-role.md new file mode 100644 index 0000000..8d1aee3 --- /dev/null +++ b/docs/CLAUDE_CODE_BRIEF_lucy-brain-role.md @@ -0,0 +1,106 @@ +# Claude-Code-Auftrag: „Brain"-Rolle für Lucy (Front- + Backend-Umbau) + +> Ziel: Lucys Hirn (aktuell `gemma-4-26B-A4B-it`) als **erstklassige, dauer-warme Rolle** im MC2-Stack +> verankern — statt es als `scout` zu führen, das nach `ttl` entladen wird. Features (Sehen/Hören/ +> Sprechen/Embedding) dürfen NICHT verloren gehen, KO-Residenz + Budget müssen sauber bleiben. + +## Kontext / Architektur (Ist-Zustand, verifiziert 30.06.) +- **Engine:** llama-swap (config: `/etc/llama-swap/config.yaml` auf der Box, läuft mit `-watch-config`). + Rollen werden als llama-swap **`aliases`** gesetzt; Warm-Bleiben über `groups:` (eine Gruppe + `brains: { swap: false }`) + `ttl`. Installierte Modelle: `Qwen3.6-35B-A3B` (fast, ttl 0), + `Qwen3.5-122B-A10B` (heavy, ttl 600), `Qwen3-Coder-Next` (coder, ttl 600), + `Qwen3-Coder-30B-A3B-Instruct` (coder_lite, ttl 300), `Qwen3-VL-8B-Instruct` (vision, ttl 300), + `Qwen3-Embedding-0.6B` (ttl 0 = immer warm), `gemma-4-26B-A4B-it` (ttl 180). +- **Gateway:** MC2 builtin auf `:9001/v1` mit virtuellen Lanes `chat` (→ fast/heavy) und + `coding` (→ coder_lite/coder). Code: `backend/services/router_logic.py`, `routing_policy.py`. + **Lucy nutzt die Lanes NICHT** — sie ist der Hermes-Agent. +- **Lucy-Hirn:** Hermes-Agent (`:8642`), Brain = `~/.hermes/config.yaml` → `model.default` + (jetzt `gemma-4-26B-A4B-it`), Delegation = `heavy`. Persona/Prompt kommt aus dem **Client** + (`client/lucy-desktop/src/renderer/src/config.ts`), nicht aus der Box-Config. +- **Hardware:** Strix Halo (Ryzen AI Max+ 395), 122 GB, GTT ~124 GB, bandbreitenlimitiert → + MoE mit wenig aktiven Params ist schnell, dichte Modelle langsam. + +## Root-Cause des Bugs +1. Kanonische Rollen `ROLE_IDS = {fast, heavy, coder, vision, scout}` — **keine `brain`/Agent-Rolle**. + (Kommentar im Code: „kein agent/reasoning mehr".) +2. Es gibt keine Verknüpfung „Hirn-Modell ⇒ muss warm bleiben". gemma trägt den Alias `scout`, + ist NICHT in der `brains`-Gruppe, `ttl 180` → entlädt im Leerlauf → Lucy lädt kalt nach (~5–10 s). +3. `roles.py` referenziert noch eine `hermes`-Rolle, die in `ROLE_IDS` nicht existiert → Inkonsistenz. + +## Aufgabe + +### Backend (`backend/`) +1. **Neue erstklassige Rolle `brain` einführen** (oder `hermes` reaktivieren) und in ALLEN + Quellen synchronisieren (heute dupliziert!): + - `services/llamaswap.py` → `ROLE_IDS` + - `services/sources.py` → `ROLE_IDS` + Titel/Icon (analog `scout: {title, icon}`) + - `services/maintenance.py` (Modell-Upgrade-Rollenliste) + - `services/roles.py` → `_capability_suit`/`_pref`/`_reason` für `brain` (Tools Pflicht, + mittlere Größe + MoE bevorzugt, niedrige Latenz). `hermes`-Altlast bereinigen. +2. **Rolle `brain` ⇒ automatisch warm + ko-resident.** Beim Zuweisen der `brain`-Rolle + (`POST /api/models/{model_id}/role`, `routers/models.py`): + - Modell via `set_group("brains", members=[...], swap=False, persist=True)` in die Warm-Gruppe + aufnehmen (bestehender Helper in `llamaswap.py`). + - `ttl: 0` setzen (oder hoch), vorheriges Brain-Modell aus `brains` entfernen + ttl entspannen. + - Embedding (`Qwen3-Embedding-0.6B`, ttl 0) MUSS warm bleiben — nicht verdrängen. +3. **Single Source of Truth für „Lucys Hirn":** beim Setzen der `brain`-Rolle auch Hermes' + `~/.hermes/config.yaml` → `model.default` auf das Modell setzen + `systemctl --user restart + hermes-gateway` (mit Backup der config). So bleibt MC2-UI-Auswahl ↔ Hermes-Brain konsistent. +4. **Budget/KO-Residenz-Safety:** Brain(warm) + Embedding(warm) + on-demand Vision + Coder müssen + in GTT (~124 GB) passen. `services/budget.py`/`fit.py` nutzen, bei OOM warnen (nicht hart laden). +5. **Lanes/IDEs unangetastet lassen:** chat/coding-Routing (`router_logic.py`) bleibt wie es ist; + `fast` bleibt für die chat-Lane warm. + +### Frontend (`frontend/src/`) +1. **Rollen-Taxonomie** um `brain` erweitern (Badges/Titel/Icon) — Duplikat zur Backend-Liste + finden & angleichen (`components/models/*`, `views/ModelsView.tsx`, evtl. `ModelBadges.ROLES`). + gemma darf NICHT mehr als `scout` erscheinen. +2. **Rollen-Zuweisungs-Modal:** `brain` auswählbar; Warm-/KO-Residenz-Status anzeigen + (ist das Brain in `brains`? warm? ttl?). Empfehlung via bestehendem `/api/roles/{role}/recommend`. +3. **Warm-Set / GTT-Budget sichtbar machen** (Dashboard/Models): was ist gerade ko-resident, + passt es ins Budget? (nutzt `/api/models` `running` + budget-Infos). +4. Optional: „Lucy-Hirn"-Selector, der die `brain`-Rolle setzt (treibt Backend #2 + #3). + +### Zusatz: MTP-Speculative-Decoding für Gemma (Durchsatz für agentische Arbeit) +Lucy ist ein **voller Agent** (Tools/MCP/PC-Control/Vision/Delegation) — Durchsatz zählt, nicht nur +TTFB. Gemma 4 bringt **MTP** (Multi-Token-Prediction) mit → 1,5–2× schneller bei null Qualitätsverlust. +- **Engine kann es bereits:** `llama-server` v9843 listet `--spec-type … draft-mtp …`. ✓ +- **Vocab-kompatibler „Draft" = Gemmas eigener MTP-Kopf** `gemma-4-26B-A4B-it-assistant` (~0,4B, + identischer Tokenizer per Konstruktion). Quelle z.B. `unsloth/gemma-4-26B-A4B-it-GGUF` (enthält den + MTP-Drafter, PR ggml-org/llama.cpp#23398). Muss nach `/srv/models/...` geladen werden (noch nicht da). +- **Flag-Änderung beachten:** `--draft-max/--draft-min` sind ENTFERNT → `--spec-draft-n-max` / + `--spec-draft-n-min`. Drafter laden via `-md --spec-type draft-mtp`. Exakte Flags + des Builds mit `llama-server --help` gegenprüfen. +- **MC2-Bug:** die Spec-Draft-Auswahl (UI + Backend) kennt **nur klassische Drafts** (vergleicht stur + `n_vocab`/`pre`) und bot fälschlich nur den Qwen-Draft an („Vocab ?"). **Erweitern:** MTP-Drafter + (`gemma4_assistant`-Arch) als gültigen, vocab-kompatiblen Draft erkennen, den passenden `-assistant`- + GGUF anbieten, und beim Aktivieren `-md … --spec-type draft-mtp --spec-draft-n-max/-n-min` in die + llama-swap-cmd schreiben. Co-Residenz: Drafter ~0,4B → vernachlässigbar. + +## Akzeptanzkriterien +- [ ] `gemma-4-26B-A4B-it` wird in der UI als **`brain`** geführt (nicht `scout`). +- [ ] Es bleibt **warm**: in `brains: swap:false`, `ttl 0`; überlebt > alter ttl Leerlauf + (Verifikation: `curl :8080/running` nach >5 Min Idle zeigt das Modell weiterhin `ready`). +- [ ] Lucy antwortet ohne Kalt-Nachladen nach Leerlauf. +- [ ] Vision (`Qwen3-VL-8B`), Embedding (`Qwen3-Embedding-0.6B`), Coder bleiben funktionsfähig & + ko-resident; **kein OOM**; IDE-Lanes (chat/coding) unverändert. +- [ ] Brain-Wechsel in der UI aktualisiert llama-swap (Warm-Gruppe) UND Hermes `model.default` + (+ Restart), reversibel (Backup). + +## Sofort-Hotfix (unabhängig vom Umbau — macht Lucy JETZT warm) +Auf der Box, bis der saubere Umbau steht: +```bash +# gemma als immer-warm + in die brains-Gruppe (Backup zuerst!) +cp /etc/llama-swap/config.yaml /etc/llama-swap/config.yaml.bak +# gemma ttl 180 -> 0 und groups.brains.members um gemma-4-26B-A4B-it ergänzen +# (manuell editieren oder via MC2 set_group), dann: +# llama-swap reloadt per -watch-config automatisch. +``` + +## Wichtige Dateien (Einstieg) +- Backend: `services/llamaswap.py` (Rollen=aliases, `set_role_alias`, `set_group`, `register_model`), + `services/roles.py`, `services/sources.py`, `services/routing_policy.py`, + `services/router_logic.py`, `services/budget.py`, `services/fit.py`, `routers/models.py`, + `routers/routing.py`. +- Frontend: `views/ModelsView.tsx`, `components/models/*`, `components/SystemDrawer.tsx`. +- Box (nicht im Repo): `/etc/llama-swap/config.yaml`, `~/.hermes/config.yaml`. diff --git a/docs/DISASTER_RECOVERY.md b/docs/DISASTER_RECOVERY.md new file mode 100644 index 0000000..135b901 --- /dev/null +++ b/docs/DISASTER_RECOVERY.md @@ -0,0 +1,326 @@ +# Konzept: Bare-Metal-Wiederaufbau + First-Run-Wizard (VOLLSTÄNDIG) + +> **Zweck:** Plan für den „hard crash"-Fall — die Box (`tobisniceaiarbeitstier`, Ubuntu 26.04, +> AMD Ryzen AI MAX+ 395 / gfx1151, 122 GB RAM) muss von **null** wiederherstellbar sein. +> **Anspruch:** *ALLES* ist erfasst — Engine, Hermes-Konfig 1:1, 3D-Avatare, Voice/Klonstimme, +> Memory, Browser, MCP, Skills, Secrets. Pro Komponente entscheidet der Nutzer im Wizard: +> **1:1 zurück** · **neu/Default** · **weglassen**. +> +> Dieses Dokument ist die **Spezifikation für eine künftige Implementierungs-Session** — es baut +> noch nichts. Stand: 2026-06-28. + +--- + +## 1. Leitprinzip: 1:1 ODER modular — der Nutzer wählt + +Der Wizard behandelt jede Komponente als **eigene Kachel mit drei Modi**: + +| Modus | Bedeutung | +|---|---| +| 📦 **1:1 aus Backup** | Exakter alter Zustand wird zurückgespielt (Configs, Daten, Klonstimme, Avatare). | +| 🆕 **Neu / Default** | Frische Installation mit sinnvollen Defaults (z.B. entfesseltes Hermes-Profil, Default-Avatar). | +| ⏭️ **Weglassen** | Komponente wird (vorerst) nicht installiert. | + +Ein „Alles 1:1"-Knopf wählt überall 📦 (wo ein Backup existiert), sonst 🆕. So bekommt der Nutzer +entweder den exakten alten Stand oder kann gezielt entrümpeln. + +--- + +## 2. Was es schon gibt (wiederverwenden) + +| Asset | Datei | Deckt ab | +|---|---|---| +| Code-Deploy | `deploy/deploy.sh` | git pull + venvs + Units + Restart. **Setzt Engine/llama-swap/Dirs/venvs voraus.** | +| Zustands-Backup | `deploy/backup.sh` + `mc2-backup.{service,timer}` | **Aktuell** (live): mem0, `~/.hermes/{config.yaml,.env,plugins}`, llama-swap-config. Retention 14. **Für echtes 1:1 zu erweitern** — fertiges Snippet in **Anhang B** (§5). | +| Restore | `deploy/restore.sh` | Spielt Tarball zurück (mit Pre-Restore-Sicherung). | +| Engine | `deploy/provision-engine.sh` | llama.cpp Vulkan/RADV-Build (root). | +| Voice-Setup | `voice_service/install.sh` | venv + Piper-Binary + dt. Piper-Stimmen + Chatterbox (best-effort). | +| Updates | `deploy/update-engine.sh`, `update-swap.sh` | Laufende Engine/Router-Updates. | +| Postchecks | `deploy/stack-postcheck.sh`, `hermes-postcheck.sh` | Funktionsprüfung → Wizard-Verifikationsschritt. | + +--- + +## 3. VOLLSTÄNDIGER Komponenten-Katalog + +> **Scan-verifiziert (2026-06-28)** gegen `backend/config.py`, alle `backend/services/*` & `routers/*`, +> `frontend/src/{nav.ts,views,components/voice}`, `voice_service/app.py`, `mem0_service/`, `deploy/*`. +> Alle persistenten Schreibpfade, Dienste, Secrets und Env-Vars sind unten erfasst. + +Legende Restore-Quelle: 📦 = aus Backup-Tarball · ⬇️ = Re-Download/Install (Skript) · 🌐 = Git · +🔑 = Secret (Nutzer/Generieren) · 🆕 = im Wizard neu gewählt. +„Im Backup?" = deckt der **aktuelle** `backup.sh` es ab. + +### A · OS & System (L0, root/sudo, einmalig) +| Komponente | Ort | Quelle | Im Backup? | +|---|---|---|---| +| Ubuntu 26.04, User `hitonabi`, `enable-linger` | — | ⬇️ manuell | n/a | +| System-Pakete: python3.14+venv, git, curl, jq, ttyd, uv | — | ⬇️ apt/curl | nein | +| Vulkan-Stack: mesa-vulkan-drivers, libvulkan1, vulkan-tools | — | ⬇️ apt | nein | +| Chrome-Libs (Browser): `agent-browser install --with-deps` | — | ⬇️ apt | nein | +| Verzeichnis-Layout: `/srv/models/{,mem0,mc2-backups,drafts}`, `/etc/llama-swap/` | — | ⬇️ mkdir+chown | nein | + +### B · Inferenz-Engine + Router (L1, root) +| Komponente | Ort | Quelle | Im Backup? | +|---|---|---|---| +| llama.cpp (Vulkan) → `llama-server` | `/opt/llamacpp-vulkan`, `/usr/local/bin/llama-server` | ⬇️ provision-engine.sh / update-engine.sh (ggml-org Release) | nein (re-build) | +| **llama-swap** Binary (Router `:8080`) | `/usr/local/bin/llama-swap` | ⬇️ **bekannt:** `mostlygeek/llama-swap`-Release (Rezept in `update-swap.sh`) | nein (re-download) | +| **llama-swap systemd-System-Unit** | `/etc/systemd/system/llama-swap.service` (+ `.d/` Drop-ins) | ⬇️ Bootstrap legt sie an — **kompletter Unit-Inhalt in Anhang A** (von der Box abgegriffen; Drop-ins via provision-engine.sh) | nein | +| llama-swap-Config (Modelle/Rollen) | `/etc/llama-swap/config.yaml` | 📦 | **ja** | +| Draft-Modelle (Spec-Decoding) | `/srv/models/drafts/` | ⬇️ Re-Download | nein | + +### C · MC2-App (L2, userspace) +| Komponente | Ort | Quelle | Im Backup? | +|---|---|---|---| +| MC2-Code | `~/mission-control-v2` | 🌐 Git (Gitea) | n/a | +| Backend-venv (Python 3.14) | `backend/.venv` | ⬇️ deploy.sh | nein (rebuild) | +| Frontend (gebaut, inkl. **3D-Avatar `avatar.vrm`**) | `frontend/dist`, `frontend/public/avatar.vrm` | 🌐 Git | n/a | +| systemd-User-Dienst `mission-control-2` (`:9001`) | `~/.config/systemd/user/` | ⬇️ deploy.sh | nein | + +### D · 3D-Avatar (Sprechen-Tab) +| Komponente | Ort | Quelle | Im Backup? | +|---|---|---|---| +| Default-Avatar (VRM) | `frontend/public/avatar.vrm` (→ dist) | 🌐 Git | n/a | +| Renderer | `frontend/src/components/voice/Avatar3D.tsx` | 🌐 Git | n/a | +| **Eigene/zusätzliche Avatare** (falls Nutzer welche ablegt) | **TODO: Ablageort definieren** (z.B. `/srv/models/avatars/` + DB-Verweis) | 📦/🆕 | **nein (Lücke)** | + +> Heute ist der Avatar **fest** (`avatar.vrm`, kommt mit dem Git-Frontend zurück). Wenn künftig +> Nutzer-Avatare hochgeladen werden, brauchen sie einen persistenten Ablageort, der ins Backup geht. + +### E · Voice-Sidecar (STT + TTS + Klonstimme) +| Komponente | Ort | Quelle | Im Backup? | +|---|---|---|---| +| Voice-venv (Python 3.12) | `~/.voice/venv` | ⬇️ install.sh | nein (rebuild) | +| STT (faster-whisper Modell) | `~/.voice/` (Cache) | ⬇️ install.sh / 1. Start | nein | +| Piper-Binary + dt. Stimmen (thorsten/kerstin) | `~/.voice/piper`, `~/.voice/voices` | ⬇️ install.sh | nein | +| Chatterbox (Premium-TTS, CPU-torch) | venv | ⬇️ install.sh (best-effort) | nein | +| **Klonstimme / Voice-Referenz-Audio** (Nutzer) | `~/.voice/refs/ref.wav` (`VOICE_REFS_DIR`, `/api/voice/reference`) | 📦 | **nein → Anhang B** | +| ElevenLabs-Key | `~/.hermes/.env` | 🔑 | ja | +| Stimm-/Lautstärke-Wahl | Browser-`localStorage` (pro Gerät) | 🆕 client | n/a | +| Dienst `voice-service` (`:8650`) | systemd-User | ⬇️ deploy.sh | nein | + +### F · Mem0 (Langzeitgedächtnis) +| Komponente | Ort | Quelle | Im Backup? | +|---|---|---|---| +| Mem0-venv (Python 3.12, uv) | `~/.mem0/venv` | ⬇️ deploy.sh | nein (rebuild) | +| **Gedächtnis-Daten (Chroma + history.db)** | `/srv/models/mem0/` | 📦 | **ja** | +| Hermes-Memory-Plugin | `~/.hermes/plugins/mc2-memory/` | 📦/🌐 | ja | +| Dienst `mem0-service` (`:8765`) | systemd-User | ⬇️ deploy.sh | nein | + +### G · Hermes-Agent (das Herz) +| Komponente | Ort | Quelle | Im Backup? | +|---|---|---|---| +| Hermes-Code | `~/.hermes/hermes-agent` | 🌐 Git (NousResearch) | nein (re-clone) | +| Bundled Node v22 | `~/.hermes/node/bin` | ⬇️ (kommt mit Hermes) | nein | +| Hermes-venv | `~/.hermes/hermes-agent/venv` | ⬇️ rebuild | nein | +| **`config.yaml` 1:1** (Toolsets, MCP, Engine, Browser, Personalities, alles) | `~/.hermes/config.yaml` | 📦 | **ja** | +| **`.env` (Secrets: TELEGRAM_BOT_TOKEN, API_SERVER_KEY, ElevenLabs …)** | `~/.hermes/.env` | 📦/🔑 | **ja** | +| Plugins | `~/.hermes/plugins/` | 📦 | ja | +| **Skills (eigene)** | `~/.hermes/skills/` (45M; `.hub`-Cache re-downloadbar) | 📦 | **nein → Anhang B (ohne .hub)** | +| Sessions/History (optional) | `~/.hermes/sessions/` (856K) | 📦 | **nein → Anhang B** | +| Checkpoints (optional) | `~/.hermes/checkpoints/` (existiert nicht) | ⏭️ skip | nein | +| **Token-/Ersparnis-Statistik** | `~/.hermes/token_stats.json` | 📦 | **nein → Anhang B** | +| Dienst `hermes-gateway` (`:8642`) | systemd-User | ⬇️ | nein | +| Hermes-Terminal (ttyd → `hermes chat`, `:7681`) | systemd-User `hermes-terminal` | ⬇️ deploy.sh (+ttyd apt) | nein | + +### H · MCP-Server (4) +| Komponente | Ort | Quelle | Im Backup? | +|---|---|---|---| +| `mission-control-memory`, `-stack` (MC2-venv) | `~/mission-control-v2/mcp/*.py` | 🌐 Git | über config.yaml | +| `hermes-pc-control`, `hermes-web-fetch` (Hermes-venv) | dito | 🌐 Git | über config.yaml | +| MCP-Verdrahtung | `~/.hermes/config.yaml → mcp_servers` | 📦 | ja | + +### I · Browser-Stack +| Komponente | Ort | Quelle | Im Backup? | +|---|---|---|---| +| agent-browser (npm global) | `~/.local/...`, symlink `~/.hermes/node/bin` | ⬇️ npm i -g | nein | +| Chrome (engine) + System-Libs | `~/.agent-browser/browsers/` + apt-Libs | ⬇️ install --with-deps | nein | +| lightpanda (optional, leicht) | `~/.local/bin/lightpanda` | ⬇️ Download | nein | +| Browser-Verdrahtung (engine=chrome, toolset) | `~/.hermes/config.yaml` | 📦 | ja | + +### J · Modelle (GGUF — der große Brocken) +| Komponente | Ort | Quelle | Im Backup? | +|---|---|---|---| +| GGUF-Modelle (Brain, fast, heavy, coder, vision, embedding …) | `/srv/models/` | ⬇️ Re-Download aus llama-swap-Manifest | **nein (zu groß, bewusst)** | + +### K · Extern (anderer Rechner) +| Komponente | Ort | Quelle | Im Backup? | +|---|---|---|---| +| PC-Executor (Windows) | `client/hermes-pc/` → Scheduled Task | 🌐 Git + Task | n/a (anderer Host) | +| Hermes-WebUI (nesquena, optional, `:8787`) | `~/hermes-webui` | ⬇️ git clone | nein | + +--- + +## 4. Ziel-Architektur + +### 4.1 `deploy/bootstrap.sh` — orchestrierter From-Zero-Lauf +- **Idempotent & resumierbar** (Schritt-Marker in `~/.mc2-bootstrap.state`). +- **Getrennt nach sudo-Bedarf**: `bootstrap-root.sh` (L0+L1, bewusst mit sudo) + `bootstrap.sh` + (L2+, sudo-frei = Kern ist `deploy.sh`). Passt zum Nordstern „Runtime ohne sudo". +- **Mündet in den Wizard**: startet MC2 im First-Run-Modus, gibt Wizard-URL aus. + +Phasen: `0 Vorflug → 1[sudo] System+Dirs → 2[sudo] Engine+llama-swap → 3 Code(MC2+Hermes+Node) +→ 4 venvs(backend/mem0/voice/hermes) → 5 Browser → 6 deploy.sh(Units/enable/restart) +→ 7 Restore(optional) → 8 Wizard hoch + postcheck`. + +### 4.2 First-Run-Wizard (browserbasiert, von MC2 serviert) +MC2 erkennt unkonfigurierten Zustand → Frontend-Route `/setup` statt Dashboard. Schritte: + +1. **Systemcheck** — Live-Ampel je Komponente aus §3 (`GET /api/setup/status` + `…/system/services`). +2. **Restore-Quelle wählen** — Backup-Tarball erkennen → globaler Modus „Alles 1:1" / „selektiv" / „frisch". +3. **Komponenten-Auswahl (Kernstück)** — pro Katalog-Eintrag aus §3 eine Kachel mit + 📦/🆕/⏭️ (siehe §1). Zeigt Größe + ob Backup-Daten vorhanden. +4. **Netzwerk & Identität** — Box-IP (→ `HERMES_TERMINAL_URL`, `PC_EXECUTOR_URL`), Hostname. +5. **Secrets** 🔑 — `TELEGRAM_BOT_TOKEN`, erlaubte User-ID, `API_SERVER_KEY` (oder generieren), + ElevenLabs-Key → `~/.hermes/.env` (chmod 600). Bei 📦 vorbefüllt aus Backup. +6. **Hermes-Profil** — Brain-Alias + Toolset-Profil (Default = entfesselt: vision/tts/memory/browser + an, image_gen/video aus — siehe [[project-hermes-setup]]). Bei 📦 = exakte alte `config.yaml`. +7. **Avatar & Voice** — Avatar wählen (Default-VRM oder eigener), Stimme/Klonstimme + (📦 Referenz-Audio zurück, oder neu aufnehmen/hochladen). +8. **Modelle** — aus llama-swap-Manifest automatisch nachladen (`POST /api/models/install`, + Fortschritt `GET /api/jobs`) ODER geführte Discover-Neuauswahl. Reihenfolge: Brain → heavy → Rest. +9. **Externe Checkliste** — PC-Executor (Windows-Task), Hermes-WebUI als Haken. +10. **Verifikation & Abschluss** — `stack-postcheck.sh` + `hermes-postcheck.sh` → grün/rot-Liste → Dashboard. + +**Technik:** neuer Router `backend/routers/setup.py` +(`GET /api/setup/status`, `POST /api/setup/{secrets,network,hermes,components,finish}`). +First-Run-Gate: MC2 prüft beim Boot Marker `~/.mc2-setup-done` bzw. Pflicht-Secrets → leitet auf `/setup`. + +--- + +## 5. Backup-Scope für echtes 1:1 ERWEITERN (umzusetzen — Snippet in Anhang B) + +Der **aktuelle** `backup.sh` (live auf der Box, unverändert) reicht für „1:1" nicht. Für die Bau-Session +liegt das **fertige Erweiterungs-Snippet in Anhang B** — es ergänzt den Tarball um: + +- **Voice-Klonstimme** → `~/.voice/refs/` (`ref.wav`) +- **Token-/Ersparnis-Statistik** → `~/.hermes/token_stats.json` +- **Hermes-Skills** → `~/.hermes/skills/` (re-downloadbarer `.hub`-Cache per `tar --exclude` ausgelassen) +- **Hermes-Sessions/History** → `~/.hermes/sessions/` + +Restore soll skills/sessions **mergen** (frisch geladenen `.hub` nicht überschreiben) und `voice-service` +mit neu starten. + +**Offen bleibt:** eigene Avatare (sobald Upload existiert — Ablageort heute undefiniert, siehe §3·D). + +**Bewusst NICHT im Backup (re-downloadbar/rebuildbar):** Piper-Stimmen (install.sh), `.hub`-Skill-Cache, +`/srv/models/mc2-discover.json` (Cache), `/srv/models/mc2-memory.db` (Legacy-Migration), alle venvs, GGUF-Modelle. + +→ Aufgabe der Bau-Session: `backup.sh` + `restore.sh` um diese Pfade erweitern (mit klarer +„opt-in für große/optionale Teile"-Logik), und den MANIFEST-Inhalt entsprechend. + +--- + +## 6. Secrets-Strategie +- Single Source: `~/.hermes/.env` (chmod 600), im Tarball (selbst 600). +- Rebuild ohne Backup → Wizard-Schritt 5 erzeugt sie. `API_SERVER_KEY` generierbar; Telegram/ElevenLabs liefert Nutzer. +- Nie ins Git, nie in Logs, nie in die MC2-DB. **Off-Box-Spiegelung des Tarballs noch offen** ([[mc2-backup-restore]]). + +## 7. Modell-Strategie +- **A (empfohlen):** `/etc/llama-swap/config.yaml` (im Backup) listet alle Modelle → Wizard leitet Repos/Quants ab und lädt automatisch (`/api/models/install`). „Ein Klick, lädt über Nacht." +- **B:** geführte Discover-Neuauswahl je Rolle. Reihenfolge Brain → heavy → Rest, danach `warmup.sh`. + +--- + +## 8. Implementierungs-Reihenfolge (neue Session) +1. ✅ **Box-Verifikation erledigt (2026-06-28, nur gelesen — nichts verändert):** llama-swap.service-Inhalt + in **Anhang A**; skills/sessions/refs/token_stats existieren (Pfade in §3 verifiziert); Backup-Erweiterung + als fertiges Snippet in **Anhang B**. **Keine offenen Box-Fragen mehr** außer §10·3–6. → mit Schritt 2 starten. +2. `backup.sh`/`restore.sh` um die 1:1-Lücken erweitern (§5). +3. `deploy/bootstrap.sh` + `bootstrap-root.sh` (Phasen, State-Marker); llama-swap-Install skripten. +4. `backend/routers/setup.py` + First-Run-Gate. +5. Frontend `/setup`-Wizard (Schritte 1–10), Komponenten-Auswahl als Kernstück; bestehende Views + (Cockpit/AgentView/Sprechen) wiederverwenden. +6. Modell-Restore-aus-Manifest. +7. **Abnahme in frischer VM** (§9). + +Vorschlag: 2–4 zuerst (Skelett lauffähig), Wizard danach. Branch + PR. + +## 9. Abnahmekriterien +- Frisches Ubuntu 26.04 → `bootstrap-root.sh` + `bootstrap.sh` → laufender Stack, kein Spezialwissen. +- Postchecks grün; Telegram, Voice (inkl. Klonstimme bei 📦), 3D-Avatar, Browser funktionieren. +- „Alles 1:1" stellt mem0, Hermes-config.yaml, Secrets, Klonstimme, Skills exakt wieder her. +- Selektiver Modus: einzelne Komponenten ⏭️ überspringbar, Stack läuft trotzdem. +- Idempotenz: zweiter Lauf = No-op. + +## 10. Offene Entscheidungen (vor dem Bau) +1. ~~llama-swap systemd-Unit-Inhalt~~ → **geklärt: kompletter Unit in Anhang A** (in der Bau-Session anlegen). +2. ~~Voice-Referenz-Audio-Ort~~ → **geklärt: `~/.voice/refs/`** (Backup-Snippet in Anhang B, in der Bau-Session umsetzen). +3. **Eigene Avatare**: künftiger Upload-/Ablage-Mechanismus + Backup-Pfad (einziger offener 1:1-Daten-Punkt). +4. **Off-Box-Backup-Ziel** (NAS/2. Platte/Cloud) — [[mc2-backup-restore]]. +5. **Python 3.14** auf frischem Ubuntu beschaffen (deadsnakes?). +6. **Bootstrap-sudo-Modell**: getrenntes `bootstrap-root.sh` (empfohlen) vs. interaktives sudo. + +## 11. Referenzen +- `backend/config.py`, [[project-mc2-architecture]], [[project-stack-state]] +- [[project-hermes-setup]], `docs/HERMES_SETUP.md` (entfesseltes Profil, Browser, PC-Executor) +- [[voice-sprechen-feature]] (Voice + 3D-Avatar), [[mem0-memory-architecture]], [[mc2-backup-restore]] +- `deploy/{deploy,backup,restore,provision-engine,stack-postcheck,warmup}.sh`, `voice_service/install.sh` + +--- + +## Anhang A — `llama-swap.service` (1:1 von der Box abgegriffen, 2026-06-28) + +Base-Unit nach `/etc/systemd/system/llama-swap.service` (root). User/GFX sind boxspezifisch +(hitonabi, gfx1151 → HSA 11.5.1) — auf anderer Hardware anpassen. Die `.d/`-Drop-ins +(`vulkan.conf`, `warmup.conf`) legt `provision-engine.sh` an. + +```ini +[Unit] +Description=llama-swap (lokaler LLM Router) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=hitonabi +Environment=HSA_OVERRIDE_GFX_VERSION=11.5.1 +Environment=PATH=/usr/local/bin:/usr/bin:/bin +ExecStart=/usr/local/bin/llama-swap --config /etc/llama-swap/config.yaml --listen 0.0.0.0:8080 --watch-config +Restart=on-failure +RestartSec=3 + +[Install] +WantedBy=multi-user.target +``` +```ini +# /etc/systemd/system/llama-swap.service.d/vulkan.conf +[Service] +Environment=LD_LIBRARY_PATH=/opt/llamacpp-vulkan +``` +```ini +# /etc/systemd/system/llama-swap.service.d/warmup.conf +[Service] +ExecStartPost=-/usr/local/bin/llama-swap-warmup.sh +``` + +**Erstinstall-Reihenfolge:** `bash deploy/update-swap.sh` (Binary) → Unit kopieren → +`sudo bash deploy/provision-engine.sh` (Engine+Drop-ins) → `sudo systemctl enable --now llama-swap`. + +--- + +## Anhang B — Backup-Scope-Erweiterung für echtes 1:1 (fertiges Snippet) + +In `deploy/backup.sh` ergänzen (Variablen oben: `VOICE="${VOICE_HOME:-$HOME/.voice}"`, +Stage zusätzlich `"$STAGE/voice"`): + +```bash +# 1:1-Erweiterung (scan-verifiziert 2026-06-28): +[ -f "$HERMES/token_stats.json" ] && cp -a "$HERMES/token_stats.json" "$STAGE/hermes/" || true +[ -d "$HERMES/skills" ] && cp -a "$HERMES/skills" "$STAGE/hermes/skills" || true +[ -d "$HERMES/sessions" ] && cp -a "$HERMES/sessions" "$STAGE/hermes/sessions" || true +[ -d "$VOICE/refs" ] && cp -a "$VOICE/refs" "$STAGE/voice/refs" || true +``` +tar-Aufruf um den re-downloadbaren Skill-Cache erleichtern: +```bash +tar --exclude='./hermes/skills/.hub' -czf "$OUT" -C "$STAGE" . +``` +In `deploy/restore.sh` spiegelbildlich (skills/sessions **mergen**, nicht ersetzen) und +`voice-service` mit neustarten: +```bash +VOICE="${VOICE_HOME:-$HOME/.voice}" +SERVICES="mem0-service voice-service mission-control-2 hermes-gateway" +[ -f "$STAGE/hermes/token_stats.json" ] && cp -a "$STAGE/hermes/token_stats.json" "$HERMES/" +[ -d "$STAGE/hermes/skills" ] && { mkdir -p "$HERMES/skills"; cp -a "$STAGE/hermes/skills/." "$HERMES/skills/"; } +[ -d "$STAGE/hermes/sessions" ] && { mkdir -p "$HERMES/sessions"; cp -a "$STAGE/hermes/sessions/." "$HERMES/sessions/"; } +[ -d "$STAGE/voice/refs" ] && { mkdir -p "$VOICE/refs"; cp -a "$STAGE/voice/refs/." "$VOICE/refs/"; } +``` diff --git a/docs/LUCY_TTS_PLAN.md b/docs/LUCY_TTS_PLAN.md new file mode 100644 index 0000000..3cce642 --- /dev/null +++ b/docs/LUCY_TTS_PLAN.md @@ -0,0 +1,149 @@ +# Lucy TTS — Optimierungs- & Strategieplan + +> Ziel: **Lucys Stimme läuft 100 % lokal & on-device** (kein Box-Zwang, keine Cloud). +> Primärengine: **Kyutai pocket-tts 2.1.0** (CPU). Strategische Alternative: **F5-TTS** (GPU/ONNX). +> Stand: 2026-06-30. Resume-fähig im Stil von `docs/STATUS.md`. + +## Leitentscheidung: Hardware +- **pocket-tts ist CPU-gebunden** — Kyutai bestätigt: *kein* GPU-Speedup (Batch 1, 100M Params). + → **RDNA2 vs. RDNA4 ist für pocket irrelevant.** Lucy läuft dort, wo der beste CPU steht. +- **GPU zählt nur für F5-TTS** (non-autoregressiv, große Matmuls). Dort gewinnt **RDNA4 (9070 XT) + DirectML** + deutlich gegen RDNA2 → falls F5 die Lucy-Stimme wird, läuft sie auf der RDNA4-Maschine. +- **Konsequenz:** `oute n_gpu_layers=999` und „pocket auf ROCm/Vulkan" werden **eingestellt**. + +--- + +## Phase A — Sofort-Wins (risikoarm, pocket_server.py) + +**A1 — Voice → safetensors exportieren (einmalig)** +- Statt `get_state_for_audio_prompt(ref)` bei jedem Boot: einmal `export_model_state(...)` → `lucy_voice.safetensors`. +- Server lädt beim Start nur noch die safetensors (liest kvcache, keine Klon-Rechnung) → schnellerer Start. +- Fallback behalten: wenn safetensors fehlt → aus `ref.mp3` klonen + direkt exportieren. + +**A2 — Referenz säubern** +- Kyutai: Sample-Qualität wird *mitreproduziert*. Sauber entrauschte/normalisierte `ref` → weniger Artefakte. +- Schritt in `_prep_ref()` ergänzen (Denoise/Highpass/Lautheit), Ergebnis cachen. + +**A3 — temp-Sweep gegen Kollaps** +- Hypothese: `temp=0.9` treibt die best-of-N-Regenerationen. Niedriger testen (0.7–0.85). +- Akzeptanz: gleiche/bessere Natürlichkeit bei **messbar weniger Regenerationen** (= weniger Latenz). + +*Gate A:* A1–A3 live, Kollaps-Rate & TTFB protokolliert. + +--- + +## Phase B — Benchmark-Harness (datenbasiert tunen) + +**B1 — `bench_lucy.py`** (lokal, CPU) +- Misst je Konfig: **RTF**, **TTFB**, **Kollaps-/Regenerations-Rate**, Whisper-Rücktranskription (Verständlichkeit). +- Sweep-Achsen: `lsd_decode_steps` (6/8/10/12), `temp`, `noise_clamp`, `quantize` on/off, `frames_after_eos`. +- Feste Testsätze (kurz/mittel/lang, wie in `ptts_test.py`). + +**B2 — CPU-Parallelität** +- pocket nutzt nur **2 Kerne** → mehrere **Satz-Worker parallel** statt globalem `LOCK`. +- Messen: Wall-Clock langer Antworten bei N Workern (1/2/3/4) vs. Qualität/Last. + +*Gate B:* dokumentierte Best-Config (RTF + Kollaps-Rate) als neue Defaults in `pocket_server.py`. + +--- + +## Phase C — Runtime-Eval (lokal schneller + Python-3.14-frei) + +**C1 — ONNX-Pfade testen** +- Kandidaten: **PocketTTS.cpp** (Single-File C++/ONNX, CLI+HTTP+FFI) und **sherpa-onnx** (Windows, viele Bindings). +- Ziel: torch-CPU schlagen **und** das Python-3.14-Packaging-Problem umgehen. +- Vergleich gegen Phase-B-Baseline (gleicher Benchmark). + +**C2 — Server-Vertrag prüfen** +- Fertige **OpenAI-kompatible Streaming-Server** (teddybear082 / ai-joe-git) gegen den aktuellen Custom-Proxy halten. +- Nur übernehmen, wenn Stimm-Wächter (F0 + Fingerabdruck) erhalten/abbildbar bleiben. + +*Gate C:* Entscheidung „torch-CPU behalten" vs. „auf ONNX-Runtime wechseln" (mit Zahlen). + +--- + +## Phase D — Strategische Weiche: pocket vs. F5 + +**D1 — F5 fair gegen pocket messen** +- `lucy-f5/` (F5-TTS DE, ONNX + DirectML, **RDNA4/9070 XT**) ist **non-autoregressiv → strukturell kein + Kollaps/Männerstimme/Wiederholung** (genau pockets Schmerz). +- Gleicher Benchmark wie Phase B: RTF, TTFB, Natürlichkeit, Stabilität. + +**D2 — Entscheidung** +- **pocket gewinnt** (gut genug stabil, CPU, „nur lokal"-Ideal): pocket = Lucy-Stimme, F5 verworfen/geparkt. +- **F5 gewinnt** (Stabilität schlägt den Latenz-Overhead der Wächter): F5 = Lucy-Stimme auf RDNA4, + **pocket bleibt schneller CPU-Fallback** (z. B. wenn keine GPU verfügbar). + +**Beobachtungsposten (extern):** distilliertes **`german`** (statt `german_24l`) ist noch nicht released +(Kyutai fixt Distillations-Datenqualität). Sobald da → größter Einzel-Win (Tempo + Stabilität), +dann `german_24l → german` swappen. Release-Feed im Blick behalten. + +--- + +## Reihenfolge & Quick-Start +1. **A1 + A2 + A3** (heute) — sofort spürbar, kein Risiko. +2. **B1 + B2** — Zahlen sammeln, Defaults härten. +3. **C1/C2** — Runtime-Wechsel nur wenn Benchmark es trägt. +4. **D1/D2** — finale Stimm-Architektur entscheiden. + +## Mess-Ergebnisse & finale Defaults (30.06., 9700X, german_24l) + +Alles auf der lokalen Maschine gemessen (Logs: `sweep_b2.log`, `ttfb_test.log`, `sweep_b2_result.json`). + +**B2-Sweep (6-Satz-Antwort, ~21s Audio):** + +| Konfig | Wall | TTFB | RTF | +|---|---|---|---| +| seriell (1×alle Kerne) | 15,8s | **3,6s** | 0,74 | +| 2w×3t | 12,9s | 6,2s | 0,62 | +| 3w×2t | 10,3s | 6,8s | 0,50 | +| 4w×2t | 9,7s | 8,2s | **0,44** | + +Erkenntnis: pocket ist **speicherbandbreiten-gebunden**. Der Pool verbessert nur die Gesamt-Wall-Clock +(Batch), verschlechtert aber die **TTFB** deutlich. Seriell liefert RTF 0,74 < 1 → generiert schneller +als Echtzeit → Streaming spielt **lückenlos** und startet am schnellsten. **Für Lucys Live-Stimme +gewinnt seriell.** Pool bleibt Opt-in für Batch (`/tts` ganze Datei): Sweet Spot **4w×2t** / **3w×2t**. + +**B3 (FP-Drift-Gate überspringt kurze Audios) + kurzer erster Chunk:** +Der MFCC-Fingerabdruck ist auf <2s Audio unzuverlässig (sim ~0,84 < 0,94) → löste 3× Fehlalarm- +Regenerierung aus. B3 prüft den Drift erst ab `LUCY_FP_MIN_S=2.0`s stimmhafter Dauer; der F0- +Männerstimmen-Wächter bleibt immer aktiv. Effekt (Drift-Warnungen pro Lauf: ~6 → 1): + +| | TTFB | Wall | +|---|---|---| +| kurzer 1. Chunk, ohne B3 | 4,71s | 19,9s | +| gebündelt (alt) | 3,74s | 15,8s | +| **kurzer 1. Chunk, mit B3** | **1,31s** | 16,6s | + +→ Lucy spricht nach **1,3s** statt 3,7s, Wall ~gleich, weiter lückenlos. + +**Finale Defaults in `pocket_server.py`:** +`LUCY_WORKERS=0` (seriell) · `LUCY_FAST_FIRST=1` (kurzer 1. Chunk) · `LUCY_FP_MIN_S=2.0` (B3) · +`LUCY_REF_CLEAN=1` (A2) · Voice aus `lucy_voice.safetensors` (A1). Pool-Opt-in für Batch: +`LUCY_WORKERS=4 LUCY_WORKER_THREADS=2`. + +**Offen / nächster Hebel:** distilliertes `german`-Modell (statt `german_24l`) abwarten — größter +Qualität/Tempo-Sprung. Optional: TTFB weiter drücken über kürzeres erstes Wort / `lsd`-Tuning nur +für den ersten Chunk. + +## Umlaute (ae/oe/ue) — Fix (30.06.) + +Symptom: Lucy spricht manchmal „u-e" statt „ü". Ursache: das LLM (Hermes/Qwen) gibt gelegentlich +ASCII-Ersatzschreibweisen (ueber/schoen/maerz) aus; pocket liest sie wörtlich. (ß vs ss ist +akustisch identisch -> ignoriert.) + +**Wurzel-Fix (empfohlen, auf der Box im Hermes-System-Prompt/Persona ergänzen):** +> „Schreibe ausschließlich korrektes Deutsch mit echten Umlauten (ä, ö, ü) und ß. Verwende niemals +> die Ersatzschreibweisen ae, oe, ue oder ss anstelle von Umlauten." + +**Schutznetz (in `pocket_server.py`, Default an `LUCY_UMLAUT_FIX=1`):** `_fix_umlauts()` wandelt NUR +bekannte deutsche Umlaut-Ganzwörter zurück (Ganzwort + gängige Flexionsendungen, case-erhaltend). +Verifiziert (`umlaut_test.py`): konvertiert über/für/größe/natürlich/mögliche/Gespräche; lässt +neue/aktuell/Steuer/Quelle/Feuer/Frauen/genau/blaue unverändert. Grenzen: reine Wortliste, deckt +nicht jedes seltene Wort — erweiterbar via `LUCY_UMLAUT_EXTRA="wort1,wort2"`. Der Wurzel-Fix bleibt +die zuverlässige Lösung. + +## Referenzen +- pocket-tts README (GPU-kein-Speedup, export-voice, Sprachen): github.com/kyutai-labs/pocket-tts +- Multilingual-Ankündigung (DE = `german_24l`, undistilliert): kyutai.org/blog/2026-05-04-pocket-tts-multilingual +- Tech-Report / Performance: kyutai.org/blog/2026-01-13-pocket-tts · deepwiki.com/kyutai-labs/pocket-tts diff --git a/docs/REVIEW_2026-07-02.md b/docs/REVIEW_2026-07-02.md new file mode 100644 index 0000000..9dd84ba --- /dev/null +++ b/docs/REVIEW_2026-07-02.md @@ -0,0 +1,221 @@ +# Komplett-Review Mission Control 2 + Lucy — 02.07.2026 + +**Methodik:** IST-Zustand live erhoben (Box per SSH, lokaler Lucy-PC, Working Tree `lucy-v2` inkl. uncommitted) — nicht aus Docs/Memory übernommen. SOLL-Zustand in 3 Recherche-Runden tagesaktuell (Stand 02.07.2026) ermittelt. Alle früheren Verdikte wurden neu auf den Prüfstand gestellt. Scope: alles außer Security. + +--- + +## 1. Management-Summary + +| Bereich | Zustand | Kernaussage | +|---|---|---| +| LLM-Stack (Box) | ✅ stark, 1 Bug | Vulkan-Pfad richtig, Qwen3.6+MTP läuft; aber chat-Lane kaputt (Autostart-Fund war Fehlalarm) | +| Lucy Voice-Latenz | 🔴 3,5–5 s | 2026-Ziel ist 0,5–0,8 s. Schuld sind STT (2,0 s) und VAD-Timer (0,9 s), **nicht** das LLM (TTFT 65 ms) | +| Lucy Avatar/App | ✅ sehr ausgereift | VRMA-Mocap, Lippensync v2, MateEngine-Features komplett; Electron 10 Major-Versionen alt | +| Backend/Frontend-Code | 🟡 solide | 3 Monolithen, etwas DRY-Schuld, dist/ im Git; keine Rot-Flaggen | +| Ökosystem-Aktualität | 🟡 | Hermes 1 Release hinter (v0.18.0 vom 01.07.); pocket-tts, mem0, llama-swap, three-vrm aktuell | +| Verdikte | ✅ alle bestätigt | Pocket TTS, Electron, Qwen3.6-Hirn, kein ZeroClaw, Mem0 — alle bestehen die Re-Prüfung | + +**Die zwei größten Hebel:** +1. **STT-Tausch** (faster-whisper medium → Parakeet-TDT 0.6B v3): ~2,0 s → ~0,2 s pro Äußerung +2. **VAD-Tausch** (RMS-Eigenbau → Silero VAD v6.2): Turn-Ende 900 → ~450 ms bei besserer Genauigkeit + +Zusammen: Voice-to-Voice von ~3,5–5 s auf realistisch **≤1,2 s**, ohne neue Hardware. + +--- + +## 2. IST-Zustand (live verifiziert) + +### 2.1 Box (192.168.178.151 — Strix Halo, gfx1151, 122 GB, Vulkan) + +| Komponente | Installiert | Aktuell (02.07.2026) | Bewertung | +|---|---|---|---| +| llama.cpp | b9843 (86b94708f) | b9859 (01.07.) | ✅ nur ~16 Builds dahinter | +| llama-swap | v233 (29.06.) | v233 | ✅ aktuell | +| Hermes Agent | **v0.17.0** (19.06.) | **v0.18.0** (01.07.) | 🟡 Update lohnt (3 P0 + 493 P1 gefixt) | +| mem0ai / chromadb | 2.0.8 / 1.5.9 | 2.0.8 | ✅ aktuell | +| Kernel | 7.0.0-27-generic | — | ✅ | + +**Live-Modell-Lineup** (`/etc/llama-swap/config.yaml`, live gelesen — der Repo-Snapshot `deploy/llama-swap.config.yaml` ist **veraltet** und zeigt noch gemma-4): + +| Alias | Modell | ctx | Besonderheiten | +|---|---|---|---| +| hermes (Brain) | Qwen3.6-35B-A3B (UD-Q4_K_M, MTP-GGUF) | 65536 | `--spec-type draft-mtp --spec-draft-n-max 3 --parallel 1 -cram 16384`, **kein** cache-reuse | +| heavy | Qwen3.5-122B-A10B | 32768 | cache-reuse 256, ttl 600 | +| coder | Qwen3-Coder-Next | 131072 | cache-reuse 256, ttl 600 | +| coder-lite | Qwen3-Coder-30B-A3B | 131072 | cache-reuse 256, ttl 300 | +| vision | Qwen3-VL-8B | 32768 | mmproj, in brains | +| embed | Qwen3-Embedding-0.6B | 8192 | ttl 0, in brains | +| scout | GLM-4.6V-Flash | 131072 | mmproj, ttl 300 | + +Gruppe `brains` (swap:false, persist:true) = embed + vision + Qwen3.6. Alle Modelle: `-ngl 999 -fa on --no-mmap --jinja`. **Kein Modell nutzt KV-Cache-Quantisierung** (alles F16). + +**Dienste live:** llama-swap, hermes-gateway, hermes-terminal, hermes-webui, mem0-service, voice-service — alle running. Ports 7681/8080/8642/8650/8765/8787/9001 belegt. + +### 2.2 🔴 Live-Bugs (selbst reproduziert) + +**B1 — ~~MC2-Backend ohne Autostart~~ FEHLALARM (korrigiert 02.07., nachverifiziert).** +:9001 läuft als **User-Unit** `mission-control-2.service` (`~/.config/systemd/user/`, enabled, `Linger=yes` → reboot-fest). Die erste SSH-Prüfung sah User-Units nicht (fehlendes XDG_RUNTIME_DIR). Einziger echter Fund: Die **stale v1-System-Unit** `mission-control.service` (disabled, /opt/mission-control:9000) liegt noch in /etc/systemd/system und stiftet Verwirrung → bei Gelegenheit mit sudo entfernen (kosmetisch, kein Risiko). + +**B2 — chat-Lane kaputt (live reproduziert).** +``` +POST /v1/chat/completions {"model":"chat",...} +→ {"error":"no router for requested model","src":"llama-swap"} +``` +Die Routing-Policy routet `chat → fast ↔ heavy`, aber llama-swap kennt den Alias `fast` nicht mehr (Qwen3.6 hat nur noch den Alias `hermes`). Lucy ist nicht betroffen (sie geht über den Hermes-Agenten :8642), aber jeder Client der chat-Lane bekommt Fehler. Fix: `fast` als zweiten Alias eintragen **oder** Policy auf `hermes` umstellen. + +**B3 — Config-Drift.** +`deploy/llama-swap.config.yaml` ist untracked UND veraltet (gemma-4-Ära). Zusätzlich fehlen im Install-Template [`backend/config.py:33`](../backend/config.py) die Produktions-Tunings (cache-reuse, parallel, MTP) → neu installierte Modelle driften von der Box-Realität weg. + +### 2.3 Gemessene Latenzkette Lucy + +Quelle: `/api/voice/metrics` (live) + eigener TTFT-Test gegen llama-swap. + +| Stufe | Messwert | Anteil am Problem | +|---|---|---| +| VAD-Turn-Ende | **900 ms** Fix-Timer (RMS-Eigenbau, [useVAD.ts](../client/lucy-desktop/src/renderer/src/lib/voice/useVAD.ts)) | groß | +| STT (faster-whisper medium int8, Box-CPU) | **avg 2.046 ms · p50 2.092 ms · p95 2.529 ms** (n=13) | **dominant** | +| LLM TTFT (Qwen3.6 warm, direkt :8080) | **65 ms** (24 Tokens in 334 ms) | ✅ kein Problem | +| TTS erster Ton (pocket, RTF 0,44 + LEAD_IN 0,35 s) | ~0,5–1 s für den ersten Satz | mittel | +| **Voice-to-Voice gesamt** | **~3,5–5 s** | Ziel 2026: **0,5–0,8 s** | + +**Fazit: Das teuerste Glied ist NICHT das LLM.** STT + VAD-Timer fressen zusammen ~3 s. Genau dort setzt die Roadmap an. + +### 2.4 Lokaler PC (RX 9070 XT / RDNA4) + +- Lucy-App zum Prüfzeitpunkt nicht gestartet (kein Electron-Prozess, :8130 frei) +- `ptts-venv`: pocket-tts **2.1.0** (= neueste Version), torch 2.12.1+cpu (bewusst CPU), onnxruntime 1.27.0, fastapi 0.138.1 +- GPU-Treiber 32.0.31021.5001 +- [client/lucy-tts/](../client/lucy-tts/) (3 GB): Produktions-TTS mit Stimmen-Wächter (F0-Floor 160 Hz, MFCC-Fingerprint ≥0,94, Best-of-N), Phase A+B des TTS-Plans abgeschlossen (beste Config: 4 Worker × 2 Threads, RTF 0,44) +- [client/lucy-f5/](../client/lucy-f5/) (5,3 GB): F5-TTS-ONNX/DirectML-Experiment — **Phase C/D (Finalentscheid pocket vs. F5) offen** +- Lucy-Desktop: Electron **33** (aktuell: **43** vom 30.06. — 2 Jahre Chromium-Rückstand), three-vrm 3.4/animation 3.5.4 (≈ aktuell), TS strict + +### 2.5 Code-Qualität (3 Explore-Agents über das ganze Repo) + +**Backend (4.889 LOC, 11 Router / 28 Services):** insgesamt sauber, Multi-Sidecar-Architektur durchdacht. Findings: +- C1: Install-Template ohne Produktions-Tunings ([backend/config.py:33](../backend/config.py)) → Drift +- C2: `_describe_images()` blockiert den Voice-Chat bis 120 s synchron ([backend/routers/voice.py](../backend/routers/voice.py)) +- C3: Thinking-Deaktivierung 3× dupliziert (voice.py, gateway.py, mem0_service/app.py) — DRY +- C4: Junk-Fact-Regex im Mem0-Sidecar hartcodiert (Wartungspunkt) +- Dead Code: `backend/services/pricing.py`, vermutlich `token_stats.py` +- Uncommitted Änderungen (voice.py No-Think, connect.py IDE-only-`coding`, mc2-memory-Guards, Mem0-Junk-Guard, voice_service install.sh) sind **alle konsistent und sinnvoll** — nur eben nicht committet + +**Frontend (React 18/Vite 6/Tailwind 4/TanStack 5):** +- Voice-Umzug in die Desktop-App sauber (keine toten Imports/Nav-Reste) ✅ +- UI-Rework (roleMeta/Health/Expert/WarmSet) vollständig; coder_lite↔coder-lite via ALIAS gelöst +- F1: [Cockpit.tsx](../frontend/src/views/models/Cockpit.tsx) (990 Z) + [SystemDrawer.tsx](../frontend/src/components/SystemDrawer.tsx) (934 Z) Monolithen +- F2: 🟡 `frontend/dist/`-Asset-Stand auf lucy-v2 inkonsistent (alte gelöscht, neue untracked) — dist-im-Git selbst ist Absicht (Box hat kein Node), avatar.vrm ist via .gitignore korrekt draußen +- F4: keine globale Error Boundary +- MC3-Prototyp ([frontend/src/mc3/](../frontend/src/mc3/)) non-destruktiv hinter `#mc3`, untracked + +**Lucy-Desktop:** +- L1: [useVoiceAgent.ts](../client/lucy-desktop/src/renderer/src/lib/voice/useVoiceAgent.ts) (377 Z) monolithisch (SSE, Chunking, Tools, Perf, Vision in einem Hook) +- L2: kein Retry/Backoff beim TTS-Warmup (Crash → 2-min-Spinner) +- L3: VAD = reines RMS mit 900-ms-Stille-Regel +- L4: Echo-Schutz = 450-ms-Cooldown-Workaround (kein echtes Barge-in) +- Neues [voice-core/](../client/lucy-desktop/src/renderer/src/voice-core/)-Adapter-Layer (STT/TTS austauschbar) ist die richtige Architektur ✅ +- H1: ~23 Dateien uncommitted, darunter die neue voice-core-Architektur → Verlustrisiko + +--- + +## 3. SOLL-Zustand (Recherche, Stand 02.07.2026) + +### 3.1 Voice-Latenz — der Stand der Technik + +- 2026-Zielmarke: **500–800 ms voice-to-voice**; Grundprinzip: **Streaming auf jeder Stufe** (STT-Partials sparen 200–400 ms, TTS startet auf Teiltext, VAD+Turn-Taking-Budget 150–300 ms) — [Latenz-Guide](https://futureagi.com/blog/how-to-optimize-voice-agent-latency-2026/), [Latenz-Budget-Design](https://smallest.ai/blog/designing-voice-assistants-stt-llm-tts-tools-and-latency-budget) +- **STT:** [Parakeet-TDT 0.6B v3](https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3) — 25 EU-Sprachen inkl. Deutsch, 6,32 % WER (besser als Whisper large-v3 mit 7,44 %), extrem schnell auch auf CPU, keine Silence-Halluzination. Deploy-Wege: [onnx-asr](https://pypi.org/project/onnx-asr/) (unterstützt CPU **und** DirectML → 9070 XT), fertige [OpenAI-kompatible FastAPI-Wrapper](https://github.com/groxaxo/parakeet-tdt-0.6b-v3-fastapi-openai). Kyutais Streaming-STT mit eingebautem semantic VAD ([delayed-streams-modeling](https://github.com/kyutai-labs/delayed-streams-modeling)) wäre architektonisch ideal, ist aber **nur EN/FR** → für Deutsch raus. +- **VAD:** [Silero VAD v6](https://github.com/snakers4/silero-vad/releases/tag/v6.0) (v6.2, ONNX): −16 % Fehler auf Noisy-Data vs. v5 — klar besser als der RMS-Eigenbau; erlaubt kürzeres Endpointing (~450 ms) bei weniger Fehlstarts. +- **Semantische Turn-Detection:** Smart Turn V2 (leichtgewichtig), [Easy Turn](https://arxiv.org/pdf/2509.23938) (akustisch+linguistisch, 4 Turn-States, open source). +- **TTS:** pocket-tts 2.1.0 ist Stand der Technik für CPU-Realtime ([kyutai](https://kyutai.org/blog/2026-01-13-pocket-tts/)). Challenger (CosyVoice2-0.5B, Chatterbox-Turbo) bieten keinen klaren Vorteil. → Einziger offener Entscheid bleibt das hauseigene F5-Experiment (Phase C/D). + +### 3.2 Box maximieren + +- **Vulkan/RADV bleibt der schnellste Pfad auf Strix Halo** (schlägt ROCm/HIP bei pp und tg) — die Box ist richtig aufgestellt ([llm-tracker Strix-Halo](https://llm-tracker.info/_TOORG/Strix-Halo), [Strix-Halo-Guide](https://github.com/hogeheer499-commits/strix-halo-guide)). ROCm 7.2/RDNA4 betrifft nur den lokalen PC. +- **Host-Memory-Prompt-Cache:** `--cache-ram` + Prefix-Restore bringt bis **93 % TTFT-Reduktion** bei Agent-Workloads mit wachsender Session ([llama.cpp #20574](https://github.com/ggml-org/llama.cpp/discussions/20574)). `-cram 16384` ist gesetzt; das Zusammenspiel mit dem (am hermes-Alias entfernten) `--cache-reuse` gehört gebencht. +- **KV-Cache-Quantisierung ungenutzt:** `-ctk/-ctv q8_0` halbiert den KV-Bedarf (relevant bei coder@131k, hermes@65k) bei praktisch verlustfreier Qualität; [TurboQuant](https://github.com/ggml-org/llama.cpp/discussions/20969) (3-bit, near-lossless ab 13B) steht vor der Integration — beobachten. +- **„MoE Speculative Trap":** Ein aktueller [Strix-Halo-Deep-Dive](https://dev.to/agustinsacco/breaking-the-moe-speculative-trap-460-ts-on-amd-strix-halo-446d) zu exakt Qwen3.6-35B-A3B zeigt: Spec-Verify kann bei sparsem MoE pro Verify-Pass fast alle 35B Gewichte anfassen — in seinem Setup war **ohne** Draft (parallel=1, KV Q8_0) 43,1 t/s vs. 17,7 t/s. Das widerspricht der eigenen Box-Messung (+35 % MIT MTP). Konsequenz: **beide Betriebsarten benchen**, auch bei vollem Kontext ([Decode-Drop bis 64 % dokumentiert](https://kmarble.dev/posts/strix-halo-full-context-decode-drops/)). +- **llama-swap-Features ungenutzt:** `capabilities` (v225), `-config-dir`-Fragmente (v230), Swap-Matrix/Groups V2 ([Releases](https://github.com/mostlygeek/llama-swap/releases)). +- Modell-Landschaft 128 GB für heavy-Kandidaten: gpt-oss-120B, Mistral Small 4 (119B-A6B), Llama 4 Scout — nur mit Bench-Gate. + +### 3.3 Ökosystem + +- **Hermes v0.18.0 „Judgment"** (01.07.): 3 P0 + 493 P1 gefixt, Background-Fan-out für Subagents, `/learn`-Skills, Memory-Graph in der Desktop-App ([Releases](https://github.com/NousResearch/hermes-agent/releases)). **Plugin-API:** `sync_turn()` bekommt optional `messages` (voller Turn-Kontext inkl. Tool-Calls); Legacy-Signatur bleibt → **mc2-memory ist update-kompatibel** und kann später Tool-Ergebnisse mitlernen ([Memory-Provider-Doku](https://hermes-agent.nousresearch.com/docs/developer-guide/memory-provider-plugin)). +- **Mem0 v3-Algorithmus** ([Migration](https://docs.mem0.ai/migration/oss-v2-to-v3)): Single-Pass-Extraktion (~2× schneller), Hybrid-Retrieval (semantisch + BM25 + Entity-Graph, ohne externe Graph-DB), +20 LoCoMo / +26 LongMemEval. 2.0.8 installiert, `custom_instructions` schon migriert → Status final verifizieren. +- **Electron 43** (30.06.), Chromium 150 / Node 24 — Lucy ist auf 33. +- **Vision:** Qwen3-VL ist aktuelle Generation ✅; [Qwen3-VL-30B-A3B](https://github.com/qwenlm/qwen3-vl) (MoE, 3B aktiv, top auf GUI-Benchmarks) wäre der Upgrade-Kandidat für die Bildschirm-Sicht. +- **Lokaler GPU-Klon:** [AMD Lemonade](https://runaihome.com/blog/amd-lemonade-local-llm-server-npu-gpu-guide-2026/) (llama.cpp-Vulkan + whisper.cpp + Kokoro, OpenAI-kompatibel, RDNA4-Support) als fertiger Unterbau; llama.cpp-Vulkan ist der [verlässlichste 9070-XT-Pfad](https://digtvbg.com/blog/llama-server-vulkan-rdna4-vllm-rocm-benchmark/). + +### 3.4 Verdikte — Ergebnis der Re-Prüfung + +| Verdikt | Ergebnis | Begründung | +|---|---|---| +| Pocket TTS bleibt | ✅ **bestätigt** | 2.1.0 aktuell, RTF 0,44 optimiert, Wächter-System; Challenger ohne klaren Vorteil. F5-Entscheid (Phase C/D) bleibt als einziger offener Punkt | +| Electron bleibt (nicht Tauri) | ✅ **bestätigt** | Alle nativen Features implementiert; aber Major-Update 33→43 einplanen | +| Qwen3.6 als Lucy-Hirn | ✅ **live bestätigt** | Läuft mit MTP, TTFT 65 ms; gemma-4 ist komplett raus | +| ZeroClaw bleibt tot | ✅ **bestätigt** | Kein neuer Anlass | +| Mem0 als Memory-Layer | ✅ **bestätigt** (neu geprüft) | Zep/Hindsight benchen höher, sind aber schwerer/teils closed; Mem0: beste Integration, v3-Algo, deployt | + +--- + +## 4. Roadmap (Aufwand/Nutzen, Voice-Speed-first) + +### P0 — Live-Bugs & Betriebssicherheit (Stunden) +| # | Maßnahme | Nutzen | +|---|---|---| +| 1 | ~~Autostart fixen~~ **erledigt als Fehlalarm** — User-Unit `mission-control-2` mit Linger ist reboot-fest; nur stale v1-Unit bei Gelegenheit löschen (sudo) | Klarheit | +| 2 | chat-Lane fixen (`fast`-Alias ergänzen oder Policy auf `hermes`) | Live-Bug, alle chat-Clients betroffen | +| 3 | Box-Config → Repo syncen + `deploy/` versionieren; Template-Drift C1 fixen | Quelle der Wahrheit | +| 4 | Hermes v0.17.0 → v0.18.0 + Health-Brain-Check | 496 Upstream-Fixes | +| 5 | Commit-Hygiene (voice-core, MC3, Lucy-Fixes); `frontend/dist/` in .gitignore | Verlustrisiko weg | + +### P1 — Voice-Latenz: 3,5–5 s → Ziel ≤1,2 s (Tage) +| # | Maßnahme | Erwartung | +|---|---|---| +| 6 | **STT-Tausch**: Parakeet-TDT 0.6B v3 statt faster-whisper medium. Variante A: Box-CPU (onnx-asr im voice_service); Variante B: lokal 9070 XT (DirectML). A/B: Deutsch-WER + Latenz | **~2,0 s → ~0,2 s** | +| 7 | **VAD-Tausch**: Silero VAD v6.2 (ONNX) statt RMS in useVAD.ts; Endpointing 900 → ~450 ms | **−450 ms** | +| 8 | TTS-TTFA: LEAD_IN 0,35 s prüfen, Erster-Satz-kurz-Regel messen (lucy_perf) | −100–300 ms | +| 9 | **Brain-Bench-Matrix** am hermes-Alias: MTP n-max 3↔4↔ohne (Speculative-Trap-These) × ±KV Q8_0 × cache-reuse/cram × -b/-ub — bei Kurz- UND Voll-Kontext | Bestes Setup evidenzbasiert | +| 10 | voice_metrics ausbauen: VAD→STT→Agent→First-Audio je Turn | Messbarkeit | +| 10b | KV Q8_0 für coder@131k/heavy erwägen | Warm-Set-Reserve | + +### P2 — Lucy v2 Kern & Code-Gesundheit (1–2 Wochen) +| # | Maßnahme | +|---|---| +| 11 | Semantische Turn-Detection (Smart Turn V2 / Easy Turn) auf Parakeet aufsetzen; Barge-in-Vorstufe statt 450-ms-Cooldown | +| 12 | F5-TTS Phase C/D abschließen → Finalentscheid pocket vs. F5 (Benchmark-Gate) | +| 13 | useVoiceAgent-Refactor in Hooks + TTS-Retry/Backoff; Electron 33→43 | +| 14 | Backend C2 (Vision async) + C3 (DRY) + Dead Code; Frontend Cockpit/SystemDrawer-Split + globale Error Boundary | + +### P3 — Strategisch (nach Signal) +| # | Maßnahme | +|---|---| +| 15 | Mem0-v3-Status final verifizieren; Junk-Regex durch v3-Retrieval entschärfen; mc2-memory auf `sync_turn(messages)` heben | +| 16 | MC3-Vollbau; llama-swap-Features (capabilities, config-dir, Swap-Matrix) | +| 17 | heavy-Bench: Qwen3.5-122B vs. gpt-oss-120B / Mistral Small 4; Vision-Upgrade Qwen3-VL-30B-A3B für Bildschirm-Sicht | +| 18 | Lokaler GPU-Klon: AMD Lemonade auf der 9070 XT evaluieren | + +--- + +## 5. Findings-Katalog (Referenz) + +| ID | Schwere | Fund | Ort | +|---|---|---|---| +| B1 | ⚪ (Fehlalarm) | :9001 läuft als User-Unit mit Linger — reboot-fest; nur stale v1-Unit als Kosmetik-Rest | Box, /etc/systemd/system/mission-control.service (v1) | +| B2 | 🔴 | chat-Lane → fast-Alias existiert nicht mehr | Box, Routing-Policy ↔ /etc/llama-swap/config.yaml | +| B3 | 🟡 | deploy/llama-swap.config.yaml untracked + veraltet | Repo | +| C1 | 🟡 | Install-Template ohne Produktions-Tunings | backend/config.py:33 | +| C2 | 🟡 | Vision-Beschreibung blockiert Chat bis 120 s | backend/routers/voice.py | +| C3 | 🟢 | Thinking-Disable 3× dupliziert | voice.py / gateway.py / mem0_service/app.py | +| C4 | 🟢 | Junk-Fact-Regex hartcodiert | mem0_service/app.py | +| C5 | 🟢 | Dead Code | backend/services/pricing.py, token_stats.py | +| F1 | 🟡 | Monolithen 990/934 Z | frontend/src/views/models/Cockpit.tsx, components/SystemDrawer.tsx | +| F2 | 🟡 (korrigiert) | dist/ im Git ist ABSICHT (Box hat kein Node, deploy = git reset --hard; s. deploy/build.sh) — echter Fund war nur der inkonsistente Asset-Stand auf lucy-v2 (behoben durch Rebuild+Commit). Build-on-Box/CI wäre P3-Option | frontend/dist/ | +| F4 | 🟢 | Keine globale Error Boundary | frontend/src/App.tsx | +| L1 | 🟡 | useVoiceAgent monolithisch (377 Z) | client/lucy-desktop/.../lib/voice/useVoiceAgent.ts | +| L2 | 🟡 | Kein TTS-Warmup-Retry | ebd. + main/index.ts | +| L3 | 🔴 | RMS-VAD mit 900-ms-Timer | client/lucy-desktop/.../lib/voice/useVAD.ts | +| L4 | 🟡 | Echo-Cooldown statt Barge-in | ebd. | +| H1 | 🟡 | ~23 Dateien uncommitted (inkl. voice-core, MC3) | lucy-v2 Working Tree | + +--- + +*Erhoben am 02.07.2026 durch Claude Code (Live-SSH auf Box, lokale PC-Prüfung, 3 Codebase-Agents, 3 Web-Recherche-Runden). Messwerte: /api/voice/metrics (n=13 STT, n=18 chat_ttfb), TTFT-Direktmessung llama-swap :8080.* diff --git a/docs/ZEROCLAW_POC_BRIEF.md b/docs/ZEROCLAW_POC_BRIEF.md new file mode 100644 index 0000000..c6c9870 --- /dev/null +++ b/docs/ZEROCLAW_POC_BRIEF.md @@ -0,0 +1,83 @@ +# Brief: ZeroClaw-PoC als Lucys schlanker Agent-Runtime (Latenz-Fix an der Wurzel) + +> Für eine **frische Claude-Code-Session**. Aufgabe: ZeroClaw (ultraleichter Rust-Agent) als +> risikoarmen Proof-of-Concept neben Hermes aufsetzen und gegen Hermes benchmarken (Prompt-Größe + +> Latenz). Hermes bleibt **unangetastet** parallel laufen — null Risiko für die laufende Lucy. + +## Warum (die ganze Vorgeschichte in Kürze) + +Lucy (Hermes-Agent, Hirn = gemma-4-26B-A4B) braucht **ewig** zum Antworten (Output top, aber 20–80 s/Turn). +Eine sehr lange Latenz-Jagd (2026-06-30) hat die Ursachen **definitiv** geklärt: + +1. **mem0 nutzte `fast` (Qwen) als LLM** (`MEM0_LLM_MODEL=fast`) — das war noch von früher, als `fast` Lucys + Hirn WAR. Nach dem Umzug auf gemma blieb mem0 auf fast → jede Erinnerungs-Op lud fast → **verdrängte + gemmas Warm-Gruppe** → gemma-KV-Cache tot → 40 s Re-Prefill. (Halb-fertige Hirn-Migration.) +2. **gemma ist architektonisch langsam auf Vulkan/Strix-Halo.** Verifiziert am Box-GGUF: + `attention.key/value_length = 512` (head_dim 512!) vs. Qwen3.6 **256**, plus mixed sliding/full + attention → Flash-Attention auf RADV ineffizient → langsamer **Prefill** + **CPU-Spike** (teils + CPU-Fallback). gemma-GENERIERUNG ist ok (~93 t/s), gecachter Prompt **0,3 s** — nur **Cache-Misses** + (Prefill, ~11–27 s) sind tödlich. +3. **gemmas Thinking ist per Default AN** (~90 Extra-Tokens/Antwort). Abschaltbar NUR via + `chat_template_kwargs:{enable_thinking:false}` (verifiziert; `/no_think` & `reasoning_effort` wirken nicht). +4. **Hermes selbst ist Schwergewicht** — DER eigentliche Overhead: 20k-Token-Prompt = **79 Tool-Schemas** + (~17,5k) + **Skills-Manifest** (27 Skills, ~8,7k) + **3-Schichten-Memory mit Auto-Injektion**. Die + Auto-Injektion **variiert den Prompt jeden Turn** → bricht gemmas Cache → Re-Prefill. + +**Verdikt:** Auch nach JEDEM Fix (Eviction behoben: mem0/aux→fast + fast ko-resident; Slot geschützt; +Thinking aus; Auto-Injektion aus; RADV ✓; FA ✓; single-slot cache-reuse) blieb gemma **6–80 s, +unzuverlässig** — der Prozess lief stabil (kein Crash/Eviction), aber gemmas Prefill kommt mit Hermes' +pro-Turn-wechselndem 20k-Prompt nicht klar. **gemma ist auf dieser HW+Agent fundamental ungeeignet für +verlässlich niedrige Latenz.** Einziger gemma-Vorteil: **deutlich besseres Deutsch** (Qwen leakt englische +Wörter, z.B. „biggest"; gemma = natürlich + echte Umlaute). + +## Die These des PoC + +**Hermes' Schwergewicht (Skills + ChromaDB + Auto-Injektion) baut den fetten, instabilen Prompt.** +Ein schlanker Agent (**ZeroClaw**: 3,4 MB Rust, SQLite-Memory statt ChromaDB, minimaler Overhead, „ruthless +about cutting") würde einen **kleinen, STABILEN** Prompt bauen → gemmas langsamer Prefill hat kaum was zu +kauen → **Lucy schnell mit gemma UND Qwen** → gemmas Deutsch gerettet + Lucy entschlackt. Wurzel-Fix statt +Modell-Pflaster. + +## PoC-Aufgabe (risikoarm, Hermes bleibt parallel) +1. **ZeroClaw** auf die Box holen (Rust-Binary; Repos: github.com/zeroclaw-labs/zeroclaw bzw. + github.com/elev8tion/zeroclaw — beides prüfen, das gepflegtere/passende nehmen). Eigener Port, **NICHT** + :8642 (Hermes) anfassen. +2. **An euer MC2-Gateway** hängen (OpenAI-kompatibel, `http://127.0.0.1:9001/v1`). Erst mit Modell `fast` + (Qwen, schnell) testen, dann `hermes` (gemma) für den Deutsch-Vergleich. +3. **Nur Kern-Tools** zuerst: Memory (ZeroClaw-eigenes SQLite ODER per MCP an mc2-memory) + 1–2 Stack-Tools. + Eure bestehenden MCP-Server (`hermes-pc-control`, `mission-control-stack`, `mission-control-memory`, + `hermes-web-fetch`) kann ZeroClaw als MCP-Client mitnutzen. +4. **Benchmark gegen Hermes (Zahlen, nicht Gefühl):** + - **Prompt-Größe** (prompt_tokens) eines simplen Turns: ZeroClaw vs. Hermes (Hermes ≈ 20.000). + - **Latenz** mehrerer Folge-Turns (Cache-Verhalten): wird der Prompt klein+stabil → cached gemma → schnell? + - Messmethode wie in der Saga: `curl` an den Agent + `/v1/chat/completions`-`usage.prompt_tokens` + + llama-swap-POST-Dauer (`journalctl -u llama-swap`). +5. **Entscheidung:** Wird Lucy mit ZeroClaw schnell (idealerweise mit gemma) → voller Umzug planen + (Persona, Memory-Migration mem0/Chroma→SQLite, MCP-Tools, Telegram/Voice). Wenn nicht → **Fallback: + Lucys Hirn auf Qwen3.6-35B-A3B** (schnell+verlässlich) + harte Deutsch-Direktive im System-Prompt. + +## Box-Fakten (für den PoC) +- **Box:** `ssh hitonabi@192.168.178.151` (key-based). Strix Halo, 122 GB, GTT ~124 GB, Vulkan/RADV. +- **MC2-Gateway:** `:9001/v1` (OpenAI-kompat). Aliase: `hermes`→gemma-4-26B (Lucys Hirn), `fast`→Qwen3.6-35B, + `heavy`→Qwen3.5-122B, `coder`/`coder-lite`, `vision`→Qwen3-VL-8B, `embed`→Qwen3-Embedding. +- **llama-swap:** `:8080` (Engine v9843, Vulkan/RADV, `--list-devices` zeigt nur die RADV-GPU — kein + llvmpipe-Fallback). gemma-cmd: `-c 65536 -fa on --cache-reuse 256 -cram 16384` + MTP-Draft. +- **Hermes:** `:8642` (NousResearch), Config `~/.hermes/config.yaml`, API-Key in `~/.hermes/.env` + (`API_SERVER_KEY`). 4 MCP-Server aktiv. **NICHT anfassen — bleibt Lucys Live-Agent bis ZeroClaw steht.** +- **mem0-Sidecar:** `:8765` (`~/.mem0/`, Chroma unter `/srv/models/mem0/chroma`), `MEM0_LLM_MODEL=fast`, + `MEM0_EMBED_MODEL=embed`. Systemd-User-Unit `~/.config/systemd/user/mem0-service.service`. +- **brains-Gruppe** (immer warm, ko-resident): gemma + fast + embed + vision. + +## Modell-Kandidaten (falls Fallback/Vergleich) +| Modell | Profil | Speed (Strix Halo) | Deutsch | +|---|---|---|---| +| gemma-4-26B-A4B | head_dim 512, Thinking, multimodal | langsam (Prefill) | **exzellent** | +| **Qwen3.6-35B-A3B** (auf Box) | head_dim 256, GQA kv=2 | **~85–100 t/s** | gut, aber English-Leaks | +| Qwen3-30B-A3B-Instruct | gleiche Familie | 755 pp / 85 tg (RADV) | wie Qwen3.6 | +| LFM2-8B-A1B (Liquid) | 8B/1B aktiv, Hybrid Conv+MoE | **~170 t/s** | klein → unsicher Deutsch | + +## Leitplanken +- **Hermes/Lucy bleibt live** — PoC läuft isoliert (eigener Port, eigene Memory-Datei). Null Risiko. +- Vor Box-Config-Änderungen Backup; llama-swap reloadt per `-watch-config`. +- Erst messen (Prompt-Größe + Latenz), dann über vollen Umzug entscheiden. + diff --git a/docs/ZEROCLAW_POC_RESULTS.md b/docs/ZEROCLAW_POC_RESULTS.md new file mode 100644 index 0000000..ea16ad0 --- /dev/null +++ b/docs/ZEROCLAW_POC_RESULTS.md @@ -0,0 +1,118 @@ +# ZeroClaw-PoC — Ergebnis & Verdikt (2026-06-30) + +> Durchführung des Plans aus `docs/ZEROCLAW_POC_BRIEF.md`. Hermes blieb die ganze Zeit +> **unangetastet** live (eigener Config-Dir, eigene SQLite-Memory, kein eigener Daemon-Port nötig – +> PoC lief als kurzlebiger CLI-Prozess). Null Risiko für die laufende Lucy. + +## Setup (reproduzierbar, alles auf der Box unter `~/zeroclaw-poc/`) +- **Binary:** ZeroClaw **v0.8.2** (`zeroclaw-labs/zeroclaw`, 32k ⭐, gepflegt – die andere Repo + `elev8tion/zeroclaw` ist ein 23-Commit-Mini-Fork). Prebuilt `x86_64-unknown-linux-gnu`, SHA256 + gegen `SHA256SUMS` verifiziert (`6b9f7e9d…`). Kein Rust-Toolchain auf der Box nötig. +- **Config:** isoliert via `--config-dir ~/zeroclaw-poc/config`. Provider = nativer `openai` + gegen das **MC2-Gateway** (`uri = http://127.0.0.1:9001/v1`, ZeroClaw hängt `/chat/completions` + selbst an; **base-URL, nicht der volle Pfad!**). Gateway braucht **keine Auth** (HTTP 200 offen). +- **Agent:** `[agents.lucy]`, `model_provider = openai.default`, `risk_profile = default` + (supervised), Memory-Backend = **sqlite**. Modellwahl pro Turn via `--model fast|hermes`. +- Stolpersteine gelöst: quickstart braucht TTY → headless via `config set --no-interactive`; + Secrets (`api_key`) brauchen `--no-interactive` + Wert; `risk_profiles.` ist Map → + per `config set` nicht adressierbar, Block direkt in `config.toml` angehängt. + +## Messungen (4 Folge-Turns, je frischer CLI-Prozess, identischer 13k-Prefix) + +| Turn | FAST (Qwen3.6-35B) | HERMES (gemma-4-26B) | input_tokens | +|---|---|---|---| +| 1 | 429 ms | **937 ms** | ~13.059 | +| 2 | 534 ms | **493 ms** | ~13.056 | +| 3 | 337 ms | **340 ms** | ~13.060 | +| 4 | 465 ms | **465 ms** | ~13.061 | + +`hermes`-Alias → verifiziert echtes `gemma-4-26B-A4B-it-…Q4_K_M.gguf` (kein Fallback auf fast); +gemma ist warm in der brains-Gruppe (llama-swap `/running`: gemma + Qwen3.6 + embed alle `ready`). + +## Kernbefunde +1. **Prompt-Größe:** ZeroClaw baut **~13.055–13.061 Tokens** pro simplem Turn — vs. Hermes **≈ 20.000**. + ~35 % kleiner. (Noch weiter reduzierbar: Default-Toolset; PoC lief mit voller Tool-Palette.) +2. **Prompt-Stabilität:** Der Prefix ist **konstant** (13.055–13.061, nur die User-Message variiert + um wenige Tokens). Genau das Gegenteil von Hermes' pro-Turn-wechselnder Auto-Injektion, die + gemmas Cache jeden Turn brach. +3. **Latenz (das Verdikt):** gemma antwortet unter ZeroClaw in **0,3–0,9 s/Turn** — gegenüber + **20–80 s** unter Hermes. Der Latenz-Abfall 937 ms → ~340 ms ab Turn 2 zeigt den **warmen Cache** + (stabiler Prefix → cache-reuse greift). gemma ist hier sogar **gleichauf mit Qwen**. + +## Verdikt +**Die PoC-These ist bestätigt.** Lucys Latenz-Problem war **nicht gemma**, sondern Hermes' +fetter, pro-Turn-instabiler 20k-Prompt, der gemmas Prefill-Cache zerschoss. Ein schlanker Agent +mit **kleinem, stabilem** Prompt macht **gemma sub-sekündlich** — und rettet damit gemmas +**exzellentes Deutsch** (kein Umstieg auf Qwen mit English-Leaks nötig). + +→ **Empfehlung: voller Umzug auf ZeroClaw planen** (mit gemma als Hirn). Kein Fallback auf Qwen nötig. + +## Umzug umgesetzt (2026-06-30, Etappe 2) +Lucy läuft als ZeroClaw-Agent auf der Box (`~/zeroclaw-poc/`), Daemon auf `127.0.0.1:8088`: +- **Persona:** openclaw-Workspace-Dateien in `config/agents/lucy/workspace/` (`IDENTITY.md`, `SOUL.md`, + `USER.md`, `AGENTS.md`) — Lucy spricht „Commander", echte Umlaute, ``-Tags. (Workspace-Pfad = + `/agents//workspace/`, NICHT `config/data`!) +- **MCP-Tools:** 4 Server / 37 Tools (`[[mcp.servers]]` als **Array** mit `name`, nicht Tabelle!) + + Bundle `lucy_tools` an `agents.lucy.mcp_bundles`. Alle verbunden, autonom nutzbar. +- **Hirn:** gemma (`hermes`), Autonomie `level="full"`, Thinking aus via + `providers.models.openai.default.chat_template_kwargs.enable_thinking=false`. +- **Aux:** `classifier_provider`/`summary_provider` → `openai.fastaux` (Qwen); Auto-Hydrate/Save aus. + +## 🔴 KV-Cache-Killer gefunden & gefixt (der eigentliche Latenz-Showstopper) +Daemon-Latenz war erst 5–22 s/Turn (wild schwankend), obwohl Direkt-ans-Gateway gemma einen stabilen +20k-Prompt in **180 ms** cached (call 1 kalt 19 s, call 2–4 = 180 ms, cached=19820). Per Mitschnitt-Proxy +(ZeroClaw→Proxy→Gateway) zwei Folge-Turns **byte-genau gedifft**: +1. **HAUPTSCHULDIGER — Tool-Reihenfolge:** ZeroClaw hängt die 37 MCP-Tools (im `tools`-Array UND im + `deferred_loading`-Textblock) in **zufälliger HashMap-Reihenfolge pro Turn** an → ~5k Token im Prompt + ändern sich jeden Turn → llama.cpp-KV-Cache ab da tot → Full-Re-Prefill. +2. **Neben-Killer — User-Timestamp:** ZeroClaw prefixt die User-Message mit `[YYYY-MM-DD HH:MM:SS ±ZZ:ZZ]` + (variiert jeden Turn; steht am Ende → kleiner). +3. **Ausgeschlossen:** Classifier (feuert gar nicht, 1 Call/Turn), mem0/Memory (feuert bei Chat nicht). + +**Fix (Binary nicht kompilierbar → Wire-Ebene):** schlanker Python-**Normalisierungs-Proxy** +(`~/zeroclaw-poc/normalizing-proxy.py`, Port 9009) zwischen ZeroClaw und Gateway: **sortiert `tools` +deterministisch** + **strippt den Timestamp**. Beide Provider-URIs zeigen auf `:9009`. Ergebnis byte-stabil +verifiziert (System + Tools identisch, nur echte User-Message variiert). **Latenz 5–22 s → ~400 ms typisch** +(Cache-Hit), vereinzelt 2–5 s (gemma cache-reuse/MTP-Rest, evtl. via `-cram 16384`); Tool-Turn ~3,6 s. +gemma-cmd: `-c 65536 -fa on --cache-reuse 256 -cram 16384 + MTP-draft`, single-slot (`--parallel 1` implizit). + +## gemma-4 Cache-Recherche (llama.cpp) + FINALER Hirn-Entscheid: Qwen3.6 +Nach dem Proxy blieben Rest-Spitzen (2–6 s). Tagesaktuelle llama.cpp-Recherche bestätigt: **bekannter, +Gemma-4-spezifischer Bug.** +- **Gemma 4 nutzt „Shared KV Cache"** (letzte Layer teilen K/V mit früheren) → llama.cpp loggt wörtlich + *„cache reuse is not supported - ignoring n_cache_reuse"* → **euer `--cache-reuse 256` ist für gemma-4 + wirkungslos.** ([Issue #21468](https://github.com/ggml-org/llama.cpp/issues/21468)) +- **Fix [PR #22288](https://github.com/ggml-org/llama.cpp/pull/22288)** (merged 24.04.2026): braucht + **`--swa-full`** (hält ganze KV-History, kein Sliding-Window-Pruning). Caveat: cache-reuse ↔ mmproj + inkompatibel. +- **Getestet an der live gemma:** `--swa-full` testweise gesetzt → mehr saubere 400-ms-Hits, ABER weiter + ~50 % Misses (2–6 s). Auch nach Toolset-Eindampfung (Prompt 18k→**4908 Tok** via + `risk_profiles.default.excluded_tools`, 18 Kern-Tools) blieb gemma 1,5–6 s **spitzig**. +- **Befund:** gemma-4 cached auf Strix Halo **fundamental unzuverlässig** (SWA + Shared-KV + MTP), egal wie + klein/stabil der Prompt. → live gemma wieder auf **Original zurückgesetzt** (Hermes unberührt; + `--swa-full` als getestete Option dokumentiert, falls Hermes es nutzen will). + +**Qwen3.6-35B-A3B als Lucys Hirn (Standard-GQA, cache-reuse funktioniert):** mit Proxy + Lean-Tools +**konstant ~1,2–1,8 s/Turn, NULL Spitzen** (vs gemma 1,5–6 s spitzig). Deutsch gut (echte Umlaute, kein +EN-Leak in Tests; seltener Kohärenz-Wackler). **Das ist der Brief-Fallback — jetzt empirisch als richtige +Wahl bestätigt.** Lucy-Daemon läuft auf `model=fast`. + +## Finaler Lucy-Stack (läuft, manuell/nohup) +``` +Desktop/Webhook → ZeroClaw-Daemon :8088 (Persona, 18 Lean-Tools, Autonomie full) + → Normalisierungs-Proxy :9009 (sort tools + strip timestamp) ← der Cache-Fix + → MC2-Gateway :9001 → llama-swap :8080 → Qwen3.6 (fast) ← rock-solid Cache +``` + +## Nächste Schritte (offen) +- **Persistenz:** Proxy + Daemon als systemd-User-Services (vom User freizugeben). +- **Voice/Telegram** an den Daemon hängen (Desktop-Client postet aktuell an MC2 `/api/voice/chat`). +- **ZeroClaw-Tool-Order-Bug** upstream melden (nicht-deterministische Tool-Sortierung killt KV-Cache). +- Optional: Deutsch-Direktive in IDENTITY.md härten gegen Qwens seltene Wackler. +- Persona/System-Prompt (Lucys Charakter) in ZeroClaw übertragen. +- Memory-Migration: mem0/Chroma → ZeroClaws SQLite (oder MCP-Bridge an `mission-control-memory`). +- MCP-Tools anbinden: `hermes-pc-control`, `mission-control-stack`, `mission-control-memory`, + `hermes-web-fetch` (ZeroClaw als MCP-Client). +- Toolset auf Kern reduzieren → Prompt < 13k drücken (noch schnellerer Prefill). +- Kanäle: Telegram + Voice an ZeroClaw hängen; Gateway-/Daemon-Betrieb (eigener Port, nicht :8642). +- Erst nach grünem Umzug Hermes ablösen.