diff --git a/.env.example b/.env.example index b11c893..f60dfa8 100644 --- a/.env.example +++ b/.env.example @@ -328,11 +328,49 @@ BENACHRICHTIGUNG_AUFBEWAHRUNG_TAGE=90 # ----------------------------------------------------------------------------- # LLM-Anbindung (optional; nur selbstgehostete Endpunkte, kein Cloud-Zwang) # ----------------------------------------------------------------------------- +# ES GIBT KEINEN RUECKFALL AUF EINEN ANBIETER. Laeuft der eigene Endpunkt +# nicht, fehlen die KI-Funktionen — sie werden nicht durch einen fremden +# Dienst ersetzt. Ein Einsatzbericht spricht ueber Menschen in ihrer +# schlechtesten Stunde; solche Texte gehoeren nirgendwo anders hin. +# +# Container starten: docker compose --profile ki up -d +# Modelle holen: docker compose exec ollama ollama pull LLM_ENABLED=false # OpenAI-kompatibler Endpunkt, z. B. eine lokale Ollama- oder vLLM-Instanz. LLM_BASE_URL=http://ollama:11434/v1 LLM_API_KEY= LLM_MODELL=qwen2.5:14b +# Zeitlimit fuer eine Antwort. Ein Bericht darf dauern, aber nicht ewig. +LLM_TIMEOUT=120 + +# Modell fuer Einbettungen (semantische Suche im Wiki). +# +# ACHTUNG: Die Spalte wikiabschnitt.einbettung ist auf 768 Dimensionen +# festgelegt — das liefert nomic-embed-text. Ein Modell mit anderer Laenge +# braucht eine Migration; wie, steht im README unter Phase 8. +LLM_EINBETTUNG_MODELL=nomic-embed-text +LLM_EINBETTUNG_DIMENSIONEN=768 + +# Modell, das Bilder lesen kann — fuer die Belegerfassung. Ohne dieses Modell +# werden Belege trotzdem abgelegt, die Angaben nur von Hand eingetragen. +# LLM_VISION_MODELL=llama3.2-vision + +# ----------------------------------------------------------------------------- +# Spracherkennung fuers Diktat (Phase 8, optional) +# +# Selbst betriebener faster-whisper im Compose-Profil "ki". Groesse ueber +# WHISPER_MODELL: "tiny" laeuft auf jedem Buerorechner, "base" ist der +# brauchbare Kompromiss, "small" erkennt Fachbegriffe merklich besser und +# will dafuer Zeit oder eine Grafikkarte. +# ----------------------------------------------------------------------------- +WHISPER_ENABLED=false +WHISPER_URL=http://whisper:8000 +WHISPER_MODELL=base +WHISPER_SPRACHE=de +# Zeitlimit fuer eine Aufnahme. Zehn Minuten Sprache brauchen Zeit. +WHISPER_TIMEOUT=300 +# Hoechstlaenge einer Aufnahme in Sekunden. +DIKTAT_MAX_SEKUNDEN=600 # ----------------------------------------------------------------------------- # Einsätze und Übungen (Phase 3) diff --git a/CHANGELOG.md b/CHANGELOG.md index b57b7d1..ff48cf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,113 @@ Die Regeln dazu stehen in [docs/VERSIONIERUNG.md](docs/VERSIONIERUNG.md). ## [Unveröffentlicht] -Nächster Schritt ist Phase 8 (Lokale KI). +Nächster Schritt ist Phase 9 (Kassenverwaltung). + +--- + +## [0.9.0] — 2026-09-04 + +Phase 8: Lokale KI. Ein Wiki mit semantischer Suche, Diktat, Berichtsassistent +und Belegerfassung — alles gegen selbst betriebene Modelle. + +**Nichts, was ein Modell erzeugt, gelangt ungeprüft in einen Nachweis.** Jede +KI-Ausgabe ist zuerst ein eigener Datensatz und nicht ein Feld im +Zieldokument. Sie ist gekennzeichnet, sie steht daneben statt mittendrin, und +sie braucht zwei gleich große Knöpfe, bevor etwas mit ihr geschieht. + +**Es läuft alles im Haus.** Ollama und faster-whisper als Container daneben, +kein Anbieter, kein Schlüssel. Es gibt keinen Rückfall auf einen Cloud-Dienst: +fehlen die Container, fehlt die Funktion. + +### Hinzugefügt + +**Datenmodell** + +- `KiVorgang` — jede Befragung eines Modells mit Eingabe, Ausgabe, Modell, + Dauer und der Entscheidung darüber. Auch Fehlschläge: ein Modell, das + dreimal am Tag in eine Zeitüberschreitung läuft, ist eine Information. +- `Wikiseite`, `Wikiabschnitt` (mit `vector(768)`) und `Wikiversion`. +- `Diktat` mit Aufnahme in MinIO, `Belegentwurf` mit allen Feldern optional — + ein Modell, das den Betrag nicht findet, soll nichts erfinden. + +**Postgres mit pgvector** + +- Eigenes Image (`docker/postgres/Dockerfile`), weil FLORIAN PostGIS **und** + pgvector braucht und es kein offizielles Image mit beidem gibt. +- HNSW-Index statt IVFFlat: IVFFlat muss auf gefülltem Bestand trainiert + werden, HNSW ist ab der ersten Zeile brauchbar. Ein Wiki wächst Seite für + Seite — es gibt nie den Moment, an dem man den Index einmal aufbaut. + +**Wiki** + +- Markdown, selbst gerendert **ohne HTML**: der Text kommt von Anwendern, und + jeder Weg über `dangerouslySetInnerHTML` wäre ein Weg für ein `