Diarisierung: Marker-Zwangsbedingungen absichern, Voiceprints als cannot-link; LLM: Sektions-Pfad ab 9k Zeichen

#79 verlor einen von vier Sprechern und lieferte eine 1082-Zeichen-Zusammenfassung.

Diarisierung: ein zweiter, falsch verankerter Marker verschmolz Saschas Cluster
in Merles (Kosinus -0,727). must-link prueft jetzt die akustische Aehnlichkeit,
Anker werden nach Trefferqualitaet gewichtet, und enrolled Stimmen wirken als
cannot-link -- damit ist der Box-Besitzer immer ein eigener Sprecher.

LLM: der Whole-Pass komprimierte das erste Thema weg. Sektions-Pfad jetzt ab
9000 Zeichen, kleinere Chunks, woertlicher Kontext aus dem Vorgaenger-Chunk und
ein gezielter Pruef-Aufruf gegen ueberdehnte Einzelaussagen.

#79: 4 Sprecher, Zusammenfassung ~5300 Zeichen, 7 Themenbloecke.
Regression: #70 -> 4, #68 -> 2, #74 -> 20 Sprecher unveraendert.
This commit is contained in:
2026-07-29 16:09:30 +02:00
parent c76f26abaf
commit 810cee1dba
9 changed files with 438 additions and 38 deletions
+42
View File
@@ -3,6 +3,48 @@
Chronik der Entwicklungsschritte. **Regel: jede zukünftige Änderung bekommt hier einen Eintrag** (Datum,
Was, Warum, betroffene Dateien/Backups).
## 2026-07-29 — #79: verlorener Sprecher + magere Zusammenfassung (Vergleich gegen MS Teams)
**Ausgangslage (Nutzer):** Aufnahme #79 (23-min-Marketing-Jour-fixe) wurde trotz live getippter Namen
falsch analysiert — 3 statt 4 Sprecher, Zusammenfassung 1 082 Zeichen ohne Inhalt. Als Messlatte lagen die
Teams-Notizen desselben Meetings vor (5 Themenblöcke + 3 Folgeaufgaben).
**Zwei unabhängige Ursachen, beide gemessen:**
1. *Diarisierung:* Stufe A lieferte korrekt 4 starke Cluster. Von 4 Markern mit 3 Namen landete der zweite
„Merle" auf **Saschas** Cluster; das bedingungslose must-link verschmolz beide (Kosinus **−0,727**).
2. *LLM:* 21k Zeichen < `WHOLE_MAX_CHARS` 32 000 und 3 < `MANY_SPEAKERS` 5 → Whole-Pass in einem Call →
das erste Thema (Timo/Sabbatical) fiel der Prompt-Kompression zum Opfer.
**Fixes `diar.js` (`.bak-marklink`):** Anker-Gewicht nach Trefferqualität (im Turn 1,0 → 25 s Tippverzögerung
0,2); must-link nur bei `cos ≥ 0,6 × gelernter Schwelle` (`DIAR_MARK_LINK_REL`), sonst Marker verwerfen +
loggen; Warnung bei mehreren Namen auf einem Cluster; **Voiceprints als cannot-link** (`DIAR_VP_MIN` 0,55,
Abstand 0,05, Namensschlüssel = Vorname) — damit ist der Box-Besitzer immer ein eigener Sprecher.
**Fixes `server.js` (`.bak-vpconstraint`, `.bak-uniqlabel`) / `recorder.js`:** Voiceprints werden in
`rediarize()` und `transcribeAndAnalyze()` in die Diarisierung durchgereicht; `applyMarkers()` verschmilzt
nur noch bei `conf = high` (`mid` benennt weiterhin); `buildBasis()` vergibt **eindeutige** Labels (in #79
trugen zwei Cluster „Markus", der LLM verschmolz daraufhin zwei Personen im Text); Stimmabdruck schlägt
einen unsicher verankerten Marker; `relabelAnalysis()` läuft am Ende JEDER Analyse (Namen, die während der
~20 min Laufzeit entstehen, landen sonst nie im fertigen Text — „Sprecher 1" blieb stehen).
**Fixes `llm.js` (`.bak-sectionmin`, `.bak-grounding`):** `SECTION_MIN_CHARS` = 9 000 (alles darüber in den
Sektions-Pfad), `MANY_SPEAKERS` 5 → 3, `CHUNK_CHARS` 4 200 → 3 200, `TAIL_CHARS` = 700 (wörtlicher Kontext
aus dem Vorgänger-Chunk), Prompt-Regeln „jedes Thema mind. ein Satz" + „nicht verallgemeinern", gezielter
Prüf-Aufruf bei Grundsatz-Aussagen, Verwerfen einer reinen Verabschiedungs-Sektion am Ende.
**Ergebnis #79:** 4 Sprecher (Sascha/Markus/Lisa/Merle, alle automatisch benannt), Zusammenfassung
**1 082 → ~5 300 Zeichen**, 7 Themenblöcke, 15–18 ToDos mit Verantwortlichen; alle Teams-Themen abgedeckt.
Regression geprüft: #70 → 4, #68 → 2, #74 → 20 Sprecher (unverändert).
**Neu im Labor:** `app/lab/lab-eval2.mjs` (Replay des echten `clusterWindows()` MIT Voiceprints),
`app/lab/vp-dump.mjs` (Voiceprints als JSON). Damit kostet eine Clustering-Iteration Sekunden statt eines
sherpa-Laufs.
**Betriebs-GOTCHA:** der A76-Takt wurde für einen sherpa-Lab-Lauf auf 2,256 GHz gesetzt — 88–89 °C, kurz
darauf hing das Board (kein Ping auf LAN und WLAN, Hard-Reset nötig). Lüfterlos gilt weiter: schwere Jobs
seriell und Cap 1,6 GHz. Nach dem Neustart hat der R1 per DHCP **192.168.1.48** bekommen (vorher .200).
## 2026-07-28 — GUI: alle Tabs nutzen die volle Fensterbreite
- **Problem:** nur „Aufnahmen" bekam `#app.wide` (max-width: none), Stimmen/Glossar/Bluetooth blieben auf