# 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