feat(rollen): echte Modellnamen als API-ID + Rollen als Tags/Alias
Modelle erscheinen jetzt mit ihrem ECHTEN Namen (= API-Name, den man in Zed/ OpenCode angibt) statt unter "coder"/"vision". Die Rolle wird ein zusaetzlicher, sprechender Name (llama-swap-`aliases`) -> in der API funktionieren BEIDE. - llamaswap.py: model_id_from_path (Repo-Ordner ohne -GGUF) + set_role_alias (Rolle als eindeutiger Alias, beim Setzen bei anderen Modellen entfernt) + ROLE_IDS (vision/coder/scout/reviewer/manager). - models.py: register schreibt Key=Modellname, Rolle als Alias; /status liefert role + aliases + api_ids; neuer POST /set_role. Rueckwaertskompatibel: Legacy- Eintraege (coder/vision ohne Alias) behalten ihren Key als Rolle. - cookbook.py: install-recipe/-model nutzen dasselbe Schema (Name + Rollen-Alias). - models.js: Zeile zeigt echten Namen + Rollen-Tag + API-Name (klick=kopieren); neuer "Rolle"-Dialog mit 5 Schnellwahl-Rollen + freier Eingabe. - cookbook.js: Profi-Download-Feld ist jetzt optionale Rolle (Name kommt vom Modell), Pflichtfeld-Pruefung entsprechend gelockert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+40
-6
@@ -17,7 +17,8 @@ from config import (CMD_TEMPLATE, CONFIG_PATH, DEFAULT_TTL, HF_DOWNLOAD_ENV, LLA
|
||||
MODELS_DIR, TOKEN, hf_bin)
|
||||
from jobengine import JOBS, start_job, attach_download_progress
|
||||
from routers.cookbook import hf_file_size
|
||||
from llamaswap import _swap_get, read_config, write_config
|
||||
from llamaswap import (_swap_get, read_config, write_config,
|
||||
model_id_from_path, set_role_alias, ROLE_IDS)
|
||||
from hw_math import extract_params_b, max_ctx_for, estimate_memory_gb
|
||||
import re
|
||||
import os
|
||||
@@ -38,12 +39,18 @@ class DownloadReq(BaseModel):
|
||||
|
||||
|
||||
class RegisterReq(BaseModel):
|
||||
alias: str
|
||||
alias: str = "" # rueckwaertskompatibel: wird als Rolle interpretiert, wenn 'role' fehlt
|
||||
role: str | None = None # Rollen-Tag (vision/coder/scout/reviewer/manager o.ae.)
|
||||
model_path: str
|
||||
ctx: int = 8192
|
||||
ttl: int | None = None
|
||||
|
||||
|
||||
class RoleReq(BaseModel):
|
||||
alias: str # die Modell-ID (config-Key)
|
||||
role: str = "" # leer = Rolle entfernen
|
||||
|
||||
|
||||
class ChatReq(BaseModel):
|
||||
model: str
|
||||
message: str
|
||||
@@ -92,17 +99,28 @@ def status():
|
||||
if q_match:
|
||||
quant = q_match.group(1).upper()
|
||||
|
||||
# Rolle aus dem llama-swap-Alias ableiten; Legacy-Eintraege ohne Alias, deren Key
|
||||
# selbst eine Rolle ist (coder/vision/...), behalten diese als Rolle.
|
||||
aliases = spec.get("aliases") or []
|
||||
if isinstance(aliases, str):
|
||||
aliases = [aliases]
|
||||
aliases = [str(a) for a in aliases]
|
||||
role = aliases[0].lower() if aliases else (name.lower() if name.lower() in ROLE_IDS else None)
|
||||
|
||||
caps = ["Text"]
|
||||
if "coder" in name.lower() or (m_path and "code" in m_path.group(1).lower()):
|
||||
if role == "coder" or "coder" in name.lower() or (m_path and "code" in m_path.group(1).lower()):
|
||||
caps = ["Code"]
|
||||
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,
|
||||
"role": role,
|
||||
"aliases": aliases,
|
||||
"api_ids": [name] + aliases,
|
||||
"ttl": spec.get("ttl", cfg.get("globalTTL", 0)),
|
||||
"cmd": cmd,
|
||||
"state": "idle",
|
||||
@@ -184,15 +202,31 @@ def register(req: RegisterReq):
|
||||
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] = {
|
||||
# Neues Schema: Schluessel = sprechender Modellname (steht so in der Modell-Liste und ist
|
||||
# der API-Name), die Rolle kommt als llama-swap-Alias obendrauf (beide Namen funktionieren).
|
||||
role = (req.role or req.alias or "").strip().lower()
|
||||
model_id = model_id_from_path(req.model_path)
|
||||
cfg["models"][model_id] = {
|
||||
"cmd": LiteralScalarString(cmd + "\n"),
|
||||
"ttl": req.ttl if req.ttl is not None else DEFAULT_TTL,
|
||||
}
|
||||
set_role_alias(cfg, model_id, role)
|
||||
write_config(cfg)
|
||||
return {"ok": True, "alias": req.alias,
|
||||
return {"ok": True, "alias": model_id, "model_id": model_id, "role": role,
|
||||
"note": "In config.yaml geschrieben. llama-swap mit -watch-config laedt automatisch neu."}
|
||||
|
||||
|
||||
@router.post("/set_role")
|
||||
def set_role(req: RoleReq):
|
||||
"""Rollen-Tag eines Modells setzen/aendern (als eindeutiger llama-swap-Alias)."""
|
||||
cfg = read_config()
|
||||
if req.alias not in cfg.get("models", {}):
|
||||
raise HTTPException(404, "Modell nicht gefunden.")
|
||||
set_role_alias(cfg, req.alias, req.role.strip().lower() or None)
|
||||
write_config(cfg)
|
||||
return {"ok": True, "alias": req.alias, "role": req.role.strip().lower()}
|
||||
|
||||
|
||||
@router.post("/update_model")
|
||||
def update_model(req: UpdateReq):
|
||||
cfg = read_config()
|
||||
|
||||
Reference in New Issue
Block a user