Files
ARIA-AGENT/docs/plan-local-llm-router.md
T
duffyduckandClaude Opus 4.8 b5ba54d05f feat(local-llm): B0 — GGUF Auto-Download via llama.cpp -hf (kein manuelles Ablegen)
Statt einer manuell abgelegten Datei zieht llama.cpp das Modell beim ersten
Start selbst von Hugging Face (-hf Qwen/Qwen3-8B-GGUF:Q4_K_M, offizielles
Repo verifiziert) und cached es unter xtts/models (persistent). Modell/Quant
via LLM_HF_REPO/LLM_HF_QUANT in der .env wechselbar, kein Code.

Diagnostic-Modellauswahl (on-demand laden/aktivieren mehrerer Modelle) als
Folge-Baustein B0.5 via llama-swap ins Plan-Doc aufgenommen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 10:33:59 +02:00

5.8 KiB
Raw Blame History

Plan B — Lokaler LLM-Router (Gamebox) neben Claude

Ziel: „Gemini-Feeling" für den Alltag, ohne die Claude-Max-Subscription aufzugeben. Ein schnelles lokales LLM beantwortet die einfachen ~80 % der Turns in <1 s; nur die schweren 20 % (Tiefe, Code, Tools, Pentest, langer Kontext) gehen an Claude. Claude bleibt das Tiefen-Hirn.

Warum das der einzige realistische Weg zu „live" ist

Gemessen (10.07.2026): CLI-Round-trip über den Claude-Max-Proxy hat einen harten Boden von ~3,5 s (Subprozess-Start pro Turn). Streaming-API würde das brechen, kostet aber API-Geld → verliert die Max-Subscription. Ein lokales LLM für die einfachen Turns umgeht den 3,5-s-Boden komplett und ist gratis (läuft auf vorhandener Gamebox-GPU). Echtes Speech-to-Speech-Duplex (Gemini Live nativ) ist mit einem Text-Modell als Hirn prinzipiell nicht drin.

Modell & Serving (entschieden)

  • Modell: Qwen3 8B, GGUF Q4_K_M (~6 GB). Bestes Tool-Calling der 7/8B- Klasse, solides Deutsch, Apache-2.0. Alt.: Mistral Small 3 7B (schneller, weniger Tool-Calling).
  • Serving: llama.cpp llama-server im Docker-Container auf der Gamebox (kein Ollama nötig — nativer OpenAI-kompatibler /v1/chat/completions).
  • VRAM-Budget: 12-GB-Karte, Whisper-small (~12 GB) + F5-TTS (~12 GB) → ~89 GB frei → passt. (FLUX ist auf 12 GB eh raus.)

Anbindung: über den RVS, wie TTS/STT (kein IP-Pflegen)

Die Gamebox ist ein anderer Host als das Brain. Statt direktem HTTP (IP/Port/ Firewall) läuft das LLM über den RVS-Token-Room, exakt wie Whisper/F5-TTS:

  • llama.cpp hört nur auf localhost der Gamebox.
  • Ein dünner RVS-Adapter daneben (Vorbild: whisper-/xtts-Bridge) verbindet sich mit dem RVS-Token, lauscht auf llm_request, ruft lokal llama-server, schickt llm_response (korreliert per requestId) zurück.
  • rvs/server.js ALLOWED_TYPES um llm_request, llm_response und (Phase 2) llm_partial erweitern.
  • Das Brain bekommt einen zweiten „Proxy" — nur über RVS statt direktem HTTP.

Router-Logik im Brain

Reihenfolge pro Turn (früh raus = schnell):

  • Tier 0 — Fast-Path (existiert): reine Steuerbefehle (Spotify, Licht) → Skill direkt, kein LLM. <1 s.
  • Tier 1 — Lokal (Qwen3): einfache Konversation, kurze Fakten, Smalltalk, Bestätigungen. Ziel <1 s.
  • Tier 2 — Claude: tief/technisch, Code, Tool-Use nötig, Pentest-Projekt, langer/komplexer Kontext.

