Consolidate analysis prompt and extend domain vocabulary

Sandbox-validated against case c414cf52 (3 runs each, fair pre+post-LLM
gazetteer pipeline): the new prompt eliminates two hallucination classes
the prior version produced — unmarked "Hypotonie" when the dictation said
"Hypertonie" (0/3 vs 2/3) and inventing units like "35 ng/l" for values
without unit (0/3 vs 2/3) — while keeping Latin terms (Punctum Maximum
etc.) intact in 3/3 runs vs 2/3.

Block layout reorganized so each rule appears exactly once: AUFGABE /
QUELLE / KORREKTUR-POLITIK / TREUE / CHRONOLOGIE / DOSIERUNGSSCHEMA /
MARKIERUNGEN. The removed "AKTIVE KORREKTUR (nicht durchreichen)" hammer
block is no longer load-bearing because the gazetteer's pre-LLM pass now
catches the typical drug-name typos before the LLM sees them.

Vocabulary additions (single-token, alphabetical, ≥5 chars):
- vocabulary.txt: Enoxaparin (was missing — Inoxaparin→Enoxaparin is a
  recurrent ASR error and the prior pipeline relied on the LLM alone)
- medical_terms.txt (new file, picked up by the dir-glob loader):
  Holosystolikum, Klappenvitien, Koronarbaum, Pumpfunktion
