Skip to content
intermediate Phase 3 · LLM API Fundamentals

Sampling Parameters and Determinism

Tune temperature, top_p, and seed to balance creativity, consistency, and control.

40m
0 problems
Topic Progress 0%

What Temperature Does to the Distribution

A ticket classifier returns billing for "charged twice for invoice 88" on Monday and other on Tuesday for the same string. The prompt never changed. The fix is not in the prompt: sampling ran with temperature left at its default of 1.0, and the runner-up token was close enough to win a coin flip somewhere in the tail.

To see why, follow one token from the model to the wire:

raw logits  -->  penalties  -->  / temperature  -->  top_p filter  -->  sampled token
 (vocabulary scores)      (repeat control)    (reshapes mass)   (cuts the tail)

The model ends every step with a score — a logit — for every token in the vocabulary. Softmax turns those scores into probabilities, and temperature enters between the two: each logit is divided by T before the softmax runs.

p(i) = exp(z_i / T) / sum(exp(z_j / T))
  • T < 1 divides the logits down, compressing the gaps and pushing mass toward the winner.
  • T = 1 leaves the distribution exactly as the model produced it.
  • T > 1 widens the gaps' effect in reverse, flattening toward uniform.

Worked example, three candidate tokens with logits [4.0, 2.0, 1.0]:

Token Logit p at T=1.0 p at T=0.5
billing 4.0 0.844 0.980
other 2.0 0.114 0.018
bug 1.0 0.042 0.002
T = 1.0   billing ████████████████████ 84%   other ██ 11%    bug █ 4%
T = 0.5   billing ████████████████████████████ 98%  other ▏2%   bug ▏0.2%

The runner-up drops from 11% to 1.8% — and this is per token, hundreds of times per answer. That 11% is where a classification label flips and where a summary wanders off topic; turning temperature down starves it.

reply = client.chat.completions.create(
    model="gpt-4o-mini",
    temperature=0,        # greedy: always take the argmax
    messages=[{"role": "user", "content": "Ticket: charged twice for invoice 88"}],
)
print(reply.choices[0].message.content)

Input: Ticket: charged twice for invoice 88 with a classify-only system prompt.

Output: billing — and the same output on the next 50 runs.

Temperature 0 is the right default for extraction, classification, and any branch that feeds an if statement. Two caveats: greedy sampling still fails on ambiguous inputs (it picks one label confidently, not the correct one), and temperature 0 is stable rather than bit-forced — provider-side model updates can move the argmax. Reproducibility beyond that is a seed question, taken up at the end.

top_p, Penalties, and the One-Knob Rule

Temperature reshapes the whole distribution. top_p does something narrower: it discards the tail.

Nucleus sampling sorts tokens by probability and keeps the smallest set whose cumulative probability reaches p. At top_p=0.9, if billing holds 60% and other holds 30%, sampling happens between those two only — every token below the line is impossible for this step, however the probabilities were shaped.

Every knob, and the job each one actually does:

Parameter Mechanism Move it when Watch out
temperature Divides logits before softmax; reshapes all masses Task is generative and you want variety or stability Default 1.0; 0 for extraction; above ~1.3 answers drift
top_p Cuts the lowest-probability tail to a mass threshold You want variety but with a hard floor on coherence Keep at 1.0 (or 0.9–1.0) unless nucleus filtering is the point
presence_penalty Flat penalty on any token already produced Repetitive content: you want the model to switch topics Values beyond ~1.0 start removing necessary terms
frequency_penalty Penalty grows with each occurrence of a token Literal loops: the same word or phrase repeating Scale with repetition count, so it fixes loops faster than presence
seed Requests reproducible sampling for identical inputs Tests, evals, bug reports that must reproduce Best effort, not a contract — see the next chapter

The one-knob rule. Temperature and top_p reshape the same distribution in overlapping ways. Set temperature=1.2 and top_p=0.7 together and a bad output cannot be attributed to either — you have two unmeasured variables in one experiment. Vary one, hold the other at its default, and every A/B run of your prompt tells you something.

reply = client.chat.completions.create(
    model="gpt-4o-mini",
    temperature=0.7,
    top_p=1.0,               # left alone: temperature is today's variable
    frequency_penalty=0.3,   # each repeat costs more than the last
    messages=[{"role": "user",
               "content": "Summarize in two sentences: our migration guide"},
    ],
)
print(reply.choices[0].message.content)

Input: a migration guide that makes every draft say "seamless migration" four times.

Output: two sentences, no phrase repeated — the third occurrence would have been penalized three times as hard as the first.

Penalties apply to tokens the model has already produced in this response, not to your prompt, so they cannot corrupt your instructions. presence_penalty fires once per distinct token — good for topic breadth; frequency_penalty accumulates — good for killing loops. Negative values do the opposite and encourage re-use, which is occasionally what a stylistic echo needs.

Seeds, Repeats, and What Cannot Be Frozen

The eval suite fails on CI, passes locally, and the diff shows two different labels for one fixed prompt. Non-determinism in tests is not a flake to rerun away — it is a parameter you failed to set.

def run_once() -> str:
    reply = client.chat.completions.create(
        model="gpt-4o-mini-2024-07-18",   # pin a snapshot, not a moving alias
        temperature=0.7,
        seed=42,                          # best-effort reproducible sampling
        messages=[{"role": "user", "content": "Name a metropolis. One word."}],
    )
    return reply.choices[0].message.content

print(run_once())     # Osaka
print(run_once())     # Osaka

Input: the same prompt twice.

Output: Osaka / Osaka — and the same again tomorrow, as long as nothing upstream moves.

