Notities uit de releasecyclus — deel 7
Vrijdagmiddag om 16:47 uur heb je een prompt-aanpassing van één teken uitgerold. De geaggregeerde evaluatiescore bewoog van 0,873 naar 0,871 — ruim binnen de ruisbodem. Maandagochtend staat je supportwachtrij in brand over een klasse queries waar je al zes maanden niet meer naar keek omdat ze stabiel waren.
Niets in het model is geregresseerd. Het model is hetzelfde model. De evaluatie is onder je vandaan gedreven. Zes maanden van langzame groei in één klantsegment haalden nooit de golden dataset, de judge-prompt werd voor het laatst in oktober gekalibreerd tegen mensen, en de retrieval-index is afgelopen woensdag stilletjes opnieuw opgebouwd op een vernieuwd embedding-model.
Dit is waar deel 6 voor waarschuwde — het model is ruwweg één alert op de zeven het juiste antwoord. Dat betekent dat je regressie-suite drift in zichzelf moet detecteren, niet alleen drift in het model. Deze post is die suite.
Wat is regressietesten voor een custom LLM eigenlijk?
Softwareregressietests stellen output == expected vast voor vaste invoer. Ze werken omdat de functie deterministisch is.
Een taalmodel is geen functie in dezelfde zin. Dezelfde prompt produceert bij temperatuur > 0 een verdeling van geldige completions, en “geldig” is multidimensionaal: heeft het de vraag beantwoord, is het antwoord gegrond in de opgehaalde context, bleef het binnen de veiligheidsenvelop, kwam het binnen het latentiebudget terug. Regressietesten van een custom LLM betekent dus de verdeling van gedrag meten tegen een bevroren basislijnverdeling — over slices die voor jou relevant zijn, met judges die tegen mensen zijn gekalibreerd, op invoer die op je productieverkeer lijkt.
Voordat hier iets van betekenisvol is, moeten drie zaken op orde zijn:
- Een golden dataset die op slice-niveau op de productie lijkt, niet in aggregaat.
- Een gekalibreerde judge — niet “we gebruiken GPT-5 als judge”, maar “we hebben Spearman ρ ≥ 0,7 gemeten tegen drie menselijke beoordelaars, voor het laatst vorige week vernieuwd”.
- Een basislijn-manifest — de exacte modelgewichten, prompt-template, retrieval-index en judge-versie die de gemeten score opleverden. Zonder dit kun je niet vaststellen of de score bewoog omdat het model veranderde of omdat de meetlat veranderde.
Divinci voert alle drie als eersteklas objecten, hash-gekoppeld, gescoord bij elke commit. De rest van deze post gaat over het samenstellen ervan.
Waarom de meeste LLM-regressie-suites echte regressies niet opvangen
De dominante 2026-faalmodus voor custom LLM’s is wat Tianpans Sigma Inference-team in hun postmortem van april 2026 de Semver Lie noemde[1]: een geaggregeerde metric blijft vlak of verbetert, terwijl één of twee productie-slices in stilte regresseren. De slice was minder dan 5% van het verkeer toen de test werd ontworpen, dus die kwam nooit in de golden dataset; zes maanden later is het 12% van het verkeer, is het model erop achteruitgegaan, en het geaggregeerde getal zou dat nooit gaan opmerken.
We hebben elk publiek LLM-release-postmortem van de afgelopen achttien maanden bekeken en het patroon herhaalt zich: de suite stond op groen omdat ze het verkeerde mat. Concreet:
- De golden dataset werd door het team handmatig geschreven bij lancering en nooit opnieuw gestratificeerd tegen verschoven verkeersverdelingen.
- De LLM-als-judge-prompt werd één keer ingesteld en nooit hergekalibreerd tegen menselijke labels. De judge-overeenstemming verviel stilletjes[2].
- De basislijnscores werden opgeslagen als ruwe getallen, niet als
(model_sha, prompt_sha, judge_sha, dataset_sha, score)-tuples — dus toen er iets regresseerde, kon niemand vertellen welke van de vier bewogen had.
Een regressie-suite die deze drie niet alle drie oplost, is gewoon een CI-stap die bij deploy op groen springt en je vals vertrouwen geeft. De oplossing is niet “meer cases”. De oplossing is slice-bewuste, versie-verankerde, judge-gekalibreerde meting, bij elke release.
Bouw een golden dataset die slice-bewuste analyse overleeft
De vier-emmer-samenstelling die we standaard uitleveren — productiemonsters 60%, adversarieel 15%, door experts gecureerde edge cases 15%, replay van faalgevallen 10% — is een redelijk vertrekpunt. Wat ervoor zorgt dat het regressies écht opvangt, is de slice-metadata die aan elke case wordt gekoppeld.
Elke vermelding in de dataset draagt: invoer, verwacht gedrag (rubric, geen exacte string), retrieval-context (indien van toepassing), en een slice-tag — domein, gebruikerssegment, query-intentie, taal, lengte-emmer, welke decomposities ook relevant zijn voor je product. De suite scoort per slice, en elke slice die onder zijn drempel zakt blokkeert de release, ook als de geaggregeerde score omhoog ging.
Twee operationele regels die we hebben geleerd af te dwingen:
Hersamplen per kwartaal. Productieverkeersverdelingen verschuiven sneller dan de meeste teams meten. We stratificeren de productiemonster-emmer elk kwartaal opnieuw tegen de laatste 90 dagen verkeer; als een slice voorbij 5% van het verkeer is gegroeid en minder dan 2% van de golden dataset uitmaakte, wordt die vóór de volgende release bijgevuld.
Elke postmortem voegt een case toe. Een regressie die de productie haalde en niet werd opgevangen, is een case die ontbrak in de dataset. Binnen 48 uur na de postmortem voegen we hem toe aan de replays-emmer en taggen we hem met de slice die hem aan het licht bracht.
Hoe detecteer je drift voordat gebruikers dat doen?
Er bestaan vier verschillende soorten drift, en een regressie-suite die alleen de laatste in de gaten houdt is een regressie-suite die de meeste regressies mist.
| Driftsoort | Wat beweegt | Detectiesignaal | Actie |
|---|---|---|---|
| Kwaliteitsdrift | De judge-score voor een vaste slice | Per-slice Spearman ρ t.o.v. basislijn daalt | Release blokkeren; diagnose volgens de boom uit deel 6 |
| Dekkingsdrift | Productieverkeersverdeling t.o.v. verdeling golden dataset | KL-divergentie tussen slice-proporties | Golden dataset hersamplen |
| Judge-drift | Overeenstemming judge-model met mensen | Spearman ρ t.o.v. een bevroren menselijk gelabelde auditset | Judge-prompt hergebruiken of judge vervangen |
| Productiedrift | Live productiescores t.o.v. offline scores op hetzelfde model | Score-gap bij replay productie-trace | Onderzoek retrieval / preprocessing / runtime |
Kwaliteitsdrift is wat de meeste suites meten; de andere drie zijn waar vrijdagmiddag-regressies zich doorgaans verschuilen. Divinci volgt alle vier tegen het basislijn-manifest, met de per-slice-score-uitsplitsing zichtbaar op elke PR en een wekelijkse judge-kalibratiejob die drift signaleert vóór die zich opstapelt.
Multidimensionale evaluatie — scoor vier dingen tegelijk, per slice
Eén samengestelde score is een slechter signaal dan vier scalaire scores. We gaten op vier dimensies:
- Task completion — heeft de respons de vraag echt beantwoord, beoordeeld door een gekalibreerde judge tegen een rubric. Slice-bewust.
- Faithfulness — voor elke respons die naar opgehaalde context verwees, is elke bewering daarin gegrond. Hallucinatie komt hier als eerste tevoorschijn.
- Veiligheid — correctheid van weigeringen, jailbreak-weerstand, blootstelling van PII / beleid. Vrijwel altijd op gate ≥ 0,99 slagingspercentage; veiligheid is een harde muur, geen zachte trade-off.
- Latentiebudget — p95 binnen de SLA van de slice. Een prompt-wijziging die de tokens-per-respons verdubbelde is een regressie, ook als de kwaliteit omhoogging.
Elke dimensie heeft zijn eigen per-slice-basislijn en zijn eigen per-slice-drempel. We combineren ze bij de gate nooit tot één gewogen scalair; we tonen ze als vier scores per slice en blokkeren op die welke als eerste zijn drempel overschreed. Een model dat 4 punten task completion won ten koste van 1 punt faithfulness op de medische slice is nog steeds een regressie.
Welke gates moeten een custom-LLM-deployment blokkeren?
We draaien een drielaagse architectuur, waarbij elke laag een andere fase van de pijplijn gate’t (zie deel 1 voor de fasetaxonomie).
Laag 1 — Smoke (elke commit, ~90 seconden). Twintig tot dertig kritieke cases getrokken uit de slices met de grootste impact. Vangt catastrofale regressies op vóór de volledige suite rekencapaciteit uitgeeft. Als smoke faalt, draait de rest niet.
Laag 2 — Volledige suite (elke PR, ~12 minuten). De complete golden dataset, gescoord per slice op alle vier de dimensies. Slice-bewuste Spearman ρ tegen het basislijn-manifest. Drempeloverschrijding blokkeert de merge. De PR-comment somt precies op welke slice op welke dimensie hoeveel bewoog, met vijf voorbeelden van falende cases.
Laag 3 — Basislijnvergelijking (release-candidates, ~25 minuten). Het kandidaatmodel wordt herspeeld tegen de laatste 14 dagen aan productie-traces — de closed-loop production-trace replay die we in deel 1 hebben uitgeleverd. Dezelfde gekalibreerde judge die de golden dataset scoort, scoort ook de replay-outputs. Elke slice waarvan de herspeelde scores meer dan zijn drempel afwijken van de offline scores blokkeert de release. Deze laag vangt drift op die de golden dataset nog niet kent.
Kalibreer je judge voordat je één enkele score vertrouwt die hij produceert
LLM-als-judge is wat dit alles voorbij een paar honderd cases laat opschalen. Het is ook waar een regressie-suite stilletjes ophoudt te werken, omdat de judge geen verplichting heeft om gekalibreerd te blijven naarmate hij wordt geüpdatet of naarmate je dataverdeling verschuift.
We kalibreren elke judge-prompt tegen een bevroren menselijk gelabelde auditset van minimaal 100 cases, gestratificeerd over dezelfde slices als de golden dataset, en we draaien de kalibratie wekelijks opnieuw. De drempel waarop we uitleveren is Spearman ρ ≥ 0,7 tegen de mediaan van menselijke beoordelaars, met Cohen’s κ ≥ 0,6 op binaire safety-oordelen. Beide liggen boven de drempel waarop is aangetoond dat MT-Bench-achtige judges menselijke beoordelaars volgen op het niveau van interhumane overeenstemming[2].
Wanneer de wekelijkse kalibratie onder de drempel zakt, wordt de judge automatisch uit dienst gesteld en wordt de dienstdoende eval-engineer gepaged. De release-pijplijn houdt kandidaten open in plaats van ze te gate’en op een judge die niet langer meet wat hij vroeger mat.
# Run the weekly judge calibration job
curl -X POST https://api.divinci.ai/v1/regression/judges/calibrate \
-H "Authorization: Bearer $DIVINCI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"judge_id": "rubric-v7",
"audit_set": "human-labels-2026-04",
"min_spearman": 0.70,
"min_kappa": 0.60,
"on_fail": "retire_judge_and_page"
}'De Divinci-differentiator — closed-loop replay van productie-traces
De gate van laag 3 is het deel dat de meeste regressie-suites niet hebben. De flow is dezelfde flow die we in deel 1 hebben uitgeleverd, met één specialisatie voor regressietesten: van elke release-candidate wordt zijn score op de offline golden dataset slice voor slice vergeleken met zijn score op een 14-daags venster van herspeelde productie-traces. De golden dataset meet wat we verwachtten dat het model zou doen. De replay meet wat het model vorige week feitelijk zou hebben gedaan.
Wanneer die twee scores meer dan het per-slice-gap-budget uit elkaar lopen, wordt de release geblokkeerd. De mismatch is het signaal: ofwel de golden dataset is niet langer representatief (dekkingsdrift), ofwel de kandidaat gedraagt zich anders op traces gevormd door productie-preprocessing en -retrieval (productiedrift). Hoe dan ook kom je het eerder te weten dan je gebruikers.
De judge die de offline run scoort, is dezelfde judge die de replay-run scoort. De audit-log registreert beide score-sets, beide judge-versies, de trace-ID’s die herspeeld zijn en de gap die het blok afvuurde. De gap zelf is het bruikbaarste diagnostische signaal dat we hebben en is wat aan degene wordt overgedragen die vervolgens de diagnoseboom uit deel 6 oppakt.
Veranker de golden dataset met een vindex-receipt
Elke score in de suite is zinloos als je hem later niet kunt reproduceren. We hashen de golden dataset bij elke release en koppelen die hash in een vindex-receipt aan de model-SHA, prompt-SHA, judge-SHA en het kalibratiedossier. Het receipt is extern verankerbaar — auditors kunnen onze exacte regressie-run zes maanden later opnieuw uitvoeren en de scores die we claimden verifiëren.
{
"release_id": "rel_3f1a-2026-05-26",
"model": { "sha": "0c1f9…", "weights_uri": "r2://models/custom-v7.2", "open_weights": true },
"prompt": { "sha": "c4a8e…", "template_id": "support-v3.4" },
"retrieval": { "index_sha": "b21f0…", "embedder": "e5-mistral-7b-instruct" },
"judge": { "sha": "d8e21…", "rubric_id": "rubric-v7", "spearman_vs_humans": 0.74 },
"dataset": { "sha": "a90b1…", "n": 512, "slices": 17, "stratified_at": "2026-04-30" },
"scores": { "aggregate": 0.872, "by_slice": { "/* … */": "/* per-slice scalars */" } },
"replay": { "trace_window_days": 14, "n_traces": 8430, "max_gap": 0.018 },
"vindex_anchor": "sha256:f0bfd2…",
"verifiable_at": "https://vindex.divinci.ai/rel_3f1a-2026-05-26"
}Voorbehoud open weights. Het bovenstaande receipt draagt gewichtsherkomst alleen wanneer het model open-weights is — vindex verankert dan de daadwerkelijke gewichts-bytes. Voor closed-API-modelbackings (OpenAI / Anthropic / Google managed models) draagt het receipt nog steeds de beslissingsketen — elke gate-score, elk judge-resultaat, het kalibratiedossier — maar het gewichtsveld is leeg en je kunt het modelartefact niet onafhankelijk verifiëren. We zeggen dit in het receipt en in de compliance-documentatie zodat auditors geen verkeerde indruk krijgen. De releases die het meest profiteren van een volledige vindex-keten zijn die waarbij je de gewichten in eigen beheer hebt.
Een vierfasen-implementatietijdlijn die we daadwerkelijk hebben uitgeleverd
Teams die proberen de volledige architectuur in week één uit te leveren, lopen vast op tooling. De volgorde hieronder is de volgorde die werkt.
Fase 1 — Basislijn (week 1). Trek een gestratificeerd monster uit de laatste 30 dagen productie-traces. Laat twee engineers elk 100 cases op task completion handmatig labelen. Bereken de interrater-overeenstemming (doel Cohen’s κ ≥ 0,6). Het getal dat eruit komt is je startende human-baseline; al het andere wordt hiertegen gekalibreerd.
Fase 2 — Harness (weken 2–3). Zet de evaluatie-harness op met de 100-case-dataset. Voeg een gekalibreerde judge toe tegen je menselijke labels. Verifieer dat de harness de menselijke scores binnen ρ ≥ 0,7 reproduceert. De meeste teams ontdekken dat hun eerste judge-prompt hier doorvalt en herschrijven hem twee keer — dat is normaal.
Fase 3 — Gates (weken 3–4). Sluit de harness aan op CI als waarschuwing, niet als blokkade. Houd het twee weken in de gaten. De drempels die je ontdekt door false-positive-percentages te observeren, zijn de enige drempels die overleven. Promoveer pas tot blokkering wanneer het false-positive-percentage onder de 5% ligt.
Fase 4 — Replay-loop (doorlopend). Zodra gates betrouwbaar blokkeren, schakel je de replay-laag voor productie-traces in. Hier komt het slice-dekkingsgat aan het oppervlak en hier voegt elke postmortem cases terug toe aan de golden dataset.
Wat dit niet oplost
Drie eerlijke beperkingen, zoals we ze in elke post in deze serie hebben gekaderd.
- Suite-drift is eindeloos werk. Regressietesten is infrastructuur, geen project. De golden dataset moet elk kwartaal opnieuw worden gestratificeerd, de judge moet elke week opnieuw worden gekalibreerd, de drempelbudgetten moeten na elke postmortem opnieuw worden afgesteld. Er is geen versie waarin je een suite uitlevert en wegloopt.
- Een perfect gekalibreerde judge is nog altijd een model. Spearman ρ = 0,74 tegen menselijke beoordelaars betekent dat ruwweg een kwart van de judge-oordelen afwijkt van de menselijke mediaan. Dat resterende meningsverschil is de ruisbodem op elke score. We tonen het expliciet in elk releaserapport; teams die vergeten dat het er is, worden er uiteindelijk door verrast.
- Closed-API-backings beperken hoeveel je kunt verifiëren. Met een closed-API-model meet de regressie-suite gedrag maar kan ze gewichtsherkomst niet verifiëren. Als je volledige reproduceerbaarheid nodig hebt — gereguleerde sectoren, geauditede deployments — zit de trade-off op de modelkeuze, niet op de suite.
Wat komt hierna
Deel 8, het laatste in deze serie, sluit de loop aan de binnenkant van CI. Waar deze post en deel 5 gingen over wat er bij de gates draait, gaat de volgende over de CI-laag die de kandidaten produceert die de gates überhaupt scoren — pre-merge-evaluatie, contract-tests voor prompt-templates, en hoe je de CI-vloot dimensioneert voor een 12-minuten-evaluatie-suite zonder het budget op te blazen. Het is de engineering-laag onder alles waarover we tot nu toe hebben geschreven.
FAQ
Wat is het verschil tussen LLM-evaluatie en LLM-regressietesten?
Evaluatie meet of een model op een tijdstip een kwaliteitsdrempel haalt, tegen een absolute rubric. Regressietesten meet of een kandidaat zich gedraagt zoals een bevroren basislijn, per slice, over meerdere dimensies. De basislijn is wat het regressietesten maakt — Divinci levert beide, en de regressie-modus pint (model_sha, prompt_sha, judge_sha, dataset_sha) vast, zodat een bewogen score identificeert welke invoer bewoog.
Hoeveel cases moet een golden dataset bevatten?
Minder dan je denkt, beter gestratificeerd dan je denkt. We hebben bruikbare regressiedekking uitgeleverd met 200 cases op vijf goed gedefinieerde slices en datasets van 5.000 cases gezien die alles misten wat ertoe deed omdat ze ongestratificeerd waren. Begin bij 200, gestratificeerd, en laat vervolgens de replay-emmer case voor case groeien vanuit postmortems.
Moet ik menselijke reviewers gebruiken of LLM-als-judge?
Allebei, met mensen die de judge kalibreren. Mensen kunnen het volume dat een release-cyclus-CI-gate moet scoren niet bijhouden. De judge vult het volume, de mensen kalibreren de judge — wekelijks gemeten met Spearman ρ ≥ 0,7. Beide afzonderlijk is een faalmodus.
Hoe test ik op niet-deterministische outputs?
Scoor de verdeling, niet de string. Scoor met een rubric die de judge kan toepassen over formuleringen heen, en draai elke invoer drie tot vijf keer op temperatuur > 0, zodat de slice-bewuste score over een verdeling van completions gaat in plaats van over één enkele sample. Verstrak de temperatuur alleen voor cases die echt deterministische output nodig hebben (gestructureerde-output-tool-calls, classificatie).
Welke metrics moet ik prioriteren voor de eerste CI-kwaliteitsgate?
Task completion en één safety-gate. Beide per slice. Meer dimensies toevoegen voordat de eerste twee gekalibreerd zijn, levert ruis op; teams die meer uitleveren, gate’en uiteindelijk meestal op de ruis. Voeg faithfulness daarna toe wanneer je retrieval aanzet; voeg latentie toe zodra de eerste twee stabiel zijn.
References
- Pan, Tianpan. "The Semver Lie: how a minor LLM update broke production." 29 april 2026. De benoemde 2026-faalmodus voor slice-bewuste regressie-analyse; geaggregeerde scores blijven vlak terwijl een slice met laag volume in stilte regresseert.
- Zheng et al. "Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena." arXiv:2306.05685. Empirisch bewijs dat sterke LLM-judges het op open taken eens zijn met menselijke beoordelaars op ongeveer interhumane-overeenstemmingsniveaus (≈ 80%), met gerapporteerde faalmodi die kalibreer-tegen-mensen-audits ontworpen zijn om op te sporen.
- Kirkpatrick et al. "Overcoming catastrophic forgetting in neural networks." PNAS / arXiv:1612.00796. Het fundamentele resultaat over catastrofaal vergeten in fijngestelde neurale netwerken — waarom een fijngesteld custom LLM moet worden regressie-getest op algeheel capaciteitsverlies, niet alleen op winst op de doeltaak.
- Amazon Web Services. "SageMaker Deployment Guardrails — blue/green deployments and canary monitoring." Het closed-API-contrast: gates op infrastructuur-metrics (latentie, errors, CPU) in plaats van op per-slice semantische kwaliteit.
- Spearman, C. "The proof and measurement of association between two things." American Journal of Psychology, 15(1):72–101, 1904. De rangcorrelatiecoëfficiënt die de slice-bewuste gate verankert — robuust tegen scoring-schaal-drift in de judge, wat de eigenschap was die we nodig hadden.
- DORA / Google Cloud. "Accelerate State of DevOps — change-failure-rate and time-to-restore-service metrics." De cross-industriële basislijn voor "hoe vaak veroorzaken deploys incidenten" en "hoe snel herstel je". Regressie-suites die bij de gate blokkeren verlagen de eerste metric; instant rollback ([deel 5](/nl/blog/automated-llm-ci-cd-pipelines-with-instant-rollback/)) verlaagt de tweede.
Ready to Build Your Custom AI Solution?
Discover how Divinci AI can help you implement RAG systems, automate quality assurance, and streamline your AI development process.
Get Started Today