Direkt zum Hauptinhalt
Engineering

Entwickelt für Agents: Warum wir deklarative Pipelines mit Apache Spark brauchen

Wir haben 528 von Agents erstellte Daten-Pipelines verglichen – deklaratives Erstellen erwies sich als kostengünstiger, schneller und effizienter als prozeduraler Code.

von Lisa Cao und Sudhanva Huruli

  • Prozedurale Pipelines verbrauchten etwa 34-mal so viel Rechenzeit wie deklarative Pipelines, hauptsächlich weil Fehler in strukturell ungültigen deklarativen Pipelines durch einen günstigen „Trockenlauf“ abgefangen werden, der sie nicht vollständig ausführt.
  • Deklarative Pipelines enthalten 51 % weniger Code für dieselbe Pipeline, sodass es viel weniger zu lesen und zu überprüfen gibt.
  • Zusammen machen diese Effizienzen deklarative Frameworks wie SDP zur klaren architektonischen Wahl für autonome Agenten, die Produktions-Pipelines erstellen.

KI-Agenten schreiben mittlerweile einen immer größeren Anteil von Produktions-Daten-Pipelines (über 70 % der SDP-Pipelines auf Databricks werden inzwischen von Agenten erstellt). Das erhöht den Einsatz in zwei Bereichen: (1) Jach der Versuche eines Agenten kostet Rechenleistung und Zeit, daher müssen Iterationen günstig und effizient auszuführen sein; und (2) Code-Reviews werden zu einem kritischen Nadelöhr, sodass der Code prägnant, lesbar und korrekt sein muss. Apache Spark® bietet zwei Programmiermodelle zum Erstellen Ihrer Pipelines – prozedural und deklarativ. Sie unterscheiden sich darin, was Sie schreiben, was Spark vor der Ausführung prüfen kann und wie viel ein Fehler kostet. Wir haben beide mit demselben Agenten für dieselben Jobs gebenchmarkt, und der deklarative Ansatz erwies sich als sicherer, günstiger und schlanker.

Eine prozedurale Pipeline besteht aus Code, der Spark Schritt für Schritt sagt, wie jedes Dataset aufgebaut werden soll. Die einzige Möglichkeit herauszufinden, ob sie funktioniert, ist sie auszuführen.

Eine deklarative Pipeline beschreibt die gewünschten Datasets und überlässt es Spark zu entscheiden, wie diese erstellt werden. Dies ähnelt dem Prompten eines LLM, bei dem dieses herausfindet, wie es vorgehen muss (mithilfe der richtigen Fähigkeiten und Tools). Dies lässt sich am besten an Code veranschaulichen, um zu sehen, wie ein einfacher Tippfehler zum Scheitern führt:

ProzeduralDeklarativ
bronze = spark.read.parquet(RAW)
bronze.write.saveAsTable("bronze")
silver = 
bronze.withColumnRenamed("revenue", 
"revenues")  # typo
silver.write.saveAsTable("silver")
gold = 
spark.read.table("silver").groupBy("revenue")
.sum("revenue")
gold.write.saveAsTable("gold")  
# runtime error
@dp.materialized_view(name="gold")
def gold():
    return 
spark.read.table("silver").groupBy("revenue")
.sum("revenue")

1. Deklarative Pipelines können vor der Ausführung validiert werden

Bugs gibt es in zwei Ausprägungen. Strukturelle Bugs können Sie erkennen, indem Sie die Pipeline lesen: eine nicht aufgelöste Spaltenreferenz, eine Tabelle, die noch nicht existiert, oder eine nicht erlaubte Konfigurationsänderung. Stille Bugs zeigen sich erst im Ergebnis, wenn der Lauf beendet ist und das Ergebnis falsch ist.

