feat(llm): Downloads parallel, abbrechbar; heruntergeladene Modelle loeschen
llm-adapter: - Paralleler Download: llama.cpp zieht ueber EINE Verbindung (oft 1-50 MB/s, auch bei 1 Gbit). Die Box holt fehlende Dateien jetzt vorher selbst in 64-MB-Stuecken ueber LLM_DOWNLOAD_CONNECTIONS (Standard 8) Verbindungen, prueft die sha256 und legt sie im HF-Cache-Layout ab, das llama.cpp selbst benutzt (blobs/<sha256>, snapshots/<commit>/<datei>, refs/main). Die Karte bleibt waehrenddessen beim alten Modell. Scheitert es, laedt llama.cpp wie bisher selbst. Fortschritt zaehlt bei sparse-Dateien nur geschriebene Bytes. - Abbrechen: llm_remove_model mit cancel=true (kein neuer Typ → RVS-Allow-List unveraendert). Waehrend des Downloads: Stopp + halbe Datei weg, Karte unveraendert. Waehrend llama.cpp laedt: wie ein Fehlschlag → Karte zurueck. Laeuft nichts mehr, schliesst die Antwort den haengenden Eintrag. - Loeschen: llm_remove_model mit deleteFiles=true entfernt das Repo aus dem Cache — nicht, solange es auf einer Karte liegt oder geladen wird. - worker_hello meldet "disk": freier Platz + heruntergeladene Modelle je Repo. Diagnostic: Abbrechen-Knopf je laufendem Download; im Katalog "auf ki-box · 18,6 GB" mit Loeschen-Knopf und eine Zeile mit dem freien Platz je Box. Getestet gegen HuggingFace (ggml-org/tiny-llamas, 4 Verbindungen, 2-MB- Stuecke: Layout + Pruefsumme + Abbruch) und Loeschen inkl. Sperren. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -874,6 +874,7 @@ function workerList() {
|
||||
// aber diese Feldliste liess sie nie zum Browser durch ("meldet keine Karten").
|
||||
slots: Array.isArray(w.slots) ? w.slots : null,
|
||||
knownModels: w.knownModels || [],
|
||||
disk: w.disk || null, // LLM-Box: freier Platz + heruntergeladene Modelle
|
||||
online: (now - (w.last_seen || 0)) < WORKER_OFFLINE_MS,
|
||||
}));
|
||||
}
|
||||
@@ -1443,6 +1444,7 @@ function connectRVS(forcePlain) {
|
||||
// in eine Karte laden koennte.
|
||||
slots: Array.isArray(p.slots) ? p.slots : (prev.slots || null),
|
||||
knownModels: Array.isArray(p.knownModels) ? p.knownModels : (prev.knownModels || []),
|
||||
disk: p.disk || prev.disk || null,
|
||||
// OpenAI-Endpunkt (nur llm-Worker): Port/Bind kommen aus der .env der
|
||||
// Box, der Key wird NIE uebertragen — nur ob einer gesetzt ist und ob
|
||||
// die .env ihn vorgibt (dann ist das Feld hier schreibgeschuetzt).
|
||||
@@ -3611,9 +3613,11 @@ wss.on("connection", (ws) => {
|
||||
targetInstance: msg.targetInstance || "", gpu: String(msg.gpu ?? "") }, timestamp: Date.now() });
|
||||
log("info", "llm", `Karte ${msg.gpu} leeren → ${msg.targetInstance || "?"}`);
|
||||
} else if (msg.action === "llm_remove_model") {
|
||||
// cancel = laufenden Download abbrechen, deleteFiles = Dateien von der Platte
|
||||
sendToRVS_raw({ type: "llm_remove_model", payload: {
|
||||
targetInstance: msg.targetInstance || "", key: msg.key }, timestamp: Date.now() });
|
||||
log("info", "llm", `remove '${msg.key}' → ${msg.targetInstance || "?"}`);
|
||||
targetInstance: msg.targetInstance || "", key: msg.key, hfRepo: msg.hfRepo || "",
|
||||
cancel: !!msg.cancel, deleteFiles: !!msg.deleteFiles }, timestamp: Date.now() });
|
||||
log("info", "llm", `${msg.cancel ? "abbrechen" : msg.deleteFiles ? "Dateien loeschen" : "remove"} '${msg.key}' → ${msg.targetInstance || "?"}`);
|
||||
} else if (msg.action === "llm_test") {
|
||||
// Test-Chat: kurze Nachricht direkt ans lokale LLM (llm_request/llm_response).
|
||||
const reqId = "diagtest_" + Date.now();
|
||||
|
||||
Reference in New Issue
Block a user