Wer mit Daten arbeitet, kennt den Frust: Dateien, die sich nicht an ihr eigenes Schema halten. CSVs, deren Spalten plötzlich mehrere Werte mit zusätzlichen Trennzeichen enthalten. Datenlager, in denen Tausende Tabellen existieren – mit unvollständiger Dokumentation. Kurz: viel Volumen, wenig Struktur und ein enormer Interpretationsaufwand.
In den letzten Monaten haben wir an zwei Szenarien gearbeitet, die genau in diesem Umfeld liegen. In beiden Fällen ging es um die Frage: Können Large Language Models (LLMs) helfen, Ordnung ins Chaos zu bringen und den Weg zu belastbaren Ergebnissen zu verkürzen? Die kurze Antwort: Ja – wenn man sie richtig einbettet. Die lange Antwort ist spannender und zeigt, wo die Grenzen sind, was wirklich funktioniert und wie man die Modelle produktiv in komplexen Datenlandschaften nutzt. Ich werde in zwei Artikeln ein paar unserer Erkenntnisse beschreiben, die wir in Zukunft für weitere LLM Use Cases anwenden werden.
Vom Datenchaos zur Struktur:
Ein häufig vorkommender Ausgangspunkt sind Datenquellen mit unsauberer Struktur. In unserem Fall eine CSV-Datei, bei der manche Spalten in Wahrheit ein kleines Universum sind: In manchen Zeilen steckt dort eine Liste von Attributen, getrennt durch ein Semikolon, in anderen Zeilen sind es kommagetrennte Paare aus Attributnamen und Werten. Die Datei war über ein Gigabyte groß, mit mehreren Hunderttausend Zeilen, für die so kein klares Schema erkennbar war.
Unsere Aufgabe war es, diese Datei in ein anderes, firmeninternes Datenschema zu übersetzen. Das Zielschema selbst war auch riesig, ein Attributraum im fünfstelligen Bereich, je nach Kategorie waren aber nur bis zu 3.000 Attribute wirklich relevant, von denen dann ein einzelner Artikel im Schnitt nur 100 - 300 wirklich befüllt. Zusätzlich war ein weiteres Problem, dass ein Attribut in dem Zielschema erst durch die Betrachtung mehrerer Spalten in der CSV bestimmt werden konnte.
Zusammenfassend hier noch einmal eine Auflistung der Schwierigkeiten:
- Nur ein kleiner Teilraum der eigentlichen Zielmenge (knapp 10 %) war relevant in der Betrachtung, während ein noch kleinerer Teil (unter 1 %) wirklich durch das eigentliche Produkt abgedeckt wurde, also Teil des Endergebnisses war.
- Einzelne Zeilen folgen keiner Gesamtstruktur, sie sind also zu unterschiedlich, um eine klassische regelbasierte Transformation mit realistischem Aufwand hinzubekommen.
- Einzelne CSV-Spalten konnten auf mehrere Attribute im Zielschema abgebildet werden
- Einzelne Attribute im Zielschema benötigten teilweise mehrere Spalten aus der CSV-Datei, um eindeutig befüllt werden zu können.
Unser Versuch war es, diese Transformation durch ein LLM durchzuführen, ein eigentlicher Widerspruch zu den Faustregeln, die wir normalerweise selbst empfehlen. Denn im Normalfall sollten LLMs nicht dort eingesetzt werden, wo regelbasierte Ansätze funktionieren. Für das Team war aber klar, dass die klassischen Lösungen hier den Rahmen sprengen würden. Es gab zu viele Ausnahmen, um diese durch Code im erwarteten Zeitfenster abdecken zu können.
Der Kernansatz: Reduzieren, Struktur erzwingen, iterativ verfeinern
Der erste Hebel ist Reduktion. Statt jede Zeile gegen das volle Zielschema zu prüfen, lassen wir das LLM zunächst die Kategorie erkennen. Damit schrumpft der relevante Attributraum drastisch, und wir konzentrieren uns nur auf das, was im jeweiligen Kontext plausibel ist. So werden Fehler unwahrscheinlicher und die Präzision steigt.
Zweiter Hebel: strukturierte Ausgaben. Wir nutzen die Fähigkeit moderner LLMs, Daten in strukturierten Outputs auszugeben. Das LLM füllt nicht „irgendwas“, sondern genau die vorgesehenen Felder, mit klaren Constraints. In Python ist das sehr einfach zu erreichen, indem Pydantic-Klassen den Datentyp vorgeben und wir diesen dem LLM mitgeben. Dies funktionierte in unseren Tests immer, sodass wir uns keine Sorgen machen mussten, dass das LLM Text ausgibt, der danach nicht vom Code interpretiert werden kann. Wir nutzen auch die Möglichkeit, Klassenattribute nicht nur durch einen Namen, sondern auch durch eine „Description” zu definieren. Das klingt banal, ändert aber die Erfolgsquote merklich: Je weniger Interpretationsspielraum, desto robuster die Ergebnisse.
Dritter Hebel: iteratives Vorgehen. Statt alle potenziell relevanten Felder in einem Rutsch zu befüllen, arbeiten wir in Etappen. Statt alle Attribute haben wir dem LLM nur zehn Attribute auf einmal mitgegeben. Zwar haben moderne Modelle große Kontextfenster, aber eine hohe Ausgabelast macht sie anfällig für Ungenauigkeit. Unsere Erfahrung: Je größer der Output-Block, desto öfter schleichen sich kleine, aber bedeutsame Fehler ein. So wurden dann Attribute nicht nur falsch befüllt, sondern teilweise komplett vergessen. Ein Stichwort sei hierzu noch erwähnt, welches wir auch noch in einem weiteren Artikel thematisieren werden: Caching von LLM-Anfragen durch bewusstes Prompten.
Details der Implementierung
Wichtig bei der Bestimmung der Kategorien, aber auch bei der Befüllung der Attribute war es, passendes Context Engineering zu betreiben. Damit ist gemeint, an den relevanten Stellen dem LLM die wichtigen externen Informationen mitzugeben und für diesen Schritt unwichtige Details wieder wegzunehmen. So haben wir während des Kategorisierungschritts dem LLM nicht nur die Namen der einzelnen Kategorien mitgegeben, sondern auch durch Domainexperten formulierte Beschreibungen, Beispielprodukte und Hinweise, was in den Daten drinstehen könnte, damit ein Produkt zu dieser Kategorie passt. Ähnlich haben wir es auch bei den Attributen gemacht. Die Präzision hat sich dramatisch erhöht, wenn jedes relevante Attribut auch eine Beschreibung hatte, worum es sich hier eigentlich genau handelt.
Eine abstrakte Ansicht der Transformationsarchitektur
Ein weiterer Trick, den wir genutzt haben, um die Genauigkeit der Ergebnisse zu verbessern, war es Chain-of-Thought-Techniken zu nutzen. In der Ausgabestruktur, sollte das LLM für jedes Attribut auch das Freitext Feld “Quelle” füllen, indem es beschreibt, wo der Wert für dieses Attribut in der Produktzeile zu finden ist, sowie auch “logische Schlussfolgerungen” wie das LLM einen Wert aus dem Text ableiten konnte. Danach sollte das LLM den boolean “Vorhanden” befüllen, also einfach nur true oder false, wenn das LLM der Meinung ist, dieses Attribut kann durch die Informationen in der Produktzeile gefüllt werden. Hierbei handelt es sich weniger um ein Debugfeld für die Menschen um eventuelle Unstimmigkeiten danach zu verstehen, sondern um echte Funktionalität. Wichtig ist, dass das LLM erst danach den echten Wert füllt. Das LLM sagt sich somit also vorher selbst vor, wie es den eigentlichen Wert zu füllen hat. Tauscht man hier die Reihenfolge, und lässt das LLM erst den Wert füllen, danach die Erklärungen, hat man nichts gewonnen, da ein falsch ausgefülltes Feld nicht durch eine nachträglich andere Erklärung geändert werden kann, da Tokens sequentiell generiert werden.
Das Ausgabeformat des LLM. Nur die attributeId, name und value werden vom System gebraucht. Die anderen beiden Werte erhöhen die Präzision, werden aber nicht gespeichert
Ein ähnlicher Chain-of-Thought-Ansatz wurde auch angewendet, um sicherzustellen, dass auch alle Attribute wirklich betrachtet werden. So kann es durchaus sein, dass aus der Liste der in diesem Schritt zehn betrachteten Attribute das LLM welche „vergisst” und gar nicht füllt. Im strukturierten Output haben wir dem LLM also mitgeteilt, zuerst alle Attribute, die gefüllt werden sollen, aufzulisten und dann am Ende jedes gefüllten Attributs die ID des nächsten Attributs zu nennen.
Schluss
Durch die Reduktion der Zielmenge, einem iterativen Vorgehen und passendem Context Engineering, sowie durchdachten Prompting, waren wir in der Lage eine zufriedenstellende Datentransformation durchzuführen. Ein wichtiger Nachteil des LLM-basierten Ansatzes, gegenüber klassischen regelbasierten Ansätzen ist natürlich die Zufälligkeit der Antwort. Wiederholt man die Transformation, so waren die Antworten auch deutlich unterschiedlich. Tatsächlich war dies aber am Ende nur noch bei Freitextfeldern der Fall, wo Farben statt Weiß, manchmal Weiß (glänzend) waren. Zahlenwerte oder Booleans können wir zuverlässig befüllen und so eine interessante und flexible Alternative zum Transformieren von Daten schaffen.
Weitere Beiträge
von Daniel Töws
Weitere Artikel in diesem Themenbereich
Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.
Blog-Autor*in
Daniel Töws
Software Developer
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.