Eine deklarative Pipeline kann vor ihrer Ausführung auf strukturelle Bugs überprüft werden, ähnlich wie der Datenfluss in einer typisierten Sprache wie Rust zur Compilezeit überprüft werden kann. Da eine deklarative Pipeline eher eine Beschreibung als ein Lauf ist, kann Spark drei Arten von Fragen beantworten, indem es sie liest:

  • Jede Spaltenreferenz wird anhand des Schemas des Datasets aufgelöst, aus dem sie liest, sodass eine nicht existierende Spalte zu einer Ablehnung statt zu einem Laufzeitfehler führt.
  • Jede Abhängigkeit zwischen Datasets wird einem Produzenten im Graphen zugeordnet, sodass eine Referenz auf eine Tabelle, die von nichts deklariert wird, vor dem Start der Pipeline erkannt wird.
  • Der Graph wird auf Vollständigkeit und Reihenfolge überprüft, sodass die Engine bestimmt, was wann läuft, anstatt sich auf die Reihenfolge zu verlassen, in der das Modell die Dinge zufällig geschrieben hat.

2. Deklarative Pipelines nehmen Spark Boilerplate-Aufgaben ab

In prozeduralem PySpark schreibt der KI-Coding-Agent die Datenoperationen wie das Filtern ungültiger Zeilen und das Joinen von Tabellen. Er schreibt auch Code, um die Schritte der Pipeline in der richtigen Reihenfolge auszuführen und ihre Ergebnisse zu speichern. Dieser unterstützende Code wiederholt viel Boilerplate über Pipelines hinweg.

In deklarativen Pipelines definiert der KI-Agent jedes Dataset und die Abfrage, die es erzeugt. Spark übernimmt die Ausführungsreihenfolge und speichert die Ergebnisse. Da Spark diesen Boilerplate-Code übernimmt, schreibt der Agent weniger Code und das Team hat weniger zu prüfen und zu warten.

Was wir getestet haben

Wir haben 22 Data-Engineering-Aufgaben getestet. Jede Aufgabe glich einem realen Ticket: Sie beschrieb ein Problem und gab die Tabelle, die Spaltennamen und die Datentypen an, die die Pipeline produzieren musste. Der Agent konnte eine beliebige Implementierung wählen, solange das Ergebnis diesen Anforderungen entsprach.

Für jede Aufgabe haben wir 12 verschiedene Eingabe-Datasets mit den Arten von unübersichtlichen Werten generiert, die in Produktionsdaten vorkommen. Der Agent schrieb für jedes Dataset eine neue Pipeline mit prozeduralem PySpark und eine weitere mit Spark Declarative Pipelines. Das ergab 264 Builds pro Ansatz und insgesamt 528: 22 Aufgaben × 12 Datasets × 2 Ansätze. Alle Builds verwendeten Opus 4.8.

Wir haben jede Pipeline ausgeführt und ihr Ergebnis mit der erforderlichen Tabelle abgeglichen. Der automatisierte Prüfer wusste nicht, welcher Ansatz das Ergebnis erzielt hatte. Deklarative Pipelines wurden zunächst einem Trockenlauf (Dry Run) von Spark unterzogen. Wenn ein Build fehlschlug, konnte der Agent ihn überarbeiten und es bis zu einem festgelegten Limit erneut versuchen.

Sie können das Ganze selbst aus dem öffentlichen Repository noch einmal ausführen: das Setup, die Prompts, Datasets, den Grader und die Ergebnisse hinter jeder Zahl.

Ergebnisse

Beide Wege schlossen fast jede Aufgabe ab (255 von 264 abgeschlossen mit dem prozeduralen und 258 von 264 mit dem deklarativen Ansatz), sodass Sie mit beiden zu einer funktionierenden Pipeline gelangen. Der Unterschied liegt in allem, was dazu gehört: wann Fehler auftraten, wie viel Code für die Korrektur erforderlich war und wie konsistent das Ergebnis war. Im Folgenden gehen wir auf die drei Vorteile deklarativer Pipelines ein, gefolgt von zwei Einschränkungen.

1. Die Validierung vor dem Lauf machte deklarative Pipelines ca. 34-mal schneller

Fehler in einer Pipeline treten vor der Ausführung, während eines Laufs oder überhaupt nicht auf. Prozedurale Pipelines stoppten vor der Ausführung keinen einzigen Fehler, da sie keine Phase vor der Ausführung besitzen. Um einen strukturellen Fehler zu finden, musste Spark die Pipeline so lange auf einem Cluster ausführen, bis sie den fehlerhaften Schritt erreichte.

