From 1d81f88eb2e2399b01c43edbdd83b27e11ba5845 Mon Sep 17 00:00:00 2001 From: Jeuner <62662523+Jeuners@users.noreply.github.com> Date: Sat, 22 Aug 2026 23:14:47 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20Mitgabe=20f=C3=BCr=20die=20Einrichtung?= =?UTF-8?q?=20auf=20einem=20zweiten=20Rechner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sammelt, was beim Aufsetzen auf einer frischen Maschine fehlt: die nicht im Repo liegenden Teile, der kurze Weg über Stufe 1 ohne Telefonie, eine Prüfleiter und die Fallen aus dem ersten Volltest. Dabei drei Lücken geschlossen, die drüben zugeschlagen hätten: - NEXTCLOUD_DECK fehlte in .env.example. DECK_STAPEL und DECK_TEILEN stehen dort, der Hauptschalter nicht — die Pipe legt dann kein Board an, obwohl alles richtig aussieht. - WHISPER_MODELL/WHISPER_COMPUTE galten laut Vorlage allgemein, greifen aber nur bei STT_BACKEND=faster. Standard ist whispercpp. Jetzt sind beide Blöcke getrennt und STT_BACKEND, WHISPERCPP_BIN/_MODELL, WHISPER_THREADS, NEXTCLOUD_USERID und FREESWITCH_LOG dokumentiert. - README hatte eine doppelte Überschrift. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_013pj3mSmL397czPaCfbL27Z --- .env.example | 27 +++++++++-- README.md | 8 +++- docs/MITGABE.md | 122 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 docs/MITGABE.md diff --git a/.env.example b/.env.example index d3958d8..b1c2b54 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,16 @@ -# --- Spracherkennung (faster-whisper, lokal) --- -WHISPER_MODELL=medium -WHISPER_COMPUTE=int8 +# --- Spracherkennung (lokal) --- +# whispercpp = Apple-GPU, nutzt ein vorhandenes ggml-Modell (Standard) +# faster = faster-whisper, lädt das Modell bei Bedarf selbst +STT_BACKEND=whispercpp # Feste Sprache erzwingen (de) oder leer lassen für Auto-Erkennung: WHISPER_SPRACHE=de +# Nur für STT_BACKEND=whispercpp: +WHISPERCPP_BIN=whisper-cli +#WHISPERCPP_MODELL=/Users/DEIN_NAME/whisper-models/ggml-large-v3-turbo.bin +WHISPER_THREADS=8 +# Nur für STT_BACKEND=faster: +WHISPER_MODELL=medium +WHISPER_COMPUTE=int8 # --- Kategorisierung (Ollama, lokal) --- OLLAMA_URL=http://127.0.0.1:11434 @@ -13,6 +21,9 @@ NEXTCLOUD_URL= NEXTCLOUD_USER= NEXTCLOUD_PASS= NEXTCLOUD_ORDNER=Anrufe +# Interne User-ID für den WebDAV-Pfad. Nur nötig, wenn der Login eine E-Mail ist +# und daher von der User-ID abweicht. +NEXTCLOUD_USERID= # --- Telefonie (SIP-Zugang der Praxis, leer lassen = keine Telefonannahme) --- SIP_USER= @@ -24,6 +35,11 @@ SIP_PROXY=voice01.sip.plusnet.de ANSAGE_TTS=piper ANSAGE_STIMME=de_DE-thorsten_emotional-medium ANSAGE_EMOTION=0 + +# --- Deck-Triage-Board (Nextcloud) --- +# Hauptschalter: ohne 1 entsteht kein Board, egal was unten steht. +NEXTCLOUD_DECK=0 +DECK_BOARD=Anrufe # Nutzer, die das Deck-Board sehen sollen (kommagetrennt) DECK_TEILEN= # Stapel des Deck-Boards (Arbeitsablauf, kommagetrennt) @@ -36,3 +52,8 @@ LEITSTAND_HOST=127.0.0.1 LEITSTAND_PORT=8088 LEITSTAND_USER=praxis LEITSTAND_PASS= + +# --- Telefonanlage (nur Stufe 2) --- +# Log von FreeSWITCH; der Leitstand liest daraus die Anruf-Ereignisse. +# Apple Silicon: /opt/homebrew/... , Intel-Mac: /usr/local/... +#FREESWITCH_LOG=/opt/homebrew/var/log/freeswitch/freeswitch.log diff --git a/README.md b/README.md index bcd1e2d..955ae8d 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,9 @@ ab (lokal und optional in Nextcloud). > Musterhausen" ist ein Platzhalter. Echte Zugangsdaten und Anrufdaten liegen > außerhalb des Repositorys (`.env`, `ablage/`, `telefon/`). +Wer das Projekt auf einem weiteren Rechner einrichtet: [docs/MITGABE.md](docs/MITGABE.md) +sammelt die Erfahrungswerte, die in dieser Anleitung nicht stehen. + ## Stufen 1. **Die Pipe** (fertig): Audio → Transkript → Kategorie → Ablage. @@ -106,7 +109,7 @@ cp .env.example .env # SIP-Zugang, Nextcloud, Leitstand-Passwort eintragen IP zeigt. - **Der Leitstand im Netz** verlangt `LEITSTAND_PASS`, sonst startet er nicht. -## Nutzung## Nutzung +## Nutzung ```bash cp .env.example .env # bei Bedarf anpassen @@ -176,6 +179,9 @@ nach `NEXTCLOUD_ORDNER/JJJJ-MM-TT/…`. Fehlt die Konfiguration, bleibt alles lo ## Deck-Board +Einschalten mit `NEXTCLOUD_DECK=1` in der `.env` — ohne diesen Schalter legt die +Pipe kein Board an, auch wenn `DECK_STAPEL` und `DECK_TEILEN` gesetzt sind. + Jeder Anruf bekommt eine Karte auf dem Board `Anrufe`. Die Stapel bilden den Arbeitsablauf ab — `Eingang · In Bearbeitung · Rückfragen · Erledigt`, anpassbar über `DECK_STAPEL`. Neue Anrufe landen immer im ersten Stapel; die Praxis zieht diff --git a/docs/MITGABE.md b/docs/MITGABE.md new file mode 100644 index 0000000..1b406f6 --- /dev/null +++ b/docs/MITGABE.md @@ -0,0 +1,122 @@ +# Mitgabe für die Einrichtung auf einem zweiten Rechner + +Diese Datei ergänzt README (Einrichtung) und HANDOFF (Stand). Sie enthält das, +was auf der anderen Seite nicht im Repository ankommt: die Erfahrungswerte aus +dem ersten Volltest, die Stellen, an denen die Vorlagen unvollständig sind, und +die Reihenfolge, in der man prüft, ob es wirklich läuft. + +## 1. Was im Repo *nicht* liegt + +| Fehlt | Woher | +|---|---| +| `.env` | aus `.env.example` kopieren, Werte eintragen (Abschnitt 3) | +| Whisper-Modell (~1,6 GB) | `~/whisper-models/ggml-large-v3-turbo.bin`, Download siehe README | +| Ollama-Modell (~6,6 GB) | `ollama pull qwen3.5:latest` | +| Piper-Stimme | `~/piper-voices/…`, nur für die Ansage (Stufe 2) nötig | +| `ablage/`, `telefon/eingang/`, `dashboard.html` | Anruf- und Patientendaten, bleiben absichtlich lokal | +| FreeSWITCH-Konfiguration mit echtem SIP-Passwort | `telefon/freeswitch/einrichten.sh` schreibt sie aus der `.env` | + +Alle Namen, Rufnummern und Beispieldaten im Repo sind erfunden. „Praxis +Musterhausen" ist Platzhalter — auch im Screenshot. + +## 2. Der kurze Weg: Stufe 1 ohne Telefonie + +Telefonie (FreeSWITCH, SIP-Trunk) ist für die Erprobung nicht nötig und macht +die meiste Arbeit. Für einen ersten Durchlauf reicht: + +```bash +brew install ffmpeg whisper-cpp +brew install ollama && ollama serve & +ollama pull qwen3.5:latest +mkdir -p ~/whisper-models && cd ~/whisper-models +curl -LO https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo.bin +cd ~/praxis-telefon-agent && cp .env.example .env +python3 -m pipe.process_call test/rezept.wav --nummer 021031234567 +``` + +Läuft das durch (~25 s), liegt das Ergebnis unter +`ablage/JJJJ-MM-TT/HH-MM-SS_021031234567/`. Nextcloud, Deck, Leitstand und +Telefonie sind alle abschaltbar und kommen erst danach dran. + +## 3. Was die `.env.example` verschweigt + +Die Vorlage deckt nicht alle Schalter ab, die `pipe/config.py` liest. Die +Voreinstellungen greifen still — mit diesen Folgen: + +| Variable | Voreinstellung | Warum das wichtig ist | +|---|---|---| +| `STT_BACKEND` | `whispercpp` | `WHISPER_MODELL`/`WHISPER_COMPUTE` aus der Vorlage gelten **nur** für `faster`. In der Voreinstellung werden sie ignoriert. | +| `WHISPERCPP_MODELL` | `~/whisper-models/ggml-large-v3-turbo.bin` | Liegt das Modell woanders, bricht die Erkennung ab. | +| `WHISPERCPP_BIN` | `whisper-cli` | Muss im `PATH` liegen (Homebrew `whisper-cpp`). | +| `WHISPER_THREADS` | `8` | Auf kleineren Maschinen herunterdrehen. | +| `NEXTCLOUD_DECK` | *aus* | **Häufigste Verwirrung:** `DECK_TEILEN` und `DECK_STAPEL` stehen in der Vorlage, der Hauptschalter nicht. Ohne `NEXTCLOUD_DECK=1` entsteht kein Board. | +| `NEXTCLOUD_USERID` | = `NEXTCLOUD_USER` | Bei E-Mail-Login weicht die interne User-ID ab, dann zeigt der WebDAV-Pfad ins Leere. | +| `FREESWITCH_LOG` | `/opt/homebrew/var/log/freeswitch/…` | Apple-Silicon-Homebrew. Auf Intel-Macs `/usr/local/...`. Sonst bleiben die Telefon-Ereignisse im Leitstand leer. | +| `ABLAGE_LOKAL`, `TELEFON_ORDNER` | im Projektordner | Für eine Ablage auf einem anderen Volume hier umbiegen. | +| `WHISPER_PROMPT` | Praxis-Kontext | Steuert, wie zuverlässig Namen und Rufnummern erkannt werden. Bei anderem Einsatzzweck anpassen. | + +`starten.sh` nutzt außerdem `FS_ETC` (Voreinstellung `/opt/homebrew/etc/freeswitch`) +und `FS_PORT` (`8099`, weil 8021 auf dem Ursprungsrechner belegt war). Auf einer +frischen Maschine ist 8021 meist frei — dann entweder `FS_PORT=8021` setzen oder +den Port in `autoload_configs/event_socket.conf.xml` auf 8099 lassen. Beides +muss zusammenpassen, sonst antwortet `fs_cli` nicht. + +## 4. Prüfleiter — in dieser Reihenfolge + +1. **Erkennung:** `python3 -m pipe.process_call test/termin.wav --nummer 0…` + → `meta.json` enthält ein plausibles `transkript`. +2. **Kategorisierung:** `test/rezept.wav` → `kategorie: rezept`, + `test/notfall.wav` → `dringlichkeit: notfall`. Bleibt `kategorie` leer, + läuft Ollama nicht oder das Modell fehlt. +3. **Name und Rückrufnummer** stehen als eigene Felder in `meta.json` — nicht + nur im Fließtext von `anliegen_kurz` (siehe Falle 1 unten). +4. **Nextcloud:** Zugangsdaten eintragen, erneut einen Anruf verarbeiten, dann + `python3 -m pipe.resync` — meldet 0 Fehler. +5. **Deck:** `NEXTCLOUD_DECK=1` **und** `DECK_TEILEN` setzen. Ohne Freigabe legt + die Pipe Karten an, die Praxis sieht ein leeres Board. +6. **Leitstand:** `python3 -m pipe.server`, dann . +7. **Telefonie** zuletzt: `./telefon/starten.sh` prüft selbst vor und bricht mit + Klartext ab. + +## 5. Fallen, die uns beim ersten Volltest getroffen haben + +1. **Name und Rückrufnummer gingen still verloren.** Beide Felder fehlten in der + `required`-Liste des JSON-Schemas; das Modell ließ sie einfach weg, obwohl es + sie kannte. Behoben — aber beim Anpassen des Schemas in `pipe/categorize.py` + sofort wieder einbaubar. Immer gegen `test/notfall.wav` gegenprüfen. +2. **WebDAV ohne Wiederholung.** Ein einzelner träger Antwortlauf schickt den + Anruf in den manuellen Nachsync. Jetzt 3 Versuche mit Backoff, Timeout 60 s. +3. **Ordnername aus der geratenen statt der CLIP-Nummer.** Die Nummer kommt aus + der Telefonanlage, nicht aus dem Transkript. +4. **Stumme ffmpeg-/whisper-Fehler.** Jetzt mit Klartext — bei eigenen + Änderungen nicht wieder auf nackte `CalledProcessError` zurückfallen. +5. **Telephone.app streitet um dieselbe SIP-Registrierung.** Vor dem Start + beenden; `starten.sh` prüft das. +6. **Rotierende Provider-Adressen.** Löst der SIP-Hostname auf mehrere IPs auf, + bricht die Registrierung dauernd ab. `SIP_PROXY` auf einen Host setzen, der + auf genau eine IP zeigt. +7. **FreeSWITCH liest aus dem Cellar**, wenn `-conf` fehlt — dann überschreibt + jedes Homebrew-Upgrade Trunk und Dialplan. + +## 6. Was bewusst noch fehlt (vor Produktivbetrieb klären) + +- **Notfall löst keinen Alarm aus.** `dringlichkeit: notfall` bekommt ein rotes + Label und steht im Dashboard oben — kein Ton, keine Push, keine Mail. Eine + Pipe, die Notfälle stumm ablegt, ist für eine Praxis gefährlicher als gar + keine. Das ist der nächste Schritt, vor der Telefonie. +- **Keine Löschfristen**, keine Verschlüsselung at rest. +- **Leitstand im Netz** (`LEITSTAND_HOST=0.0.0.0`) verlangt `LEITSTAND_PASS` — + die Seiten zeigen Transkripte und Aufnahmen von Patienten. +- **Ansage** nennt 112 und weist auf die Aufzeichnung hin. Beides ist bei einer + Arztpraxis Pflicht und darf beim Umtexten nicht wegfallen. +- **Mehrsprachigkeit:** `WHISPER_SPRACHE=de` ist fest. Für EN/AR auf `auto`. + +## 7. Nützliche Rückmeldung + +Wenn auf der anderen Seite etwas abweicht, sind vor allem diese Punkte für uns +hier interessant: + +- andere Hardware/OS-Version und wie lange ein Anruf dann braucht (hier ~24 s), +- ob `qwen3.5:latest` bei 16 GB RAM neben laufender Telefonie noch passt, +- jede Stelle, an der README oder `.env.example` nicht gereicht haben — die + gehört dann dort hinein, nicht in diese Datei.