feat(analyse): Kontextnotiz zum Gespraech nach dem Stop

Ein Freitextfeld ("Kontext zum Gespraech") in der Detailansicht, nach dem
Stop aufgeklappt. Der Text geht als Hintergrundwissen in die LLM-Analyse:
Personen, Firmen, Anlass und Eigennamen muessen nicht mehr aus dem
fehlerbehafteten ASR-Text erraten werden.

Bewusst EIN Feld statt eines Formulars mit Teilnehmer-/Anlass-/Begriffs-
feldern (Entscheidung des Nutzers): die Box benutzen auch technisch nicht
versierte Menschen. Gefuehrt wird ueber den Platzhaltertext, die Struktur
zieht die Analyse selbst aus der Prosa.

- recordings.context_note/-_at, db.setContextNote/getContextNote
- PATCH /api/recordings/:id/context; Antwort `applies` sagt ehrlich, ob die
  Notiz die laufende Verarbeitung noch erreicht (auto/running/reanalyze)
- analyzeRecording liest die Notiz erst kurz vor dem LLM-Aufruf, damit
  waehrend der minutenlangen Vorstufen Getipptes noch zaehlt
- llm.contextBlock: eigener """-Block mit Verbot, daraus Aussagen, Ergebnisse
  oder Aufgaben abzuleiten (sonst schreibt das 4B-Modell die Notiz als
  Gesagtes zurueck); eingespeist in Single-, Whole- und Sektions-Pfad
- zwei Deckel: 1200 Zeichen fuer Prompts, die die Notiz einmal sehen,
  600 fuer die Chunk-Prompts (dort landet sie in jedem Chunk von 3200)
- GUI-Karte zeichnet sich selbst neu (kein openRecording -> Audio laeuft
  weiter), ungespeicherter Text ueberlebt den Neuaufbau nach der Analyse

Verifiziert an #97: Kontext greift (korrekte Namen, richtiges Thema), die
absichtlich eingelegten Fremdfakten der Testnotiz erscheinen nicht in der
Zusammenfassung. Alte Analyse danach zurueckgeschrieben.

Doku: Kapitel 05 (neuer Abschnitt + Flussdiagramm + Deckel-Tabelle),
Kapitel 03 (Sequenzdiagramm + API), Changelog 2026-08-17.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude
2026-08-17 16:10:38 +02:00
parent 3d628b4b96
commit 0f530b575a
8 changed files with 332 additions and 30 deletions
+6
View File
@@ -22,6 +22,10 @@ sequenceDiagram
REC->>DB: WAV + MP3 + Zeile (status=transcribing)
SRV->>DB: addMarkers() → Tabelle markers
Note over REC: kehrt nach ~1,5 s zurück — GUI frei
GUI->>GUI: Kontextbox klappt auf (Freitext, seit 2026-08-17)
GUI->>SRV: PATCH /api/recordings/:id/context {context_note}
SRV->>DB: setContextNote() → recordings.context_note
Note over GUI,DB: Die Transkription läuft noch Minuten —<br/>der getippte Kontext ist rechtzeitig da (Kap. 05)
REC->>REC: A76-Takt kappen (1,6 GHz)
REC->>WH: transcribeWav() [BatchedInferencePipeline, batch=8]
WH-->>REC: Wörter + Zeitstempel
@@ -32,6 +36,7 @@ sequenceDiagram
SRV->>SRV: applyMarkers(): Cluster benennen + Stimmen lernen
REC->>REC: finally: Takt zurück
SRV->>LLM: analyzeRecording() (fire-and-forget, analysis_status=pending)
LLM->>DB: getContextNote() — Notiz erst JETZT gelesen (Kap. 05)
LLM->>DB: Titel/Summary/Teilnehmer/Todos (analysis_status=done, analysis_ms)
GUI->>SRV: Polling analysis_status
```
@@ -153,6 +158,7 @@ Datenverlust, aber auch keinen Weg mehr, die Aufnahme aus der GUI zu beenden. No
| `POST /api/recordings/:id/retranscribe` | Hängende/fehlgeschlagene Transkription neu starten |
| `POST /api/recordings/:id/reanalyze` `{numSpeakers?}` | Diarization **immer** neu (leer/0 = automatisch, Zahl = Anzahl gepinnt) + LLM neu |
| `POST /api/recordings/:id/reanalyze-llm` | Nur LLM neu, Diarization/Wörter bleiben |
| `PATCH /api/recordings/:id/context` `{context_note}` | Kontextnotiz speichern (leer = löschen); Antwort `applies` = `auto` / `running` / `reanalyze` sagt, ob die laufende Verarbeitung sie noch erreicht |
| `POST /api/recordings/:id/speaker` `{speaker,name,enroll}` | Sprecher benennen + optional Stimme lernen |
| `/api/glossary` (CRUD) | Eigennamen-Glossar |