Veröffentlicht am: 16. September 2025

10 Minuten Lesezeit

Wie du mit der GitLab Duo Agent Platform deine DataOps transformiert

So wird aus manueller Programmierung eine vollautomatische Generierung, erklärt am Beispiel der dbt-Modellerstellung.

Die manuelle Erstellung von dbt-Modellen ist ein mühsamer Prozess, der Stunden an Arbeitszeit verschlingt. Besonders wenn keine (größeren) Geschäftstransformationen vorgenommen werden, gehört diese Aufgabe nicht zu den attraktivsten Tätigkeiten eines Dateningenieurs.

Aber was wäre, wenn du diesen gesamten Prozess automatisieren könntest? In dieser Anleitung zeige ich dir genau, wie GitLab Duo Agent Platform umfassende dbt-Modelle in nur wenigen Minuten generiert – komplett mit ordnungsgemäßer Struktur, Tests und Dokumentation.

Was wir aufbauen

Unser Marketing-Team möchte Werbeinvestitionen effektiv verwalten und optimieren. Eine der Werbeplattformen ist Reddit, daher extrahieren wir Daten von der Reddit Ads API in unsere unternehmensweite Datenplattform Snowflake. Bei GitLab haben wir drei Speicherebenen:

  1. raw-Ebene – erster Landepunkt für unverarbeitete Daten aus externen Quellen; noch nicht für geschäftliche Nutzung bereit

  2. prep-Ebene – erste Transformationsebene mit Quellmodellen; noch nicht für allgemeine geschäftliche Nutzung bereit

  3. prod-Ebene – final transformierte Daten, bereit für geschäftliche Nutzung und Tableau-Berichte

Diagramm der Speicherebenen

Für diese Anleitung sind die Daten bereits durch unsere Extraktionslösung Fivetran in der raw-Ebene gelandet, und wir werden dbt-Modelle generieren, die die Daten von der prep-Ebene zur prod-Ebene verarbeiten.

Ohne eine einzige Zeile dbt-Code selbst schreiben zu müssen, werden wir am Ende der Anleitung Folgendes haben:

  • Quellmodelle in der prep-Ebene

  • Workspace-Modelle in der prod-Ebene

  • Vollständige dbt-Konfigurationen für alle 13 Tabellen (einschließlich 112 Spalten) im Reddit Ads-Datensatz

  • Test-Abfragen zur Validierung der Ergebnisse

Der gesamte Prozess dauert weniger als 10 Minuten – im Vergleich zu den Stunden, die normalerweise dafür benötigt würden. Hier sind die zu befolgenden Schritte:

1. Die Datenstruktur vorbereiten

Bevor GitLab Duo unsere Modelle generieren kann, muss es die vollständige Tabellenstruktur verstehen. Der Schlüssel liegt darin, eine Abfrage gegen Snowflakes Informationsschema auszuführen, da wir derzeit untersuchen, wie wir GitLab Duo über das Model Context Protocol (MCP) mit unserer Snowflake-Instanz verbinden können:


SELECT 
    table_name,
    column_name,
    data_type,
    is_nullable,
    CASE 
        WHEN is_nullable = 'NO' THEN 'PRIMARY_KEY'
        ELSE NULL 
    END as key_type
FROM raw.information_schema.columns

WHERE table_schema = 'REDDIT_ADS'

ORDER BY table_name, ordinal_position;

Diese Abfrage erfasst:

  • Alle Tabellen- und Spaltennamen

  • Datentypen für die korrekte Modellstruktur

  • Nullable-Einschränkungen

  • Primärschlüssel-Identifikation (nicht-nullable Spalten in diesem Datensatz)

Profi-Tipp: Im Reddit Ads-Datensatz dienen alle nicht-nullable Spalten als Primärschlüssel – ein Muster. Ich habe dies überprüft, indem ich Tabellen wie ad_group kontrollierte, die zwei nicht-nullable Spalten (account_id und id) hat, die beide als Primärschlüssel markiert sind. Die Ausführung dieser Abfrage lieferte 112 Zeilen Metadaten, die ich als CSV-Datei für die Modellgenerierung exportierte. Während dieser manuelle Schritt heute gut funktioniert, untersuchen wir eine direkte Integration von GitLab Duo mit unserer Datenplattform über MCP, um diesen Prozess vollständig zu automatisieren.

2. GitLab Duo einrichten

Es gibt zwei Möglichkeiten, mit GitLab Duo zu interagieren:

  1. Web-UI-Chat-Funktion

  2. Visual Studio Code-Plugin

