Wanneer een ontwikkelaar een prompt aanpast, een modelversie upgrade of de retrieval-parameters in een RAG-systeem wijzigt, ontstaat er direct een beslismoment: accepteren we deze aanpassing naar de productieomgeving, of draaien we de commit terug? Om deze beslissing niet te laten afhangen van onderbuikgevoel of steekproefsgewijze handmatige inspectie, is een geautomatiseerde drempelwaarde in je Continuous Integration en Continuous Deployment (CI/CD) pijplijn noodzakelijk. Door bij elke wijziging automatisch een vaste evaluatieset te draaien en de uitkomst kwantitatief te vergelijken met de baseline (de huidige productiestand), kan de pijplijn een harde 'go/no-go' afdwingen op basis van vooraf vastgestelde kwaliteits- en tolerantiegrenzen.
Dit artikel gaat verder dan het basisprincipe van herhaaldelijk testen; waar een analyse van regressietesten voor prompts stopt bij het concept van herhaling, richt deze handleiding zich op de technische integratie van continue bewaking binnen softwarepijplijnen. We behandelen reproduceerbaarheid hierbij expliciet als een technische randvoorwaarde en niet als een zelfstandig onderwerp. Het doel is het bouwen van een robuust, geautomatiseerd systeem dat kwaliteitsverval ("drift" of onbedoelde regressie) opvangt voordat code of configuraties het productieplatform bereiken.
Het meetprobleem: continue kwaliteitsborging bij dynamische variabelen
In traditionele softwareontwikkeling leidt dezelfde invoer onder identieke omstandigheden tot exact dezelfde uitvoer. Bij applicaties gebouwd op Large Language Models (LLM's) introduceert elke component variabiliteit. Een wijziging aan de systeemprompt kan de nauwkeurigheid van gestructureerde data-extractie verhogen, maar tegelijkertijd de toon van een samenvatting negatief beïnvloeden. Evenzo kan een update van een embedding-model in de retrieval-laag de relevantie van de context veranderen, wat weer doorwerkt in de uiteindelijke antwoorden van het generatieve model.
Het overzien van al deze onderlinge afhankelijkheden is met handmatig testen onmogelijk. Zonder automatische toetsing ontstaan drie specifieke risico's:
- Onzichtbare regressie: Een verbetering op vijf specifieke randgevallen veroorzaakt ongemerkt een kwaliteitsdaling op 20% van de reguliere gebruikersvragen.
- Versieverschil bij providers: Weliswaar blijft de modelnaam hetzelfde (bijvoorbeeld bij een rolling release van een API-provider), maar de onderliggende gewichten veranderen, waardoor de uitvoer subtiel verschuift.
- Gebrek aan een objectieve beslisregel: Leden van het ontwikkelteam discussiëren over subjectieve voorkeuren in plaats van te testen tegen een kwantitatieve ondergrens.
De oplossing voor dit meetprobleem is het inrichten van een geautomatiseerde testsuite die bij elke Pull Request (PR) of commit wordt geëxecuteerd, vergelijkbaar met unit- en integratietesten in reguliere software-engineering.
Een reproduceerbare meetopzet inrichten
Om een automatische evaluatie betrouwbaar te laten functioneren in een CI/CD-pijplijn, moet de meetopzet strikt gestructureerd en reproduceerbaar zijn. Een wankele testopzet leidt tot valse waarschuwingen (waardoor de pijplijn onterecht blokkeert) of onterechte goedkeuringen. Een volledige meetopzet binnen de pijplijn vereist het verplicht vastleggen van vier kerncomponenten.
1. De vastgezette variabelen (Determinisme)
Tijdens een evaluatierun moeten alle externe factoren waar mogelijk worden bevroren. Dit betekent dat het CI/CD-script exact de volgende parameters moet specificeren:
- Promptversie en Systeempromptversie: Vastgelegd via semantisch versiebeheer in Git (zie ook versiebeheer voor prompts in code voor de implementatie in de applicatielaag).
- Exacte Modelidentificatie: Gebruik geen generieke aliases zoals
gpt-4oals de provider ook specifieke snapshot-versies aanbiedt (zoalsgpt-4o-2024-08-06). - Inference-parameters: Zet de
temperatureop 0.0 voor maximale determinisme, of leg bij een hogere temperatuur een vaste zaadwaarde (seedparameter) vast indien het model dit ondersteunt. Leg tevenstop_p,frequency_penaltyenpresence_penaltyvast. - Retrieval-configuratie: Indien van toepassing op een RAG-pijplijn: fixeerde index-versie, het aantal opgehaalde documenten ($k$) en de similarity-drempelwaarde.
2. Aantal herhalingen (Steekproefdekking)
Omdat LLM's zelfs bij temperature=0 kleine variaties kunnen vertonen (als gevolg van floating-point berekeningen op parallelle GPU-clusters), is een enkele evaluatierun per testgeval onvoldoende voor een robuust oordeel. De meetopzet moet voorzien in minimaal $N=3$ tot $N=5$ herhalingen per query op de evaluatieset om de standaarddeviatie te berekenen. Om te bepalen of een drempelwaarde overschreden wordt zonder door ruis te worden beïnvloed, is inzicht in statistiek voor evaluaties onmisbaar.
3. Scoremethodiek (Rubrieken en Beoordelaars)
Kwaliteit moet worden omgezet in een kwantitatieve score tussen 0.0 en 1.0 of een binair label (pass/fail). Afhankelijk van het type taak worden drie evaluatiemethoden gebruikt:
- Deterministic matching: Voor gestructureerde output (JSON, SQL, Regex). Hierbij controleert de testsuite de syntactische en semantische validiteit. Een uitstekend voorbeeld hiervan is het evalueren van JSON-validiteit bij belasting om te verifiëren of het model zich aan het beoogde schema blijft houden.
- Traditionele NLP-metrieken: ROUGE, BLEU of BERTScore voor vergelijkingen met een referentieantwoord. Zeer snel en goedkoop, maar beperkt in het herkennen van inhoudelijk correcte parafrases.
- Modelbeoordelaar (LLM-as-a-Judge): Een krachtiger, secundair LLM dat de output beoordeelt aan de hand van een expliciete kwaliteitsrubriek (bijvoorbeeld op nauwkeurigheid, volledigheid en toon).
4. IJking van de beoordelaar
Wanneer een LLM wordt ingezet als beoordelaar in de CI/CD-pijplijn, moet de betrouwbaarheid van deze beoordelaar zelf continu worden gecontroleerd. Dit gebeurt door de scores van de modelbeoordelaar regelmatig te vergelijken met een menselijk gevalideerde dataset (gold standard) en de Cohen's Kappa of Pearson-correlatiecoëfficiënt te berekenen. Voor de precieze opzet hiervan verwijzen we naar het artikel over LLM-as-a-Judge en het ijken van beoordelaars.
Nederlandse taal- en cultuurvalkuilen in de testset
Voor applicaties die worden ingezet in de Nederlandse markt levert een algemene (Engelsgeoriënteerde) testset onvoldoende garanties. De geautomatiseerde testset moet expliciet casuïstiek bevatten waarin specifieke kenmerken van de Nederlandse taal en context worden beproefd. Als deze categorieën niet structureel in de pijplijn worden getoetst, ontstaan er snel onopgemerkte fouten in productie.
Aanspreekvorm (U versus Jij)
In het Nederlands is het onderscheid tussen formeel (u) en informeel (jij/je) zakelijk en operationeel cruciaal. Een wijziging in de systeemprompt kan ertoe leiden dat het model onbedoeld overschakelt van een formele naar een informele toon. De testset moet prompt-variaties bevatten waarin expliciet wordt gecontroleerd of het model de instructie over de aanspreekvorm consistent handhaaft over meerdere gesprekscursussen.
Samenstellingen en Woordeenheid
Het Nederlands kent het verschijnsel van aan elkaar geschreven samenstellingen (bijvoorbeeld kwaliteitsbewakingssysteem of integratietestomgeving). Veel taalmodellen, die primair op Engelse tokenisatie zijn getraind, neigen ertoe deze woorden los van elkaar te schrijven ("kwaliteits bewakings systeem"). Dit staat bekend als de Engelse ziekte. De geautomatiseerde evaluatie moet de output van het model controleren op correcte spelling van samengestelde zelfstandige naamwoorden, aangezien dit direct invloed heeft op de professionele uitstraling.
Regionale varianten (NL-NL versus BE-NL)
Afhankelijk van de doelgroep kan de gewenste terminologie verschillen tussen Nederland en Vlaanderen (bijvoorbeeld vrijblijvende offerte versus offerte zonder verbintenis, of pinnen versus bancontact). Een robuuste testset bevat testcases die specifiek valideren dat de door de applicatie gegenereerde termen aansluiten bij het juiste taalgebied.
Entiteiten, Wetgeving en Naamgeving
Nederlandse entiteiten zoals BSN-nummers, postcodes (1234 AB), KVK-nummers en specifieke wetgeving (zoals de AVG of specifieke bouwbesluiten) vereisen exacte verwerking. Een generiek model kan neigen naar het formatteren van adressen of nummers volgens Amerikaanse standaarden. De testsuite in de CI/CD-pijplijn moet via reguliere expressies en kwalitatieve checks verifiëren dat Nederlandse entiteiten correct worden herkend en gegenereerd.
Kosten en budgettaire beheersing van de evaluatiepijplijn
Het automatisch uitvoeren van een volledige evaluatieset bij elke Git push of PR-update kan aanzienlijke kosten met zich meebrengen. Elk testgeval verbruikt input- en outputtokens, en bij het gebruik van een modelbeoordelaar (LLM-as-a-Judge) worden die kosten verdubbeld. Voor een gedetailleerde analyse van de basiskosten verwijzen we naar het overzicht over de kosten van evalueren. In een CI/CD-context veranderen deze eenmalige kosten in een terugkerende operationele post.
Note: De onderstaande rekenvoorbeelden en cijfers zijn gebaseerd op een verzonnen scenario ter illustratie van de kostenstructuur en vormen geen gemeten empirische resultaten uit een specifieke productieomgeving.
Om te voorkomen dat de CI/CD-pijplijn onbeperkt API-budget verbruikt, moeten ontwikkelaars budgettaire beheersmaatregelen treffen. Onderstaande tabel geeft een overzicht van de geschatte kosten per evaluatierun bij verschillende omvangstypes van testsets.
| Type Testset | Aantal Vragen ($N=1$) | Herhalingen ($N$) | Totaal Aantal Calls | Geschat Tokenverbruik | Geschatte Kosten per Run (USD) |
|---|---|---|---|---|---|
Strategieën voor kostenbeheersing
Om de kosten beheersbaar te houden zonder in te boeten op kwaliteit, worden in de praktijk drie technieken gecombineerd:
- Gelaagde Pijplijnuitvoering (Tiered Evaluation):
- Tier 1 (PR Level): Voer alleen een snelle 'Smoke Test' uit van 15 tot 20 kritische testcases met lage temperatuur en lichte beoordeling (bijvoorbeeld binaire reguliere expressies of JSON-schema checks).
- Tier 2 (Merge/Main Branch): Voer de volledige regressieset uit (100–200 testcases) met $N=3$ herhalingen inclusief LLM-as-a-Judge beoordeling.
- Tier 3 (Nachtelijke build): Uitgebreide stress- en belastingtesten met historische gegevens uit de hele database. Zie hiervoor ook de methode om evaluatiedata uit productie te hergebruiken.
- Caching van ongewijzigde componenten: Als alleen de prompt van de samenvatting is gewijzigd, hoeft de retrieval-stap voor de testset niet opnieuw te worden uitgevoerd als de context-outputs eerder zijn opgeslagen.
- Programmatische kostenlimieten: Stel op de API-sleutels die voor de CI/CD-pijplijn worden gebruikt harde limieten in. Zorg dat de pijplijn gecontroleerd faalt zodra een budgetdrempel wordt bereikt. Raadpleeg voor het opzetten van deze beveiliging de gids over het instellen van harde kostenlimieten en quota.
Architectuur van de geautomatiseerde evaluatiepijplijn
Een complete integratie van evaluaties in de CI/CD-pijplijn bestaat uit meerdere opeenvolgende stappen. Onderstaand stroomschema illustreert hoe een code- of promptwijziging door het systeem stroomt en tot een besluit leidt.
[ Developer Commit / PR ]
│
▼
[ Step 1: CI Pipeline Triggered ]
│
▼
[ Step 2: Fetch Testset & Baseline Scores ]
│
▼
[ Step 3: Execute LLM Application Run ]
├── Fixed Prompts / Models
├── Target API Calls (N-iterations)
└── Log Inputs, Outputs & Latency
│
▼
[ Step 4: Run Evaluators ]
├── Deterministic Checks (JSON Schema, Regex)
├── Code-based NLP Metrics (ROUGE / BERTScore)
└── Model Judge (LLM-as-a-Judge)
│
▼
[ Step 5: Statistical Comparison vs. Baseline ]
│
┌───────┴────────────────────────┐
▼ ▼
[ Delta ≥ Threshold ] [ Delta < Threshold ]
│ │
▼ ▼
[ PASS: Merge Allowed ] [ FAIL: Block Deployment ]
│
▼
[ Trigger Rollback & Log Alert ]
Systeemeisen en integratiepunten
Om dit proces in bijvoorbeeld GitHub Actions, GitLab CI of Azure DevOps te laten draaien, moeten de volgende onderdelen aanwezig zijn:
- Test-runner script: Een Python- of TypeScript-script dat de testsuite inleest, de API-calls naar het te testen model uitvoert en de resultaten opvangt. Om prestatieregressies tijdig op te sporen, kan binnen dit script ook de responstijd worden gemonitord. Lees meer over het correct verwerken van respons-tijden in latency-percentielen meten.
- Opslag van baselines: De scores van de huidige productiestand moeten ergens centraal zijn opgeslagen (bijvoorbeeld als JSON-artefact in een object storage bucket) zodat de CI-runner de nieuwe resultaten hiermee kan vergelijken.
- Logging en observabiliteit: Alle gegenereerde antwoorden, API-responsen en evaluatieresultaten uit de CI-run moeten traceerbaar opgeslagen worden ter analyse bij een gefaalde build. Zie hiervoor de richtlijnen over observability en logging op onze API-hub.
Van evaluatiescore naar automatische PR-besluitvorming
De uiteindelijke stap in de pijplijn is het automatisch omzetten van de ruwe testresultaten naar een actie: het goedkeuren of blokkeren van een Pull Request. Hierbij mag niet alleen naar een gemiddelde score worden gekeken, maar moeten specifieke drempelwaarden (guardrails) worden gedefinieerd.
Note: De in de onderstaande voorbeelden genoemde percentages en drempelwaarden zijn verzonnen voorbeelden ter illustratie van configuratie-logica en vormen geen universele standaarden.
Een voorbeeld van een besliskaart-configuratie in een CI-script:
# Example evaluation_rules.yaml (Illustratief voorbeeld)
rules:
- metric: json_validity
min_threshold: 1.00 # Harde eis: 100% van de outputs moet geldige JSON zijn
action_on_fail: BLOCK
- metric: factual_accuracy
min_threshold: 0.95 # Minimaal 95% nauwkeurigheid vereist
max_drop_vs_baseline: 0.01 # Maximaal 1% daling toegestaan t.o.v. baseline
action_on_fail: BLOCK
- metric: tone_formal_nl
min_threshold: 0.90
max_drop_vs_baseline: 0.05
action_on_fail: WARN # Geef een waarschuwing op de PR, maar blokkeer niet direct
- metric: latency_p95
max_threshold_ms: 2500 # P95 latency mag niet boven 2,5 seconden komen
action_on_fail: BLOCK
Door deze regels automatisch te laten toetsen door de CI-runner, ontstaat een transparant proces. Als een ontwikkelaar bijvoorbeeld een systeemprompt aanpast (zie ook systeemprompt-variatie en consistentie meten) en de nauwkeurigheid op de testset daalt met 3%, rapporteert de pijplijn direct op welke specifieke testgevallen de regressie heeft plaatsgevonden. Het team kan zo de wijziging gericht herstellen of de commit terugdraaien.
Netwerkbrug: Van Meten naar Bouwen
Het opzetten van continue evaluaties op het subdomein benchmark.llmnet.nl richt zich op het **meten** en analyseren van modelkwaliteit. Echter, zodra de evaluatiecriteria en drempelwaarden zijn vastgesteld, verplaatst het werk zich naar het **bouwen** en onderhouden van de daadwerkelijke software-architectuur.
Voor het technisch realiseren van de testrunner, de integratie van API-calls binnen je bestaande CI/CD-pijplijn en het opvangen van API-fouten tijdens testruns, lees je verder op onze API-gids over het automatisch testen van LLM-integraties. Zonder een solide integratielaag in de codebase blijft een evaluatieset immers een theoretisch model dat niet geautomatiseerd kan worden afgedwongen.