Routing-Signal (heuristisch zuerst, deterministisch & schnell): Nachrichtenlänge, Schlüsselwörter, ob ein Tool nötig scheint, Projekt-Kontext (Pentest-Projekt → immer Claude), Konversationstiefe.

Escalation statt perfekter Vorab-Klassifikation: Das lokale Modell bekommt die Anweisung, bei Unsicherheit oder Tool-Bedarf NICHT zu raten, sondern zu eskalieren (z.B. Antwort <<ESCALATE>>). Das Brain routet den Turn dann an Claude. So sind Fehlklassifikationen billig — lieber einmal lokal→Claude als eine falsche lokale Antwort.

Persona auf BEIDEN Modellen

Das lokale Modell braucht ARIAs Identität, sonst bricht es aus der Rolle (gelernt aus dem --system-prompt-Debakel). Aber schlanker:

  • IDENTITY_SEED + Kern-Persona: ja.
  • Volles Memory / alle Skill-Schemas / Tool-Block: nein (Tier 1 macht keine Tools). Hält den lokalen Prompt klein → schnell.
  • Persona kommt lokal auch als echter System-Prompt (llama.cpp system-Rolle).

Phasen

  • B0 — Infra: llama.cpp-Container + RVS-Adapter auf der Gamebox, ALLOWED_TYPES, local_llm_chat() im Brain. Isoliert testen („sag hallo").
  • B1 — Router: Heuristik Tier-1/2 + Escalation, schlanke Persona lokal. Einfache Turns → lokal. Messen: Trefferquote & Latenz.
  • B2 — Streaming/Voice: llm_partial → TTS beginnt beim ersten Satz → der „live"-Sprung. Hier den Gong-/Ohr-Re-Arm-Bug mit-fixen (Barge-In, sauberes Re-Listen).
  • B3 (optional): dem lokalen Modell ein paar schnelle, sichere Tools geben.

Offene Entscheidungen (für Stefan)

  1. Modell: Qwen3 8B (Tool-Calling) — oder doch Mistral Small 3 7B (Speed)?
  2. Routing v1: rein heuristisch + Escalation (empfohlen) — oder gleich ein Mini-Classifier?
  3. Tools lokal: in v1 bewusst KEINE (alles Tool-artige → Claude) — ok?

Folge-Baustein: Modell-Auswahl in ARIA Diagnostic (B0.5)

Ziel: In Diagnostic ein Modell auswählen; ist es nicht da, lädt der Container es on-demand und aktiviert es. Spiegelt zwei bestehende Muster: den whisperModel-Hotswap (RVS-Config-Broadcast → Bridge hot-swapped) und die kuratierte Claude-Tier-Liste aus models.json.

Kernproblem: llama.cpp-Server serviert ein Modell pro Prozess — „anderes aktivieren" = neu laden/swappen.

Lösung: llama-swap (Proxy vor llama.cpp): kennt eine Liste von Modellen, lädt bei Anfrage das gewünschte on-demand (Download via -hf beim ersten Mal), swappt bei VRAM-Knappheit das alte raus. OpenAI-kompatibel — der llm-adapter zeigt statt auf llama:8081 auf llama-swap.

Bausteine:

  • llama-swap-Service in xtts/docker-compose.yml (ersetzt/ergänzt llama), Config mit den verfügbaren Modellen (Name → -hf-Command).
  • Kuratierte Liste local_models.json (analog models.json) — Diagnostic-UI liest sie, zeigt Dropdown „Lokales Modell".
  • Diagnostic → RVS-Config-Broadcast localLlmModel → llm-adapter setzt das model-Feld seiner llama-swap-Requests → swap/Download passiert automatisch.
  • Status zurück an Diagnostic (lädt / bereit / VRAM-OOM), analog whisper-Status.

Bis dahin: ein Modell via -hf Auto-Download (B0, erledigt). Erst end-to-end grün, dann dieser Komfort-Layer.

Nicht-Ziele

  • Kein echter Gemini-Live-Duplex-Klon (Text-Modell als Hirn).
  • FLUX bleibt optional/später (dickere GPU). Bild-Generierung separat als pluggbarer Provider (ChatGPT/DALL·E-Alternative) — eigenes Feature, nicht Teil B.