4.4 KiB
Architektur
Überblick
VoiceLog ist eine Single-File-FastAPI-Anwendung (app.py, ~2000 Zeilen). Es gibt keine Templates, kein separates Frontend-Build-System und keine weiteren Module. HTML wird serverseitig als Python-f-Strings erzeugt; Bootstrap 5.3 (CDN) übernimmt das Layout.
Browser
│
▼
FastAPI (app.py, Port 8094)
├── SQLite (DB_PATH, Standard: /data/ui.db)
├── ThreadPoolExecutor (2 Workers)
│ ├── Upload-Job → Transcription-API (API_BASE)
│ └── Analyse-Job → Ollama (OLLAMA_BASE_URL)
└── Dateisystem (JOB_DIR, Standard: /data/jobs/)
Traefik sitzt als Reverse-Proxy davor und terminiert TLS (https://voicelog.aquantico.lan).
Datenmodell (SQLite)
projects
| Spalte | Typ | Beschreibung |
|---|---|---|
id |
INTEGER PK | |
name |
TEXT UNIQUE | Projektname |
created_at |
TEXT | ISO-8601-UTC |
prompts
| Spalte | Typ | Beschreibung |
|---|---|---|
id |
INTEGER PK | |
name |
TEXT UNIQUE | Anzeigename |
prompt |
TEXT | Prompttext für das LLM |
created_at |
TEXT | |
updated_at |
TEXT | |
llm_use_default |
INTEGER | 1 = globale KI-Einstellungen nutzen (Standard) |
llm_model |
TEXT | Überschreibt globales Modell wenn llm_use_default=0 |
llm_think |
TEXT | "true" / "false" |
llm_num_ctx |
TEXT | Kontextgröße oder "auto" |
llm_num_predict |
INTEGER | Max. Ausgabe-Tokens |
llm_repeat_penalty |
REAL | |
llm_repeat_last_n |
INTEGER |
documents
| Spalte | Typ | Beschreibung |
|---|---|---|
id |
INTEGER PK | |
project_id |
INTEGER FK | → projects |
kind |
TEXT | transcript oder analysis |
title |
TEXT | |
content_md |
TEXT | Inhalt (Markdown) |
source_document_id |
INTEGER FK | Bei analysis: Quell-Transkript |
prompt_id |
INTEGER FK | Bei analysis: verwendeter Prompt |
raw_json |
TEXT | Rohantwort der externen API als JSON |
created_at |
TEXT |
jobs
| Spalte | Typ | Beschreibung |
|---|---|---|
id |
INTEGER PK | |
kind |
TEXT | upload oder analysis |
status |
TEXT | queued → running → done / error / cancelled |
project_id |
INTEGER | |
document_id |
INTEGER | Quell-Dokument (bei analysis) |
prompt_id |
INTEGER | |
title |
TEXT | Anzeigename |
file_path |
TEXT | Temporärer Pfad der Audiodatei (bei upload) |
error |
TEXT | Fehlermeldung bei Status error |
result_document_id |
INTEGER | Erzeugtes Dokument nach done |
user_prompt |
TEXT | Zusatzinformation vom Nutzer |
llm_prompt |
TEXT | Vollständiger LLM-Prompt inkl. [num_ctx=…]-Header |
llm_response |
TEXT | Rohausgabe des LLM |
llm_thinking |
TEXT | Thinking-Chain-of-Thought-Ausgabe |
created_at |
TEXT | |
started_at |
TEXT | |
finished_at |
TEXT |
settings
Einfache Key-Value-Tabelle für persistente Laufzeiteinstellungen.
| Spalte | Typ |
|---|---|
key |
TEXT PK |
value |
TEXT |
Bekannte Keys: ollama_model, ollama_think, ollama_num_ctx, ollama_num_predict, ollama_repeat_penalty, ollama_repeat_last_n.
Hintergrundverarbeitung
Jobs werden über enqueue_job() in die DB geschrieben und sofort an einen ThreadPoolExecutor(max_workers=2) übergeben.
Upload-Job (_process_upload_job)
- Liest temporäre Audiodatei aus
JOB_DIR - Sendet sie als
multipart/form-dataan{API_BASE}/transcribe-diarize - Speichert
formatted_textaus der Antwort alstranscript-Dokument - Löscht die temporäre Datei
Analyse-Job (_process_analysis_job)
- Lädt Dokument und Prompt aus der DB
- Prüft
llm_use_defaultam Prompt: globale oder promptspezifische KI-Einstellungen - Berechnet
num_ctxdynamisch über_estimate_num_ctx()(außer bei manuellem Override) - Streamt Anfrage an
{OLLAMA_BASE_URL}/api/generate - Puffert
thinking- undresponse-Chunks in_JOB_STREAMS(für Live-Anzeige) - Speichert Ergebnis als
analysis-Dokument
Beide Worker prüfen nach jedem externen Call, ob der Job zwischenzeitlich auf cancelled gesetzt wurde.
Datenbankmigrationen
Werden inline in init_db() mit ALTER TABLE … ADD COLUMN in try/except-Blöcken ausgeführt. Die DB wird beim Start automatisch angelegt und migriert.
PWA
Die App liefert /manifest.webmanifest, /icon.svg und /sw.js direkt aus Route-Handlern aus und ist damit als Progressive Web App installierbar.