Naar de inhoud
NLEN
Illustratie: Temperature en top-p calibreren voor determinisme

Temperature en top-p calibreren voor deterministische output

Door Ivo Donker — samengesteld met AI-ondersteuning (Claude & Gemini)

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:

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:

  1. 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.
  2. 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.
  3. 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.
Meetkader: De onderstaande tabel toont de verwachte kwalitatieve gedragslijnen per parameterconfiguratie. Dit dient als richtlijn voor calibratieprotocollen en niet als een vaste universele benchmarksituatie.
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:

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:

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:

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: