Zum Inhalt

Architektur

Grafix ist als containerisierte Webanwendung mit klarer Schichtentrennung aufgebaut. Eine browserseitige Oberfläche kommuniziert mit einer Python-Backend-Anwendung, die sowohl die Intent-Erkennung über einen LLM-Endpoint als auch die regelbasierte Diagramm-Erzeugung durchführt. Die Generierung der Diagramme ist konsequent von der Intent-Erkennung getrennt: Das Sprachmodell entscheidet ausschließlich, was gemacht werden soll; wie das Diagramm gezeichnet wird, bestimmt eine deterministische Template-Engine.

Auf einen Blick

  • Container-basierte Auslieferung über Docker mit Reverse-Proxy-Anbindung.
  • Browserseitiges Canvas-Rendering über die Bibliothek Fabric.js, serverseitige Logik in Python.
  • Multi-Agenten-Pipeline mit nur einem LLM-Call pro Anfrage; alle weiteren Stufen regelbasiert.
  • Strikte Trennung von Intent-Erkennung (LLM) und Layout-Erzeugung (Template-Engine).
  • Anbindung eines internen LLM-Dienstes über eine OpenAI-kompatible Schnittstelle.
  • Session-Verwaltung im Anwendungsspeicher mit vollständiger Historie pro Session.
  • 27 Vorlagen als eigenständige Klassen, abgeleitet von einer gemeinsamen Basisklasse.

Architekturüberblick

Die Anwendung gliedert sich in fünf Schichten:

  1. Oberfläche (Browser) — Eine über Gradio bereitgestellte Web-UI mit Chat-Eingabe, Template-Galerie, Bearbeitungsformularen und einem Canvas-Bereich. Das Canvas wird über Fabric.js gerendert; Auswahl, Verschiebung und Textbearbeitung erfolgen direkt im Browser.
  2. Orchestrierung — Ein zentraler Orchestrator nimmt die Anfrage entgegen, ruft den Intent Agent auf, führt die erkannten Intents aus, übergibt das Ergebnis an den Validation Agent und abschließend an den Consistency Agent.
  3. Agenten — Vier spezialisierte Komponenten: Intent Agent (LLM-basiert), Execution-Logik (regelbasiert), Validation Agent (LLM-basiert, bei Bedarf), Consistency Agent (regelbasiert).
  4. Template-Engine — Ein Satz aus 27 Vorlagenklassen, jede mit eigener Geometrie- und Skalierungslogik. Die Engine erzeugt aus einer Vorlage und einer Element-Liste ein Fabric.js-kompatibles JSON-Dokument mit absoluten Positionen.
  5. Session- und Export-Dienste — Verwaltung der Aktions-Historie pro Session, Bereitstellung des Kontextes für nachfolgende LLM-Calls, Aufbereitung der Export-Daten für PNG (clientseitig) und JSON (serverseitig).

Workflow einer Anfrage

flowchart TD
    A[Nutzeranfrage im Chat] --> B[Session-Service]
    B --> C[Kontextaufbereitung<br/>Historie + aktuelles Canvas]
    C --> D[Intent Agent<br/>LLM-Klassifikation]
    D --> E{Konfidenz<br/>ausreichend?}
    E -- nein --> F[Rückfrage an Nutzer]
    E -- ja --> G[Orchestrator<br/>regelbasiert]
    G --> H{Intent-Typ}
    H -- create --> I[Template-Engine<br/>Layout berechnen]
    H -- modify_slot --> J[Slot-Update<br/>im bestehenden Canvas]
    H -- modify_style --> K[Stil-Update<br/>im bestehenden Canvas]
    H -- upgrade_template --> L[Template-Wechsel<br/>Inhalte übertragen]
    I --> M[Validation Agent]
    J --> M
    K --> M
    L --> M
    M --> N[Consistency Agent<br/>regelbasiert]
    N --> O[Aktion in Session-Historie<br/>protokollieren]
    O --> P[Canvas an Browser<br/>Fabric.js-Rendering]
    F --> O

Eine Nutzeranfrage erreicht zunächst den Session-Service, der die laufende Session ermittelt oder eine neue anlegt. Anschließend wird ein Kontext aus der bisherigen Aktions-Historie und dem aktuellen Canvas-Zustand zusammengestellt. Dieser Kontext geht zusammen mit der eigentlichen Nutzereingabe an den Intent Agent, der ein Sprachmodell über eine OpenAI-kompatible Schnittstelle aufruft. Das Sprachmodell liefert eine strukturierte Klassifikation als JSON: erkannte Aktionstypen (Erstellen, Slot ändern, Stil ändern, Element hinzufügen oder entfernen, Template wechseln, Rückfrage), zugehörige Parameter, Konfidenzwert und Begründung.

Liegt die Konfidenz zu niedrig oder ist die Anfrage mehrdeutig, wird statt einer Aktion eine Rückfrage zurückgegeben. Andernfalls übernimmt der Orchestrator die Ausführung. Diese Stufe arbeitet vollständig regelbasiert und greift nicht erneut auf das Sprachmodell zu. Je nach erkanntem Intent ruft der Orchestrator entweder die Template-Engine (für Neuerstellung oder Template-Wechsel) auf oder modifiziert das bestehende Canvas-JSON gezielt (für Slot- oder Stil-Änderungen).

