Text-to-SQL mit semantischer Schicht: NVIDIA Auto Ontology im Praxistest

Andreas Nigg
Andreas Nigg · Mitgründer, Pondhouse Data
Veröffentlicht 8 Min. Lesezeit
Text-to-SQL mit semantischer Schicht: NVIDIA Auto Ontology im Praxistest
Inhalt

NVIDIA Auto Ontology ist eine Open-Source-Bibliothek, die Text-to-SQL zuverlässiger machen soll. Sie liest die Metadaten Ihrer Datenbanken und baut daraus eine semantische Schicht: Geschäftsbegriffe wie "Kunde" oder "Rechnungsposition", die Wege, wie Tabellen zusammenhängen, und geprüfte SQL-Ausdrücke für Kennzahlen. Ein Agent beantwortet Fragen in natürlicher Sprache dann nicht mehr direkt aus dem rohen Schema, sondern über diese Schicht.

Wir haben Auto Ontology mit Microsofts Beispieldatenbank Wide World Importers und den Cloud-Modellen von build.nvidia.com ausprobiert. Kurz zusammengefasst: Die automatisch erzeugte Ontologie ist beeindruckend, und Fragen über drei bis fünf Tabellen hinweg funktionieren. Mit den gehosteten Modellen braucht es heute aber drei Anpassungen im Code, und zwei von vier Antworten waren falsch, ohne dass man es der Antwort angesehen hätte. Dieser Beitrag erklärt das Konzept, zeigt die Einrichtung samt der Stolpersteine und unsere Ergebnisse.

Warum Text-to-SQL eine semantische Schicht braucht

Ein Sprachmodell, das SQL schreiben soll, sieht zunächst nur Tabellen und Spalten. Es weiß nicht, dass "Umsatz" in Ihrer Datenbank die Spalte extendedprice in den Rechnungspositionen ist und nicht der Betrag aus der Buchhaltungstabelle. Es weiß auch nicht, über welchen Weg ein Bundesland mit einer Rechnung verbunden ist. Bei kleinen Schemas lässt sich das noch per Prompt erklären. Bei Dutzenden Tabellen mit Archiv-Kopien, Historientabellen und ähnlich klingenden Spalten rät das Modell, und das Ergebnis sieht trotzdem plausibel aus.

Die übliche Antwort darauf ist eine semantische Schicht: ein Modell der Geschäftsbegriffe, das festlegt, was eine Kennzahl bedeutet und wie sie berechnet wird. In Projekten pflegt man so etwas meist von Hand, etwa als Metriken in dbt oder in einem BI-Werkzeug. Den manuellen Ansatz haben wir in unserem Beitrag über einen Text-to-SQL-Agenten für BigQuery beschrieben. Auto Ontology versucht, diese Schicht automatisch zu erzeugen und sie dann von Menschen prüfen zu lassen.

So funktioniert Auto Ontology

Die Ontologie besteht aus drei Arten von Definitionen:

  • Begriffe (Terms): Geschäftskonzepte wie Customer, Invoice oder Stock Item, jeweils mit Beschreibung, Synonymen und den Spalten, in denen sie stecken.
  • Beziehungen: wie Tabellen zusammenhängen, inklusive Zwischentabellen, abgeleitet aus Schlüsseln und aus den Daten.
  • SQL-Attribute: geprüfte SQL-Ausdrücke zu einem Begriff, etwa eine Marge oder eine rollierende Summe. Der Agent verwendet sie wieder, damit dieselbe Kennzahl immer gleich berechnet wird.

Die Arbeit passiert in drei Schritten:

