Decoding & Sampling: Temperature, Top-p & Inference-Time Control
How do decoding rules select a token from the model's probabilities?
The idea
Reshape the distribution, then draw from it: temperature sharpens or flattens the probabilities without ever changing their order, and top-p deletes the unlikely tail and renormalizes what is left.
Builds on Maximum Likelihood and Scaled Dot-Product Attention & Transformer Layers.
The picture
A language model produces a score, or logit, for each token in its vocabulary. Softmax turns those scores into probabilities, and decoding selects the next token. We apply temperature and top-p sampling to the same distribution: temperature changes how concentrated the probabilities are but never sets any to zero, and top-p keeps the most probable tokens until their total reaches and removes the rest. This notebook uses probabilities and softmax.
Greedy or sample. Greedy decoding always takes the most probable word, so the same prompt always gives the same text. Sampling draws a word in proportion to its probability, so an unlikely word is picked now and then. The figure's bars are the distribution a sample is drawn from.
Temperature. Before the softmax, divide every logit by a temperature . Below 1, the gaps between logits grow and the top word takes more of the probability; above 1, they shrink and the probability spreads out. The order never changes, and no word ever reaches zero.
Top-p. Then walk down the words from the most probable, keep them until their probabilities add up to , and delete the rest. The kept words are renormalized so they sum to 1 again. How many words survive depends on the shape of the distribution: few when the model is confident, many when it is not.
Decoding is not a cosmetic detail. It trades determinism against diversity, and it decides whether an unreliable tail word can be drawn at all.
From one token to a complete output
Did the model stop, or did we stop it?
A next-token probability is only one edge of a path. To find the chance of a whole output, multiply the probabilities of its actual draws—and keep the reason it ended.
This small example uses three tokens: A, B and EOS (end of sequence). The logits depend only on the previous token: one row applies at the start and one after each of A and B. This example is separate from the five-word figure above and the ten-token demo further down.
The maximum counts EOS. Drawing EOS ends the output, even on the last allowed step. Reaching the limit without EOS is a cutoff; no extra token is drawn. Try reducing the maximum from 2 to 1 first, then restore 2 and change top-p to 0.75.
- At the startAdraw probability 0.5
- After AEOSdraw probability 0.5
0.5 × 0.5 = 25% of all runs. Ended by drawing EOS.
Extracted answer: A under the rule below.
What counts as an answer here? Only a nonempty output that ends with EOS. Its last ordinary token is the answer: B → A → EOS means A. An output that is just EOS, and every cutoff, give no answer. This is the rule we chose for this example, not a rule for all models.
- EOS, answer A25%
- EOS, answer B6.25%
- EOS, empty25%
- Length limit, no answer43.75%
Total: 100%. The probability of cutoffs stays in this distribution. Discarding it and rescaling the rest would answer a different, conditional question.
Inspect the three next-token rows and every complete output
The logits are log(weights). Apply temperature, then top-p, separately after each history. Ties use A, B, EOS order; keep the first token that reaches the threshold. No top-k is applied.
| History | Weights | After temperature | After top-p |
|---|---|---|---|
| Start | 2, 1, 1 | 0.5, 0.25, 0.25 | 0.5, 0.25, 0.25 |
| Last token A | 1, 1, 2 | 0.25, 0.25, 0.5 | 0.25, 0.25, 0.5 |
| Last token B | 1, 2, 1 | 0.25, 0.5, 0.25 | 0.25, 0.5, 0.25 |
| Output | Probability | Ended by | Answer |
|---|---|---|---|
| EOS | 25% | EOS | None |
| A → A | 12.5% | length limit | None |
| A → B | 12.5% | length limit | None |
| A → EOS | 25% | EOS | A |
| B → A | 6.25% | length limit | None |
| B → B | 12.5% | length limit | None |
| B → EOS | 6.25% | EOS | B |
Use this distribution to choose an answer
Draw two independent outputs with these exact settings. Suppose A is the correct answer, but use a flawed ranker: B outranks A, which outranks no answer. Ties keep the first output. The ranking does not estimate correctness.
Within one output, multiply probabilities conditioned on its history; its tokens need not be independent. Independence is a separate assumption, made only between the two complete outputs.
- One draw answers A
- 25%
- Two draws contain A
- 43.75%
- The ranker returns A
- 40.625%
The middle quantity is coverage: 1 − (1 − qA)². The last requires at least one A and no B: (1 − qB)² − qNone². Here qA, qB and qNone are the probabilities of answer A, answer B and no answer found above. Every control change recomputes them.
For example, the pair A → EOS and B → EOS contains A, but the ranker returns B. Reversing the draw order does not repair that preference.
Continue to test-time compute to investigate coverage and selection under a budget. That lesson starts from a different, assumed distribution over four outputs (50, 25, 18 and 7 percent), not one derived from this decoder.
Every output is enumerated exactly from hand-picked logits; nothing is sampled from a model or measured. Real serving systems may apply further processing. Numbers are rounded for display.
The mathematics
Let be the logits for token at some step.
Temperature rescales logits
Temperature produces:
- Smaller sharpens (more deterministic).
- Larger flattens (more exploratory).
Nucleus (top-p) truncation deletes the tail, then renormalizes
Let be the smallest set of tokens whose probability mass is at least (after sorting by probability):
Then you sample from , the truncated and renormalized distribution.
This is why top-p changes behaviour: it changes the distribution you sample from (Holtzman et al., 2020, §3.1). Top-k sampling is the fixed-size version: it keeps the most probable tokens whatever their total probability (Fan et al., 2018).
From conditional draws to a terminal record
The optional sequence investigation uses a different,
hand-built model with tokens A, B and EOS (end of sequence). In that token order,
the logit weights are [2, 1, 1] at the start, [1, 1, 2] after A, and
[1, 2, 1] after B. A logit is the natural logarithm of its weight. Only the
last ordinary token affects the next row. Apply temperature first and then
top-p to that row, with ties in A, B, EOS order. There is no top-k filter.
Let be this transformed probability of token given history . Let be the maximum number of emitted tokens, including EOS. A record ends on its first EOS, or at tokens if none is EOS. For a record in this finite event space, its probability is
No history in the product contains an earlier EOS. In particular, a cutoff has no extra EOS factor. EOS drawn on step is still a sampled end. The exhaustive records sum to one, including cutoff mass. Filtering can make some records impossible; their probability is zero rather than missing.
At , A → EOS has probability . The second factor comes from the after-A row, not the start row. A → A has probability , and ends by cutoff.
- EOS: probability 1/4; ends by EOS; no answer because it is empty.
- A → EOS: probability 1/4; ends by EOS; answer A.
- B → EOS: probability 1/16; ends by EOS; answer B.
- A → A: probability 1/8; length limit; no answer.
- A → B: probability 1/8; length limit; no answer.
- B → A: probability 1/16; length limit; no answer.
- B → B: probability 1/8; length limit; no answer.
Our answer rule accepts only a nonempty EOS-ended record, using its last ordinary token as the answer. At , for example, both A → A → EOS and B → A → EOS contribute to answer A. Empty EOS and every cutoff have no answer under this rule. A consumer that accepts truncated text would need a different extraction rule; it cannot reuse these answer probabilities.
Write for the sums of over these three answer classes. At the default they are . For two independent records, stipulate that A is correct, but let a flawed ranker prefer B over A over no answer, breaking ties in favour of the first record. Then
The latter event is “no B, but at least one A.” Changing temperature, top-p or requires recomputing and these answer probabilities. Dropping cutoff records and rescaling would instead condition on not being cut off.
What comes from the source. Holtzman et al. §§3.1 and 3.3 define nucleus sampling and temperature; in §4.1 their generated passages end at an end-of-document token or a 200-token limit. The three-token example, the length convention, the answer rule and the ranker above are this page's own choices, not a reproduction of their experiment or of any provider's API.
Try it
First a worked example, then one to finish, then problems on your own. Check your answer before you look at the solution. Answers typed here are not kept when you leave.
1 · Worked example
Temperature 1, top-p 0.9, by hand
Logits for tea, coffee, water, milk, ink. Temperature , top-p . Which words can be drawn, and with what probabilities?
Scale. Divide by : the logits are unchanged.
Say the next step to yourself first.2 · Finish it
Turn the temperature down
Same logits, now at and with no filter. The first steps are done. What is tea's probability? Give three decimal places.
Scale. Divide by : .
Exponentiate. ; the total is .
- Your turn.
3 · On your own
The same p, a different nucleus
Same logits, top-p , but now . How many of the five words can be drawn?
4 · On your own
Which filter lets water through?
At , top-k with and top-p with keep the same three words. Now set . Which filter still lets water be drawn?
5 · Finish it
Raise the temperature, and a word comes back
Four words A, B, C, D have logits , chosen so that the exponentials and probabilities are exact fractions. Top-p is . At only A survives the filter. At , what is B's probability after the filter? Give a fraction or three decimal places.
At . The exponentials are , with total , so A has . That already reaches , so the nucleus is A alone.
At . Halve every logit. The exponentials are , with total , so the probabilities are .
- Your turn.
6 · On your own
Add the same number to every logit
Keep the four words at and , and add to every logit. What changes?
7 · Finish it
Change the filter; rebuild the answer probability
In the separate A/B/EOS example, keep temperature 1 and maximum 2 emitted tokens, but set top-p to 0.75. What is the probability of A → EOS? Explain both conditional factors, root-EOS mass and total cutoff mass. Why is this a new unconditional law, rather than the old law with cutoff runs discarded? You may use the figure.
Find the rows. The start row is and the after-A row is in A, B, EOS order.
Keep and rescale. Ties keep the earlier token. At the start, A and B reach ; after A, EOS and A reach .
- Your turn.
8 · On your own
Read the stop reason before extracting an answer
Under the last-token rule, what answer does A → B → EOS yield at limit 3? What does A → B yield at limit 2? Before reusing the answer probabilities in a downstream selector, what would you check about how each output stopped and how its answer was extracted? What do this toy's results not establish about a paper or real model? This is an optional self-check; the explanation and figure stay available.
The code
import numpy as np
def softmax(z):
z = z - z.max()
ez = np.exp(z)
return ez / ez.sum()
def top_p_filter(p, probs):
idx = np.argsort(-probs)
keep = np.zeros_like(probs, dtype=bool)
cum = 0.0
for i in idx:
keep[i] = True
cum += probs[i]
if cum >= p:
break
q = probs * keep
return q / q.sum()
rng = np.random.RandomState(0)
logits = np.array([3.0, 2.0, 1.0, 0.2, -0.5]) # 5 tokens
for tau, p in [(1.0, 1.0), (0.7, 0.9), (1.4, 0.9)]:
probs = softmax(logits / tau)
probs = top_p_filter(p, probs)
samples = rng.choice(len(probs), size=20000, p=probs)
counts = np.bincount(samples, minlength=len(probs)) / len(samples)
print("tau=", tau, "top_p=", p, "freqs=", np.round(counts, 3))
Enumerate every stopped record
This standard-library Python code lists every possible output directly: each
sequence of A and B tokens, with or without a final EOS. It does not sample or
call a model, and it runs on your machine, not in the page. max_tokens
includes EOS. The returned table keeps outputs whose probability is zero.
from itertools import product
from math import prod
TOKENS = ("A", "B", "EOS")
WEIGHTS = {"start": (2, 1, 1), "A": (1, 1, 2), "B": (1, 2, 1)}
def terminal_law(temperature=1, top_p=1, max_tokens=2):
if temperature not in (0.5, 1, 2):
raise ValueError("Unsupported temperature")
if top_p not in (0.5, 0.75, 1):
raise ValueError("Unsupported top_p")
if max_tokens not in (1, 2, 3):
raise ValueError("Unsupported max_tokens")
rows = {}
for context, weights in WEIGHTS.items():
# exp(log(weight) / temperature) = weight**(1 / temperature).
raw = [w ** (1 / temperature) for w in weights]
probabilities = [v / sum(raw) for v in raw]
order = sorted(range(3), key=lambda i: (-probabilities[i], i))
kept, mass = [], 0.0
for i in order:
kept.append(i)
mass += probabilities[i]
if mass >= top_p:
break
rows[context] = [probabilities[i] / mass if i in kept else 0.0
for i in range(3)]
events = []
for length in range(max_tokens):
events.extend(prefix + ("EOS",)
for prefix in product(("A", "B"), repeat=length))
events.extend(product(("A", "B"), repeat=max_tokens))
records = []
answers = {"A": 0.0, "B": 0.0, "none": 0.0}
for tokens in events:
factors = [rows["start" if i == 0 else tokens[i - 1]][TOKENS.index(token)]
for i, token in enumerate(tokens)]
probability = prod(factors)
stop = "EOS" if tokens[-1] == "EOS" else "length-limit"
answer = tokens[-2] if stop == "EOS" and len(tokens) > 1 else None
answers[answer or "none"] += probability
records.append(dict(tokens=tokens, probability=probability,
factors=factors, stop=stop, answer=answer))
# Enumerate both independent draws. The flawed ranker favours B over A.
rank = {None: 0, "A": 1, "B": 2}
covered = selected = 0.0
for first, second in product(records, repeat=2):
mass = first["probability"] * second["probability"]
covered += mass if "A" in (first["answer"], second["answer"]) else 0
winner = second if rank[second["answer"]] > rank[first["answer"]] else first
selected += mass if winner["answer"] == "A" else 0
assert abs(sum(r["probability"] for r in records) - 1) < 1e-12
return dict(records=records, answers=answers,
coverageA=covered, selectedA=selected)
if __name__ == "__main__":
for settings in ((1, 1, 2), (1, 0.75, 2), (1, 1, 1), (2, 1, 3)):
law = terminal_law(*settings)
print("temperature, top_p, max_tokens:", settings)
for record in law["records"]:
print(record)
print("Answer masses:", law["answers"])
print("A coverage / selected:", law["coverageA"], law["selectedA"])
Keep it
Can changing the temperature change which word is most likely? Why?
Answer from memory, then check
No. Temperature divides every logit by the same positive , which scales the gaps but keeps their order. It changes how much the top word leads, not which word leads.
What happens to the distribution as , and as ?
Answer from memory, then check
As every gap grows without limit and all the probability goes to the top word: sampling becomes greedy decoding. As the gaps vanish and every word tends to the same probability.
What exactly does top-p with keep, and what happens to the rest?
Answer from memory, then check
The smallest set of most probable words whose probabilities add up to at least 0.9. Every other word gets probability 0, and the kept probabilities are divided by their total so they sum to 1 again.
Why does top-p sometimes keep two words and sometimes four, at the same ?
Answer from memory, then check
Its size follows the shape of the distribution: a confident model reaches with few words, a flat one needs many. With the logits and it keeps two words at , three at and four at . Top-k always keeps .
Two words' logits differ by 1. At temperature , how many times likelier is the higher one?
Answer from memory, then check
: 7.39 at , 2.72 at , 1.65 at . The ratio depends only on the gap and , not on the other words, and renormalizing after top-p leaves it unchanged.
Why can a softmax subtract the largest logit before exponentiating?
Answer from memory, then check
Adding the same constant to every logit multiplies every exponential, and their total, by , which cancels. Probabilities depend only on differences between logits, so subtracting the maximum changes nothing except keeping the exponentials from overflowing.
Recalling an answer from memory makes it last longer than rereading it (Roediger and Karpicke, 2006). Add these 6 cards and they come back tomorrow, then after gaps of 3, 7, 16, 35 and 75 days while you still remember them. They stay in this browser only.
The edge
The arithmetic is exact; the right settings are not. Holtzman et al. (2020) showed that always choosing the likeliest words makes a language model's text bland and repetitive, while sampling from the whole distribution lets in the unreliable tail. Nucleus sampling was their answer to both, found by measuring text, not derived. The most probable output can be a poor one: for some translation models, exact search finds that the single most probable translation is often the empty one (Stahlberg and Byrne, 2019). Why the most probable text is so often not the best text is still argued. One proposal is that good text is typical rather than maximal, made of words about as surprising as the model expects on average (Meister et al., 2023). Which rule and which temperature suit a given task is still found by trying.