fix(ram): nur ein grosses Modell resident (Analyse starb im OOM-Killer)

rkllm_server braucht 6,5 GB von 7,74 GB. Blieb daneben ein anderer
Dauerhelfer resident, wurde rkllm beim Laden OOM-getoetet -- bei #101 in
allen 5 Startversuchen, weil das Retry nichts freigab. Ausloeser war der
warme CT2-Whisper-Daemon, den die 2-Sekunden-Aufnahme davor gestartet
hatte. Zweiter Fall: rkllm blieb nach der Analyse fuer immer resident, und
der Suchindex startete e5-small daneben.

gate.js bekommt eine Freigabe-Registry (registerReleaser/freeRam/
killAndWait, verdrahtet in server.js wie setProbe). Vor jedem rkllm-Versuch
und vor dem NPU-Whisper-Lauf werden die anderen Helfer beendet und ihr
Prozessende abgewartet; analyzeRecording gibt rkllm vor dem Suchindex frei.
Alle Helfer starten faul neu.

Verifiziert mit der Abfolge, die scheiterte: 12-s-Clip (CT2-Daemon
resident) -> Analyse #101 laeuft durch (221 s, done), rkllm lud in 22 s,
kein OOM, danach 5,3 GB frei statt 100 MB.
This commit is contained in:
2026-08-07 15:55:31 +02:00
parent c5daee25af
commit ff285011d2
8 changed files with 277 additions and 7 deletions
+38
View File
@@ -3,6 +3,44 @@
Chronik der Entwicklungsschritte. **Regel: jede zukünftige Änderung bekommt hier einen Eintrag** (Datum,
Was, Warum, betroffene Dateien/Backups).
## 2026-08-07 (2) — „KI-Analyse fehlgeschlagen" bei einer 34-Sekunden-Aufnahme: zwei Modelle gleichzeitig
**Symptom:** Aufnahme #101 (34 s, 2 Personen) — Transkript und Sprecherspuren da, aber
„KI-Analyse fehlgeschlagen". Also **nicht** dieselbe Ursache wie der Vormittags-Fix: der betraf die
Länge, dieser die *Reihenfolge*. Gemeinsam ist nur der OOM-Killer.
**Ursache 1:** `rkllm_server` braucht 6,5 GB von 7,74 GB. Die 2-Sekunden-Aufnahme #100 unmittelbar davor
hatte über den Kurz-Clip-Pfad den warmen CT2-Whisper-Daemon (0,9 GB) gestartet, der per Design resident
bleibt. Beim rkllm-Load war er noch da → OOM-getötet, und zwar in **allen 5 Startversuchen**, weil das
Retry nichts freigab: `[rkllm] start 5/5 failed: rkllm beendet vor READY`.
**Ursache 2:** rkllm blieb nach einer Analyse für immer resident (der Prozess von 10:37 lebte um 13:27
noch). Der Suchindex am Ende von `analyzeRecording()` startet aber e5-small (1,15 GB) — daneben erschlug
der Kernel rkllm (13:27:09). Dasselbe Muster war auch der Dauerzustand „nur ~100 MB frei".
**Fix:** `gate.js` bekommt eine Freigabe-Registry (`registerReleaser`/`freeRam(keep)`/`killAndWait`,
verdrahtet in `server.js` wie schon `setProbe`). Wer ein großes Modell lädt, beendet vorher die anderen
Dauerhelfer und wartet auf ihr Prozessende — vor **jedem** der 5 rkllm-Versuche und vor dem
NPU-Whisper-Lauf. Dazu gibt `analyzeRecording()` rkllm frei, **bevor** der Suchindex läuft. Alle Helfer
starten faul neu; verloren geht nur Ladezeit.
**Verifiziert** mit genau der Abfolge, die scheiterte: 12-s-Clip (CT2-Daemon resident) → Analyse #101 →
`ram: für rkllm freigegeben — cpu-transcriber, text-embedder, spk-embedder`, rkllm lud in 22 s, Analyse
„Auto und Budget" in 221 s fertig (`done`), kein OOM, danach **5,3 GB frei** statt 100 MB.
Dateien: `app/gate.js`, `app/llm.js`, `app/server.js`, `app/recorder.js`, `app/spk.js`, `app/emb.js`
(Board-Backups `.bak-ramfree`), Kapitel [05 – LLM-Analyse](05-llm-analyse.md) (neuer Abschnitt
„Speicherhaushalt" mit Messtabelle und Diagramm).
**Offen, getrennt davon (gemessen, nicht gefixt):** dieselbe Aufnahme zeigt 4 Sprecher statt 2, und die
Stimmabdruck-Erkennung ist auf ROHEN Kosinus nicht trennscharf — `Sascha` ↔ `Sascha Wolf` (dieselbe
Person, zwei Einträge) liegt bei 0,928, aber `Sascha Wolf` ↔ `Johannes` (verschiedene Personen) bei
**0,912** und `Sascha` ↔ `Fabio Haase` bei 0,876. Bei `DIAR_VP_MIN` 0,55 passt damit fast jeder auf
jeden; eine höhere Schwelle würde nur alles ablehnen. `Jens` ↔ `Jens Kuppler` ist mit Kosinus **1,000**
sogar eine exakte Dublette. Der Clustering-Teil hat dieses Problem 2026-07-27 durch Mittelwert-Zentrierung
gelöst — die Abdruck-Erkennung arbeitet noch ohne. Dazu kommt die Über-Segmentierung kurzer Clips
(diagnostiziert 2026-07-31, Kap. 04).
## 2026-08-07 — Lange Aufnahmen scheiterten: sherpa-Diarisierung lief in den OOM-Killer
**Symptom:** Aufnahme #99 (53:56) endete mit „Transkription fehlgeschlagen“ (Badge „KI-Fehler“), beim