Zum Inhalt

Architektur

Die Anwendung folgt einem geschichteten Aufbau mit klarer Trennung zwischen Bedienoberfläche, Eingabeverarbeitung, Berechnungskern und Ausgabeformaten. Eine zentrale Designentscheidung ist die Isolation des LLMs auf die Eingabeverarbeitung: sobald die Parameter strukturiert vorliegen, übernimmt ein deterministischer Rechenkern. Dadurch sind die Berechnungsergebnisse reproduzierbar und unabhängig vom verwendeten Modell.

Auf einen Blick

  • Schichtenmodell mit Bedienoberfläche, LLM-gestützter Parser-Schicht, deterministischem Rechenkern, Sitzungsverwaltung und Ausgabeschicht
  • Strikte Trennung von KI-gestützter Eingabeverarbeitung und regelbasierter Berechnung
  • Zustandsverwaltung über eine Zustandsmaschine mit definierten Übergängen
  • Konfiguration vollständig über Umgebungsvariablen, Tarifdaten als separate Konfigurationsmodule
  • Containerisierung über Docker; Reverse-Proxy-fähig über konfigurierbares URL-Präfix
  • Anbindung des LLMs über eine OpenAI-kompatible Chat-API
  • Importwerkzeug zur Aktualisierung der Tarifdaten aus externen Excel-Quellen

Architekturbeschreibung

Komponentenübersicht

flowchart TB
    User([Nutzer])

    subgraph UI["Bedienoberfläche"]
        Form[Formular]
        Chat[Chat]
        Result[Ergebnisanzeige]
    end

    subgraph Session["Sitzungsverwaltung"]
        State[Zustandsmaschine]
        History[Verlauf]
    end

    subgraph Parser["Parser-Schicht"]
        Extractor[Parameter-Extraktor]
        Validator[Schema-Validator]
        LLMClient[LLM-Client]
    end

    subgraph Calculator["Rechenkern (deterministisch)"]
        Core[Berechnungslogik]
        Periods[Jahresscheiben]
        Steps[Stufenaufstieg]
    end

    subgraph Output["Ausgabe"]
        Tables[Markdown-Tabellen]
        Excel[Excel-Export]
        PDF[PDF-Export]
    end

    subgraph Config["Konfiguration"]
        TVL[Entgelttabelle]
        AG[AG-Anteile]
        SHK[SHK-Sätze]
    end

    LLM[(OpenAI-kompatible<br/>Chat-API)]
    Importer[Tarifdaten-Importer]
    Excel_Source[(Excel-Quelle)]

    User --> Form
    User --> Chat
    Form --> Session
    Chat --> Session
    Session --> State
    Session --> Parser
    Extractor --> LLMClient
    Extractor --> Validator
    LLMClient <--> LLM
    Session --> Calculator
    Calculator --> Core
    Core --> Periods
    Core --> Steps
    Calculator --> Output
    Output --> Result
    Output --> Excel
    Output --> PDF
    Result --> User

    Config -.-> Calculator
    Importer --> Config
    Excel_Source --> Importer

Bedienoberfläche und Sitzungsverwaltung

Die Bedienoberfläche ist als zweispaltiges Layout aufgebaut. Die linke Spalte enthält ein Formular mit Akkordeons für Einstellungen, Stelleneingabe und Stellenliste; die rechte Spalte führt einen Chat-Verlauf und zeigt das Berechnungsergebnis. Beide Eingabewege schreiben in dieselbe Stellenliste, sodass sie in einer Sitzung kombiniert werden können.

Die Sitzungsverwaltung verwaltet pro Nutzer einen Zustand (z.B. initial, parsing, clarifying, calculating, complete, q_and_a, fallback) und einen Konversationsverlauf. Eine Zustandsmaschine lässt nur definierte Übergänge zu; nach einer festgelegten Anzahl an erfolglosen Parse-Versuchen wechselt sie in den Fallback-Modus und aktiviert das Formular.