Ablauf von Auto Ontology: erzeugen, freigeben, beantworten

  1. Erzeugen: Ein Ingestion-Dienst liest Schemas, Spaltenprofile und Beispielwerte, leitet daraus Tabelle für Tabelle Begriffe ab, erkennt Join-Pfade und schlägt SQL-Attribute vor. Alles landet in Postgres, die Embeddings für die Suche in pgvector.
  2. Freigeben: Fachleute testen mit echten Fragen, korrigieren Begriffe und SQL-Attribute in der Web-Oberfläche und markieren sie als zertifiziert.
  3. Beantworten: Für jede Frage erkennt der Agent die Absicht und die genannten Begriffe, sucht passende Begriffe, Spalten und SQL-Attribute per Embedding-Suche, schreibt daraus SQL, prüft Filterwerte gegen die Datenbank, repariert das SQL bei Fehlern und führt es aus. Zurück kommen die Antwort, das SQL und die einzelnen Schritte.

Dazu gibt es eine Web-Oberfläche, eine REST-API und einen MCP-Server, über den andere Agenten die Ontologie nutzen können, etwa um vorab zu prüfen, ob eine Frage mit den vorhandenen Daten überhaupt beantwortbar ist. Wie MCP-Server grundsätzlich funktionieren, zeigen wir in unserem Beitrag zu FastMCP.

In der Oberfläche lässt sich die erzeugte Ontologie als Graph erkunden. Jeder Kreis ist ein Begriff, jede Linie eine erkannte Beziehung:

Die erzeugte Ontologie von Wide World Importers als Graph

Für Wissen, das in Dokumenten statt in Datenbankschemas steckt, baut der Neo4j LLM Knowledge Graph Builder (auf Englisch) einen ähnlichen Graphen aus PDFs und Webseiten.

Das Projekt steht unter der Apache-2.0-Lizenz, hat noch kein getaggtes Release und nimmt laut README derzeit keine externen Beiträge an. Wir haben den Stand vom 4. November 2026 getestet (Commit 2a24f5d, Paketversion 1.1.0).

Einrichtung mit Docker Compose

Der offizielle Weg laut README ist Docker Compose. Sie brauchen Docker mit Compose v2, uv und einen API-Key von build.nvidia.com. Die wichtigsten Werte in der .env:

1DEFAULT_MODELS_API_KEY=nvapi-...
2AUTH_SECRET=<lange Zufallszeichenkette>
3APP_URL=http://localhost:3000
4POSTGRES_PASSWORD=<neues Passwort>
5CONNECTION_STRINGS=postgresql://postgres:<dasselbe Passwort>@postgres:5432/wideworldimporters
6AUTO_ONTOLOGY_ADMIN_PASSWORD=<neues Passwort>
7PGADMIN_PASSWORD=<neues Passwort>

Dann Postgres starten, die Beispieldatenbank laden und den Rest bauen:

1docker compose up -d --wait postgres
2git clone https://github.com/NVIDIA/auto-ontology-eval.git ../auto-ontology-eval
3(cd ../auto-ontology-eval && uv sync && cp .env.example .env && \
4 POSTGRES_PASSWORD='<dasselbe Passwort>' \
5 uv run python scripts/seed/seed_wwi.py --database-name wideworldimporters --drop)
6docker compose up -d --build

Unter http://localhost:3000 melden Sie sich mit dem Admin-Konto aus der .env an und schalten unter Settings, Semantic Compilation die Kompilierung ein. Die Ingestion läuft beim Start, die Kompilierung direkt danach.

Als Modelle sind nvidia/nemotron-3.5-lightning-30b-a3b für alle Sprachmodell-Aufgaben und nvidia/nemotron-3.5-embed-1b für Embeddings voreingestellt. Für jede Rolle (Reasoning, Extraktion, Embeddings, Reranking) lassen sich Endpunkt, Modell und Key getrennt setzen, auch für selbst gehostete NIMs.

Drei Stolpersteine mit den Cloud-Modellen von NVIDIA

Mit den gehosteten Modellen auf build.nvidia.com lief Auto Ontology bei uns zunächst nicht durch. Die Ursachen liegen im Zusammenspiel von Code und gehosteten Endpunkten, betreffen also auch das Compose-Setup. Wir haben jede davon direkt gegen die API nachgestellt.

