diff --git a/server/src/transcribe/ollama.rs b/server/src/transcribe/ollama.rs index dbd3da9..a63a768 100644 --- a/server/src/transcribe/ollama.rs +++ b/server/src/transcribe/ollama.rs @@ -5,7 +5,7 @@ use tracing::debug; /// Smartwatch-aware system prompt: leading word must be the diagnosis/region /// so the doctor can distinguish cases from the watch face. -const SYSTEM_PROMPT: &str = "Du bist ein Assistent für Ärzte. Extrahiere aus dem folgenden deutschen medizinischen Diktat prägnante Schlüsselwörter in einer einzigen Zeile (so kurz wie möglich, idealerweise 3–6 Wörter, maximal 60 Zeichen).\n\nDer Oneliner wird auf einem winzigen Smartwatch-Display angezeigt. Nur die ersten Zeichen sind sicher lesbar, deshalb zählt das ERSTE WORT am meisten.\n\nRegeln:\n- Beginne mit dem wichtigsten Begriff: Körperregion, Organ oder markanter Befund (z.B. \"Kniegelenk\", \"Herzkatheter\", \"HOCM\", \"Thorax-CT\").\n- KEINE Füllwörter am Anfang: kein \"Patient\", \"Fall\", \"Verdacht auf\", \"Untersuchung von\", \"Diktat zu\", \"Zusammenfassung\", Artikel.\n- KEINE wertenden Adjektive wie \"massiv\", \"ausgeprägt\", \"deutlich\", \"hochgradig\" — nur nackte Begriffe.\n- Nenne Schlüsselwörter, an denen der Arzt den Fall wiedererkennt. Keine medizinische Interpretation, keine Therapievorschläge, keine Nebenbefunde.\n- Keine Anführungszeichen, kein Punkt am Ende, keine Einleitung.\n- Wenn der Arzt im Diktat eine eigene Bezeichnung nennt (z.B. \"Bezeichnung: …\" oder \"Fall-ID: …\"), übernimm GENAU diese als Anfang.\n- Nur die eine Zeile, nichts davor oder danach.\n\nBeispiele:\nDiktat: \"Also, Patient kommt mit Schmerzen im rechten Knie, V.a. Meniskusriss...\"\n→ Knie re., V.a. Meniskusriss\n\nDiktat: \"Bezeichnung: Schulter links. Impingement-Syndrom...\"\n→ Schulter links, Impingement\n\nDiktat: \"...HOCM mit ausgeprägter Septumhypertrophie, SAM-Phänomen, Valsalva-Manöver zeigt LVOT-Gradient...\"\n→ HOCM, Septumhypertrophie, SAM-Phänomen"; +const SYSTEM_PROMPT: &str = "Du bist ein Assistent für Ärzte. Extrahiere aus dem folgenden deutschen medizinischen Diktat prägnante Schlüsselwörter in einer einzigen Zeile (so kurz wie möglich, idealerweise 3–6 Wörter, maximal 60 Zeichen).\n\nDer Oneliner wird auf einem winzigen Smartwatch-Display angezeigt. Nur die ersten Zeichen sind sicher lesbar, deshalb zählt das ERSTE WORT am meisten.\n\nRegeln:\n- Beginne mit dem wichtigsten Begriff: Körperregion, Organ oder markanter Befund (z.B. \"Kniegelenk\", \"Herzkatheter\", \"HOCM\", \"Thorax-CT\").\n- KEINE Füllwörter am Anfang: kein \"Patient\", \"Fall\", \"Verdacht auf\", \"Untersuchung von\", \"Diktat zu\", \"Zusammenfassung\", Artikel.\n- KEINE wertenden Adjektive wie \"massiv\", \"ausgeprägt\", \"deutlich\", \"hochgradig\" — nur nackte Begriffe.\n- Nenne Schlüsselwörter, an denen der Arzt den Fall wiedererkennt. Keine medizinische Interpretation, keine Therapievorschläge, keine Nebenbefunde.\n- Keine Anführungszeichen, kein Punkt am Ende, keine Einleitung.\n- Wenn der Arzt im Diktat eine eigene Bezeichnung nennt (z.B. \"Bezeichnung: …\" oder \"Fall-ID: …\"), übernimm GENAU diese als Anfang.\n- Nur die eine Zeile, nichts davor oder danach.\n\nBeispiele:\nDiktat: \"Also, Patient kommt mit Schmerzen im rechten Knie, V.a. Meniskusriss...\"\n→ Knie re., V.a. Meniskusriss\n\nDiktat: \"Bezeichnung: Schulter links. Impingement-Syndrom...\"\n→ Schulter links, Impingement\n\nDiktat: \"...HOCM mit ausgeprägter Septumhypertrophie, SAM-Phänomen, Valsalva-Manöver zeigt LVOT-Gradient...\"\n→ HOCM, Septumhypertrophie, SAM-Phänomen. Wenn du kein Schlüsselwort findest, gib einen LEEREN String zurück."; /// Deterministic leading-filler prefixes stripped after the LLM response. /// The trailing space is part of the match — we only strip whole tokens. @@ -94,8 +94,14 @@ pub async fn generate_oneliner( keep_alive: keep_alive_seconds, options: Options { temperature: 0.2 }, messages: vec![ - Message { role: "system", content: SYSTEM_PROMPT }, - Message { role: "user", content: transcript }, + Message { + role: "system", + content: SYSTEM_PROMPT, + }, + Message { + role: "user", + content: transcript, + }, ], }; @@ -136,7 +142,11 @@ pub(crate) fn normalize(raw: &str) -> String { let mut s: &str = raw.trim(); // First non-empty line. - s = s.lines().find(|l| !l.trim().is_empty()).unwrap_or("").trim(); + s = s + .lines() + .find(|l| !l.trim().is_empty()) + .unwrap_or("") + .trim(); // A single pair of surrounding quotes (' or "). let bytes = s.as_bytes(); @@ -186,7 +196,10 @@ mod tests { #[test] fn normalize_passes_clean_input() { - assert_eq!(normalize("HOCM mit Septum-Hypertrophie"), "HOCM mit Septum-Hypertrophie"); + assert_eq!( + normalize("HOCM mit Septum-Hypertrophie"), + "HOCM mit Septum-Hypertrophie" + ); } #[test]