feat: leere Rollen ehrlich anzeigen + Vision-cmd automatisch (mmproj/jinja)

- status(): Flag "incomplete" fuer Rollen ohne Modell (-m), z.B. provision.sh-
  Platzhalter. Wurden bisher irrefuehrend als "bereit / ? . 8K . ?" gezeigt.
- Modelle-Tab: leere Rollen klar als "kein Modell hinterlegt / leer" + Aktion
  "Modell zuweisen" (-> Cookbook); nicht im Schnelltest-Dropdown waehlbar
- register(): erkennt einen mmproj-Projektor im selben Ordner und ergaenzt
  --mmproj + --jinja automatisch (Vision braucht das in llama.cpp)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-06-21 18:38:16 +02:00
parent f44da4b8e2
commit 45ab32955a
2 changed files with 39 additions and 1 deletions
+21
View File
@@ -98,11 +98,15 @@ def status():
if "--mmproj" in cmd:
caps.append("Bild")
# "incomplete" = Rolle existiert in der config, hat aber kein Modell (-m) hinterlegt
# (z.B. von provision.sh angelegter Platzhalter). Ehrlich kennzeichnen statt "bereit".
incomplete = not (m_path and m_path.group(1))
configured[name] = {
"name": name,
"ttl": spec.get("ttl", cfg.get("globalTTL", 0)),
"cmd": cmd,
"state": "idle",
"incomplete": incomplete,
"port": None,
"meta": {
"ctx": ctx,
@@ -157,12 +161,29 @@ def download(req: DownloadReq):
return {"job_id": job_id, "expected_path": str(target / req.file)}
def _augment_vision(cmd: str, model_path: str) -> str:
"""Liegt im selben Ordner ein mmproj-Projektor, --mmproj + --jinja ergaenzen —
Vision-Modelle brauchen das in llama.cpp (siehe CLAUDE.md). No-op, wenn schon gesetzt
oder kein Projektor da."""
if "--mmproj" in cmd:
return cmd
try:
d = os.path.dirname(model_path)
for f in sorted(os.listdir(d)):
if "mmproj" in f.lower() and f.lower().endswith(".gguf"):
return cmd.rstrip() + f" --mmproj {os.path.join(d, f)} --jinja"
except OSError:
pass
return cmd
@router.post("/register")
def register(req: RegisterReq):
# Bewusst KEIN exists()-Check: beim frischen Download läuft der hf-Job noch, die Datei kommt
# erst gleich. Eintrag jetzt schon schreiben → llama-swap (-watch-config) lädt, sobald sie da ist.
cfg = read_config()
cmd = CMD_TEMPLATE.replace("{model}", req.model_path).replace("{ctx}", str(req.ctx))
cmd = _augment_vision(cmd, req.model_path)
cfg["models"][req.alias] = {
"cmd": LiteralScalarString(cmd + "\n"),
"ttl": req.ttl if req.ttl is not None else DEFAULT_TTL,