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:
2026-10-19 13:32:37 +02:00
co-authored by Claude Opus 5.5
parent f8ae2f4613
commit 79a901089b
4 changed files with 71 additions and 7 deletions
+31 -1
View File
@@ -9175,13 +9175,25 @@
const job = Object.values(_llmJobs || {}).find(j => j.instanceId === b.instanceId && String(j.gpu) === String(sl.gpu)
&& !['ready', 'error'].includes(j.phase));
const jobTxt = job ? (job.phase === 'download' && job.percent != null ? `lädt ${job.percent.toFixed(0)} %` : 'lädt …') : '';
rows.push(`<div style="display:grid;grid-template-columns:minmax(220px,1fr) minmax(260px,2fr) 160px;gap:10px;align-items:center;">
// Kontextfenster dieser Karte. Mehr Kontext = mehr VRAM; passt es
// nicht, setzt die Box die Karte von selbst zurueck.
const CTX = [4096, 8192, 16384, 32768, 65536, 131072];
const curCtx = sl.ctx || 0;
const ctxOpts = (curCtx && !CTX.includes(curCtx) ? [curCtx, ...CTX] : CTX)
.map(n => `<option value="${n}"${n === curCtx ? ' selected' : ''}>${n >= 1024 ? (n / 1024) + 'k' : n} Tokens</option>`).join('');
const ctxSel = sl.model
? `<select data-box="${escapeHtml(b.instanceId)}" data-gpu="${escapeHtml(sl.gpu)}" data-model="${escapeHtml(sl.model)}" data-current="${curCtx}"
onchange="onLlmCardCtx(this)" ${job ? 'disabled' : ''} title="Kontextfenster (Eingabe + Ausgabe). Mehr braucht mehr Grafikspeicher."
style="background:#1E1E2E;border:1px solid #333;border-radius:4px;padding:5px 6px;color:#E0E0F0;font-size:12px;">${ctxOpts}</select>`
: '<span></span>';
rows.push(`<div style="display:grid;grid-template-columns:minmax(220px,1fr) minmax(260px,2fr) 130px 160px;gap:10px;align-items:center;">
<div><b style="color:#E0E0F0;">${escapeHtml(b.node)}</b> · Karte ${escapeHtml(sl.gpu)}
<div style="color:#555570;font-size:11px;">${escapeHtml(sl.gpuName || '')}${vramGB ? ' · ' + vramGB.toFixed(0) + ' GB' : ''}${sl.vramUsedMB >= 0 ? ' · belegt ' + (sl.vramUsedMB / 1024).toFixed(1) + ' GB' : ''}${sl.ctx ? ' · Kontext ' + sl.ctx : ''}</div>
${sl.onCpu ? '<div style="color:#FF9F0A;font-size:11px;" title="llama.cpp findet die Karte nicht und rechnet langsam auf der CPU. Ursache meist: Treiber zu alt fuer das CUDA im llama-swap-Image. Abhilfe: auf der Box sudo ./bootstrap.sh --upgrade-driver">⚠ Modell läuft auf der CPU, Karte leer — Treiber zu alt? (bootstrap.sh --upgrade-driver)</div>' : ''}</div>
<select data-box="${escapeHtml(b.instanceId)}" data-gpu="${escapeHtml(sl.gpu)}" data-current="${escapeHtml(sl.model || '')}"
onchange="onLlmCardSelect(this)" ${job ? 'disabled' : ''}
style="background:#1E1E2E;border:1px solid #333;border-radius:4px;padding:5px 8px;color:#E0E0F0;font-size:12px;">${opts.join('')}</select>
${ctxSel}
<span style="color:${job ? '#FFD60A' : c};font-size:12px;">${jobTxt || st}</span>
</div>`);
}
@@ -9189,6 +9201,24 @@
box.innerHTML = rows.join('');
}
// Kontextfenster einer Karte aendern = dasselbe Modell mit anderem -c neu
// laden. Programme bekommen den neuen Wert automatisch (ctx in
// llm_cluster_models). Passt es nicht in den Grafikspeicher, setzt die Box
// die Karte auf den alten Stand zurueck.
function onLlmCardCtx(sel) {
const target = sel.dataset.box, gpu = sel.dataset.gpu, model = sel.dataset.model;
const cur = Number(sel.dataset.current || 0), next = Number(sel.value);
if (next === cur) return;
const m = _llmCatalog.find(x => x.id === model);
if (!m || !m.hfRepo) { alert(`${model} steht nicht im Modell-Katalog — Kontext so nicht änderbar.`); sel.value = cur; return; }
const more = next > cur;
if (!confirm(`${model} auf ${_boxName(target)} · Karte ${gpu} mit ${next} statt ${cur || '?'} Tokens Kontext neu laden?\n\n`
+ (more ? 'Mehr Kontext braucht mehr Grafikspeicher. Passt es nicht, setzt die Box die Karte von selbst auf den alten Stand zurück.\n\n' : '')
+ 'Die Box startet ihre Modelle dabei kurz neu. Programme bekommen den neuen Wert automatisch.')) { sel.value = cur; return; }
send({ action: 'llm_provision_model', targetInstance: target, gpu, key: m.id, hfRepo: m.hfRepo, quant: m.quant, ctx: next });
openLlmDownloads();
}
function onLlmCardSelect(sel) {
const target = sel.dataset.box, gpu = sel.dataset.gpu, current = sel.dataset.current, next = sel.value;
const node = _boxName(target);