Über die von uns gemessenen Builds hinweg benötigten prozedurale Läufe 596 Executor-Sekunden im Vergleich zu 17 bei deklarativen Läufen. Die Dry-Run-Validierung von deklarativem Code fing strukturelle Fehler frühzeitig ab und reduzierte die Rechenleistung um das 34-Fache.

Prozedurale Pipelines

2. Deklarativer Pipeline-Code war halb so groß wie prozedurale Pipelines

Unter den abgeschlossenen Builds waren deklarative Pipelines etwa halb so groß, mit einem Median von 64 Zeilen im Vergleich zu 131 bei prozeduralen Pipelines.

Die prozeduralen Implementierungen variierten zudem stärker. Für denselben Job verwendeten einige Spark-Transformationen, während andere die Daten in den Speicher luden und sie zeilenweise verarbeiteten. Beide bestanden die Testdaten, aber die In-Memory-Version kann fehlschlagen, wenn die Daten wachsen. Im gesamten Benchmark verwendeten 19 prozedurale Builds diese Abkürzung. Keiner der deklarativen Builds tat dies.

Kürzerer, konsistenterer Code bedeutet für ein Team weniger Aufwand beim Review und ein einheitliches Muster zur Wartung.

Deklarativer Pipeline-Code

3. Bei Logikfehlern lagen beide gleich auf

Das sind die beiden Vorteile. Bei den Tests haben wir außerdem zwei Einschränkungen identifiziert.

Erstens kann ein Trockenlauf (Dry Run) nur strukturelle Fehler erkennen. Er kann keinen stillen Fehler erkennen: eine Pipeline, die sauber läuft und das falsche Ergebnis liefert, was die gefährlichere Art ist. In diesem Punkt schnitten beide gleich ab: Ihre Quoten für stille Fehler wichen um weniger als ca. 15 % voneinander ab, ein Unterschied, der zu klein ist, als dass er ins Gewicht fallen würde. Durch den deklarativen Ansatz lassen sich strukturelle Fehler günstig erkennen; für die Logik leistet er keinen Beitrag, da diese nach wie vor Tests und Reviews erfordert.

4. Deklarativ investiert mehr im Voraus, um später mehr zu sparen

Deklarativ investiert an einer Stelle mehr. Der Agent iteriert über den Trockenlauf (Dry Run) und versucht es so lange erneut, bis die Pipeline fehlerfrei ist. Er denkt also eher in Token im Voraus nach, anstatt Probleme später auf einem Cluster zu entdecken. Die Token sind ein fester Einmalbetrag, der während des Schreibens der Pipeline bezahlt wird; die Menge ändert sich nicht je nach Datengröße oder Häufigkeit der Pipeline-Ausführungen. Verschwendete Cluster-Rechenleistung ist genau das Gegenteil: Sie tritt bei jedem fehlerhaften Lauf erneut auf und wächst mit den Daten. Je mehr Sie also verarbeiten, desto teurer wird ein fehlerhafter Build. Die Zahlung fixer Kosten im Voraus, um kontinuierlich wachsende Kosten zu vermeiden, zahlt sich umso mehr aus, je größer Ihre Pipelines und Daten werden.

Alles im direkten Vergleich

Die Gesamtheit der gemessenen Unterschiede ist unten dargestellt.

DimensionProzedurales PySparkDeklarativ (SDP)
Was der Agent produziertCode, der ausgeführt wirdEine Beschreibung, die überprüft wird
Strukturelle FehlerTreten mitten im Lauf auf, nach partiellen Schreibvorgängen oder nie; keine wurde vor der Ausgabe gestopptWerden beim Trockenlauf (Dry Run) erkannt; 55 von 264 wurden vor jeder Ausgabe gestoppt
Kosten

Cluster-Zeit: ca. 34x höher (bis zu ca. 521 Executor-Sekunden bei einem fehlerhaften Lauf)

LLM-Token: Basislinie

Cluster-Zeit: Basislinie (ca. 0,5 Executor-Sekunden bei einem fehlerhaften Lauf)

