290 lines
12 KiB
Markdown
290 lines
12 KiB
Markdown
# 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 C:\Pfad\zur\Installation\pdf-umbenenner-bootstrap\target\pdf-umbenenner-bootstrap-0.0.1-SNAPSHOT.jar`
|
||
4. Starten in: `C:\Pfad\zur\Installation` (muss das Verzeichnis mit `config\application.properties` und `config\prompts\` enthalten)
|
||
|
||
> **Hinweis:** Das „Starten in"-Verzeichnis ist das Arbeitsverzeichnis der Anwendung.
|
||
> Die Konfigurationsdatei `config/application.properties` sowie das Prompt-Verzeichnis
|
||
> `config/prompts/` müssen relativ zu diesem Verzeichnis erreichbar sein. Der JAR-Pfad
|
||
> in den Argumenten muss absolut oder relativ zum Starten-in-Verzeichnis korrekt angegeben sein.
|
||
|
||
---
|
||
|
||
## 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 (allgemein)
|
||
|
||
| 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) |
|
||
| `ai.provider.active` | Aktiver KI-Provider: `openai-compatible` oder `claude` |
|
||
| `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) |
|
||
|
||
### Provider-Parameter
|
||
|
||
Nur der **aktive** Provider muss vollständig konfiguriert sein. Der inaktive Provider wird nicht validiert.
|
||
|
||
**OpenAI-kompatibler Provider** (`ai.provider.active=openai-compatible`):
|
||
|
||
| Parameter | Beschreibung |
|
||
|-----------|--------------|
|
||
| `ai.provider.openai-compatible.baseUrl` | Basis-URL des KI-Dienstes (z. B. `https://api.openai.com/v1`) |
|
||
| `ai.provider.openai-compatible.model` | Modellname (z. B. `gpt-4o-mini`) |
|
||
| `ai.provider.openai-compatible.timeoutSeconds` | HTTP-Timeout in Sekunden (ganzzahlig, > 0) |
|
||
| `ai.provider.openai-compatible.apiKey` | API-Schlüssel (Umgebungsvariable `OPENAI_COMPATIBLE_API_KEY` hat Vorrang) |
|
||
|
||
**Anthropic Claude-Provider** (`ai.provider.active=claude`):
|
||
|
||
| Parameter | Beschreibung |
|
||
|-----------|--------------|
|
||
| `ai.provider.claude.baseUrl` | Basis-URL (optional; Standard: `https://api.anthropic.com`) |
|
||
| `ai.provider.claude.model` | Modellname (z. B. `claude-3-5-sonnet-20241022`) |
|
||
| `ai.provider.claude.timeoutSeconds` | HTTP-Timeout in Sekunden (ganzzahlig, > 0) |
|
||
| `ai.provider.claude.apiKey` | API-Schlüssel (Umgebungsvariable `ANTHROPIC_API_KEY` hat Vorrang) |
|
||
|
||
### Optionale Parameter
|
||
|
||
| Parameter | Beschreibung | Standard |
|
||
|---------------------|--------------|---------|
|
||
| `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
|
||
|
||
Pro Provider-Familie existiert eine eigene Umgebungsvariable, die Vorrang vor dem Properties-Wert hat:
|
||
|
||
| Provider | Umgebungsvariable |
|
||
|---|---|
|
||
| `openai-compatible` | `OPENAI_COMPATIBLE_API_KEY` |
|
||
| `claude` | `ANTHROPIC_API_KEY` |
|
||
|
||
Schlüssel verschiedener Provider-Familien werden niemals vermischt.
|
||
|
||
---
|
||
|
||
## Migration älterer Konfigurationsdateien
|
||
|
||
Ältere Konfigurationsdateien, die noch die flachen Schlüssel `api.baseUrl`, `api.model`,
|
||
`api.timeoutSeconds` und `api.key` verwenden, werden beim ersten Start **automatisch**
|
||
in das aktuelle Schema überführt.
|
||
|
||
### Was passiert
|
||
|
||
1. Die Anwendung erkennt die veraltete Form anhand der flachen `api.*`-Schlüssel.
|
||
2. **Vor jeder Änderung** wird eine Sicherungskopie der Originaldatei angelegt:
|
||
- Standardfall: `config/application.properties.bak`
|
||
- Falls `.bak` bereits existiert: `config/application.properties.bak.1`, `.bak.2`, …
|
||
- Bestehende Sicherungen werden **niemals überschrieben**.
|
||
3. Die Datei wird in-place in das neue Schema überführt:
|
||
- `api.baseUrl` → `ai.provider.openai-compatible.baseUrl`
|
||
- `api.model` → `ai.provider.openai-compatible.model`
|
||
- `api.timeoutSeconds` → `ai.provider.openai-compatible.timeoutSeconds`
|
||
- `api.key` → `ai.provider.openai-compatible.apiKey`
|
||
- `ai.provider.active=openai-compatible` wird ergänzt.
|
||
- Alle übrigen Schlüssel bleiben unverändert.
|
||
4. Die migrierte Datei wird über eine temporäre Datei (`*.tmp`) und atomischen
|
||
Move/Rename geschrieben. Das Original wird niemals teilbeschrieben.
|
||
5. Die migrierte Datei wird sofort neu eingelesen und validiert.
|
||
|
||
### Bei Migrationsfehler
|
||
|
||
Schlägt die Validierung der migrierten Datei fehl, bricht die Anwendung mit Exit-Code `1` ab.
|
||
Die Sicherungskopie (`.bak`) bleibt in diesem Fall erhalten und enthält die unveränderte
|
||
Originaldatei. Die Konfiguration muss dann manuell korrigiert werden.
|
||
|
||
### Betreiber-Hinweis
|
||
|
||
Die Umgebungsvariable `PDF_UMBENENNER_API_KEY` des Vorgängerstands wird **nicht** automatisch
|
||
umbenannt. Falls dieser Wert bislang verwendet wurde, muss er auf `OPENAI_COMPATIBLE_API_KEY`
|
||
umgestellt werden.
|
||
|
||
---
|
||
|
||
## 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
|
||
|
||
Die folgende Tabelle beschreibt die persistenten Statuszustände der Dokument-Stammsätze
|
||
in der SQLite-Datenbank. Diese Zustände sind nach Abschluss eines Verarbeitungsversuchs
|
||
dauerhaft gespeichert.
|
||
|
||
| Status | Bedeutung |
|
||
|-----------------------------|-----------|
|
||
| `READY_FOR_AI` | Verarbeitbar, KI-Pfad noch nicht durchlaufen |
|
||
| `PROPOSAL_READY` | KI-Benennungsvorschlag liegt vor, Zielkopie noch nicht geschrieben |
|
||
| `SUCCESS` | Erfolgreich verarbeitet und kopiert (terminaler Endzustand) |
|
||
| `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 |
|
||
|
||
Zusätzlich kennt das System den transienten Zustand `PROCESSING`, der während der aktiven
|
||
Verarbeitung eines Dokuments im Stammsatz gesetzt werden kann. Er wird nach Abschluss des
|
||
Verarbeitungsversuchs stets durch einen der obigen Zustände ersetzt und ist kein gültiger
|
||
Endstatus in der Datenbank.
|
||
|
||
### 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
|