Die Template-Engine ist das Herzstück der deterministischen Diagramm-Erzeugung. Jede der 27 Vorlagen ist als eigenständige Klasse implementiert, die aus einer gemeinsamen Basisklasse abgeleitet ist. Die Klasse definiert Mindest- und Höchstanzahl von Elementen, Skalierungslogik, Farb- und Schattenbehandlung sowie die konkrete Geometrieberechnung. Das Ergebnis ist ein JSON-Dokument im Fabric.js-Format mit absoluten Koordinaten für jedes Objekt.

Anschließend prüft der Validation Agent, ob das Ergebnis zum erkannten Intent passt. Eine zweite Prüfung übernimmt der Consistency Agent: Sichtbarkeit, Abstände, Ausrichtung, Überlappungen und Farbnutzung werden regelbasiert geprüft. Dabei erkennt der Agent strukturierte Templates an typischen Object-IDs (etwa level1_, content_, text_left) und unterlässt in diesen Fällen automatische Korrekturen, um die Geometrie der Vorlage nicht zu beschädigen. Lediglich bei manuell bearbeiteten oder offensichtlich fehlerhaften Layouts werden Auto-Fixes angewandt.

Der letzte Schritt protokolliert die Aktion in der Session-Historie und überträgt das Canvas-JSON an die Oberfläche. Im Browser rendert Fabric.js das Diagramm und erlaubt die anschließende Direktbearbeitung.

Rolle des Sprachmodells

Das Sprachmodell wird ausschließlich für die Intent-Klassifikation verwendet, nicht für die Erzeugung des Canvas-JSON. Diese Trennung hat zwei Konsequenzen: Erstens entstehen keine Layout-Probleme, die typischerweise auftreten, wenn ein LLM Koordinaten generiert. Zweitens reicht ein einziger LLM-Call pro Nutzeranfrage. Der Validation Agent kann zwar zusätzlich aufgerufen werden, ist aber für den Standardfall nicht erforderlich.

Die strukturierte Ausgabe des Intent Agents wird als JSON erwartet. Bei Parsing-Fehlern oder unvollständigen Antworten greift ein Fallback-Mechanismus, der eine Rückfrage an den Nutzer auslöst, statt eine fehlerhafte Aktion durchzuführen.

Session und Kontext

Sessions werden im Anwendungsspeicher gehalten und enthalten eine geordnete Liste von Aktionen. Jede Aktion dokumentiert die ursprüngliche Eingabe, den erkannten Aktionstyp, das resultierende Aktions-JSON, den Canvas-Zustand vor und nach der Aktion sowie Konfidenz und Begründung der Klassifikation.

Vor jedem LLM-Call wird die Historie in zwei Repräsentationen aufbereitet — als natürlichsprachige Zusammenfassung und als kompaktes JSON. Beide Darstellungen werden dem Sprachmodell als Kontext vorgelegt. Diese Vorgehensweise wirkt als impliziter Few-Shot-Mechanismus: Bereits korrekt klassifizierte frühere Aktionen dienen als Beispiele für die aktuelle Klassifikation.

Nebenläufigkeit, Robustheit und Konfiguration

Die Anwendung läuft als einzelner Containerprozess, der mehrere parallele Sessions im Speicher hält. Die Session-IDs werden serverseitig generiert. Aktionen einer Session werden nicht über Sessions hinweg vermischt.

Robustheit gegenüber unzuverlässigen LLM-Antworten erreicht die Pipeline durch mehrere Mechanismen: tolerantes JSON-Parsen (Markdown-Codeblöcke und ungenaue Klammerung werden akzeptiert), Fallback bei nicht parsbaren Antworten (Rückfrage statt Halluzination), konfidenzbasierte Eskalation an den Validation Agent und Layout-Korrektur durch den Consistency Agent.

Die Konfiguration erfolgt über Umgebungsvariablen — unter anderem für den LLM-Endpoint, das Modell, den Konfidenz-Schwellwert und den URL-Präfix für den Reverse-Proxy-Betrieb. Eine Beispiel-Konfigurationsdatei liegt der Anwendung bei.

Technologie-Übersicht

  • Sprache und Laufzeit — Python 3.12 als serverseitige Laufzeit.
  • Web-Oberfläche — Gradio für die Bereitstellung der Bedienoberfläche im Browser.
  • Canvas-Rendering — Fabric.js für die clientseitige Darstellung und Direktbearbeitung der Diagramme.
  • LLM-Anbindung — OpenAI-kompatible Schnittstelle für die Kommunikation mit dem internen Sprachmodell-Dienst.
  • Datenmodellierung — Pydantic für typisierte Datenmodelle und konfigurationsgesteuerte Einstellungen.
  • Bildverarbeitung — Pillow für die serverseitige Bildaufbereitung im Export.
  • Containerisierung — Docker und docker-compose für Build und Betrieb; Anbindung an einen vorgelagerten Reverse-Proxy für die Bereitstellung unter einem URL-Pfad.