Die ersten beiden Teile dieser Serie haben die Grundprinzipien gelegt. Ein Semantic Layer gibt Ihrer Organisation ein einheitliches, governance-gestütztes Vokabular, dem sowohl Menschen als auch KI-Systeme vertrauen können. Ein Data Flywheel gibt Ihrem Team die operative Disziplin, GenAI-Systeme kontinuierlich zu verbessern, statt sie stillschweigend degradieren zu lassen. Dieser dritte Teil ist der Punkt, an dem diese Prinzipien auf funktionierenden Code treffen.
Im Mittelpunkt steht Databricks Genie, die in die Databricks-Plattform integrierte "Ask Your Data"-Oberfläche in natürlicher Sprache. Genie erlaubt es Business-Usern, Fragen in Alltagssprache zu stellen und SQL-gestützte Antworten auf ihre echten Daten zu erhalten. Genie ist in vielerlei Hinsicht die direkte Umsetzung dessen, wofür die ersten beiden Artikel plädiert haben: ein Data Assistant auf einem governance-gestützten Fundament, der die Lücke zwischen Business-Fragen und vertrauenswürdigen Daten schließt. Doch Genie ohne Evaluierungs-Framework einzuführen, ist genau das, was Teil 2 als hoffnungsgetriebenes Deployment bezeichnet hat. Dieser Artikel beschreibt, wie man daraus ein technisch fundiertes Deployment macht – und wie man die Learning Loop schließt, die aus einem deployten Genie Agent ein System macht, das sich messbar über Zeit verbessert.
Das Problem, das Genie löst – und das Problem, das es schafft
Genie überzeugt gerade durch seine Zugänglichkeit. Ein Finanzanalyst kann fragen "Wie hoch waren die Gesamtumsätze in Japan im letzten Quartal?", ohne eine einzige Zeile SQL zu schreiben. Die Antwort kommt innerhalb von Sekunden, gestützt auf dieselben Tabellen, die das Datenteam verwaltet. Für Organisationen, die in einen Semantic Layer investiert haben, ist das der eigentliche Gewinn: Das semantische Modell erfüllt seinen Zweck, und der Endanwender muss nie erfahren, dass es überhaupt existiert.
Das Problem ist, dass diese Zugänglichkeit eine Vertrauenslücke schafft. Wenn ein Business-User eine Antwort aus einem Dashboard erhält, kann er die zugrunde liegende Query einsehen. Bei Genie sieht er nur das Ergebnis. Ist dieses Ergebnis falsch – hat Genie die falschen Tabellen verknüpft, "letztes Quartal" missverstanden oder Transaktionen statt Umsätze summiert – merkt der Nutzer das möglicherweise gar nicht. Es kann sein, dass es erst auffällt, wenn die Zahl in einer Vorstandspräsentation auftaucht.
Die eigentliche Gefahr ist, dass die Antwort nicht falsch aussieht. Genie präsentiert Ergebnisse mit derselben Formatierung und demselben scheinbaren Autoritätsanspruch – unabhängig davon, ob das zugrunde liegende SQL korrekt ist. Es gibt keinen Konfidenzwert, keine Rangfolge von Alternativen, kein Sternchen. Ein Assistent, der gelegentlich falschliegt, dabei aber immer selbstsicher wirkt, ist gefährlicher als einer, der sichtbar scheitert – denn ein sichtbares Scheitern kann man abfangen. Genau dafür existiert der hier beschriebene Evaluierungs-Harness: um dieses stille Scheitern erkennbar zu machen.
Was der Harness leistet
Der Harness ist ein Databricks-Notebook, das den Evaluierungszweig des Data Flywheels speziell für Genie Agents umsetzt. Er erfüllt vier Aufgaben:
Stellt Fragen programmatisch. Statt Genie manuell über die UI zu testen, steuert der Harness Genie über die Genie Conversation API an: Er stellt natürlichsprachliche Fragen, pollt, bis die Antwort bereitsteht, und extrahiert das generierte SQL sowie die Query-Ergebnisse aus der Antwort.
Vergleicht mit Ground Truth. Jeder Testfall enthält ein erwartetes SQL-Statement und, sofern das Ergebnis ein bekannter Wert ist, ein erwartetes Resultat. Der Harness prüft, ob das generierte SQL dem erwarteten Muster entspricht und ob das Ergebnis das enthält, was es enthalten sollte.
Bewertet semantische SQL-Korrektheit. Exaktes String-Matching ist für die SQL-Bewertung zu unflexibel – zwei Queries können syntaktisch unterschiedlich, aber semantisch identisch sein. Der Harness nutzt einen LLM-as-a-Judge, um zu beurteilen, ob das generierte SQL dieselbe Ergebnismenge liefern würde wie das erwartete SQL, auch wenn die Formulierung abweicht.
Verfolgt Verbesserungen über Zeit in MLflow. Jeder Evaluierungslauf wird als MLflow-Experiment geloggt und erzeugt so eine Zeitreihe von Accuracy-Werten. Genau das macht aus dem Flywheel ein funktionierendes System: Sie sehen lauf für Lauf, ob eine Änderung an Genies Instructions oder Beispiel-SQL die Performance verbessert oder verschlechtert hat.
Das vollständige Notebook ist im begleitenden Repository verfügbar. Es läuft gegen samples.bakehouse, ein Databricks-Beispieldatensatz, der in jedem Workspace verfügbar ist – es ist also kein zusätzliches Daten-Setup nötig. Um den Harness an Ihren eigenen Genie Agent anzupassen, setzen Sie SPACE_ID in der Configuration-Zelle und ersetzen Sie die Testfälle durch für Ihr Datenmodell relevante Fragen.
Native Benchmarks
Databricks bietet natürlich auch eigene Benchmarking-Funktionen für Genie an. Diese nativen Benchmarks unterteilen sich klar in zwei Modi, und keiner der beiden ersetzt den hier beschriebenen Ansatz. Der Chat-Modus bewertet Genauigkeit, indem er eine bereitgestellte SQL-Antwort ausführt und die Ergebnismenge mit dem von Genie generierten Ergebnis vergleicht – er beurteilt nicht die Query selbst, sondern nur, ob die ausgegebenen Zeilen übereinstimmen. Der Agent-Modus nutzt zwar einen LLM-Judge, bewertet damit aber den narrativen Bericht des Agent-Modus, nicht den logischen Vergleich zweier SQL-Queries. Das, was der hier beschriebene Ansatz zusätzlich leistet, ist, beide Queries zu lesen und zu beurteilen, ob WHERE country = 'Japan' und WHERE f.country = 'Japan' dasselbe bedeuten – dafür gibt es kein eingebautes Äquivalent. Der Ansatz erkennt außerdem eine andere Art von Fehler als der Ergebnismengen-Vergleich: Eine Query, die strukturell falsch ist, aber zufällig auf den heutigen Beispieldaten die richtigen Zeilen liefert, würde im Chat-Modus nicht auffallen – ein Judge, der das SQL direkt liest, erkennt das in der Regel schon.
Das Design der Test-Suite
Die Test-Suite ist das wichtigste Artefakt, das der Harness hervorbringt, und sie verdient mehr Sorgfalt, als ihr in der Praxis oft zuteilwird. Eine Test-Suite, die nur einfache Fälle abdeckt, erzeugt falsches Vertrauen. Eine gute Test-Suite ist ein bewusster Querschnitt der Fragen, die reale Nutzer tatsächlich stellen.
Der Harness organisiert Testfälle entlang zweier Achsen: Kategorie und Schwierigkeitsgrad. Die Kategorien spiegeln die SQL-Komplexität wider – einfache Aggregationen, gefilterte Abfragen, GROUP BY, Single-Table-Joins, Multi-Table-Joins, zeitbasierte Filter und mehrdeutige Formulierungen, bei denen die richtige Interpretation nicht allein aus der Frage hervorgeht. Der Schwierigkeitsgrad reicht von einfach bis schwer, wobei schwere Fälle typischerweise Multi-Hop-Joins über drei oder mehr Tabellen erfordern.
Ein paar Designprinzipien sind es wert, explizit gemacht zu werden. Erstens: Mehrdeutige Fragen bewusst einbeziehen. "Was ist das beliebteste Produkt?" ist tatsächlich mehrdeutig – bedeutet "beliebt" die meisten Transaktionen oder den höchsten Umsatz? Wie Genie diese Mehrdeutigkeit auflöst, ist eine Systemeigenschaft, die es wert ist, gemessen zu werden. Zweitens: Wenn das Ergebnis ein bekannter Wert ist, diesen fix vorgeben. Wenn die korrekte Antwort auf "Wie viele Transaktionen wurden mit Visa bezahlt?" 1.083 lautet, gehört diese Zahl in den Testfall. Exakte Ergebnis-Checks sind günstig und fangen Regressionen ab, die der SQL-Judge unter Umständen übersieht. Drittens: Die Test-Suite sollte wachsen. Ein initialer Satz von acht Fragen, wie im begleitenden Evaluierungs-Harness-Notebook, deckt die offensichtlichen Fälle ab. Produktivdaten werden Fragen zutage fördern, die man nicht vorhergesehen hat – diese sollten der Suite hinzugefügt werden, sobald sie auftauchen.
Das Polling-Pattern
Genie verarbeitet Fragen asynchron. Wenn Sie eine Frage über die Conversation API einreichen, erhalten Sie sofort eine Conversation-ID und eine Message-ID zurück, aber die Antwort liegt noch nicht vor. Genie ruft noch Metadaten ab, plant die Query, generiert SQL und führt es gegen das Warehouse aus. Der Harness pollt den Message-Endpoint in einem konfigurierbaren Intervall, bis der Status einen finalen Zustand erreicht.
1terminal_statuses = {"COMPLETED", "FAILED", "CANCELLED", "QUERY_RESULT_EXPIRED"}
2
3for attempt in range(MAX_POLL_ATTEMPTS):
4 msg_response = w.api_client.do(
5 method="GET",
6 path=f"/api/2.0/genie/spaces/{space_id}/conversations/{conversation_id}/messages/{message_id}"
7 )
8 status = msg_response.get("status", "UNKNOWN")
9 if status in terminal_statuses:
10 return {"status": status, "message": msg_response, ...}
11 time.sleep(POLL_INTERVAL_SECONDS)
SQL aus der Antwort extrahieren
Genie liefert seine Ausgabe in einem strukturierten attachments-Array im Message-Objekt. Das generierte SQL liegt unter attachments[].query.query – bemerkenswerterweise heißt das Feld query, nicht sql.
1def extract_sql(message: dict) -> str:
2 attachments = message.get("message", message).get("attachments", []) or []
3 for attachment in attachments:
4 if "query" in attachment:
5 query_info = attachment["query"]
6 if "query" in query_info:
7 return query_info["query"]
8 if "sql" in query_info: # fallback for older API versions
9 return query_info["sql"]
10 return ""
Dieselbe Attachment-Struktur trägt auch Query-Ergebnisse und Genies textuelle Antwort. Diese sauber zu trennen – SQL, Ergebniszeilen und erklärender Text – ist für die Evaluierung wichtig, da jede Komponente eine eigene Bewertungsstrategie erfordert.
Der SQL-Judge
Exaktes SQL-Matching scheitert aus einem einfachen Grund: WHERE country = 'Japan' und WHERE f.country = 'Japan' sind derselbe Filter. JOIN ... ON t.franchiseID = f.franchiseID und JOIN ... USING (franchiseID) sind derselbe Join. Ein Judge, der zeichengenaue Gleichheit verlangt, wird korrekte Antworten fälschlicherweise als Fehler markieren.
Der Harness nutzt MLflows make_judge, um einen benutzerdefinierten LLM-Evaluator zu definieren, der semantische Äquivalenz beurteilt statt syntaktischer Identität. Der Judge erhält die ursprüngliche Frage, das generierte SQL und das erwartete SQL und gibt einen Wahrheitswert zurück: Würden diese beiden Queries dieselbe Ergebnismenge liefern?
1SQL_JUDGE_INSTRUCTIONS = """
2You are an expert SQL evaluator for Databricks SQL. Determine whether the
3generated SQL is semantically equivalent to the expected SQL, meaning they
4would produce the same result set.
5
6Acceptable differences (still rate True):
7- Different column aliases, join syntax, whitespace, equivalent date functions
8
9Must match (rate False if different):
10- Different tables, different aggregation functions, missing/extra filters,
11 different GROUP BY columns, different LIMIT values
12"""
13
14sql_correctness_judge = make_judge(
15 name="sql_semantic_correctness",
16 instructions=SQL_JUDGE_INSTRUCTIONS,
17 model="databricks:/databricks-claude-sonnet-4",
18 feedback_value_type=bool,
19)
Der binäre Feedback-Typ ist eine bewusste Entscheidung, die das Prinzip aus Teil 2 wieder aufgreift: Binäre Metriken lassen sich deutlich leichter kalibrieren und nachvollziehen als abgestufte. Eine SQL-Query liefert entweder das richtige Ergebnis oder nicht. Den Judge auf einer Skala von eins bis fünf bewerten zu lassen, würde Unschärfe einführen, die es erschwert, Regressionen zu erkennen und Ergebnisse gegenüber Stakeholdern zu erklären.
Die Ergebnisse lesen
Der Harness liefert nach jedem Lauf zwei Outputs. Der erste ist eine unmittelbare Auswertung im Notebook: Gesamt-Completion-Rate, Accuracy pro Kategorie, Accuracy pro Schwierigkeitsgrad sowie eine Liste aller vollständig fehlgeschlagenen Fragen. Die Ansicht pro Kategorie ist am handlungsrelevantesten – sie zeigt nicht nur, dass etwas nicht stimmt, sondern womit genau Genie Schwierigkeiten hat.
Das lässt sich natürlich auch problemlos visualisieren.
Der zweite Output ist ein MLflow-Run, der automatisch geloggt wird. Das ist es, was das Flywheel überhaupt erst ermöglicht. Jeder Run erfasst die Space-ID, die Anzahl der Testfälle, den Zeitpunkt der Evaluierung und den aggregierten Accuracy-Score des SQL-Judges.
Hier lässt sich auch das detaillierte Feedback der Judges zu einzelnen Queries einsehen.
Läufe über die Zeit zu vergleichen, ist so einfach wie das Experiment abzufragen:
1runs = mlflow.search_runs(experiment_names=[EXPERIMENT_NAME])
2display(runs[["run_id", "start_time", "metrics.sql_semantic_correctness/rating/average"]])
Ein steigender Accuracy-Score bedeutet, dass Ihre Instructions und Beispiel-SQL sich verbessern. Ein plötzlicher Einbruch bedeutet eine Regression – entweder in Ihrer Konfiguration oder im zugrunde liegenden Modell, das, wie Teil 2 bereits festgehalten hat, ein Service ist, der sich unbemerkt unter Ihnen verändern kann.
Der Verbesserungs-Loop in der Praxis
Der Evaluierungs-Harness ist keine einmalige Übung. Er ist die Instrumentierung, die das Data Flywheel für Genie Agents operativ macht. Der Loop sieht in der Praxis so aus:
Harness laufen lassen und schwache Kategorien identifizieren. Liegt die Accuracy bei Join-Queries bei 60 %, die konkreten Fehlschläge untersuchen. Wählt Genie den falschen Join-Key? Weiß es nicht, dass franchiseID die Transactions-Tabelle mit der Franchises-Tabelle verbindet? Die Lösung ist meist eine von vier Optionen: eine textuelle Instruction, die die Beziehung in natürlicher Sprache beschreibt, ein Beispiel-SQL-Paar, das Genie das erwartete Join-Muster beibringt, eine Column-Konfiguration, die Beispielwerte für mehrdeutige Filterfelder offenlegt, oder eine Join-Spezifikation, die die Beziehung explizit in der Genie Ontology festlegt.
Fix anwenden, Harness erneut laufen lassen und die MLflow-Runs vergleichen. Ist der Score in der fehlerhaften Kategorie gestiegen und nichts anderes verschlechtert, ist der Fix gut. Ist die Accuracy in einer anderen Kategorie gesunken, stand die Instruction im Konflikt mit etwas anderem – eine Erinnerung daran, dass Prompt-Komplexität, wie in Teil 2 besprochen, ihre eigene Form von technischer Schuld ist.
Über die Zeit wird die Test-Suite selbst zu einem wertvollen Artefakt. Sie kodiert die Erwartungen der Organisation an das Verhalten von Genie in Form ausführbarer Spezifikationen. Neue Teammitglieder können sie sofort ausführen, um den aktuellen Zustand des Systems zu verstehen. Stakeholdern können Accuracy-Scores statt Demos gezeigt werden. Und wenn sich das zugrunde liegende Datenmodell ändert – eine Tabelle wird umbenannt, eine Spalte hinzugefügt, ein Join-Key aktualisiert –, fängt der Harness die Regression ab, bevor sie einen Nutzer erreicht.
Fazit
Dieser Artikel hat die Prinzipien aus Teil 01 und 02 in funktionierenden Code überführt: einen Harness, der Fragen an Genie stellt, SQL-Korrektheit semantisch beurteilt und Accuracy über Zeit in MLflow protokolliert. Was er nicht beantwortet, ist die Frage, was zu tun ist, wenn eine Kategorie schlecht abschneidet. Das ist das Thema von Teil 04: wie man die Harness-Ergebnisse liest, Fehlermuster diagnostiziert und iteriert, ohne neue Regressionen einzuführen.
Mit einem Harness ausgestattet, wird ein Genie Agent zu etwas, das man untersuchen, verbessern und hinter das man stehen kann. Verlässliche KI zu bauen bedeutet nicht, alles beim ersten Versuch richtig zu machen – es bedeutet, die Feedback-Infrastruktur zu bauen, die es realistisch macht, es irgendwann und kontinuierlich richtig zu machen.
Weitere Artikel in diesem Themenbereich
Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.
Blog-Autor*in
Niklas Niggemann
Werkstudent Data & AI
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.