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:
@@ -239,6 +239,57 @@ flowchart LR
|
||||
Wichtig: Begriffslisten **niemals** als Whisper-`--initial-prompt` (Echo-Loop, verifiziert) und dem 3–4B-Modell
|
||||
keine „ersetze X durch Y“-Anweisung anvertrauen (unzuverlässig) — deshalb die deterministische Text-Ersetzung.
|
||||
|
||||
## Kontextnotiz des Nutzers (seit 2026-08-17)
|
||||
|
||||
Nach dem Stop bietet die Detailansicht **ein Freitextfeld** an: „Kontext zum Gespräch“. Was dort steht,
|
||||
geht als **Hintergrundwissen** in die Analyse — nicht als Gesprächsinhalt. Damit weiß das Modell, wer
|
||||
dabei war, worum es ging und wie Eigennamen geschrieben werden, statt das alles aus fehlerbehaftetem
|
||||
ASR-Text zu erraten.
|
||||
|
||||
**Bewusst EIN Feld, kein Formular** (Entscheidung des Nutzers): die Box benutzen später auch technisch
|
||||
nicht versierte Menschen, und „Kontext hinzufügen“ ist eine Hürde weniger als Teilnehmer-, Anlass- und
|
||||
Begriffsfelder auszufüllen. Die Struktur zieht sich die Analyse selbst aus der Prosa. Geführt wird über
|
||||
den **Platzhaltertext** („Wer war dabei, worum ging es, wichtige Namen oder Begriffe? … z. B.: Call mit
|
||||
Herrn Meier von Firma Krämer wegen Angebot Halle 3 …“) statt über Pflichtfelder.
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
STOP["Stop gedrückt"] --> BOX["Kontextbox klappt AUF und ist fokussiert<br/>(state.ctxPromptFor, main.js)"]
|
||||
BOX --> SAVE["PATCH /api/recordings/:id/context<br/>db.setContextNote → recordings.context_note<br/>(Deckel 4 000 Zeichen, leer = löschen)"]
|
||||
SAVE --> WHEN{"Wie weit ist die<br/>Verarbeitung?"}
|
||||
WHEN -- "status=transcribing" --> AUTO["applies='auto':<br/>Analyse liest die Notiz danach → fließt sicher ein"]
|
||||
WHEN -- "analysis_status=pending" --> RUN["applies='running':<br/>Analyse läuft schon, kann die Notiz verpasst haben<br/>→ GUI verweist auf '↻ Analyse neu'"]
|
||||
WHEN -- "done / error" --> RE["applies='reanalyze':<br/>GUI fragt nach und startet reanalyze-llm<br/>(Sprecher bleiben, nur LLM neu)"]
|
||||
AUTO --> READ
|
||||
RE --> READ
|
||||
READ["analyzeRecording: db.getContextNote(id)<br/>ERST kurz vor dem LLM-Aufruf gelesen<br/>(Sprecher-Erkennung davor dauert Minuten —<br/>was der Nutzer in der Zeit tippt, zählt noch)"] --> INJ["llm.analyze({context}) → contextBlock()"]
|
||||
INJ --> P1["analyzeSingle: PROMPT_CLEAN(_LABELED) + PROMPT_JSON"]
|
||||
INJ --> P2["analyzeWhole: PROMPT_WHOLE_ANALYZE"]
|
||||
INJ --> P3["analyzeLong: JEDER Chunk-Prompt (gekürzt)<br/>+ Titel- und Überblick-Mikro-Call"]
|
||||
```
|
||||
|
||||
**Halluzinationsbremse.** Die Notiz steht in einem eigenen, mit `"""` abgegrenzten Block mit der
|
||||
ausdrücklichen Auflage: nur für Schreibweisen, Zuordnung, Anlass und Gewichtung nutzen, **keine**
|
||||
Aussagen, Ergebnisse, Entscheidungen oder Aufgaben daraus übernehmen, Notiz nicht erwähnen. Ohne diese
|
||||
Klammer schreibt ein 4B-Modell die Notiz als Gesagtes in die Zusammenfassung zurück — dieselbe Falle wie
|
||||
beim `CORRECTION_HINT` (siehe dessen STRENG-Satz).
|
||||
|
||||
**Zwei Deckel**, weil die Notiz je Pfad unterschiedlich oft im Prompt landet:
|
||||
|
||||
| Konstante | Wert | Gilt für |
|
||||
|---|---|---|
|
||||
| `db.CONTEXT_MAX` | 4 000 Zeichen | Speicherung (Spalte ist TEXT) |
|
||||
| `LLM_CONTEXT_CHARS` | 1 200 Zeichen | Prompts, die die Notiz **einmal** sehen (Single/Whole/Titel/Überblick) |
|
||||
| `LLM_CONTEXT_CHUNK_CHARS` | 600 Zeichen | Chunk-Prompts des Sektions-Pfads — dort geht die Notiz in **jeden** Chunk (`CHUNK_CHARS` = 3 200, eine lange Notiz wäre ein Drittel Ballast) |
|
||||
|
||||
Im Sektions-Pfad fällt die Notiz auf dem **letzten** von drei Versuchen zusammen mit dem `hint` weg: hat
|
||||
das Modell zweimal die Feldbeschreibung nachgeplappert, ist jeder Zusatztext vor dem Abschnitt verdächtig.
|
||||
|
||||
**Grenze:** die Notiz verbessert Titel, Zusammenfassung, Teilnehmer und ToDos. Das **Transkript selbst**
|
||||
verbessert sie nicht — Whisper ist zu dem Zeitpunkt schon gelaufen, und Begriffslisten dürfen ohnehin
|
||||
nicht als `--initial-prompt` an Whisper (Echo-Loop, siehe Glossar-Abschnitt). Wer Schreibweisen dauerhaft
|
||||
korrigiert haben will, nimmt das Glossar; die Notiz gilt nur für dieses eine Gespräch.
|
||||
|
||||
## Zusammenspiel mit Whisper auf der NPU
|
||||
|
||||
rkllm (LLM) und Whisper-NPU-Encoder können nicht gleichzeitig resident sein (RAM-Contention, äußerte sich
|
||||
|
||||
Reference in New Issue
Block a user