docs: add project documentation (architecture, API, interfaces, config, deployment)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 12:02:47 +02:00
parent 21712c972d
commit 2db89bc33a
6 changed files with 475 additions and 0 deletions

124
doc/architecture.md Normal file
View File

@@ -0,0 +1,124 @@
# 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`)
1. Liest temporäre Audiodatei aus `JOB_DIR`
2. Sendet sie als `multipart/form-data` an `{API_BASE}/transcribe-diarize`
3. Speichert `formatted_text` aus der Antwort als `transcript`-Dokument
4. Löscht die temporäre Datei
### Analyse-Job (`_process_analysis_job`)
1. Lädt Dokument und Prompt aus der DB
2. Prüft `llm_use_default` am Prompt: globale oder promptspezifische KI-Einstellungen
3. Berechnet `num_ctx` dynamisch über `_estimate_num_ctx()` (außer bei manuellem Override)
4. Streamt Anfrage an `{OLLAMA_BASE_URL}/api/generate`
5. Puffert `thinking`- und `response`-Chunks in `_JOB_STREAMS` (für Live-Anzeige)
6. 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.