1
0

Vorbereitungen zu V1.1

This commit is contained in:
2026-04-08 22:21:32 +02:00
parent 559b051ab3
commit 9c2a205137
3 changed files with 556 additions and 146 deletions

View File

@@ -1,5 +1,11 @@
# Technik und Architektur PDF-Umbenenner mit KI
> **Versionshinweis v2**
> Diese Fassung erweitert die KI-Anbindung um einen zweiten, gleichwertig unterstützten Provider.
> Geändert wurden ausschließlich die Abschnitte, die für die Mehrprovider-Fähigkeit erforderlich sind:
> Technologiestack (Abschnitt 5), KI-Integration (Abschnitt 11), Konfiguration (Abschnitt 14) sowie die Abschlussbewertung (Abschnitt 19).
> Alle übrigen Abschnitte bleiben inhaltlich unverändert.
## 1. Ziel und Geltungsbereich
Dieses Dokument beschreibt die verbindliche technische Zielarchitektur für den **PDF-Umbenenner**.
@@ -130,7 +136,7 @@ Enthält technische Implementierungen der Outbound-Ports, insbesondere:
- Dateisystem
- PDFBox
- SQLite
- OpenAI-kompatibler HTTP-Client
- KI-HTTP-Clients (eine Implementierung je unterstütztem Provider, siehe Abschnitt 11)
- Properties-/Umgebungs-Konfiguration
- Run-Lock
- Clock
@@ -139,7 +145,8 @@ Enthält technische Implementierungen der Outbound-Ports, insbesondere:
Verantwortlich für:
- Laden und Validieren der Konfiguration
- Erzeugen des Objektgraphen
- Verdrahtung aller Adapter und Ports
- Auswahl und Verdrahtung der **einen** aktiven KI-Provider-Implementierung
- Verdrahtung aller übrigen Adapter und Ports
- Start des CLI-Adapters
- Setzen des Exit-Codes
@@ -162,13 +169,18 @@ Verbindlich eingesetzt werden:
- **SQLite** als lokaler Persistenzspeicher
- **SQLite JDBC-Treiber**
- **Log4j2** für Logging
- **OpenAI-kompatible HTTP-API** für KI-Zugriff
- **Java HTTP Client** oder technisch gleichwertige Standard-HTTP-Komponente
- **JSON-Bibliothek** für robuste JSON-Serialisierung und -Validierung
Für die KI-Anbindung werden **zwei gleichwertig unterstützte Provider-Familien** technisch zugelassen:
- **OpenAI-kompatible HTTP-Schnittstelle** (Chat-Completions-Stil)
- **native Anthropic Messages API** für Claude-Modelle
Pro Lauf ist genau **eine** dieser Provider-Implementierungen aktiv. Die Auswahl erfolgt ausschließlich über Konfiguration (siehe Abschnitt 14).
Nicht verbindlich festgelegt sind:
- konkreter KI-Provider
- konkrete KI-Basis-URL
- konkreter KI-Provider innerhalb einer Provider-Familie
- konkrete Basis-URL
- konkreter Modellname
Diese drei Punkte sind **reine Konfiguration** und ausdrücklich **keine Architekturentscheidung**.
@@ -196,6 +208,8 @@ Verbindlich zweckmäßige Outbound-Ports:
- `RunLockPort`
- `ClockPort`
Der `AiNamingPort` bleibt **provider-neutral**. Er kennt weder OpenAI- noch Anthropic-spezifische Typen, Header, URLs oder Antwortformate. Provider-spezifische Details (Endpunkt, Authentifizierung, Request-/Response-Format) leben ausschließlich in den jeweiligen Adapter-Out-Implementierungen.
### 6.3 Logging
Logging ist **kein fachlicher Port**. Logging ist technische Infrastruktur.
@@ -234,6 +248,8 @@ Die Verarbeitung einer einzelnen Datei erfolgt in dieser Reihenfolge:
16. temporäre Zieldatei final verschieben/umbenennen
17. Erfolg und Versuchshistorie persistent speichern
Die Verarbeitungsschritte sind **provider-unabhängig**. Welcher konkrete KI-Adapter Schritt 9 ausführt, ist außerhalb der Application nicht sichtbar.
### 7.3 Erfolgskriterium
Ein Dokument gilt genau dann als erfolgreich verarbeitet, wenn:
1. brauchbarer PDF-Text vorliegt,
@@ -288,63 +304,15 @@ Beispiele:
- `2026-03-31 - Stromabrechnung(1).pdf`
- `2026-03-31 - Stromabrechnung(2).pdf`
### 8.6 Windows-Kompatibilität
Die Anwendung stellt zusätzlich sicher, dass der Zielname für Windows zulässig ist.
---
Unzulässige Zeichen sind technisch zu entfernen oder kontrolliert zu ersetzen.
## 9. Retry- und Fehlersemantik
> Inhaltlich unverändert gegenüber der Vorgängerfassung. Nur die Erkenntnis, dass technische KI-Fehler unabhängig vom konkreten Provider als transient klassifiziert werden, gilt jetzt für **beide** Provider-Familien gleichermaßen.
---
## 9. Fehlerklassifikation und Retry-Regeln
### 9.1 Grundsatz
Nur **retryable** Fehler dürfen in späteren Läufen erneut verarbeitet werden.
**Finale** Fehler werden in späteren Läufen übersprungen.
### 9.2 Deterministische Inhaltsfehler
Deterministische Inhaltsfehler sind insbesondere:
- kein brauchbarer PDF-Text
- Seitenlimit überschritten
- Dokument inhaltlich mehrdeutig
- kein brauchbarer Titel
- generischer oder unzulässiger Titel
- von der KI gelieferter Datumswert ist vorhanden, aber unbrauchbar oder nicht interpretierbar
Regel:
- genau **1 Retry** in einem späteren Scheduler-Lauf
- danach **finaler Fehler**
### 9.3 Transiente technische Fehler
Transiente technische Fehler sind insbesondere:
- KI nicht erreichbar
- HTTP-Timeout
- temporäre IO-Fehler
- temporäre SQLite-Sperre
- ungültiges oder nicht parsebares KI-JSON
- sonstige vorübergehende technische Infrastrukturfehler
Regel:
- Retry in späteren Läufen bis zum konfigurierten Maximalwert
### 9.4 Technischer Sofort-Wiederholversuch
Zusätzlich zulässig ist genau **ein technischer Sofort-Wiederholversuch** innerhalb desselben Laufs für den Zielkopiervorgang, wenn das Schreiben der Zieldatei fehlschlägt.
Dieser Mechanismus ist **kein fachlicher Retry** und wird getrennt vom laufübergreifenden Retry-Modell behandelt.
### 9.5 Statusmodell
Verbindlich zweckmäßige Statuswerte:
- `SUCCESS`
- `FAILED_RETRYABLE`
- `FAILED_FINAL`
- `SKIPPED_ALREADY_PROCESSED`
- `SKIPPED_FINAL_FAILURE`
Ein technischer Zwischenstatus `PROCESSING` ist zusätzlich zulässig und sinnvoll.
---
## 10. Idempotenz und Identifikation
## 10. Identifikation und Reproduzierbarkeit
### 10.1 Identifikation
Die Identifikation eines Dokuments erfolgt **nicht** über den Dateinamen.
@@ -362,35 +330,63 @@ Daraus folgt:
Reproduzierbarkeit bedeutet technisch:
- nach einem erfolgreichen Lauf bleibt das gespeicherte Ergebnis stabil
- erfolgreiche Dateien werden nicht erneut KI-basiert bewertet
- KI-Aufrufe werden, soweit die API es zulässt, mit möglichst geringer Varianz konfiguriert
- Prompt-Version und Modellname werden persistiert
- KI-Aufrufe werden, soweit die jeweilige API es zulässt, mit möglichst geringer Varianz konfiguriert
- Prompt-Version, Modellname **und der Name des aktiven Providers** werden persistiert
---
## 11. KI-Integration
### 11.1 Schnittstelle
Die KI wird ausschließlich über eine **OpenAI-kompatible HTTP-Schnittstelle** angebunden.
### 11.1 Unterstützte Provider-Familien
Die KI wird über genau **eine** der folgenden Provider-Familien angebunden:
Basis-URL, Modellname und API-Key sind reine Konfiguration.
1. **OpenAI-kompatible HTTP-Schnittstelle**
Chat-Completions-Stil. Geeignet für OpenAI selbst und für jeden API-kompatiblen Drittanbieter.
2. **Native Anthropic Messages API**
Die offizielle Anthropic-Schnittstelle zur Nutzung von Claude-Modellen.
### 11.2 Prompt
Pro Lauf ist genau **ein** Provider aktiv. Es gibt:
- **keine** automatische Fallback-Umschaltung
- **keine** parallele Nutzung mehrerer Provider in einem Lauf
- **keine** Profilverwaltung mit mehreren Konfigurationen je Provider-Familie
Die Auswahl erfolgt ausschließlich über Konfiguration. Ein Fehler des aktiven Providers ist und bleibt ein Fehler dieses einen Pfads und folgt der bestehenden Retry- und Fehlersemantik.
### 11.2 Architekturelle Einbettung
- Pro Provider-Familie existiert **genau eine** Implementierung des `AiNamingPort` im Modul `pdf-umbenenner-adapter-out`.
- Provider-spezifische Endpunkte, Header, Authentifizierungsverfahren, Request- und Response-Strukturen leben ausschließlich in der jeweiligen Adapter-Implementierung.
- Application und Domain bleiben provider-neutral. Sie kennen weder den Begriff „OpenAI" noch „Claude".
- Das **Bootstrap-Modul** wählt anhand der Konfiguration die eine aktive Implementierung aus und verdrahtet sie als `AiNamingPort`.
- Adapter dürfen nicht voneinander abhängen. Es gibt keinen gemeinsamen „abstrakten KI-Adapter" als Infrastrukturschicht zwischen Port und konkreten Adaptern.
### 11.3 Einheitlicher fachlicher Vertrag
Unabhängig vom aktiven Provider gilt derselbe fachliche Vertrag:
- gleicher fachlicher Input (Prompt, Textausschnitt, Modellbezug)
- gleicher fachlicher Output (Domain-Typ `NamingProposal`)
- gleiche Validierungs- und Folgeprozesse in der Application
- keine provider-spezifische Verzweigung im fachlichen Kern
Jede provider-spezifische Antwort wird im Adapter auf denselben Domain-Typ abgebildet. Eine Sonderbehandlung im Use-Case oder in der Domain ist unzulässig.
### 11.4 Prompt
Der Prompt wird **nicht** im Code fest verdrahtet.
Verbindlich:
- externe Prompt-Datei
- Prompt-Version oder Prompt-Dateiname wird mitpersistiert
- der Prompt darf die KI zur Ausgabe eines deutschen Titels anweisen
- derselbe Prompt wird providerübergreifend verwendet; provider-spezifische Anpassungen finden ausschließlich in der Adapter-Implementierung statt
### 11.3 Textmenge
### 11.5 Textmenge
Es wird nicht zwingend der komplette extrahierte PDF-Text an die KI gesendet.
Verbindlich:
- die maximale Zeichenzahl ist konfigurierbar
- die Begrenzung muss vor dem KI-Aufruf technisch angewendet werden
- die Begrenzung gilt providerunabhängig
### 11.4 Antwortformat
Die KI muss genau ein parsebares JSON-Objekt liefern.
### 11.6 Antwortformat
Die KI muss unabhängig vom aktiven Provider fachlich genau ein parsebares JSON-Objekt liefern.
Zweckmäßiges Schema:
@@ -408,7 +404,9 @@ Regeln:
- `date` ist optional, wenn kein belastbares Datum ableitbar ist
- liefert die KI kein `date`, setzt die Anwendung das aktuelle Datum als Fallback
### 11.5 Antwortvalidierung
Wie der Adapter dieses Schema aus der jeweiligen Provider-Antwort extrahiert (z. B. aus `choices[].message.content` bei OpenAI-kompatiblen Schnittstellen oder aus dem Content-Block-Array der Anthropic Messages API), ist eine reine Adapter-Implementierungsfrage.
### 11.7 Antwortvalidierung
Die Antwort gilt nur dann als technisch brauchbar, wenn:
- JSON parsebar ist
- `title` vorhanden ist
@@ -418,6 +416,11 @@ Zusätzlich gilt fachlich:
- `title` muss validierbar und brauchbar sein
- ein vorhandenes `date` muss im Format `YYYY-MM-DD` interpretierbar sein
Diese Validierung ist provider-unabhängig und liegt in Application/Domain.
### 11.8 Fehlerklassifikation
Technische Fehler des aktiven Providers (HTTP-Fehler, Timeouts, ungültige Antwortstrukturen, Authentifizierungsfehler) werden im Adapter erkannt und auf die bestehende technische Fehlersemantik des Projekts abgebildet (transient vs. deterministisch). Es entsteht keine neue Fehlerkategorie. Der inaktive Provider wird in keiner Fehlersituation als Backup verwendet.
---
## 12. PDF-Verarbeitung
@@ -457,6 +460,8 @@ Die Persistenz wird zweckmäßig in **zwei Ebenen** geführt:
1. **Dokument-Stammsatz** pro Fingerprint
2. **Versuchshistorie** mit einem Datensatz pro Verarbeitungsversuch
Das bestehende Schema bleibt erhalten. Es wird ausschließlich um die Information erweitert, **welcher Provider** den jeweiligen Versuch erzeugt hat (siehe 13.4). Eine neue Wahrheitsquelle entsteht nicht.
### 13.3 Dokument-Stammsatz
Mindestens zweckmäßig zu speichern:
- interne ID
@@ -485,6 +490,7 @@ Für **jeden Versuch separat** zu speichern:
- Fehlerklasse
- Fehlermeldung
- Retryable-Flag
- **Provider-Identifikator des aktiven KI-Providers für diesen Versuch**
- Modellname
- Prompt-Identifikator
- verarbeitete Seitenzahl
@@ -496,11 +502,16 @@ Für **jeden Versuch separat** zu speichern:
- finaler Titel
- finaler Zieldateiname
Der Provider-Identifikator macht jeden Versuch eindeutig nachvollziehbar einer Provider-Familie zuordenbar, ohne den fachlichen Vertrag zu verändern.
### 13.5 Sensible Inhalte
Die vollständige KI-Rohantwort wird in SQLite gespeichert.
Sie soll **standardmäßig nicht vollständig in Logdateien** geschrieben werden.
### 13.6 Rückwärtsverträglichkeit
Bestehende Datenbestände aus dem Stand vor v2 müssen weiterhin lesbar, fortschreibbar und korrekt interpretierbar bleiben. Schema-Erweiterungen erfolgen additiv und mit definierten Defaultwerten für historische Versuche ohne Provider-Identifikator.
---
## 14. Konfiguration
@@ -508,33 +519,77 @@ Sie soll **standardmäßig nicht vollständig in Logdateien** geschrieben werden
### 14.1 Format
Die technische Konfiguration erfolgt über `.properties`.
### 14.2 Mindestparameter
### 14.2 Provider-Auswahl
Genau ein Provider ist aktiv. Die Auswahl erfolgt über einen einzigen Pflichtparameter, der den aktiven Provider benennt. Zulässige Werte sind die Bezeichner der unterstützten Provider-Familien aus Abschnitt 11.1.
### 14.3 Mindestparameter
Verbindlich zweckmäßige Parameter:
- `source.folder`
- `target.folder`
- `sqlite.file`
- `api.baseUrl`
- `api.model`
- `api.timeoutSeconds`
- **`ai.provider.active`** Auswahl des aktiven Providers (Pflicht)
- `max.retries.transient`
- `max.pages`
- `max.text.characters`
- `prompt.template.file`
Pro unterstützter Provider-Familie existiert ein eigener Parameter-Namensraum mit zweckmäßig mindestens:
- Modellname
- API-Schlüssel
- Timeout
- Basis-URL (optional, wo betrieblich sinnvoll)
Konkretes Schema (zweckmäßig, frei wählbare Bezeichner):
```properties
ai.provider.active=openai-compatible
ai.provider.openai-compatible.baseUrl=...
ai.provider.openai-compatible.model=...
ai.provider.openai-compatible.timeoutSeconds=...
ai.provider.openai-compatible.apiKey=...
ai.provider.claude.baseUrl=...
ai.provider.claude.model=...
ai.provider.claude.timeoutSeconds=...
ai.provider.claude.apiKey=...
```
Zusätzlich zweckmäßig:
- `runtime.lock.file`
- `log.directory`
- `log.level`
- `api.key`
- `log.ai.sensitive`
### 14.3 API-Key
Der API-Key darf über Umgebungsvariable oder Properties geliefert werden.
### 14.4 API-Schlüssel
API-Schlüssel dürfen über Umgebungsvariable oder Properties geliefert werden.
Verbindlich:
- Umgebungsvariable hat Vorrang
- pro Provider-Familie existiert eine **eigene definierte Umgebungsvariable**
- die Umgebungsvariable hat **Vorrang** vor dem Properties-Wert derselben Provider-Familie
- Schlüssel verschiedener Provider-Familien werden niemals vermischt
### 14.4 Konfigurationsvalidierung
Beim Start müssen alle Pflichtparameter validiert werden.
### 14.5 Migration historischer Konfigurationen
Bestehende Properties-Dateien aus dem Stand vor v2 (mit flachen Schlüsseln wie `api.baseUrl`, `api.model`, `api.timeoutSeconds`, `api.key`) sind eine eindeutig erkennbare Legacy-Form.
Beim ersten Start mit erkannter Legacy-Form gilt verbindlich:
1. Legacy-Form erkennen
2. **`.bak`-Sicherung** der Originaldatei anlegen
3. Inhalt in das neue Schema überführen
- die Legacy-Werte werden in den Namensraum der Provider-Familie **`openai-compatible`** überführt
- `ai.provider.active` wird auf `openai-compatible` gesetzt
4. neue Datei schreiben (In-Place-Update)
5. Datei erneut laden und validieren
6. erst danach den normalen Lauf fortsetzen
Es ist **kein** Ziel, alte und neue Struktur dauerhaft gleichrangig als Endformat zu pflegen.
### 14.6 Konfigurationsvalidierung
Beim Start müssen alle Pflichtparameter validiert werden, insbesondere:
- `ai.provider.active` ist gesetzt und benennt einen unterstützten Provider
- für den aktiven Provider sind alle Pflichtwerte vorhanden und technisch konsistent
- für den **inaktiven** Provider werden keine Pflichtwerte erzwungen
Bei ungültiger Startkonfiguration:
- beginnt kein Verarbeitungslauf
@@ -553,6 +608,7 @@ Das Logging muss mindestens enthalten:
- Laufstart
- Laufende
- Lauf-ID
- **aktiver KI-Provider für den Lauf**
- erkannte Quelldatei
- Überspringen bereits erfolgreicher Dateien
- Überspringen final fehlgeschlagener Dateien
@@ -566,6 +622,7 @@ Standardmäßig gilt:
- vollständige KI-Rohantwort **in SQLite**
- `reasoning` darf geloggt werden, sofern dies betrieblich gewünscht ist
- die Ausgabe sensibler Inhalte muss konfigurierbar sein
- die Sensibilitätsregel gilt provider-unabhängig
### 15.4 Speicherort
Das Log-Verzeichnis ist konfigurierbar. Ohne explizite Konfiguration ist ein lokales `logs/`-Verzeichnis im Programmkontext zweckmäßig.
@@ -598,7 +655,7 @@ Verbindliche Interpretation:
- `1`: Lauf konnte wegen hartem Start-/Bootstrap-Fehler nicht ordnungsgemäß beginnen oder fortgesetzt werden
Typische `1`-Fälle:
- ungültige Konfiguration
- ungültige Konfiguration (einschließlich fehlender oder unbekannter `ai.provider.active`)
- Run-Lock nicht erwerbbar
- essentielle Ressourcen beim Start nicht verfügbar
@@ -616,23 +673,30 @@ Nicht Bestandteil dieser Architektur sind:
- menschlicher Review-Workflow
- interne Scheduler-Logik
- fachliche Identifikation über Dateinamen
- automatische Fallback-Umschaltung zwischen KI-Providern
- parallele Nutzung mehrerer KI-Provider in einem Lauf
- mehrere konkurrierende Konfigurationen je Provider-Familie (Profilverwaltung)
- Provider-Familien jenseits der in Abschnitt 11.1 explizit genannten
---
## 19. Abschlussbewertung
Der technische Zielstand ist mit den hier festgelegten Regeln:
Der technische Zielstand ist mit den in dieser Fassung festgelegten Regeln:
- konsistent
- widerspruchsfrei
- hexagonal sauber geschnitten
- für einen minimalen produktiven PDF-Umbenenner zweckmäßig
- offen für genau zwei gleichwertig unterstützte KI-Provider-Familien, ohne den fachlichen Kern zu verändern
Besonders verbindlich geklärt sind jetzt:
Besonders verbindlich geklärt sind:
- Dateinamensformat mit `YYYY-MM-DD - Titel.pdf`
- Dublettenregel mit `(1)`, `(2)`, ...
- Trennung zwischen finalen und retrybaren Fehlern
- Fallback-Datum durch die Anwendung
- Zwei-Ebenen-Persistenz mit Versuchshistorie
- Zwei-Ebenen-Persistenz mit Versuchshistorie inkl. Provider-Identifikator
- Exit-Code-Regel für harte Startfehler
- OpenAI-kompatible Schnittstelle ohne fest verdrahteten Provider
- Unterstützung von OpenAI-kompatibler Schnittstelle **und** nativer Anthropic Messages API
- genau **ein** aktiver Provider pro Lauf, ohne Fallback
- Verlagerung technischer Persistenzobjekte aus der Domain heraus
- Migration historischer flacher Properties-Konfiguration mit `.bak`-Sicherung