Architektur¶
Die Anwendung ist als monolithischer Python-Dienst aufgebaut, der in einer einzigen Container-Instanz betrieben wird. Innerhalb des Dienstes sind die Verantwortlichkeiten in vier voneinander getrennten Schichten organisiert: Benutzeroberfläche, Dokumenten-Aufbereitung, Sprachmodell-Anbindung und Konfiguration. Externe Dienste werden ausschließlich für die LLM-Inferenz angesprochen; die gesamte Dokumentenverarbeitung erfolgt lokal innerhalb des Containers.
Auf einen Blick¶
- Container-basiertes Deployment (Docker, optional über Docker Compose)
- Schichtenarchitektur mit klarer Trennung von Oberfläche, Pipeline, LLM-Anbindung und Konfiguration
- Webframework Gradio als kombinierte UI- und HTTP-Schicht
- Aufbereitungspipeline mit Extraktion, Bereinigung, Deduplizierung, Markdown-Konvertierung und Referenzierung
- Sprachmodell-Anbindung über das OpenAI-API-Protokoll mit Streaming-Unterstützung
- In-Memory-Sitzungsverwaltung pro Browser-Sitzung
- Konfiguration ausschließlich über Umgebungsvariablen und CLI-Argumente
Architekturüberblick¶
Die UI-Schicht basiert auf Gradio und stellt sowohl die HTTP-Schnittstelle als auch das Frontend bereit. Sie nimmt Datei-Uploads entgegen, leitet Anfragen an die Pipeline weiter, streamt Modellantworten zurück und verwaltet pro Browser-Sitzung einen eigenen Zustand mit den geladenen Dokumenten und dem Chatverlauf.
Die Aufbereitungsschicht kapselt alle Schritte, die zwischen einem hochgeladenen Dokument und dem dem Sprachmodell übergebenen Kontext liegen. Sie ist in drei Teilbereiche gegliedert: Extraktion (Auslesen der Rohinhalte aus binären Formaten), Optimierung (Bereinigung, Deduplizierung, Markdown-Formatierung) und Referenzierung (Vergabe eindeutiger Absatzmarker für die Quellennachverfolgung).
Die LLM-Schicht verwaltet den Mehrdokumentenkontext, prüft Tokenlimits, baut den Prompt mit System- und Nutzeranweisungen auf und führt den Aufruf gegen den konfigurierten Sprachmodell-Endpunkt durch. Die Antwort wird im Streaming entgegengenommen und unmittelbar an die UI-Schicht weitergeleitet.
Die Konfigurationsschicht liest Umgebungsvariablen und CLI-Argumente ein, validiert sie und stellt sie als typisierte Datenklassen den übrigen Komponenten zur Verfügung.
flowchart TB
User([Nutzer])
subgraph Container[Container]
UI[Gradio UI<br/>Datei-Upload · Chat · Streaming]
subgraph Pipeline[Aufbereitungspipeline]
EX[Extraktion<br/>unstructured + pypdf]
CL[Bereinigung<br/>Header · Footer · Seitenzahlen]
DD[Deduplizierung<br/>Hash + Fuzzy-Match]
FM[Markdown-Formatter]
RF[Referenzsystem<br/>P1, P2, ...]
end
subgraph LLM[LLM-Anbindung]
MM[Multi-Document Manager<br/>Token- und Limit-Kontrolle]
IF[LLM-Interface<br/>OpenAI-API-Client]
end
WX[Word-Export<br/>python-docx]
CFG[Konfiguration<br/>ENV + CLI]
end
LLMSrv[(Sprachmodell-Endpunkt<br/>OpenAI-API-kompatibel)]
User -->|Upload| UI
UI --> EX
EX --> CL --> DD --> FM --> RF
RF --> MM
User -->|Frage| UI
UI --> MM --> IF
IF -->|HTTPS| LLMSrv
LLMSrv -.->|Streaming| IF
IF -.-> UI
UI -.-> User
UI -.-> WX
WX -.->|.docx| User
CFG -.-> UI
CFG -.-> IF
CFG -.-> Pipeline
Workflow¶
Der typische Ablauf beginnt mit dem Upload eines oder mehrerer Dokumente. Die UI-Schicht reicht jede Datei an die Extraktionskomponente weiter, die das Dokument anhand des Dateityps an einen passenden Parser übergibt. Für PDFs werden zusätzlich interaktive Formularfelder (AcroForm) ausgelesen und an den extrahierten Text angehängt. Das Ergebnis ist ein strukturierter Rohtext mit Überschriftsmarkierungen und — wo verfügbar — Seitenangaben.
Im Optimierungsschritt entfernt die Bereinigungskomponente wiederkehrende Headers, Footers, Seitenzahlen und typografische Artefakte über kompilierte Regex-Muster und eine Häufigkeitsanalyse. Anschließend prüft die Deduplizierung jedes Element gegen einen wachsenden Speicher zuvor gesehener Inhalte: Exakte Duplikate werden über MD5-Hashes erkannt, Near-Duplicates über Sequenz-Matching mit konfigurierbarem Ähnlichkeitsschwellwert. Tabellen und Listen werden zusätzlich strukturell verglichen. Der Markdown-Formatter überführt das Ergebnis in einheitliches Markdown und erhält dabei Listen, Tabellen und Überschriften.
Im Referenzierungsschritt wird jedem hinreichend langen Absatz eine eindeutige ID in der Form [Pn] zugewiesen. Eine interne Map speichert für jede ID einen Vorschautext, den vollständigen Absatz, den zugehörigen Dokumentnamen und — falls erkennbar — die Seitennummer. Diese Map dient später der Auflösung der vom Modell ausgegebenen Marker.
Stellt der Nutzer eine Frage, kombiniert der Multi-Document Manager alle aktiven Dokumente zu einem zusammengesetzten Kontext und prüft, ob dieser zusammen mit der Frage in das Kontextlimit passt. Das LLM-Interface baut einen Systemprompt — mit oder ohne Anweisung zur Nutzung von Quellenmarkern — und einen Nutzerprompt auf und ruft den Sprachmodell-Endpunkt im Streaming-Modus auf. Eingehende Token werden gepuffert, an Satzgrenzen oder bei vollem Buffer in die UI gespielt und dort fortlaufend gerendert. Nach Abschluss der Antwort werden vorhandene Marker [Pn] extrahiert, gegen die Referenzmap aufgelöst und gruppiert nach Dokument als Quellenliste angehängt.
Auf Anforderung erzeugt der Word-Exporter aus dem Chatverlauf ein formatiertes .docx-Dokument einschließlich der Quellenangaben.
Nebenläufigkeit, Robustheit und Konfiguration¶
Die Anwendung nutzt die Queue-Funktionalität von Gradio für die Anfrageserialisierung und ermöglicht das gezielte Abbrechen einer laufenden Streaming-Antwort durch den Nutzer. Sitzungen werden durch eine UUID identifiziert und im Arbeitsspeicher gehalten; nach Sitzungsende wird der zugehörige Speicher freigegeben. Fehler bei der Dokumentextraktion werden auf einen generischen Fallback-Pfad umgeleitet und je Datei separat in der Oberfläche zurückgemeldet, sodass eine fehlerhafte Datei nicht den gesamten Verarbeitungslauf blockiert. Tokenüberschreitungen werden vor dem LLM-Aufruf erkannt und mit einer entsprechenden Meldung abgewiesen.
Die Konfiguration erfolgt vollständig deklarativ über Umgebungsvariablen oder CLI-Argumente. Eine zentrale Konfigurationsklasse liest die Werte ein, validiert sie und stellt sie typisiert zur Verfügung. Damit lässt sich die Anwendung ohne Codeänderung an unterschiedliche Sprachmodell-Endpunkte, Subpfad-Deployments hinter einem Reverse Proxy und abweichende Tokenlimits anpassen.
Technologie-Übersicht¶
| Bereich | Komponente |
|---|---|
| Sprache und Laufzeit | Python 3.13 |
| Webframework / UI | Gradio (Version 5+) |
| Dokumentextraktion | unstructured (PDF, DOCX, PPTX), pypdf für interaktive Formularfelder, pdfplumber, openpyxl, python-pptx |
| Sprachmodell-Anbindung | OpenAI Python SDK (OpenAI-API-Protokoll) |
| Word-Export | python-docx |
| Hilfsbibliotheken | beautifulsoup4, lxml, chardet, python-magic, tiktoken |
| Containerisierung | Docker (Multi-Stage-Build), Docker Compose |
| Systemabhängigkeiten | poppler-utils, tesseract-ocr, libreoffice, libmagic |