This commit is contained in:
2026-04-27 23:27:05 +02:00
parent 86e7affbc6
commit 330e84e473
3 changed files with 35 additions and 27 deletions
+25 -27
View File
@@ -3,44 +3,42 @@ use super::AnalysisInput;
/// System prompt for the consolidation LLM. /// System prompt for the consolidation LLM.
/// Temperature 0 is set on the request; the prompt enforces "no interpretation". /// Temperature 0 is set on the request; the prompt enforces "no interpretation".
/// ///
/// Sandbox-validated against case c414cf52 (3 runs each): /// Sandbox-validated against case c414cf52 (3 runs each, fair pipeline with
/// - active correction of known drug names (Inoxaparin→Enoxaparin etc.) /// pre- and post-LLM gazetteer pass against the current vocab):
/// without curve-fitting examples /// - eliminates two hallucination classes the previous prompt produced —
/// - explicit fidelity clause for anatomical locations, values+units, /// unmarked "Hypotonie" when the dictation said "Hypertonie" (0/3 vs 2/3),
/// recording order /// and inventing a unit ("35 ng/l") for a dictated value without unit
/// - explicit conflict-resolution: take the chronologically latest /// (0/3 vs 2/3)
/// statement, never fabricate a "course of events" narrative /// - keeps Latin terms intact ("Punctum Maximum", "Apex Cordis", "Axilla"
/// - explicit format clause: flowing prose, no inline section markers, /// in 3/3 vs 2/3)
/// no markdown headings /// - relies on the gazetteer for drug-name correction (Enoxaparin etc.) —
/// the prompt no longer needs a separate "AKTIVE KORREKTUR" hammer-block
/// because the gazetteer's pre-LLM pass repairs the typical typos before
/// the LLM ever sees them
/// - block layout: AUFGABE / QUELLE / KORREKTUR-POLITIK / TREUE / CHRONOLOGIE
/// / DOSIERUNGSSCHEMA / MARKIERUNGEN — each rule appears exactly once
pub const SYSTEM_PROMPT: &str = r#"Du bist ein medizinischer Assistent. pub const SYSTEM_PROMPT: &str = r#"Du bist ein medizinischer Assistent.
Fasse die folgenden diktierten Abschnitte zu einem zusammenhängenden Fließtext zusammen. Bereinigen und strukturieren, nichts hinzufügen, keine medizinische Interpretation, keine Diagnose, keine Arztbrief-Struktur. Entferne Redundanzen. Antworte auf Deutsch. Nur der zusammengefasste Text, keine Einleitung, kein Abschlusssatz. AUFGABE: Fasse die folgenden diktierten Abschnitte zu einem zusammenhängenden, deutschen Fließtext zusammen — bereinigen und strukturieren, keine Diagnose, keine Arztbrief-Struktur, keine Einleitung, kein Abschlusssatz, nur der konsolidierte Text. Mehrere Absätze erlaubt. KEINE Inline-Sektionsmarker (kein "Status:", "Diagnostik:", "Therapie:", "Plan:"), KEINE Markdown-Headings, KEINE Aufzählungspunkte.
FORMAT: Ein einziger zusammenhängender Fließtext, mehrere Absätze erlaubt. KEINE Inline-Sektionsmarker (kein "Status:", "Diagnostik:", "Therapie:", "Plan:"), KEINE Markdown-Headings, KEINE Aufzählungspunkte. QUELLE: Das Diktat wurde automatisch transkribiert und entlt typische ASR-Fehler — phonetisch ähnliche Verwechslungen und zerschnittene Komposita (z.B. "Spolade" statt "Schokolade", "posbrandial" statt "postprandial", "in Faust" statt "infaust").
WICHTIG: Das Diktat wurde automatisch transkribiert und enthält typische ASR-Fehler wie phonetisch ähnliche Verwechslungen und zerschnittene Komposita (z.B. "Spolade" statt "Schokolade", "posbrandial" statt "postprandial", "in Faust" statt "infaust"). Korrigiere diese Fehler AKTIV. Bei Unsicherheit, wie die Korrektur lauten müsste: behalte das Original bei und markiere es.
AKTIVE KORREKTUR (nicht durchreichen): Bekannte Wirkstoffnamen, etablierte medizinische Akronyme und Standard-Termini sind aktiv zu korrigieren, wenn der ASR-Fehler eindeutig ist. Wenn die korrigierte Form ein bekannter Wirkstoff oder Standard-Begriff ist und keine andere medizinische Lesart Sinn ergibt: Korrektur ohne Markierung übernehmen.
KORREKTUR-POLITIK:
- Bekannte Wirkstoffnamen, etablierte medizinische Akronyme und Standard-Termini bei eindeutigem ASR-Fehler aktiv und unmarkiert korrigieren.
- Bei Unsicherheit: Original behalten und mit ==...== markieren statt zu raten. KEINE medizinisch klingenden Komposita aus phonetischer Nähe konstruieren.
TREUE ZUM DIKTAT (höchste Priorität — vor allen anderen Regeln): TREUE ZUM DIKTAT (höchste Priorität — vor allen anderen Regeln):
- Anatomische Lokalisationen, Werte mit Einheiten, Wirkstoffnamen, Dosierungen und genannte Befunde NIEMALS umformulieren, eindampfen oder weglassen. Wörtlich übernehmen. - Anatomische Lokalisationen, Werte mit Einheiten, Wirkstoffnamen, Dosierungen und genannte Befunde NIEMALS umformulieren, eindampfen oder weglassen. Wörtlich übernehmen.
- KEINE medizinisch klingenden Komposita aus phonetischer Nähe konstruieren. Wenn ein Token kein klares Wort ergibt: markiere es mit ==...== und lass den Rohinhalt stehen, statt zu raten. - KEINE neuen Tatsachen oder medizinischen Interpretationen hinzufügen, auch nicht naheliegende.
- KEINE neuen Tatsachen hinzufügen, auch nicht naheliegende medizinische Interpretationen. - Werte mit Einheiten zusammenhalten ("35 ng/l", nicht nur "35"). Fehlt die Einheit im Diktat: Zahl markieren.
- Werte mit Einheiten zusammenhalten ("35 ng/l", nicht nur "35"). Wenn die Einheit im Diktat fehlt: markiere die Zahl.
CHRONOLOGIE:
- Diktat-Reihenfolge erhalten — Befunde aus späteren Aufnahmen nicht in die Anamnese verschieben, auch wenn sie thematisch verwandt wirken. - Diktat-Reihenfolge erhalten — Befunde aus späteren Aufnahmen nicht in die Anamnese verschieben, auch wenn sie thematisch verwandt wirken.
- Bei widersprüchlichen Aussagen über mehrere Aufnahmen die chronologisch letzte übernehmen, die frühere weglassen oder als ==text== markieren. KEINE Verlaufsgeschichte konstruieren (NICHT "die im weiteren Verlauf als X beurteilt wird"). Wenn eine frühere Aufnahme einen offensichtlichen ASR-Fehler enthält und alle späteren die korrigierte Form zeigen: die spätere als korrekt nehmen, früheren Fehler nicht erwähnen.
WIDERSPRÜCHE ZWISCHEN AUFNAHMEN: Bei widersprüchlichen Aussagen über mehrere Aufnahmen die chronologisch letzte Aussage übernehmen, die frühere weglassen oder als ==text== markieren. KEINE Verlaufsgeschichte konstruieren (NICHT "die im weiteren Verlauf als X beurteilt wird"). Wenn eine frühere Aufnahme einen offensichtlichen ASR-Fehler enthält und alle späteren Aufnahmen die korrigierte Form zeigen: die spätere als korrekt nehmen, früheren Fehler nicht erwähnen.
DOSIERUNGSSCHEMA: 34 kleine Zahlen im Medikationskontext sind morgens-mittags-abends(-nachts). Schreibe kompakt: "eins null zwei" → "1-0-2", "eins null zwei null" → "1-0-2-0". Nur bei klarem Medikationskontext anwenden, sonst Original behalten und markieren. DOSIERUNGSSCHEMA: 34 kleine Zahlen im Medikationskontext sind morgens-mittags-abends(-nachts). Schreibe kompakt: "eins null zwei" → "1-0-2", "eins null zwei null" → "1-0-2-0". Nur bei klarem Medikationskontext anwenden, sonst Original behalten und markieren.
MARKIERUNGEN IM FORMAT "==text==" signalisieren dem Arzt "bitte prüfen". MARKIERUNGEN: ==text== signalisiert dem Arzt "bitte prüfen". Sparsam einsetzen — eindeutig korrigierte Wirkstoffe und klar gesprochene Fachbegriffe bleiben unmarkiert. Keine anderen Annotations-Formen ("(unsicher)", "[TODO]" o.ä.) verwenden."#;
Markiere jede zweifelhafte Stelle, bei der die Korrektur nicht eindeutig ist.
Markiere zusätzlich: Zahlen ohne klaren Kontext oder Einheit.
Markiere sparsam — eindeutig korrigierte Wirkstoffe und geläufige, klar gesprochene Fachbegriffe bleiben unmarkiert.
WICHTIG: Es sind keine anderen Arten von Annotationen erlaubt (z.B. "(unsicher)", "[TODO]")."#;
/// Render the user-content portion of the chat request from the persisted /// Render the user-content portion of the chat request from the persisted
/// JSON input. Recordings with blank text are skipped — they carry no signal /// JSON input. Recordings with blank text are skipped — they carry no signal
+9
View File
@@ -0,0 +1,9 @@
# Medical domain terms (anatomy, findings, technical compound nouns).
# Single-token entries only — multi-word terms ("Punctum maximum") cannot
# be represented because the tokenizer splits on whitespace.
# Same conventions as vocabulary.txt: ≥5 chars, alphabetical, one per line,
# phonetically distinctive (DL≤2 must not collide with everyday German).
Holosystolikum
Klappenvitien
Koronarbaum
Pumpfunktion
+1
View File
@@ -48,6 +48,7 @@ Duloxetin
Edoxaban Edoxaban
Eliquis Eliquis
Enalapril Enalapril
Enoxaparin
Erythromycin Erythromycin
Escitalopram Escitalopram
Esomeprazol Esomeprazol