c48e583790
Engine-Cutover ROCm/HIP -> Vulkan/RADV (gfx1151): +12-22% tg auf MoE (llama-bench
verifiziert, fast 53->65 t/s). ROCm-Build bleibt als Rollback unter /opt/llamacpp.
- Backend: vocab-aware Speculative Decoding. services/gguf_meta.py liest den
Tokenizer-Fingerprint (model/pre/n_vocab) direkt aus dem GGUF-Header (ohne Modell-Load);
register_model + migrate_config haengen nur VOCAB-KOMPATIBLE Drafts an (inkl. --spec-type,
das in dieser llama.cpp-Generation noetig ist). Neue Endpoints /api/models/drafts + /{id}/draft.
- Frontend: idiotensichere Spec-Draft-UI (SpecDraftModal) - nur kompatible Drafts waehlbar,
inkompatible gesperrt mit Begruendung; SPEC/SPEC?-Badge nach echtem Aktiv-Status; Rolle in AddModel.
- maintenance.py: Engine-Update-Quelle -> ggml-org/llama.cpp (Build-Nummer-Vergleich),
ENGINE_PATH=/opt/llamacpp-vulkan.
- Startup-Warmup der brains (deploy/warmup.sh, self-detaching ExecStartPost) + deploy/provision-engine.sh.
- Cleanup: tote LiteLLM gateway/config.yaml + alle Referenzen (config.py/backup.py/backup.sh) entfernt;
README + docs/memory aktualisiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
76 lines
4.3 KiB
Python
76 lines
4.3 KiB
Python
"""
|
|
Zentrale Konfiguration für Mission Control 2.0.
|
|
|
|
Eine Quelle der Wahrheit für Pfade, URLs und Defaults — alles über Env-Vars
|
|
überschreibbar. Bewusst schlank: MC 2.0 ist ein Glue-Cockpit, das vorhandene
|
|
Dienste (llama-swap, LiteLLM-Gateway, Hermes) steuert, statt sie nachzubauen.
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
from ruamel.yaml import YAML
|
|
|
|
# --- Engine (llama-swap) -----------------------------------------------------
|
|
LLAMA_SWAP_URL = os.environ.get("MC_LLAMA_SWAP_URL", "http://127.0.0.1:8080").rstrip("/")
|
|
CONFIG_PATH = Path(os.environ.get("MC_CONFIG_PATH", "/etc/llama-swap/config.yaml"))
|
|
MODELS_DIR = Path(os.environ.get("MC_MODELS_DIR", "/srv/models"))
|
|
# Cache der Modell-Entdeckung ("aktuell beste Modelle", live von HuggingFace).
|
|
# Persistent neben den Modellen (übersteht Deploys). TTL = Frische-Fenster.
|
|
DISCOVER_CACHE_PATH = Path(os.environ.get("MC_DISCOVER_CACHE", str(MODELS_DIR / "mc2-discover.json")))
|
|
DISCOVER_TTL = int(os.environ.get("MC_DISCOVER_TTL", "43200")) # 12 h
|
|
# Geteiltes Gedächtnis (SQLite, WAL). Persistent neben den Modellen.
|
|
MEMORY_DB = Path(os.environ.get("MC_MEMORY_DB", str(MODELS_DIR / "mc2-memory.db")))
|
|
# Befehl-Vorlage für llama-swap: {model}=GGUF-Pfad, {ctx}=Kontext, ${PORT} bleibt stehen.
|
|
# Hinweis: --prompt-cache/--prompt-cache-all sind llama-CLI-Flags, NICHT llama-server —
|
|
# llama-server lehnt sie ab ("invalid argument") und startet dann nicht. Prompt-Caching
|
|
# macht llama-server ohnehin automatisch pro Slot (KV-Reuse).
|
|
_DEFAULT_CMD_TEMPLATE = (
|
|
"llama-server -m {model} --host 127.0.0.1 --port ${PORT} "
|
|
"-c {ctx} -ngl 999 -fa 1 --no-mmap"
|
|
)
|
|
CMD_TEMPLATE = os.environ.get("MC_CMD_TEMPLATE", _DEFAULT_CMD_TEMPLATE)
|
|
if "{model}" not in CMD_TEMPLATE:
|
|
CMD_TEMPLATE = _DEFAULT_CMD_TEMPLATE
|
|
DEFAULT_TTL = int(os.environ.get("MC_DEFAULT_TTL", "300"))
|
|
# Verzeichnis mit Draft-Modellen für Speculative Decoding. Beim Hinzufügen eines
|
|
# fast/coder-Modells wird hieraus automatisch ein **vocab-kompatibler** Draft gewählt
|
|
# (Vocab-Check via services.gguf_meta; ein inkompatibler Draft lässt llama.cpp scheitern).
|
|
DRAFTS_DIR = Path(os.environ.get("MC_DRAFTS_DIR", str(MODELS_DIR / "drafts")))
|
|
# Optionaler expliziter Default-Draft (leer = Auto-Erkennung aus DRAFTS_DIR). Wird nur
|
|
# verwendet, wenn er zum Ziel-Modell vocab-kompatibel ist. (Früher fix qwen2.5 → entfernt,
|
|
# weil das mit neueren Vocabs wie Qwen3.6 inkompatibel ist und Spec stillschweigend brach.)
|
|
SPEC_DRAFT_MODEL_PATH = os.environ.get("MC_SPEC_DRAFT_MODEL", "")
|
|
# Speculative-Decoding-Typ (llama.cpp dieser Generation braucht --spec-type zusätzlich
|
|
# zu --spec-draft-model, sonst ist Spec inaktiv).
|
|
SPEC_TYPE = os.environ.get("MC_SPEC_TYPE", "draft-simple")
|
|
# Env für HuggingFace-Downloads: XET deaktivieren (Hänger bei ~6 MB, siehe v1-Gotcha).
|
|
HF_DOWNLOAD_ENV = {"HF_HUB_DISABLE_XET": "1"}
|
|
|
|
# --- Routing-Gateway (builtin in MC2, model: auto) ---------------------------
|
|
# MC2 IST der Gateway (services/gateway.py + routers/gateway_proxy.py). KEIN externer
|
|
# LiteLLM-Dienst (scheitert auf Python 3.14). Daher keine Gateway-Config-Datei mehr.
|
|
GATEWAY_URL = os.environ.get("MC_GATEWAY_URL", f"http://127.0.0.1:{os.environ.get('MC_PORT', '9000')}").rstrip("/")
|
|
|
|
# --- Hermes Agent (eigener Dienst auf der Box) -------------------------------
|
|
# Gateway (OpenAI-API des Agenten) + standalone Web-UI (nesquena/hermes-webui).
|
|
HERMES_API_URL = os.environ.get("HERMES_API_URL", "http://127.0.0.1:8642").rstrip("/")
|
|
HERMES_WEBUI_URL = os.environ.get("HERMES_WEBUI_URL", "http://127.0.0.1:8787").rstrip("/")
|
|
HERMES_HOME = Path(os.path.expanduser(os.environ.get("HERMES_HOME", "~/.hermes")))
|
|
# PC Executor — läuft auf dem Windows-PC, erreichbar über LAN.
|
|
PC_EXECUTOR_URL = os.environ.get("MC_PC_EXECUTOR_URL", "http://192.168.178.98:7777").rstrip("/")
|
|
|
|
# --- Server ------------------------------------------------------------------
|
|
HOST = os.environ.get("MC_HOST", "0.0.0.0")
|
|
PORT = int(os.environ.get("MC_PORT", "9000"))
|
|
# Gebautes React-Frontend (frontend/dist). In Prod liefert FastAPI es statisch aus;
|
|
# im Dev läuft der Vite-Dev-Server separat und proxyt /api hierher.
|
|
FRONTEND_DIST = Path(os.environ.get("MC_FRONTEND_DIST", str(Path(__file__).resolve().parent.parent / "frontend" / "dist")))
|
|
|
|
# Version (Phase 0 — Greenfield-Skeleton).
|
|
VERSION = "2.0.0-w8"
|
|
|
|
# Gemeinsame YAML-Instanz (preserve_quotes hält Kommentare/Quotes in config.yaml).
|
|
yaml = YAML()
|
|
yaml.preserve_quotes = True
|