Temperature en top-p calibreren voor deterministische output
Bij het bouwen van evaluatiepijplijnen en geautomatiseerde extractietaken bepaalt de afstelling van sampling-parameters direct of een taalmodel betrouwbare, herhaalbare antwoorden levert. Wanneer een benchmark twee verschillende runs draait op dezelfde testset, moet het verschil in score het gevolg zijn van een inhoudelijke prompt- of modelwijziging, niet van willekeurige ruis in de token-selectie. In dit artikel bepalen we met welke meetopzet sampling-parameters gecalibreerd worden voor maximale voorspelbaarheid en reproduceerbaarheid.
Dit artikel onderscheidt zich nadrukkelijk van algemene overzichten over reproduceerbaarheid van AI-evaluaties door niet te focussen op de volledige testomgeving, maar specifiek in te zoomen op de wiskundige interactie tussen softmax-temperature, nucleus sampling (top-p), zaadwaarden (seeds) en floating-point non-determinisme op GPU-clusters. Waar fundamentele theorie over de wiskundige definities te vinden is in het achtergrondartikel over sampling-parameters zoals temperature en top-p, richt deze gids zich op concrete kwantitatieve meetprotocollen om variantie uit te bannen.
De interactie tussen temperature en top-p
Een taalmodel produceert per generatiestap een vector van ongegenereerde logit-waarden over het gehele vocabulaire. Voordat een token daadwerkelijk wordt geselecteerd, worden deze logits getransformeerd naar een waarschijnlijkheidsverdeling via de softmax-functie, geschaald door de parameter temperature (T). Wanneer T nadert naar 0,0, nadert de verdeling een scherpe piek: het token met de allerhoogste logit krijgt een waarschijnlijkheid van vrijwel 100 procent. Dit noemen we greedy decoding.
Nucleus sampling, oftewel top-p, grijpt in op een ander niveau: het sorteert alle tokens op aflopende kans en selecteert de kleinste verzameling tokens waarvan de cumulatieve waarschijnlijkheid de drempelwaarde p bereikt. Alle tokens buiten deze cumulatieve drempel worden afgesneden (hun effectieve kans wordt nul gesteld), waarna de resterende kansen worden genormaliseerd. Als temperature 0,0 staat ingesteld, heeft top-p in theorie geen effect meer, omdat de hoogste logit reeds alle waarschijnlijkheid naar zich toe trekt. In veel API-implementaties leidt een gelijktijdige manipulatie van beide waarden echter tot subtiele afrondingsfouten of onverwacht samplinggedrag als de gateway intern eerst filtert en daarna normaliseert.
Voor evaluaties en deterministische taken is de vuistregel: pas nooit beide knoppen tegelijk dynamisch aan. Kies ofwel voor pure greedy decoding (temperature 0,0), ofwel voor een gekalibreerde temperature in combinatie met een vaste top-p cutoff (top-p 1,0), tenzij er expliciet een afgeknotte distributie nodig is om zeldzame afwijkingen in logit-tails te onderdrukken.
Waarom temperature 0 toch variatie kan vertonen
Een veelvoorkomende aanname onder ontwikkelaars is dat temperature: 0 per definitie leidt tot 100 procent identieke output over herhaalde runs. In productieomgevingen met gehoste LLM-API's blijkt dit regelmatig niet het geval te zijn. Zelfs met greedy decoding zien we soms afwijkende woorden, andere leestekens of gewijzigde JSON-structuren tussen opeenvolgende calls met exact dezelfde payload.
Dit fenomeen kent drie technische hoofdoorzaken:
- Niet-associatieve floating-point optelling: Moderne GPU-architecturen voeren matrixvermenigvuldigingen parallel uit via gevectoriseerde floating-point operaties (FP16, BF16 of FP8). Omdat floating-point optelling niet strikt associatief is (waarbij de som van a en b plus c niet exact gelijk hoeft te zijn aan a plus de som van b en c door afrondingsverschillen op het laagste bitniveau), kan een wisselende volgorde van parallelle threads leiden tot minieme fracties verschil in de uiteindelijke logit-waarde. Als twee concurrerende tokens vrijwel identieke kansen hebben, kan dit minimale afrondingsverschil de rangorde van de greedy selectie doen kantelen.
- Mixture-of-Experts (MoE) routering en dynamische batching: Bij modellen die gebruikmaken van MoE-architecturen worden tokens dynamisch gerouteerd naar verschillende expert-netwerken. Als de serving-engine gebruikmaakt van dynamic batching, hangt de exacte samenstelling van de batch af van concurrerende verzoeken op de cluster. Tokens kunnen bij zware belasting over andere experts worden verdeeld of via fallback-paden lopen, wat minieme numerieke fluctuaties veroorzaakt.
- Quantization- en kernel-variatie: Grote modelproviders draaien hun workloads over heterogene GPU-vloten. Een verzoek kan de ene seconde landen op een cluster met een specifieke Triton-kernel en de volgende seconde op hardware met een andere optimalisatieslag, wat leidt tot kleine variaties in de softmax-uitkomst.
Kwantitatieve meetopzet: de determinisme-index
Om vast te stellen hoe deterministisch een model reageert op specifieke parameterinstellingen, moeten we een reproduceerbare meetopzet hanteren. We meten de consistentie door dezelfde set prompts N keer aan te roepen over een vast tijdsinterval en de paarsgewijze gelijkheid van de gegenereerde token-sequenties te berekenen.
We definiëren hiervoor drie concrete metrieken:
- Exact Match Rate (EMR): Het percentage runs waarin de output van een run karakter-voor-karakter en token-voor-token identiek is aan de basisrun.
- Levenshtein Similarity (LS): De genormaliseerde bewerkafstand tussen tekstsequenties, die kwantificeert hoe dicht niet-identieke outputs bij elkaar liggen op een schaal van 0 tot 1.
- Semantic Cosine Stability (SCS): De cosinusovereenkomst tussen de vector-embeddings van de gegenereerde teksten om te controleren of de feitelijke betekenis verschuift bij kleine tekstuele mutaties.
| Configuratie (T, top-p, zaadwaarde) | Verwachte Exact Match Rate | Levenshtein-stabiliteit | Spreidingsgraad | Typische toepassing |
|---|---|---|---|---|
| Temperature 0,0 · Top-p 1,0 · Vaste zaadwaarde | Zeer hoog (nagenoeg stabiel, minieme GPU-jitter mogelijk) | Uitzonderlijk hoog (bijna 1,0) | Verwaarloosbaar | JSON-extractie, Classificatie, Regressietests |
| Temperature 0,2 · Top-p 0,9 · Vaste zaadwaarde | Matig tot hoog (kleine tekstvariaties) | Hoog | Gering | Code-generatie met alternatieven |
| Temperature 0,7 · Top-p 0,95 · Geen zaadwaarde | Zeer laag tot nul (unieke woordkeuzes) | Matig | Aanzienlijk | Creatieve teksten, Brainstorming |
| Temperature 1,0 · Top-p 1,0 · Geen zaadwaarde | Volledig afwezig (maximale verdelingsspreiding) | Laag | Maximaal | Exploratie van zeldzame woordcombinaties |
Bij het uitvoeren van dergelijke analyses is het noodzakelijk om de statistische betrouwbaarheid te borgen door voldoende steekproeven te nemen. Zie het fundament over statistiek voor LLM-evaluaties om te berekenen hoeveel herhalingen per prompt vereist zijn om toevallige GPU-jitter betrouwbaar te onderscheiden van structurele parameter-effecten.
Stappenplan voor het calibreren van sampling-parameters
Om een modelconfiguratie voor een specifieke pipeline te calibreren, doorlopen we een systematisch protocol van vier stappen. We leggen alle omgevingsfactoren vast voordat we conclusies trekken over de optimale instellingen.
Stap 1: Isoleren van de baseline via greedy sampling
Begin elke calibratieronde door de parameter temperature op 0.0 te zetten en top-p op 1.0. Als de provider een zaadwaarde ondersteunt (zoals de seed parameter), zet deze dan vast op een constante integer (bijvoorbeeld 42). Voer de complete evaluatieset minimaal 10 keer uit over een tijdsbestek van 24 uur om piekuren en wisselende GPU-nodes mee te wegen.
Stap 2: Bepalen van de tolerantiegrens voor de use-case
Niet elke toepassing vereist een EMR van 100 procent. Bepaal vooraf wat de acceptabele foutmarge is:
- Strikte schema-extractie: Vereist 100 procent syntactische geldigheid. Hierbij mag de woordkeuze in vrije tekstvelden iets variëren zolang de JSON-parser zonder fouten valideert. Gebruik altijd gevalideerde interfaces zoals beschreven in de handleiding over betrouwbare structured output en JSON.
- Tekstclassificatie en labeling: Vereist 100 procent label-consistentie. Een kleine variatie in de redenering (Chain-of-Thought) is acceptabel mits het uiteindelijke categorielabel ongewijzigd blijft.
- RAG-synthese: Vereist semantische stabiliteit met een hoge embedding-overeenkomst. Kleine synoniemwisselingen zijn toegestaan zolang er geen feitelijke hallucinaties optreden.
Stap 3: Het testen van top-k en top-p drempelwaarden
Als een model bij temperature 0,0 toch drift vertoont door logit-ties (twee tokens met vrijwel gelijke kans), test dan een combinatie met een strakke top-p drempel (zoals top-p 0,85) of top-k filtering (zoals k gelijk aan 1 tot 5). Hiermee dwingt men de decoder om de staart van de waarschijnlijkheidsverdeling rigoureus af te kappen voordat parallelle floating-point operaties de rangorde kunnen beïnvloeden.
Stap 4: Vastleggen in geautomatiseerde regressietesten
Zodra de optimale configuratie is vastgesteld, wordt deze als onveranderlijke configuratie opgeslagen in de testsuite. Wijzigingen in model-checkpoints of provider-routing worden hierdoor direct zichtbaar zodra de EMR onder de gedefinieerde drempelwaarde zakt.
Voorbeeldcode: reproduceerbaarheid en variantie meten in Python
Het onderstaande Python-script toont hoe we de variantie en de Exact Match Rate van een model-endpoint geautomatiseerd kunnen kwantificeren over meerdere iteraties. Het script voert herhaalde calls uit, vergelijkt de outputs en rapporteert de stabiliteit.
import hashlib
from typing import List, Dict, Any
def bereken_determinisme_metrics(outputs: List[str]) -> Dict[str, Any]:
"""
Kwantificeert de mate van determinisme over een lijst van gegenereerde teksten.
"""
if not outputs:
return {"error": "Geen data"}
totaal = len(outputs)
unieke_hashes = set()
hash_frequenties: Dict[str, int] = {}
for tekst in outputs:
# Genereer een SHA-256 hash van de genormaliseerde tekst
genormaliseerd = tekst.strip()
h = hashlib.sha256(genormaliseerd.encode("utf-8")).hexdigest()
unieke_hashes.add(h)
hash_frequenties[h] = hash_frequenties.get(h, 0) + 1
meest_voorkomende_aantal = max(hash_frequenties.values())
exact_match_rate = (meest_voorkomende_aantal / totaal) * 100.0
return {
"totaal_runs": totaal,
"unieke_varianten": len(unieke_hashes),
"exact_match_rate_pct": round(exact_match_rate, 2),
"is_volledig_deterministisch": len(unieke_hashes) == 1
}
# Simulatie van een testset-run over 5 opeenvolgende calls
test_antwoorden = [
'{"status": "succes", "categorie": "financieel", "score": 0.95}',
'{"status": "succes", "categorie": "financieel", "score": 0.95}',
'{"status": "succes", "categorie": "financieel", "score": 0.95}',
'{"status": "succes", "categorie": "financieel", "score": 0.95}',
'{"status": "succes", "categorie": "financieel", "score": 0.95}'
]
resultaat = bereken_determinisme_metrics(test_antwoorden)
print(f"Exact Match Rate: {resultaat['exact_match_rate_pct']}%")
print(f"Aantal varianten: {resultaat['unieke_varianten']}")
Wanneer we dit script integreren in continue integratietests, worden afwijkingen direct gelogd. Als het endpoint onder belasting plotseling verschillende outputs retourneert voor dezelfde invoer, kan dit duiden op een gewijzigde backend-routering bij de API-leverancier. Bekijk voor een bredere analyse van concurrency-effecten het artikel over JSON-validiteit evalueren bij belasting.
Nederlandstalige valkuilen bij sampling-variatie
Bij het evalueren van Nederlandstalige prompts treden specifieke taalkundige fenomenen op die de gevoeligheid voor sampling-parameters vergroten ten opzichte van het Engels. Dit heeft te maken met de representatie van de Nederlandse taal in de tokenizers van de meeste grote modellen.
Ten eerste hebben Nederlandse woorden vaker meerdere subtokens per woord dan Engelse termen. Samengestelde woorden zoals aansprakelijkheidsverzekering of uitvoeringsbesluit worden opgeknipt in 3 tot 5 afzonderlijke tokens. Als de temperature net iets boven 0,0 ligt (bijvoorbeeld temperature 0,3), cumuleert de onzekerheid over opeenvolgende subtokens. Een kleine afwijking in het tweede subtoken dwingt het model om een geheel ander samengesteld woord af te maken, wat leidt tot een disproportioneel grote bewerkafstand.
Ten tweede zijn formele en informele aanspreekvormen (zoals u versus je/jij) in het Nederlands vaak semantisch equivalent, waardoor hun respectievelijke logits zeer dicht bij elkaar liggen. Bij de minste floating-point jitter kan het model halverwege een alinea wisselen van aanspreekvorm:
- Run 1 (temperature 0): "U kunt het formulier invullen en opsturen naar uw adviseur."
- Run 2 (temperature 0 onder GPU-jitter): "Je kunt het formulier invullen en opsturen naar je adviseur."
Hoewel de feitelijke inhoud identiek is, resulteert dit in een Exact Match Rate van nul procent. In testframeworks die prompts analyseren op consistentie is het daarom verstandig om systeemprompts expliciet vast te zetten op één specifieke stijlvorm. Zie het onderzoek over systeemprompt-variatie en consistentie meten voor technieken om stijlschommelingen contractueel in te kaderen.
De rol van random seeds en client-side caching
Verschillende grote API-providers bieden een seed parameter aan in hun REST-interfaces. Het meesturen van een vast getal (zoals seed: 1337) instrueert de backend om te streven naar deterministische sampling binnen dezelfde hardwareconfiguratie. Providers koppelen hier vaak een system_fingerprint response-header aan terug.
Wanneer de system_fingerprint tussen twee aanroepen verandert, geeft de provider daarmee aan dat de backend-infrastructuur (zoals model-weights, kernelversies of quantisatieniveaus) is gewijzigd. In dat geval is het verlies van determinisme verklaarbaar en ligt de oorzaak niet in de sampling-parameters zelf. Voor acceptatietesten in productieomgevingen is het monitoren van deze vingerafdruk een essentieel onderdeel; raadpleeg het overzicht over acceptatietests inrichten voor niet-deterministische output voor organisatorische kaders rond model-releases.
Daarnaast is client-side caching het meest effectieve instrument om determinisme te garanderen waar de API tekortschiet. Door een hash te genereren van de payload (inclusief modelversie, prompt, temperature, top-p en seed) kunnen identieke verzoeken lokaal worden afgehandeld zonder netwerk- of GPU-overhead. Dit reduceert zowel de latentie als de tokenkosten tot nul voor herhaalde benchmarkvragen.
Kosten en rekentijd van calibratietests
Het systematisch calibreren van sampling-parameters brengt operationele kosten met zich mee, omdat elke prompt tientallen keren moet worden geëvalueerd over verschillende parametercombinaties. Om het budget onder controle te houden, kan men werken met een getrapte testmatrix.
Een standaard calibratiematrix voor een dataset van 100 testvragen ziet er als volgt uit:
- Fase 1 (Grove filtering): 100 vragen maal 3 configuraties (temperature 0,0, 0,2 en 0,7) maal 3 herhalingen resulteert in 900 API-aanroepen. Hiermee wordt de algemene spreiding en gevoeligheid in kaart gebracht.
- Fase 2 (Fijnafstelling): De 20 meest volatiele prompts uit fase 1 worden geselecteerd voor diepgaande analyse: 20 vragen maal 5 top-p variaties (tussen 0,80 en 1,00) maal 10 herhalingen levert 1.000 API-aanroepen op.
In totaal vergt een degelijke calibratie ongeveer 1.900 verzoeken. Bij een gemiddelde prompt-lengte van 500 input-tokens en 200 output-tokens verbruikt dit protocol circa 950.000 input-tokens en 380.000 output-tokens. Door deze test éénmalig per kwartaal of bij grote model-upgrades uit te voeren, voorkomt men honderden uren aan debugtijd in downstream applicaties.
Conclusie en checklist voor productie
Deterministische output van taalmodellen is geen vanzelfsprekendheid, maar het resultaat van zorgvuldige parametercalibratie en infrastructurele controle. Door temperature, top-p en zaadwaarden systematisch te testen en vast te leggen, bouwt men evaluaties en pipelines die bestand zijn tegen willekeurige ruis.
Gebruik de volgende checklist vóór het in productie nemen van een deterministische pipeline:
- Stel
temperaturein op0.0voor extractie, JSON en kwantitatieve evaluaties. - Zet
top-pop een vaste waarde (standaard1.0bij temperature 0, of0.9bij lichte sampling) en vermijd het gelijktijdig wijzigen van beide variabelen. - Stuur altijd een expliciete, constante
seedmee indien ondersteund door de provider. - Log de
system_fingerprintbij elke API-call om infrastructurele wijzigingen direct te detecteren. - Definieer duidelijke evaluatiemetrieken (Exact Match Rate voor code en JSON, Semantic Cosine Stability voor vrije tekstgeneratie).
- Houd rekening met Nederlandse taaleigenschappen zoals samengestelde woorden en aanspreekvormen bij het vaststellen van tolerantiegrenzen.


