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:
@@ -3,6 +3,67 @@
|
||||
Chronik der Entwicklungsschritte. **Regel: jede zukünftige Änderung bekommt hier einen Eintrag** (Datum,
|
||||
Was, Warum, betroffene Dateien/Backups).
|
||||
|
||||
## 2026-08-17 — Kontext zum Gespräch: ein Freitextfeld nach dem Stop
|
||||
|
||||
**Wunsch:** nach dem Beenden einer Aufnahme die Möglichkeit haben, Kontext zum gerade geführten
|
||||
Call/Meeting zu ergänzen — das verbessert die Analyse nach dem Transkript erheblich, weil das Modell
|
||||
Personen, Firmen, Anlass und Eigennamen nicht mehr aus fehlerbehaftetem ASR-Text erraten muss.
|
||||
|
||||
**Entscheidung des Nutzers: EIN Freitextfeld, kein Formular.** Ein Vorschlag mit Teilnehmer-, Anlass-,
|
||||
Projekt- und Begriffsfeldern wurde ausdrücklich verworfen: die Box benutzen später auch technisch nicht
|
||||
versierte Menschen, und „Kontext hinzufügen“ ist eine Hürde weniger als vier Pflichtfelder. Geführt wird
|
||||
über den Platzhaltertext, die Struktur (Namen, Begriffe) zieht sich die Analyse selbst aus der Prosa.
|
||||
|
||||
**Umsetzung:**
|
||||
|
||||
- Neue Spalten `recordings.context_note` / `context_note_at` (`ensureSchema`), `db.setContextNote()`
|
||||
(Deckel 4 000 Zeichen, leerer Text löscht) und `db.getContextNote()`.
|
||||
- `PATCH /api/recordings/:id/context`. Die Antwort enthält `applies` und sagt damit **ehrlich**, ob die
|
||||
Notiz die laufende Verarbeitung noch erreicht: `auto` (wird noch transkribiert → fließt sicher ein),
|
||||
`running` (Analyse läuft schon, kann sie verpasst haben), `reanalyze` (fertig → nur ein neuer Lauf
|
||||
nutzt sie; die GUI fragt dann nach und startet `reanalyze-llm`).
|
||||
- `analyzeRecording()` liest die Notiz **erst kurz vor dem LLM-Aufruf** (`db.getContextNote`), nicht aus
|
||||
der Zeile vom Anfang: Sprecher-Erkennung und Transkription davor brauchen Minuten, und was der Nutzer
|
||||
in dieser Zeit tippt, soll noch mitzählen.
|
||||
- `llm.js`: neuer `contextBlock()` — die Notiz kommt in einem eigenen `"""`-Block mit der Auflage, sie
|
||||
**nur** für Schreibweisen, Zuordnung, Anlass und Gewichtung zu nutzen und daraus keine Aussagen,
|
||||
Ergebnisse oder Aufgaben abzuleiten. Eingespeist in alle Pfade: `analyzeSingle` (`PROMPT_CLEAN`,
|
||||
`PROMPT_CLEAN_LABELED`, `PROMPT_JSON`), `analyzeWhole` (`PROMPT_WHOLE_ANALYZE`) und `analyzeLong`
|
||||
(jeder Chunk-Prompt + Titel- und Überblick-Mikro-Call). Zwei Deckel: 1 200 Zeichen für die Prompts, die
|
||||
die Notiz einmal sehen, 600 für die Chunk-Prompts (dort landet sie in **jedem** Chunk von 3 200
|
||||
Zeichen). Auf dem letzten von drei Chunk-Versuchen fällt sie mit dem `hint` weg.
|
||||
- GUI: Karte „📝 Kontext zum Gespräch“ über den Modulen der Detailansicht. Nach dem Stop steht sie offen
|
||||
und fokussiert (`state.ctxPromptFor`), sonst eingeklappt mit dem gespeicherten Text und
|
||||
„✏️ Bearbeiten“. Sie zeichnet sich **selbst** neu statt über `openRecording()` — ein Neuaufbau der
|
||||
Detailansicht setzt den `<audio>`-Tag zurück und würde das Abspielen unterbrechen. Getippter,
|
||||
ungespeicherter Text überlebt den Neuaufbau nach Ende der Analyse (`state.ctxDrafts`). Strg+Enter
|
||||
speichert, Enter macht Absätze.
|
||||
|
||||
**Verifiziert** an der laufenden App: Endpunkt liefert `applies:"reanalyze"` bei fertiger Analyse und
|
||||
`applies:"auto"` während einer laufenden Transkription (8-s-Wegwerfaufnahme #115, danach in den
|
||||
Papierkorb). Echter LLM-Lauf auf #97 (37 s, Single-Pfad) mit einer Testnotiz: Log zeigt
|
||||
`llm: Kontextnotiz des Nutzers wird mitgegeben (196 Zeichen)`, die Zusammenfassung wurde messbar besser
|
||||
(„Stimmerkennung“ + korrekte Namen Sascha/Fabio statt des ASR-Fehlers „Audioaufnahme … Lichter-Modus“ mit
|
||||
falscher Sprecherzuordnung) — und die absichtlich in die Notiz gelegten Fremdfakten („Rückruf ist für
|
||||
Freitag geplant“, „Halle 3 wurde verkauft“) tauchten **nicht** in Zusammenfassung oder ToDos auf, die
|
||||
Halluzinationsbremse hält also. Die alte Analyse von #97 war vor dem Test gesichert und wurde danach
|
||||
zurückgeschrieben, die Testnotiz entfernt. `vite build` sauber, `systemctl restart callrec` erst nach
|
||||
Prüfung auf `analysis_status='pending'`.
|
||||
|
||||
**Offene Grenze:** die Notiz verbessert Titel/Zusammenfassung/Teilnehmer/ToDos, nicht das Transkript —
|
||||
Whisper ist zu dem Zeitpunkt schon gelaufen. Dauerhaft falsche Schreibweisen gehören ins Glossar.
|
||||
Ebenfalls noch nicht: die Notiz im Suchindex (`passages`) und ein Hinweis „kein Kontext“ in der
|
||||
Aufnahmenliste.
|
||||
|
||||
Dateien: `app/db.js` (`ensureSchema`, `setContextNote`, `getContextNote`, `CONTEXT_MAX`), `app/server.js`
|
||||
(`PATCH …/context`, `analyzeRecording`), `app/llm.js` (`contextBlock`, `CONTEXT_MAX_CHARS`,
|
||||
`CONTEXT_CHUNK_CHARS`, alle Prompt-Bausteine + `analyze/analyzeSingle/analyzeWhole/analyzeLong`),
|
||||
`app/web/src/main.js` (Kontextkarte, `state.ctxPromptFor`/`ctxDrafts`, `toggleRecord`),
|
||||
`app/web/src/style.css` (`.ctxbox`, `.ctx-*`).
|
||||
Board-Backups: `.bak-ctxnote` (db.js, server.js, llm.js, web/src/main.js, web/src/style.css).
|
||||
Kapitel 05 (neuer Abschnitt „Kontextnotiz des Nutzers" + Flussdiagramm + Deckel-Tabelle), Kapitel 03
|
||||
(Sequenzdiagramm + API-Tabelle).
|
||||
|
||||
## 2026-08-14 — Angeheftete Aufnahmen per Drag & Drop zwischen Unterreitern verschieben
|
||||
|
||||
**Wunsch:** eine im Projekt abgelegte Aufnahme sollte sich innerhalb des Ordners umhängen lassen, z. B. von
|
||||
|
||||
Reference in New Issue
Block a user