${esc(d.anliegen)}
diff --git a/pipe/categorize.py b/pipe/categorize.py index b9802bb..d161060 100644 --- a/pipe/categorize.py +++ b/pipe/categorize.py @@ -61,6 +61,7 @@ _SCHEMA = { "anrufer_name": {"type": ["string", "null"]}, "rueckrufnummer": {"type": ["string", "null"]}, "rueckruf_gewuenscht": {"type": "boolean"}, + "email": {"type": ["string", "null"]}, "sprache": {"type": "string"}, "anliegen_kurz": {"type": "string"}, "stichworte": {"type": "array", "items": {"type": "string"}}, @@ -70,10 +71,34 @@ _SCHEMA = { # sie im Transkript standen. Der Typ erlaubt weiterhin null, wenn nichts da ist. "required": [ "kategorie", "dringlichkeit", "anrufer_name", "rueckrufnummer", - "rueckruf_gewuenscht", "sprache", "anliegen_kurz", "stichworte", + "rueckruf_gewuenscht", "email", "sprache", "anliegen_kurz", "stichworte", ], } +# Deterministische Reparatur, wenn Whisper gesprochenes "at" beim Diktieren +# einer E-Mail-Adresse als Punkt transkribiert statt als "@" (beobachtet: +# "gdg at dillenberg punkt net" -> Transkript "gdg.dillenberg.net", komplett +# ohne @ - kein Kategorisierungs-, sondern ein Spracherkennungs-Problem). +# Nur ein Repair-Vorschlag, kein stiller Ersatz: das erste Segment (ohne +# eigenen Punkt) vor einer domain.tld-Form wird zu einem @ - mehrdeutig +# (koennte auch eine genannte Subdomain sein), deshalb im UI als "vermutete +# Korrektur" markiert statt das Transkript selbst zu veraendern. +_EMAIL_OHNE_AT = re.compile( + r"^([a-z0-9_-]+)\.([a-z0-9-]+\.[a-z]{2,})$", re.IGNORECASE) + + +def _repariere_email(wert: str | None) -> tuple[str | None, bool]: + """Gibt (email, vermutete_korrektur) zurueck.""" + if not wert: + return wert, False + wert = wert.strip() + if "@" in wert: + return wert, False + treffer = _EMAIL_OHNE_AT.match(wert) + if not treffer: + return wert, False + return f"{treffer.group(1)}@{treffer.group(2)}", True + @lru_cache(maxsize=1) def _prompt() -> str: @@ -228,9 +253,11 @@ def _bereinige(d: dict) -> dict: d.setdefault("anrufer_name", None) d.setdefault("rueckrufnummer", None) d.setdefault("rueckruf_gewuenscht", False) + d.setdefault("email", None) d.setdefault("sprache", "de") d.setdefault("anliegen_kurz", "") d.setdefault("stichworte", []) if not isinstance(d["stichworte"], list): d["stichworte"] = [] + d["email"], d["email_vermutete_korrektur"] = _repariere_email(d.get("email")) return d diff --git a/pipe/config.py b/pipe/config.py index e030daa..0f0741e 100644 --- a/pipe/config.py +++ b/pipe/config.py @@ -59,7 +59,9 @@ WHISPER_PROMPT = os.environ.get( "WHISPER_PROMPT", "Anruf auf dem Anrufbeantworter einer Hausarztpraxis. Der Anrufer nennt " "seinen Namen, sein Anliegen und eine Rückrufnummer. Häufig geht es um " - "Termin, Rezept, Überweisung, Befund, Krankschreibung oder Schmerzen.", + "Termin, Rezept, Überweisung, Befund, Krankschreibung oder Schmerzen. " + "Nennt der Anrufer eine E-Mail-Adresse, wird sie mit @-Zeichen " + "geschrieben, zum Beispiel max.mueller@example.de.", ).strip() # faster-whisper (nur bei STT_BACKEND=faster) diff --git a/pipe/server.py b/pipe/server.py index c971c01..d9cce8f 100644 --- a/pipe/server.py +++ b/pipe/server.py @@ -141,6 +141,8 @@ def anrufe() -> list[dict]: "name": e.get("anrufer_name"), "nummer": d.get("anrufer_nummer") or e.get("rueckrufnummer"), "rueckrufnummer": e.get("rueckrufnummer"), + "email": e.get("email"), + "email_korrigiert": bool(e.get("email_vermutete_korrektur")), "rueckruf": bool(e.get("rueckruf_gewuenscht")), "anliegen": e.get("anliegen_kurz") or "", "stichworte": e.get("stichworte") or [], @@ -641,11 +643,20 @@ function karte(d){ const abweichend=d.rueckrufnummer&&waehlbar(d.rueckrufnummer)!==waehlbar(d.nummer); const rueckrufZeile=abweichend?`
`:''; + // email_korrigiert: Whisper transkribiert gesprochenes "at" beim Diktieren + // manchmal als Punkt statt "@" (z.B. "gdg.dillenberg.net" statt + // "gdg@dillenberg.net") - categorize.py repariert das als Vorschlag, aber + // mehrdeutig (koennte auch eine genannte Subdomain sein), deshalb hier + // sichtbar als Vermutung markiert statt stillschweigend uebernommen. + const emailZeile=d.email?``:''; return `${esc(d.anliegen)}