1
0

M8 komplett umgesetzt

This commit is contained in:
2026-04-08 16:30:13 +02:00
parent a3f47ba560
commit d61316c699
21 changed files with 2377 additions and 89 deletions

214
docs/betrieb.md Normal file
View File

@@ -0,0 +1,214 @@
# Betriebsdokumentation PDF Umbenenner
## Zweck
Der PDF Umbenenner liest bereits OCR-verarbeitete, durchsuchbare PDF-Dateien aus einem
konfigurierten Quellordner, ermittelt per KI-Aufruf einen normierten deutschen Dateinamen
und legt eine Kopie im konfigurierten Zielordner ab. Die Quelldatei bleibt unverändert.
---
## Voraussetzungen
- Java 21 (JRE oder JDK)
- Zugang zu einem OpenAI-kompatiblen KI-Dienst (API-Schlüssel erforderlich)
- Quellordner mit OCR-verarbeiteten PDF-Dateien
- Schreibzugriff auf Zielordner und Datenbankverzeichnis
---
## Start des ausführbaren JAR
Das ausführbare JAR wird durch den Maven-Build im Verzeichnis
`pdf-umbenenner-bootstrap/target/` erzeugt:
```
java -jar pdf-umbenenner-bootstrap/target/pdf-umbenenner-bootstrap-0.0.1-SNAPSHOT.jar
```
Die Anwendung liest die Konfiguration aus `config/application.properties` relativ zum
Arbeitsverzeichnis, in dem der Befehl ausgeführt wird.
### Start über Windows Task Scheduler
Empfohlene Startsequenz für den Windows Task Scheduler:
1. Aktion: Programm/Skript starten
2. Programm: `java`
3. Argumente: `-jar pdf-umbenenner-bootstrap-0.0.1-SNAPSHOT.jar`
4. Starten in: Verzeichnis mit `config/application.properties` und `config/prompts/`
---
## Konfiguration
Die Konfiguration wird aus `config/application.properties` geladen.
Vorlagen für lokale und Test-Konfigurationen befinden sich in:
- `config/application-local.example.properties`
- `config/application-test.example.properties`
### Pflichtparameter
| Parameter | Beschreibung |
|------------------------|--------------|
| `source.folder` | Quellordner mit OCR-PDFs (muss vorhanden und lesbar sein) |
| `target.folder` | Zielordner für umbenannte Kopien (wird angelegt, wenn nicht vorhanden) |
| `sqlite.file` | SQLite-Datenbankdatei (übergeordnetes Verzeichnis muss existieren) |
| `api.baseUrl` | Basis-URL des KI-Dienstes (z. B. `https://api.openai.com/v1`) |
| `api.model` | Modellname (z. B. `gpt-4o-mini`) |
| `api.timeoutSeconds` | HTTP-Timeout für KI-Anfragen in Sekunden (ganzzahlig, > 0) |
| `max.retries.transient`| Maximale transiente Fehlversuche pro Dokument (ganzzahlig, >= 1) |
| `max.pages` | Maximale Seitenzahl pro Dokument (ganzzahlig, > 0) |
| `max.text.characters` | Maximale Zeichenanzahl des Dokumenttexts für KI-Anfragen (ganzzahlig, > 0) |
| `prompt.template.file` | Pfad zur externen Prompt-Datei (muss vorhanden sein) |
### Optionale Parameter
| Parameter | Beschreibung | Standard |
|----------------------|--------------|---------|
| `api.key` | API-Schlüssel (alternativ: Umgebungsvariable `PDF_UMBENENNER_API_KEY`) | |
| `runtime.lock.file` | Lock-Datei für Startschutz | `pdf-umbenenner.lock` im Arbeitsverzeichnis |
| `log.directory` | Log-Verzeichnis | `./logs/` |
| `log.level` | Log-Level (`DEBUG`, `INFO`, `WARN`, `ERROR`) | `INFO` |
| `log.ai.sensitive` | KI-Rohantwort und Reasoning ins Log schreiben (`true`/`false`) | `false` |
### API-Schlüssel
Der API-Schlüssel kann auf zwei Wegen gesetzt werden:
1. **Umgebungsvariable `PDF_UMBENENNER_API_KEY`** (empfohlen, hat Vorrang)
2. Property `api.key` in `config/application.properties`
Die Umgebungsvariable hat immer Vorrang über die Properties-Datei.
---
## Prompt-Konfiguration
Der Prompt wird aus der in `prompt.template.file` konfigurierten externen Textdatei geladen.
Der Dateiname der Prompt-Datei dient als Prompt-Identifikator in der Versuchshistorie
(SQLite) und ermöglicht so die Nachvollziehbarkeit, welche Prompt-Version für welchen
Verarbeitungsversuch verwendet wurde.
Eine Vorlage befindet sich in `config/prompts/template.txt` und kann direkt verwendet oder
an den jeweiligen KI-Dienst angepasst werden.
Die Anwendung ergänzt den Prompt automatisch um:
- einen Dokumenttext-Abschnitt
- eine explizite JSON-Antwortspezifikation mit den Feldern `title`, `reasoning` und `date`
Der Prompt in `template.txt` muss deshalb **keine** JSON-Formatanweisung enthalten
nur den inhaltlichen Auftrag an die KI.
---
## Zielformat
Jede erfolgreich verarbeitete PDF-Datei wird im Zielordner unter folgendem Namen abgelegt:
```
YYYY-MM-DD - Titel.pdf
```
Bei Namenskollisionen wird ein laufendes Suffix angehängt:
```
YYYY-MM-DD - Titel(1).pdf
YYYY-MM-DD - Titel(2).pdf
```
Das Suffix zählt nicht zu den 20 Zeichen des Basistitels.
---
## Retry- und Skip-Verhalten
### Dokumentstatus
| Status | Bedeutung |
|---------------------------|-----------|
| `SUCCESS` | Erfolgreich verarbeitet und kopiert |
| `FAILED_RETRYABLE` | Fehlgeschlagen, erneuter Versuch in späterem Lauf möglich |
| `FAILED_FINAL` | Terminal fehlgeschlagen, wird nicht erneut verarbeitet |
| `SKIPPED_ALREADY_PROCESSED` | Übersprungen Dokument bereits erfolgreich verarbeitet |
| `SKIPPED_FINAL_FAILURE` | Übersprungen Dokument terminal fehlgeschlagen |
### Retry-Regeln
**Deterministische Inhaltsfehler** (z. B. kein extrahierbarer Text, Seitenlimit überschritten,
unbrauchbarer KI-Titel):
- Erster Fehler → `FAILED_RETRYABLE` (ein Wiederholversuch in späterem Lauf erlaubt)
- Zweiter Fehler → `FAILED_FINAL` (kein weiterer Versuch)
**Transiente technische Fehler** (z. B. KI nicht erreichbar, HTTP-Timeout):
- Wiederholbar bis zum Grenzwert `max.retries.transient`
- Bei Erreichen des Grenzwerts → `FAILED_FINAL`
**Technischer Sofort-Wiederholversuch:**
Bei einem Schreibfehler der Zielkopie wird innerhalb desselben Laufs exakt ein
Sofort-Wiederholversuch unternommen. Dieser zählt nicht zum laufübergreifenden
Fehlerzähler.
---
## Logging
Logs werden in das konfigurierte `log.directory` geschrieben (Standard: `./logs/`).
Log-Rotation erfolgt täglich und bei Erreichen von 10 MB je Datei.
### Sensible KI-Inhalte
Standardmäßig werden die vollständige KI-Rohantwort und das KI-Reasoning **nicht** ins Log
geschrieben, sondern ausschließlich in der SQLite-Datenbank gespeichert.
Die Ausgabe kann für Diagnosezwecke mit `log.ai.sensitive=true` freigeschaltet werden.
Erlaubte Werte: `true` oder `false`. Jeder andere Wert ist ungültig und verhindert den Start.
---
## Exit-Codes
| Code | Bedeutung |
|------|-----------|
| `0` | Lauf technisch ordnungsgemäß ausgeführt (auch bei dokumentbezogenen Teilfehlern) |
| `1` | Harter Start- oder Bootstrap-Fehler (ungültige Konfiguration, Lock nicht erwerbbar, Schema-Initialisierungsfehler) |
Dokumentbezogene Fehler einzelner PDF-Dateien führen **nicht** zu Exit-Code `1`.
---
## Startschutz (Parallelinstanzschutz)
Die Anwendung verwendet eine exklusive Lock-Datei, um parallele Instanzen zu verhindern.
Wenn bereits eine Instanz läuft, beendet sich die neue Instanz sofort mit Exit-Code `1`.
Der Pfad der Lock-Datei ist über `runtime.lock.file` konfigurierbar.
Ohne Konfiguration wird `pdf-umbenenner.lock` im Arbeitsverzeichnis verwendet.
---
## SQLite-Datenbank
Die SQLite-Datei enthält:
- **Dokument-Stammsätze**: Gesamtstatus, Fehlerzähler, letzter Zieldateiname, Zeitstempel
- **Versuchshistorie**: Jeder Verarbeitungsversuch mit Modell, Prompt-Identifikator,
KI-Rohantwort, Reasoning, Datum, Titel und Fehlerstatus
Die Datenbank ist die führende Wahrheitsquelle für Bearbeitungsstatus und Nachvollziehbarkeit.
Sie muss nicht manuell verwaltet werden das Schema wird beim Start automatisch initialisiert.
---
## Systemgrenzen
- Nur OCR-verarbeitete, durchsuchbare PDF-Dateien werden verarbeitet
- Keine eingebaute OCR-Funktion
- Kein Web-UI, keine REST-API, keine interaktive Bedienung
- Kein interner Scheduler der Start erfolgt extern (z. B. Windows Task Scheduler)
- Quelldateien werden nie überschrieben, verschoben oder gelöscht
- Die Identifikation erfolgt über SHA-256-Fingerprint des Dateiinhalts, nicht über Dateinamen