LLM-Token: ca. 2,3x (Median-Build ≈ 0,50 $ vs. 0,26 $, Opus 4.8 Listenpreise)

Code-GrößeBasislinie

Zeilen Code: ca. 51 % weniger (Median)

AST-Größe: ca. 44 % kleiner

Stille Bugs (liefen sauber durch, falsches Ergebnis)73 von 264 (27,7 %)85 von 264 (32,2 %)

Fazit

Im Produktionsmaßstab erweist sich der deklarative Ansatz als überlegen. Er kostet etwa 2,3-mal so viel an LLM-Token, verschwendet dafür aber nie Cluster-Zeit für eine Pipeline, die ohnehin nicht funktioniert hätte. Im Produktionsmaßstab ist der deklarative Ansatz von Vorteil, da er geringfügig höhere Kosten für LLM-Token gegen die garantierte Vermeidung von verschwendeter Cluster-Zeit bei fehlschlagenden Pipelines eintauscht. Dies wird mit wachsendem Datenvolumen zunehmend kosteneffizienter, da die Verschwendung von Rechenleistung proportional steigt, während die Token-Kosten konstant bleiben.

Wenn Sie Agents für Pipeline-Arbeiten evaluieren, nehmen Sie die Art und Weise, wie der Agent schreibt, genauso ernst wie die Auswahl des Agents. Ein besserer Agent macht weniger Fehler; eine deklarative Pipeline macht Fehler günstig und fängt sie ab, bevor sie etwas kosten.

Das Repository dokumentiert das Design, die Daten und die vollständige Herkunft. Um mit Ihren Agents unter Verwendung von Spark Declarative Pipelines zu beginnen, lesen Sie den offiziellen Programmierleitfaden und nutzen Sie das SDP-Skill mit PySpark.

FAQ

Muss ich dem KI-Agenten vertrauen, damit das funktioniert?

Nein, und genau darum geht es. Der deklarative Agent schreibt ausschließlich deklarativen Pipeline-Code – eine Beschreibung der gewünschten Tabellen –, und Spark selbst überprüft diese Beschreibung, bevor irgendetwas ausgeführt wird. Die Überprüfung ist Teil der Plattform: Sie vertrauen der Auswertung der Pipeline durch Spark und nicht dem Modell. Der Agent führt niemals Code aus oder liest selbst Ihre Daten.

Betrifft dies nur Spark Declarative Pipelines oder gilt das allgemeiner?

Es gilt allgemeiner für deklarative Ansätze: überall dort, wo Sie „Das ist es, was ich möchte“ von „Erstelle es jetzt“ trennen können, sodass der erste Teil eigenständig überprüft werden kann. Sie finden dieselbe Struktur in SQL selbst, in Infrastructure-as-Code-Tools und in Schema-First-APIs. Spark Declarative Pipelines ist das Tool, das wir gebenchmarkt haben, aber die Überlegung gilt für jedes entsprechend aufgebaute Tool.

Der deklarative Agent verbraucht 2,3-mal so viele Token. Ist das nicht ein Ausschlusskriterium?

Nicht bei realistischen Pipeline-Größen. Die 2,3-fache Menge entspricht etwa 0,50 USD an Token pro medianem deklarativem Build, verglichen mit 0,26 USD für prozedurale Builds zu den Listenpreisen von Opus 4.8. Ein fehlgeschlagener prozeduraler Durchlauf hat etwa 521 Executor-Sekunden verbraucht, während ein abgelehnter deklarativer Durchlauf etwa eine halbe Sekunde kostete – das Vermeiden einiger weniger fehlerhafter Durchläufe deckt also viele zusätzliche Token ab, und die Lücke wird mit wachsendem Datenvolumen nur noch größer. Die Token-Preise variieren je nach genutztem Modelldienst, während die Rechenkosten konstanter und einfacher einzuplanen sind.

(Dieser Blogbeitrag wurde mit KI-gestützten Tools übersetzt.) Originalbeitrag

Verwandte Tags:

Data Engineering und Open-Source

Erhalten Sie die neuesten Beiträge in Ihrem Posteingang

Abonnieren Sie unseren Blog und erhalten Sie die neuesten Beiträge direkt in Ihren Posteingang.