Phase 8: Lokale KI
Wiki mit semantischer Suche ueber pgvector, Diktat ueber faster-whisper, Berichtsassistent und Belegerfassung — alles gegen selbst betriebene Modelle. Dazu zwei Protokollansichten: was die Maschine getan hat und was Menschen getan haben. Nichts, was ein Modell erzeugt, gelangt ungeprueft in einen Nachweis. Jede Ausgabe ist zuerst ein eigener Datensatz, gekennzeichnet, mit zwei gleich grossen Knoepfen davor. Die Datenbank haelt gegen: Eingabe, Ausgabe und Modell sind unveraenderlich, geloescht wird nicht, entschieden wird einmal. Kein Rueckfall auf einen Anbieter: fehlen die Container, fehlt die Funktion. Dafuer bleibt alles andere ohne Modell vollstaendig benutzbar — geprueft von vierzehn E2E-Tests, die ohne laufendes Modell durchlaufen. Postgres bringt jetzt PostGIS und pgvector mit (eigenes Image), Ollama und faster-whisper stehen im Compose-Profil "ki". 73 neue Unit-Tests, 14 neue E2E-Tests, Version 0.9.0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
12243f177d
commit
f7ccd9a908
+100
-2
@@ -87,6 +87,16 @@ x-app-env: &app-env
|
||||
LLM_BASE_URL: ${LLM_BASE_URL:-}
|
||||
LLM_API_KEY: ${LLM_API_KEY:-}
|
||||
LLM_MODELL: ${LLM_MODELL:-}
|
||||
LLM_TIMEOUT: ${LLM_TIMEOUT:-120}
|
||||
LLM_EINBETTUNG_MODELL: ${LLM_EINBETTUNG_MODELL:-nomic-embed-text}
|
||||
LLM_EINBETTUNG_DIMENSIONEN: ${LLM_EINBETTUNG_DIMENSIONEN:-768}
|
||||
LLM_VISION_MODELL: ${LLM_VISION_MODELL:-}
|
||||
WHISPER_ENABLED: ${WHISPER_ENABLED:-false}
|
||||
WHISPER_URL: ${WHISPER_URL:-}
|
||||
WHISPER_MODELL: ${WHISPER_MODELL:-base}
|
||||
WHISPER_SPRACHE: ${WHISPER_SPRACHE:-de}
|
||||
WHISPER_TIMEOUT: ${WHISPER_TIMEOUT:-300}
|
||||
DIKTAT_MAX_SEKUNDEN: ${DIKTAT_MAX_SEKUNDEN:-600}
|
||||
GEOCODING_ENABLED: ${GEOCODING_ENABLED:-false}
|
||||
NOMINATIM_URL: ${NOMINATIM_URL:-}
|
||||
GEOCODING_TIMEOUT: ${GEOCODING_TIMEOUT:-5}
|
||||
@@ -144,10 +154,18 @@ services:
|
||||
logging: *logging
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# PostgreSQL 17 mit PostGIS. Einziger Ort für relationale Daten.
|
||||
# PostgreSQL 17 mit PostGIS und pgvector. Einziger Ort für relationale Daten.
|
||||
#
|
||||
# Eigenes Image, weil FLORIAN beides braucht und es kein offizielles gibt,
|
||||
# das beides mitbringt — siehe docker/postgres/Dockerfile. Beim ersten
|
||||
# `docker compose up` wird es gebaut; bei einer bestehenden Installation
|
||||
# genügt `docker compose build postgres` und ein Neustart des Dienstes. Das
|
||||
# Datenverzeichnis bleibt unberührt, die Hauptversion ändert sich nicht.
|
||||
# ---------------------------------------------------------------------------
|
||||
postgres:
|
||||
image: postgis/postgis:17-3.5
|
||||
build:
|
||||
context: ./docker/postgres
|
||||
image: florian-postgres:${IMAGE_TAG:-17-3.5-pgvector}
|
||||
container_name: florian-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
@@ -318,6 +336,82 @@ services:
|
||||
- intern
|
||||
logging: *logging
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Ollama — Sprachmodelle im eigenen Haus (Phase 8).
|
||||
#
|
||||
# Nur mit Profil: docker compose --profile ki up -d
|
||||
#
|
||||
# Es gibt bewusst KEINEN Rückfall auf einen Anbieter. Läuft dieser Container
|
||||
# nicht, fehlen die KI-Funktionen — sie werden nicht durch einen fremden
|
||||
# Dienst ersetzt. Ein Einsatzbericht spricht über Menschen in ihrer
|
||||
# schlechtesten Stunde; solche Texte gehören nirgendwo anders hin.
|
||||
#
|
||||
# Nach dem ersten Start müssen die Modelle geholt werden:
|
||||
#
|
||||
# docker compose exec ollama ollama pull qwen2.5:14b # Text
|
||||
# docker compose exec ollama ollama pull nomic-embed-text # Einbettungen
|
||||
# docker compose exec ollama ollama pull llama3.2-vision # Belege (optional)
|
||||
#
|
||||
# Auf einem Rechner ohne Grafikkarte läuft das Einbettungsmodell noch flott,
|
||||
# das Textmodell zäh und das Vision-Modell praktisch nicht. Deshalb sind alle
|
||||
# drei einzeln konfigurierbar: eine Wehr kann das Wiki durchsuchbar machen,
|
||||
# ohne Berichte schreiben zu lassen.
|
||||
#
|
||||
# Für eine Nvidia-Karte zusätzlich das Compose-Fragment aus dem README
|
||||
# einbinden (deploy.resources.reservations.devices) — es steht nicht fest
|
||||
# hier drin, weil es ohne Karte den Start verhindert.
|
||||
# ---------------------------------------------------------------------------
|
||||
ollama:
|
||||
image: ollama/ollama:0.5.7
|
||||
container_name: florian-ollama
|
||||
restart: unless-stopped
|
||||
profiles: [ki]
|
||||
environment:
|
||||
# Modelle bleiben geladen, statt nach fünf Minuten aus dem Speicher zu
|
||||
# fallen. Wer zweimal am Tag einen Bericht schreibt, wartet sonst jedes
|
||||
# Mal auf das Nachladen.
|
||||
OLLAMA_KEEP_ALIVE: ${OLLAMA_KEEP_ALIVE:-30m}
|
||||
OLLAMA_HOST: "0.0.0.0:11434"
|
||||
volumes:
|
||||
- ollama-data:/root/.ollama
|
||||
ports:
|
||||
- "${OLLAMA_PORT:-11435}:11434"
|
||||
networks:
|
||||
- intern
|
||||
logging: *logging
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# faster-whisper — Spracherkennung fürs Diktat (Phase 8).
|
||||
#
|
||||
# Nur mit Profil: docker compose --profile ki up -d
|
||||
#
|
||||
# OpenAI-kompatible Schnittstelle, aber vollständig lokal. Das Modell wird
|
||||
# beim ersten Aufruf geholt und dann behalten.
|
||||
#
|
||||
# WHISPER_MODELL steuert die Größe: "tiny" läuft auf jedem Bürorechner,
|
||||
# "base" ist der brauchbare Kompromiss, "small" erkennt Fachbegriffe
|
||||
# merklich besser und will dafür Zeit oder eine Grafikkarte.
|
||||
# ---------------------------------------------------------------------------
|
||||
whisper:
|
||||
image: fedirz/faster-whisper-server:latest-cpu
|
||||
container_name: florian-whisper
|
||||
restart: unless-stopped
|
||||
profiles: [ki]
|
||||
environment:
|
||||
WHISPER__MODEL: ${WHISPER_MODELL:-base}
|
||||
WHISPER__INFERENCE_DEVICE: ${WHISPER_GERAET:-cpu}
|
||||
# Nach zehn Minuten ohne Anfrage den Speicher freigeben. Eine Wehr
|
||||
# diktiert nicht stündlich.
|
||||
WHISPER__TTL: ${WHISPER_TTL:-600}
|
||||
ENABLE_UI: "false"
|
||||
volumes:
|
||||
- whisper-data:/root/.cache/huggingface
|
||||
ports:
|
||||
- "${WHISPER_PORT:-8087}:8000"
|
||||
networks:
|
||||
- intern
|
||||
logging: *logging
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ntfy — Push aufs Handy, ohne dass etwas das Haus verlässt (Phase 7).
|
||||
#
|
||||
@@ -434,6 +528,10 @@ volumes:
|
||||
redis-data:
|
||||
minio-data:
|
||||
traefik-acme:
|
||||
# Phase 8: die Modelle. Sie sind mehrere Gigabyte groß und sollen einen
|
||||
# Neustart des Containers überleben — sonst werden sie jedes Mal neu geholt.
|
||||
ollama-data:
|
||||
whisper-data:
|
||||
|
||||
networks:
|
||||
# Nur was von außen erreichbar sein muss, hängt hier drin.
|
||||
|
||||
Reference in New Issue
Block a user