Ich habe mich für das VS Code-Plugin entschieden, da ich die dbt-Modelle lokal ausführen kann, um sie zu testen.

3. Den 'magischen' Prompt eingeben

Hier ist der exakte Prompt, den ich zur Generierung des gesamten dbt-Codes verwendet habe:


Create dbt models for all the tables in the file structure.csv.


I want to have the source models created, with a filter that dedupes the data based on the primary key. Create these in a new folder reddit_ads.

I want to have workspace models created and store these in the workspace_marketing schema.


Take this MR as example: [I've referenced to previous source implementation]. Here is the same done for Source A, but now it needs to be done for Reddit Ads. 


Please check the dbt style guide when creating the code: https://handbook.gitlab.com/handbook/enterprise-data/platform/dbt-guide/

Schlüsselelemente, die diesen Prompt effektiv machten:

  • Klare Spezifikationen für sowohl Quell- als auch Workspace-Modelle

  • Referenzbeispiel aus einem vorherigen ähnlichen Merge Request

  • Style Guide-Referenz zur Sicherstellung von Codequalität und Konsistenz

  • Spezifisches Schema-Targeting für ordnungsgemäße Organisation

4. GitLab Duos Prozess

Nach dem Einreichen des Prompts machte sich GitLab Duo an die Arbeit. Der gesamte Generierungsprozess dauerte einige Minuten, während dessen GitLab Duo:

  1. Die CSV-Eingabedatei las und analysierte

  2. Tabellenstrukturen aus den Metadaten untersuchte

  3. Unseren dbt-Style-Guide als Referenz für Coding-Standards nutzte

  4. Ähnliche Merge Requests berücksichtigte für die korrekte Strukturierung

  5. Quellmodelle für alle 13 Tabellen generierte

  6. Workspace-Modelle für alle 13 Tabellen erstellte

  7. Unterstützende dbt-Dateien generierte:

    • sources.yml-Konfiguration
    • schema.yml-Dateien mit Tests und Dokumentation
    • Aktualisierte dbt_project.yml mit Schema-Referenzen

Die Ergebnisse

Die Ausgabe war bemerkenswert:

  • 1 modifizierte Datei: dbt_project.yml (reddit_ads Schema-Konfiguration hinzugefügt)

  • 29 neue Dateien:

    • 26 dbt-Modelle (13 Quell- + 13 Workspace-Modelle)
    • 3 YAML-Dateien
  • Fast 900 Zeilen Code automatisch generiert

  • Integrierte Daten-Tests, einschließlich Unique-Constraints auf Primärschlüssel-Spalten

  • Generische Beschreibungen für alle Modelle und Spalten

  • Saubere Deduplizierungs-Logik in Quellmodellen

  • Saubere, konsistente Code-Struktur gemäß dem GitLab dbt-Style-Guide


transform/snowflake-dbt/

├── dbt_project.yml                                                    [MODIFIZIERT]

└── models/
    ├── sources/
    │   └── reddit_ads/
    │       ├── reddit_ads_ad_group_source.sql                        [NEU]
    │       ├── reddit_ads_ad_source.sql                              [NEU]
    │       ├── reddit_ads_business_account_source.sql                [NEU]
    │       ├── reddit_ads_campaign_source.sql                        [NEU]
    │       ├── reddit_ads_custom_audience_history_source.sql         [NEU]
    │       ├── reddit_ads_geolocation_source.sql                     [NEU]
    │       ├── reddit_ads_interest_source.sql                        [NEU]
    │       ├── reddit_ads_targeting_community_source.sql             [NEU]
    │       ├── reddit_ads_targeting_custom_audience_source.sql       [NEU]
    │       ├── reddit_ads_targeting_device_source.sql                [NEU]
    │       ├── reddit_ads_targeting_geolocation_source.sql           [NEU]
    │       ├── reddit_ads_targeting_interest_source.sql              [NEU]
    │       ├── reddit_ads_time_zone_source.sql                       [NEU]
    │       ├── schema.yml                                            [NEU]
    │       └── sources.yml                                           [NEU]
    └── workspaces/
        └── workspace_marketing/
            └── reddit_ads/
                ├── schema.yml                                        [NEU]
                ├── wk_reddit_ads_ad.sql                              [NEU]
                ├── wk_reddit_ads_ad_group.sql                        [NEU]
                ├── wk_reddit_ads_business_account.sql                [NEU]
                ├── wk_reddit_ads_campaign.sql                        [NEU]
                ├── wk_reddit_ads_custom_audience_history.sql         [NEU]
                ├── wk_reddit_ads_geolocation.sql                     [NEU]
                ├── wk_reddit_ads_interest.sql                        [NEU]
                ├── wk_reddit_ads_targeting_community.sql             [NEU]
                ├── wk_reddit_ads_targeting_custom_audience.sql       [NEU]
                ├── wk_reddit_ads_targeting_device.sql                [NEU]
                ├── wk_reddit_ads_targeting_geolocation.sql           [NEU]
                ├── wk_reddit_ads_targeting_interest.sql              [NEU]
                └── wk_reddit_ads_time_zone.sql                       [NEU]

Beispiel des generierten Codes

Hier ist ein Beispiel für die Qualität des generierten Codes. Für die time_zone-Tabelle erstellte GitLab Duo:

Prep-Ebene Quellmodell


WITH source AS (
  SELECT *
  FROM {{ source('reddit_ads','time_zone') }}
  QUALIFY ROW_NUMBER() OVER (PARTITION BY id ORDER BY _fivetran_synced DESC) = 1
),


renamed AS (
  SELECT
    id::VARCHAR                               AS time_zone_id,
    code::VARCHAR                             AS time_zone_code,
    dst_offset::NUMBER                        AS time_zone_dst_offset,
    is_dst_active::BOOLEAN                    AS is_time_zone_dst_active,
    name::VARCHAR                             AS time_zone_name,
    offset::NUMBER                            AS time_zone_offset,
    _fivetran_synced::TIMESTAMP               AS fivetran_synced_at
  FROM source
)


SELECT * FROM renamed

Schema.yml


models:
  - name: reddit_ads_time_zone_source
    description: Zeitzonendaten aus dem Reddit Ads-System
    columns:
      - name: time_zone_id
        description: Eindeutige Kennung für Zeitzoneneinträge
        data_tests:
          - unique
          - not_null
      - name: time_zone_code
        description: Code für die Zeitzone
      - name: time_zone_dst_offset
        description: Sommerzeitverschiebung für die Zeitzone
      - name: is_time_zone_dst_active
        description: Flag, das angibt, ob Sommerzeit aktiv ist
      - name: time_zone_name
        description: Name der Zeitzone
      - name: time_zone_offset
        description: Verschiebung für die Zeitzone
      - name: fivetran_synced_at
        description: Zeitstempel, wann der Datensatz zuletzt von Fivetran synchronisiert wurde

Source.yml


sources:
  - name: reddit_ads
    database: RAW
    schema: reddit_ads
    loaded_at_field: _fivetran_synced
    loader: fivetran
    description: Reddit Ads-Daten

    quoting:
      database: true
      schema: false
      identifier: false

    tables:
      - name: time_zone

Workspace-Modell


WITH source AS (
  SELECT *
  FROM {{ ref('reddit_ads_time_zone_source') }}
)


SELECT * FROM source

5. Qualitätsvalidierung

Nachdem der Code gut aussah, habe ich ihn zum MR gepusht und die CI-Test-Pipeline ausgeführt, um den Code zu testen und das Ergebnis zu validieren. Ich bat GitLab Duo, eine Validierungsabfrage zu erstellen:


Create a test query to test the row counts between the raw layer and the workspace layer. Keep in mind that we do deduplication, so we can compare both using distinct on the primary keys.

Die KI generierte eine umfassende Validierungsabfrage, die:

  • Zeilenanzahlen zwischen raw- und workspace-Ebenen verglich

  • Die Deduplizierungs-Logik berücksichtigte

  • Alle 13 Tabellen testete

  • Datenerhaltungsprozentsätze berechnete

Generierte SQL-Test-Abfrage

-- Reddit Ads Zeilenanzahl-Validierungstest

-- Vergleicht eindeutige Zählungen zwischen RAW-Ebene und WORKSPACE_MARKETING-Ebene

-- Berücksichtigt Deduplizierungs-Logik in Quellmodellen


WITH raw_counts AS (
  -- Tabellen mit einzelnem Primärschlüssel
  SELECT 'ad' AS table_name, COUNT(DISTINCT id) AS raw_count
  FROM RAW.REDDIT_ADS.AD
  
  UNION ALL
  
  SELECT 'business_account' AS table_name, COUNT(DISTINCT id) AS raw_count
  FROM RAW.REDDIT_ADS.BUSINESS_ACCOUNT
  
  UNION ALL
  
  SELECT 'campaign' AS table_name, COUNT(DISTINCT id) AS raw_count
  FROM RAW.REDDIT_ADS.CAMPAIGN
  
  UNION ALL
  
  SELECT 'custom_audience_history' AS table_name, COUNT(DISTINCT id) AS raw_count
  FROM RAW.REDDIT_ADS.CUSTOM_AUDIENCE_HISTORY
  
  UNION ALL
  
  SELECT 'geolocation' AS table_name, COUNT(DISTINCT id) AS raw_count
  FROM RAW.REDDIT_ADS.GEOLOCATION
  
  UNION ALL
  
  SELECT 'interest' AS table_name, COUNT(DISTINCT id) AS raw_count
  FROM RAW.REDDIT_ADS.INTEREST
  
  UNION ALL
  
  SELECT 'time_zone' AS table_name, COUNT(DISTINCT id) AS raw_count
  FROM RAW.REDDIT_ADS.TIME_ZONE
  
  -- Tabellen mit zusammengesetzten Primärschlüsseln
  UNION ALL
  
  SELECT 'ad_group' AS table_name, COUNT(DISTINCT CONCAT(account_id, '|', id)) AS raw_count
  FROM RAW.REDDIT_ADS.AD_GROUP
  
  UNION ALL
  
  SELECT 'targeting_community' AS table_name, COUNT(DISTINCT CONCAT(ad_group_id, '|', community_id)) AS raw_count
  FROM RAW.REDDIT_ADS.TARGETING_COMMUNITY
  
  UNION ALL
  
  SELECT 'targeting_custom_audience' AS table_name, COUNT(DISTINCT CONCAT(ad_group_id, '|', custom_audience_id)) AS raw_count
  FROM RAW.REDDIT_ADS.TARGETING_CUSTOM_AUDIENCE
  
  UNION ALL
  
  SELECT 'targeting_device' AS table_name, COUNT(DISTINCT _fivetran_id) AS raw_count
  FROM RAW.REDDIT_ADS.TARGETING_DEVICE
  
  UNION ALL
  
  SELECT 'targeting_geolocation' AS table_name, COUNT(DISTINCT CONCAT(ad_group_id, '|', geolocation_id)) AS raw_count
  FROM RAW.REDDIT_ADS.TARGETING_GEOLOCATION
  
  UNION ALL
  
  SELECT 'targeting_interest' AS table_name, COUNT(DISTINCT CONCAT(ad_group_id, '|', interest_id)) AS raw_count
  FROM RAW.REDDIT_ADS.TARGETING_INTEREST
),


workspace_counts AS (
  -- Workspace-Ebene zählt unter Verwendung von Primärschlüsseln aus schema.yml
  SELECT 'ad' AS table_name, COUNT(DISTINCT ad_id) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_AD
  
  UNION ALL
  
  SELECT 'business_account' AS table_name, COUNT(DISTINCT business_account_id) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_BUSINESS_ACCOUNT
  
  UNION ALL
  
  SELECT 'campaign' AS table_name, COUNT(DISTINCT campaign_id) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_CAMPAIGN
  
  UNION ALL
  
  SELECT 'custom_audience_history' AS table_name, COUNT(DISTINCT custom_audience_id) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_CUSTOM_AUDIENCE_HISTORY
  
  UNION ALL
  
  SELECT 'geolocation' AS table_name, COUNT(DISTINCT geolocation_id) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_GEOLOCATION
  
  UNION ALL
  
  SELECT 'interest' AS table_name, COUNT(DISTINCT interest_id) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_INTEREST
  
  UNION ALL
  
  SELECT 'time_zone' AS table_name, COUNT(DISTINCT time_zone_id) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_TIME_ZONE
  
  -- Tabellen mit zusammengesetzten Primärschlüsseln
  UNION ALL
  
  SELECT 'ad_group' AS table_name, COUNT(DISTINCT CONCAT(ad_group_account_id, '|', ad_group_id)) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_AD_GROUP
  
  UNION ALL
  
  SELECT 'targeting_community' AS table_name, COUNT(DISTINCT CONCAT(targeting_community_ad_group_id, '|', targeting_community_id)) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_TARGETING_COMMUNITY
  
  UNION ALL
  
  SELECT 'targeting_custom_audience' AS table_name, COUNT(DISTINCT CONCAT(targeting_custom_audience_ad_group_id, '|', targeting_custom_audience_id)) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_TARGETING_CUSTOM_AUDIENCE
  
  UNION ALL
  
  SELECT 'targeting_device' AS table_name, COUNT(DISTINCT targeting_device_fivetran_id) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_TARGETING_DEVICE
  
  UNION ALL
  
  SELECT 'targeting_geolocation' AS table_name, COUNT(DISTINCT CONCAT(targeting_geolocation_ad_group_id, '|', targeting_geolocation_id)) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_TARGETING_GEOLOCATION
  
  UNION ALL
  
  SELECT 'targeting_interest' AS table_name, COUNT(DISTINCT CONCAT(targeting_interest_ad_group_id, '|', targeting_interest_id)) AS workspace_count
  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_TARGETING_INTEREST
)


-- Abschließender Vergleich mit Validierungsergebnissen

SELECT 
  r.table_name,
  r.raw_count,
  w.workspace_count,
  r.raw_count - w.workspace_count AS count_difference,
  CASE 
    WHEN r.raw_count = w.workspace_count THEN '✅ BESTANDEN'
    WHEN r.raw_count > w.workspace_count THEN '⚠️ RAW > WORKSPACE (Erwartet durch Deduplizierung)'
    ELSE '❌ FEHLGESCHLAGEN - WORKSPACE > RAW (Unerwartet)'
  END AS validation_status,
  ROUND((w.workspace_count::FLOAT / r.raw_count::FLOAT) * 100, 2) AS data_retention_percentage
FROM raw_counts r

JOIN workspace_counts w ON r.table_name = w.table_name

ORDER BY r.table_name;

Tabelle mit Abfrageergebnissen

Die Ausführung dieser Abfrage zeigte:

  • Null Unterschiede in der Zeilenanzahl nach Deduplizierung

  • 100% Datenerhaltung über alle Tabellen hinweg

  • Alle Tests erfolgreich bestanden

Das Fazit: Massive Zeitersparnis

  • Traditioneller Ansatz: 6-8 Stunden manuelles Programmieren, Testen und Debugging

  • GitLab Duo-Ansatz: 6-8 Minuten Generierung + Überprüfungszeit

Dies bedeutet eine 60-fache Verbesserung der Entwicklereffizienz (von 6-8 Stunden auf 6-8 Minuten) bei gleichbleibend hoher Codequalität.

Best Practices für den Erfolg

Basierend auf dieser Erfahrung sind hier die wichtigsten Empfehlungen:

Bereite deine Metadaten vor

  • Extrahiere vollständige Tabellenstrukturen einschließlich Datentypen und Einschränkungen

  • Identifiziere Primärschlüssel und Beziehungen im Voraus

  • Exportiere saubere, gut formatierte CSV-Eingabedateien

Hinweis: Durch die Verbindung von GitLab Duo über MCP mit deinen (Meta-)Daten könntest du diesen manuellen Schritt ausschließen.

Biete klaren Kontext

  • Referenziere nach Möglichkeit bestehende Beispiel-MRs

  • Spezifiziere deine Codierungsstandards und Style Guides

  • Sei explizit bei Ordnerstruktur und Namenskonventionen

Validiere gründlich

  • Erstelle immer Validierungsabfragen für die Datenintegrität

  • Teste lokal vor dem Mergen

  • Führe deine CI/CD-Pipeline aus, um Probleme zu erkennen

Nutze KI für Folgeaufgaben

  • Generiere Testabfragen automatisch

  • Erstelle Dokumentationsvorlagen

  • Baue Validierungsskripte

Was kommt als Nächstes

Diese Demonstration zeigt, wie KI-gestützte Entwicklungstools wie GitLab Duo auch Data-Engineering-Workflows transformieren. Die Fähigkeit, Hunderte von Zeilen produktionsreifem Code in Minuten zu generieren – komplett mit Tests, Dokumentation und ordnungsgemäßer Struktur – stellt einen fundamentalen Wandel dar, wie wir an repetitive Entwicklungsaufgaben herangehen.

Indem wir KI nutzen, um die repetitiven Aspekte der dbt-Modellerstellung zu bewältigen, können sich Dateningenieure auf Aktivitäten mit höherem Wert konzentrieren, wie Datenmodellierungsstrategie, Performance-Optimierung und Implementierung von Geschäftslogik.

Bereit, es selbst auszuprobieren? Beginne mit einem kleinen Datensatz, bereite deine Metadaten sorgfältig vor und sieh zu, wie GitLab Duo Stunden an Arbeit in Minuten automatisierter Generierung verwandelt.

Teste GitLab Duo Agent Platform noch heute.

Weiterlesen

Wir möchten gern von dir hören

Hat dir dieser Blogbeitrag gefallen oder hast du Fragen oder Feedback? Erstelle ein neues Diskussionsthema im GitLab-Community-Forum und tausche deine Eindrücke aus.
Share your feedback

Mehr als 50 % der Fortune-100-Unternehmen vertrauen GitLab

Stelle jetzt bessere Software schneller bereit

Erlebe, was dein Team mit der intelligenten

DevSecOps-Plattform erreichen kann.