1. Die Ingestion meldet Erfolg, erzeugt aber keine Embeddings. Im Log steht "Data ingestion finished successfully", dazu aber 0 Embeddings und Hunderte Fehler "HTTP 500, service inference failed". Auto Ontology schickt 32 Texte pro Embedding-Anfrage. Der gehostete Endpunkt für nemotron-3.5-embed-1b beantwortete Anfragen mit mehreren Texten bei uns meistens mit 500, eine Anfrage pro Text dagegen zuverlässig, auch mit 16 parallelen Anfragen. Sehr lange Einzeltexte scheiterten trotz truncate: END ebenfalls.

2. Strukturierte Ausgaben werden abgelehnt. Für NVIDIA-Modelle nutzt Auto Ontology den LangChain-Client ChatNVIDIA. Der schickt das gewünschte JSON-Schema als nvext.guided_json, und der gehostete Endpunkt antwortet mit HTTP 400: "unknown field guided_json". Der OpenAI-kompatible Weg über response_format mit json_schema funktioniert dagegen.

3. Das Modell denkt sich in das Token-Limit. Nemotron 3.5 denkt vor jeder Antwort nach. Für eine kleine JSON-Antwort waren das in unserem Test über 900 Tokens, und bei größeren Aufgaben lief es in das Limit von 8.192 Tokens (LengthFinishReasonError). Die Kompilierung wurde dadurch sehr langsam. Mit chat_template_kwargs: {"enable_thinking": false} kam dieselbe Antwort mit rund 40 Tokens in unter einer Sekunde.

Unsere Anpassungen setzen genau dort an: ein Text pro Embedding-Anfrage mit 16 parallelen Anfragen, Texte auf 4.000 Zeichen gekürzt, NVIDIA-Modelle über den vorhandenen ChatOpenAI-Zweig und die Denkphase abgeschaltet. Das sind Workarounds für den getesteten Commit, keine offiziellen Fixes. Weil Compose die Dienste aus dem lokalen Quellcode baut, wenden Sie sie vor docker compose up -d --build im Repository an:

1# Workarounds for the hosted NVIDIA models (not official fixes)
2sed -i 's/ inference_batch_size: int = 32/ inference_batch_size: int = 1/; s/ nim_http_max_concurrent: int = 32/ nim_http_max_concurrent: int = 16/' auto_ontology/utils/embedding.py
3sed -i 's/ input=\[prefix + stripped\[i\] for i in indices\],/ input=[(prefix + stripped[i])[:4000] for i in indices],/' auto_ontology/utils/embedding.py
4sed -i 's/ if model.startswith(("openai\/", "azure\/", "aws\/")):/ if model.startswith(("openai\/", "azure\/", "aws\/", "nvidia\/")):/' auto_ontology/utils/llm_invoke.py
5python3 - <<'PY'
6from pathlib import Path
7p = Path("auto_ontology/utils/llm_invoke.py"); s = p.read_text()
8old = " timeout=LLM_INVOKE_TIMEOUT_S,\n max_retries=0,\n )"
9assert s.count(old) == 1
10p.write_text(s.replace(old, " timeout=LLM_INVOKE_TIMEOUT_S,\n max_retries=0,\n extra_body={\"chat_template_kwargs\": {\"enable_thinking\": False}} if model.startswith(\"nvidia/\") else None,\n )"))
11PY
12git diff --stat
1 auto_ontology/utils/embedding.py | 6 +++---
2 auto_ontology/utils/llm_invoke.py | 3 ++-
3 2 files changed, 5 insertions(+), 4 deletions(-)

Danach liefen die 640 Embeddings der Beispieldatenbank in 14 Sekunden ohne Fehler durch. Ganz frei von Token-Limits war der Lauf trotzdem nicht: Einzelne Schritte erreichten sie weiterhin, Auto Ontology fing das aber mit Wiederholungen und einem zweiten Anlauf über den Reasoning-Client ab.

