feat(llm): Kontextfenster pro Karte einstellbar + Fehlerart context_exceeded
Anlass: die Software-Schmiede bekam "request (8274 tokens) exceeds the available context size (8192 tokens)". Sie holt ctx vom Cluster zwar ab, kuerzt aber nach einem eigenen, von Hand eingetragenen Wert (32768). ARIA-Seite: - Neue Fehlerart context_exceeded (statt model_error) mit promptTokens und ctx — Programme koennen automatisch kuerzen und nochmal senden, statt Text auszuwerten. llm-adapter liest es aus llama.cpps exceed_context_size_error, der Cluster-Router reicht es durch und wiederholt es nicht anderswo. - Diagnostic → LLM-Karten: Kontextfenster pro Karte (4k … 128k). Laedt das Modell mit neuem -c; Programme sehen den neuen Wert ueber ctx. Passt es nicht in den Grafikspeicher, setzt die Box zurueck — jetzt inkl. Registry (vorher blieb bei einem Fehlschlag der zu grosse ctx in aria_models.json stehen und waere beim naechsten Start wieder gescheitert). - Doku: context_exceeded, ctx kann sich aendern, "danach kuerzen, nicht nur anzeigen". Getestet gegen llama-swap: Kontext 512 → 1024 (gleiche Karte), Fehlschlag bei 65536 → Registry + Config wieder 1024, zu langer Verlauf → context_exceeded mit promptTokens=6030, ctx=1024. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -356,6 +356,24 @@ def _sanitize_messages(messages: list) -> list:
|
||||
return out
|
||||
|
||||
|
||||
def _llama_error_info(exc: Exception) -> dict:
|
||||
"""Maschinenlesbare Fehlerart. Wichtigster Fall: der Verlauf ist laenger
|
||||
als das Kontextfenster — dann soll ein Programm automatisch kuerzen und
|
||||
nochmal fragen koennen, statt einen Text auszuwerten."""
|
||||
resp = getattr(exc, "response", None)
|
||||
if resp is None:
|
||||
return {}
|
||||
try:
|
||||
e = (resp.json() or {}).get("error") or {}
|
||||
except Exception:
|
||||
return {}
|
||||
if isinstance(e, dict) and e.get("type") == "exceed_context_size_error":
|
||||
return {"errorCode": "context_exceeded",
|
||||
"promptTokens": int(e.get("n_prompt_tokens") or 0),
|
||||
"ctx": int(e.get("n_ctx") or 0)}
|
||||
return {}
|
||||
|
||||
|
||||
def _llama_error_text(exc: Exception) -> str:
|
||||
"""Bei HTTP-Fehlern den GRUND von llama.cpp mitnehmen. Bisher kam nur
|
||||
"Server error '500 …'" an — die eigentliche Erklaerung steht im Body."""
|
||||
@@ -419,7 +437,7 @@ async def _call_llama(messages: list, *, max_tokens: int, temperature: float,
|
||||
except Exception as e:
|
||||
msg = _llama_error_text(e)
|
||||
logger.warning("llama.cpp-Call fehlgeschlagen: %s", msg[:300])
|
||||
return {"ok": False, "content": "", "error": msg[:700]}
|
||||
return {"ok": False, "content": "", "error": msg[:700], **_llama_error_info(e)}
|
||||
|
||||
|
||||
# B0.5-2: Lade-Status ans Diagnostic (service_status, service="llm"). Wir kennen
|
||||
@@ -678,6 +696,8 @@ async def _do_llm_request(ws, payload: dict) -> None:
|
||||
"tool_calls": tc,
|
||||
"error": res.get("error"),
|
||||
"model": model,
|
||||
# Fehlerart fuer Programme (z.B. context_exceeded + promptTokens + ctx)
|
||||
**{k: res[k] for k in ("errorCode", "promptTokens", "ctx") if res.get(k)},
|
||||
# Wer hat geantwortet: Box + Karte. Hilft Clients mit mehreren Boxen.
|
||||
"instanceId": INSTANCE_ID, "node": NODE_NAME, "gpu": _card_of(model),
|
||||
"usage": res.get("usage") or {},
|
||||
@@ -927,6 +947,10 @@ async def _handle_provision(ws, payload: dict) -> None:
|
||||
error=f"{key} liegt schon auf Karte {elsewhere} dieser Box — ein Modell pro Box nur einmal.")
|
||||
quant_note = ""
|
||||
repo_files = None
|
||||
# Fuer ein Zuruecksetzen: der bisherige Registry-Eintrag dieses Modells.
|
||||
# Noetig, wenn nur das Kontextfenster geaendert wird (gleiches Modell, gleiche
|
||||
# Karte) — sonst bliebe nach einem Fehlschlag der zu grosse Wert stehen.
|
||||
old_entry = next((dict(e) for e in _load_registry() if e.get("key") == key), None)
|
||||
if repo:
|
||||
wanted = (payload.get("quant") or "Q4_K_M").strip()
|
||||
quant = wanted
|
||||
@@ -1012,6 +1036,10 @@ async def _handle_provision(ws, payload: dict) -> None:
|
||||
else:
|
||||
slots.pop(card, None)
|
||||
_save_slots(slots)
|
||||
reg = [e for e in _load_registry() if e.get("key") != key]
|
||||
if old_entry:
|
||||
reg.append(old_entry)
|
||||
_save_registry(reg)
|
||||
_generate_config()
|
||||
await _reload_llama()
|
||||
await _announce(ws)
|
||||
|
||||
Reference in New Issue
Block a user