docs: add project documentation (architecture, API, interfaces, config, deployment)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
124
doc/architecture.md
Normal file
124
doc/architecture.md
Normal 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.
|
||||
Reference in New Issue
Block a user