Was im Test herauskam

Die Kompilierung der 51 Tabellen von Wide World Importers dauerte in zwei Läufen acht und gut zehn Minuten (504 und 621 Sekunden) und ergab 51 beziehungsweise 52 Begriffe, darunter Customer, Invoice, Invoice Line, Order und Stock Item. Auffällig: Archivtabellen wurden zu eigenen Begriffen, etwa "Buying Group Archive" neben "Buyinggroups". Genau solche Dubletten muss man bei der Freigabe aufräumen, sonst wählt der Agent im Zweifel die falsche Tabelle. In der Begriffsliste startet jeder erzeugte Begriff mit dem Status "Pending Approval":

Erzeugte Begriffe in Auto Ontology, alle noch ohne Freigabe

Danach haben wir vier typische Analysefragen gestellt und das erzeugte SQL selbst gegen die Datenbank geprüft. Die Laufzeiten lagen zwischen einer halben Minute und knapp sieben Minuten pro Frage.

FrageSQLWas passiert ist
Umsatz eines bestimmten Produkts in Pennsylvania im Juni 2015falschFilter auf das Bundesland fehlt
Top-5-Kunden nach Rechnungswert 2015richtig
Bestellungen pro Monat 2016richtig
Top-5-Artikel nach verkaufter Menge 2016falschaus der falschen Tabelle gezählt

Die erste Frage ist die Beispielfrage aus dem README. Das SQL des Agenten sah so aus (zur besseren Lesbarkeit umgebrochen):

1SELECT SUM(il.extendedprice) AS total_revenue
2FROM wideworldimporters.warehouse.stockitems AS si
3JOIN wideworldimporters.sales.invoicelines AS il ON si.stockitemid = il.stockitemid
4JOIN wideworldimporters.sales.invoices AS inv ON il.invoiceid = inv.invoiceid
5WHERE si.stockitemname LIKE '%sushi roll%'
6 AND si.stockitemname LIKE '%USB%'
7 AND inv.invoicedate >= '2015-06-01' AND inv.invoicedate < '2015-07-01'

Produkt und Zeitraum stimmen, der Bundesstaat fehlt. Das Ergebnis war der Umsatz in allen Bundesstaaten: 5.225,60 statt 588,80 US-Dollar. Für das richtige Ergebnis braucht es den Weg von der Rechnung über Kunde und Stadt zum Bundesland, den das README in seinem Beispiel zeigt. Die Antwort des Agenten beschrieb Produkt und Zeitraum korrekt und erwähnte das Bundesland einfach nicht. Wer nur die Antwort liest, merkt den Fehler nicht.

Bei der Mengenfrage nahm der Agent die Tabelle der Lagerbewegungen, in der auch Wareneingänge stehen, statt der Rechnungspositionen. Das ist ein klassischer Fall für ein zertifiziertes SQL-Attribut "verkaufte Menge": Ist es einmal festgelegt, rechnet der Agent es nicht jedes Mal neu aus.

Die beiden richtigen Antworten zeigen, was gut funktioniert: Joins über mehrere Tabellen, Gruppierung nach Monat und Sortierung mit Limit erzeugt der Agent sauber, und er liefert das SQL immer mit. Das macht die Prüfung überhaupt erst möglich. So sieht die Antwort auf die Frage nach den Bestellungen pro Monat im Chat aus:

Antwort im Chat von Auto Ontology mit SQL und Ergebnistabelle

Unter jeder Antwort zeigt Auto Ontology die Schritte des Agenten, von der Einordnung der Frage über die Auswahl der Tabellen bis zur Prüfung des SQL. Wer eine Antwort prüfen will, findet dort, warum der Agent welche Tabelle genommen hat:

Die Schritte des Agenten zu einer Antwort