A seed requests that the provider reproduce the same sampling choices for identical inputs. What it does not do:

  • Survive model updates. A snapshot alias like gpt-4o-mini can be repointed; weights change, probabilities change, and the seed reproduces nothing. Pin the dated snapshot id.
  • Force bit-identical outputs. Server-side batching, floating-point reduction order, and replica routing mean identical requests can, rarely, diverge. Where a provider exposes a fingerprint of the running system (OpenAI returns system_fingerprint), record it next to the result — a changed fingerprint invalidates the comparison.
  • Fix the prompt side. If your input contains a timestamp, a retrieval hit, or a tool result that varies, the seed is irrelevant: determinism requires identical inputs first.

The discipline this buys, layer by layer:

stable output = pinned model snapshot
              + identical input (no timestamps, no live retrieval)
              + seed set
              + temperature controlled for the task
              + fingerprint recorded

Assertions still belong on structure — the label is one of three enums, the JSON parses, the required keys exist — rather than on exact strings, because exact-string equality is the assertion that fails the day the provider ships a patch. Offline Eval Harness builds suites on that assumption, and Regression Suites covers what to do when a run does move. Determinism governs the content of the answer; whether the answer arrives all at once or in fragments is Streaming Responses and Time-to-First-Token.

Quiz

1. A classification prompt flips between two labels run to run. Temperature is at its default 1.0. What does lowering it toward 0 do?

Question 1 options

2. You want more varied brainstorming ideas but keep answers coherent. How should you change the knobs?

Question 2 options

3. A summary repeats the same phrase eight times in one paragraph. Which parameter targets that behavior directly?

Question 3 options

4. Two runs with seed=42 produce different outputs. Which explanation is most likely?

Question 4 options

Flashcards

Question

What does temperature actually change?

Answer

It divides logits before softmax. Below 1 it compresses gaps and concentrates mass on the top tokens; at 1 the model's distribution passes through unchanged; above 1 it flattens toward uniform.

Question

What is top_p nucleus sampling?

Answer

Keep the smallest set of tokens whose cumulative probability reaches p and sample only among them. p=1.0 disables the cut; lower p discards the tail entirely rather than just down-weighting it.

Question

presence_penalty vs frequency_penalty?

Answer

presence: flat penalty on any token already produced — pushes topic shifts. frequency: penalty scales with occurrence count — kills literal repetition loops. Both apply to generated tokens, not your prompt.

Question

Why vary only one sampling knob at a time?

Answer

temperature and top_p reshape the same distribution. Changing both in one run makes any output difference unattributable — one variable per experiment, the other held at its default.

Question

What does a seed guarantee, and what breaks it?

Answer

Best-effort reproduction of sampling choices for identical inputs on the same model snapshot. Model updates, changed inputs (timestamps, live retrieval), and provider-side batching all break it — pin the snapshot and record the fingerprint.

Revision Notes

Key Takeaways

  • 1. Temperature divides logits before softmax — lower concentrates on the argmax, higher flattens toward uniform, per token and hundreds of times per answer
  • 2. top_p cuts the tail instead of reshaping it; temperature and top_p overlap, so change one and hold the other
  • 3. frequency_penalty scales with repetition count while presence_penalty fires once — different tools for loops versus topic breadth
  • 4. A seed plus a pinned snapshot plus identical inputs is the reproducibility contract, and even that is best effort
  • 5. Assertions in evals belong on structure, because exact-string equality breaks on any provider-side patch

Interview Tips

  • • Be ready to derive what temperature does to logits — an interviewer asking 'what happens at T=0.1' wants the softmax story, not 'it's less random'
  • • Have a crisp one-liner for the one-knob rule: two changed variables, no attributable experiment
  • • Expect the loop-repetition question: name frequency_penalty, say how it accumulates, and contrast it with presence_penalty
  • • For the determinism question, give the full stack: pinned snapshot, identical input, seed, fingerprint, structural assertions

Cheat Sheet

Sampling Parameters and Determinism — Cheat Sheet

Pipeline for one token

logits --> presence/frequency penalties --> / temperature --> top_p cut --> sample

Parameter table

Knob Effect Setting rule
temperature Divides logits before softmax 0 for classification/extraction · 0.2–0.7 typical generative · 0.7–1.0 creative · >1.3 risks drift
top_p Keeps only the smallest set reaching cumulative mass p Leave at 1.0 unless nucleus filtering is deliberate
presence_penalty Flat penalty per distinct token already generated 0.3–1.0 to force topic variety
frequency_penalty Penalty grows with occurrence count 0.2–0.5 to break repetition loops
seed Reproducible sampling attempt Set in tests; pair with a pinned snapshot id

Working example

client.chat.completions.create(
    model="gpt-4o-mini-2024-07-18",
    temperature=0,        # argmax: stable labels
    messages=[...],
)
# generative: temperature=0.7, top_p=1.0, seed=42

Numbers worth memorizing

  • logits [4.0, 2.0, 1.0] → p = 0.844 / 0.114 / 0.042 at T=1, and 0.980 / 0.018 / 0.002 at T=0.5
  • the tail you cut at T=0.5 is the tail that flips a label

Determinism checklist

  1. Pin a dated model snapshot, never a moving alias
  2. Identical input — no timestamps, no live retrieval inside the prompt
  3. seed set, temperature fixed
  4. Record system_fingerprint when the API returns one
  5. Assert on structure (enum membership, parseable JSON), not exact strings

Continue Learning

Before You Start

  • No prerequisites listed.

Next Topics

Related Reading