Parser-Schicht

Der Parameter-Extraktor formuliert die Anfrage an das LLM, extrahiert die JSON-Antwort und führt eine schemabasierte Validierung mit Pydantic durch. Vor der eigentlichen Validierung läuft eine Vorprüfung: liefert das LLM eine Stellenliste mit fehlenden Pflichtfeldern, wird sie in eine konkrete Rückfrage umgewandelt. Schlägt die Verarbeitung fehl, ruft der Extraktor das LLM erneut mit einem fehlerorientierten Prompt auf; wiederholte Fehlschläge werden an die Sitzungsverwaltung gemeldet.

Der LLM-Client kapselt die Kommunikation mit einer OpenAI-kompatiblen Chat-API. Die Verfügbarkeit der Schnittstelle wird beim Sitzungsstart geprüft; bei nicht erreichbarem Endpunkt fällt das System auf einen Mock-Client zurück, mit dem sich die Anwendung auch ohne aktives LLM betreiben lässt.

Nach einer abgeschlossenen Berechnung übernimmt eine zweite Prompt-Konfiguration den Q&A-Modus: das LLM beantwortet Fragen zur Kalkulation auf Basis des bereits berechneten Ergebnisses, das ihm als Kontext mitgegeben wird. Eigenständige numerische Werte werden in diesem Modus nicht berechnet.

Rechenkern

Der Rechenkern arbeitet vollständig deterministisch und unabhängig vom LLM. Eine Kalkulation umfasst mehrere Stellen; jede Stelle wird zunächst in Jahresscheiben zerlegt. Pro Scheibe werden Grundentgelt, Arbeitgeber-Brutto, anteilige Zuwendung und Gesamtkosten ermittelt. Tarifsteigerungen werden kumulativ pro Jahr angewandt; geplante Stufenaufstiege erzeugen innerhalb des betroffenen Jahres einen Übergang zwischen alter und neuer Stufe. Studentische Hilfskräfte werden separat auf Stundenbasis berechnet, mit einer Begrenzung auf 80 Stunden pro Monat und einem jahresweise fortgeschriebenen Stundensatz.

Für die BUND-Aufschlüsselung werden Renten-, Kranken-, Arbeitslosen- und Pflegeversicherung als feste Anteile des Bruttos separat ausgewiesen. Sämtliche Berechnungen erfolgen mit Dezimal-Arithmetik, um Rundungsabweichungen zu vermeiden.

Konfiguration und Tarifdaten

Tarifdaten (Entgelttabelle, Zuwendungssätze, Arbeitgeberanteile, SHK-Stundensätze) liegen als separate Konfigurationsmodule vor und werden vom Rechenkern zur Laufzeit eingelesen. Anwendungsparameter (LLM-Endpunkt, Server-Host und -Port, URL-Präfix, Standard-Tarifgebiet, Tarifsteigerungen, Log-Level) werden über Umgebungsvariablen gesteuert. Ein eigenständiges Kommandozeilenwerkzeug importiert aktualisierte Tarifdaten aus Excel-Dateien und erzeugt daraus die Konfigurationsmodule; eine Validierungsoption prüft die Plausibilität.

Betrieb

Die Anwendung wird als Docker-Container betrieben. Der Container exponiert einen einzelnen HTTP-Port; ein Health-Check prüft die Erreichbarkeit der Bedienoberfläche. Über das konfigurierbare URL-Präfix lässt sich die Anwendung hinter einem Reverse-Proxy unter einem beliebigen Pfad betreiben. Der Standardnutzer im Container besitzt keine Root-Rechte.

Eingesetzte Technologien

  • Web-Framework: Gradio
  • Schema-Validierung: Pydantic
  • HTTP-Client: requests
  • Excel-Verarbeitung: openpyxl, pandas, xlrd
  • PDF-Erstellung: reportlab
  • LLM-Schnittstelle: OpenAI-kompatible Chat-API
  • Containerisierung: Docker
  • Testumgebung: pytest