Was Sie vor einem Einsatz klären sollten

Aus dem Test und dem README ergeben sich vier Punkte:

  1. Nur lesender Datenbankzugriff. Auto Ontology prüft nicht selbst, ob das erzeugte SQL nur liest. Auf die Bitte "Delete all invoices from 2013." hat der Agent in unserem Test DELETE-Befehle erzeugt und ausgeführt. Dass nichts gelöscht wurde, lag an den Fremdschlüsseln der Beispieldatenbank. Der Quickstart verbindet den Agenten als Postgres-Superuser. Im echten Einsatz gehört in CONNECTION_STRINGS ein Benutzer, der nur lesen darf, oder eine Lese-Replica.
  2. Interne Dienste schützen. Backend (Port 3001) und Ingestion-Dienst (3002) gehören laut README in ein privates Netz. Das Backend vertraut der Benutzerkennung, die das Frontend in einem Header mitschickt, und der Ingestion-Dienst hat keine eigene Anmeldung. Zugriff für Menschen und Agenten sollte nur über das Frontend auf Port 3000 laufen.
  3. Freigabe einplanen. Die automatisch erzeugten Begriffe sind ein Entwurf. Bevor Zahlen in Berichte gehen, sollten Fachleute die wichtigsten Begriffe und Kennzahlen gegen Referenzabfragen prüfen und zertifizieren.
  4. Antwortzeiten realistisch einschätzen. Mit den gehosteten Modellen brauchten manche Fragen mehrere Minuten. Ob selbst gehostete NIMs oder ein anderer Endpunkt das deutlich beschleunigen, haben wir nicht getestet.

Unsere Einschätzung

Der interessanteste Teil von Auto Ontology ist die automatische Erzeugung. Aus 51 Tabellen wurde in acht bis zehn Minuten eine Ontologie mit Begriffen und Join-Pfaden, die ein Agent sofort nutzen konnte. Diese Modellierung ist sonst mühsame Handarbeit.

Fertig für den produktiven Einsatz ist das Projekt aus unserer Sicht noch nicht: Es gibt kein Release, mit den gehosteten Modellen braucht es Anpassungen im Code, und die Hälfte unserer Testfragen bekam falsches SQL mit einer plausibel klingenden Antwort. Das ist kein spezielles Problem von Auto Ontology, sondern gilt für Text-to-SQL allgemein. Auto Ontology bringt aber das richtige Werkzeug dagegen gleich mit: die Freigabe von Begriffen und SQL-Attributen durch Fachleute. Für eine Evaluierung mit den eigenen Daten lohnt es sich schon jetzt, solange man diese Freigabe ernst nimmt.

Wenn Sie Text-to-SQL auf Ihre Unternehmensdaten bringen wollen, unterstützen wir Sie gern bei der Auswahl, beim Datenmodell und beim Aufbau der Prüfung. Melden Sie sich bei uns. Wie man Daten in BigQuery per MCP für Agenten bereitstellt, zeigen wir in diesem Beitrag zum BigQuery-MCP-Server.

Weiterlesen

Sie möchten zuverlässige KI-Agenten-Systeme bauen?

Wir haben auf Basis aktueller Forschung einen ausführlichen Leitfaden (auf Englisch) erstellt, wie Sie robuste KI-Agenten-Systeme bauen, die auch im produktiven Betrieb funktionieren. Der Leitfaden behandelt:

  • die 14 systematischen Fehlerquellen in Multi-Agenten-Systemen
  • belegte Best Practices für das Design von Agenten
  • strukturierte Kommunikationsprotokolle und Prüfmechanismen
Andreas Nigg

Über den Autor

Andreas Nigg

Mitgründer, Pondhouse Data

Andreas entwickelt seit mehr als acht Jahren Datenanwendungen. Bei Pondhouse Data konzipiert und baut er KI-Systeme und integriert sie in komplexe, gewachsene Unternehmensumgebungen.