Skip to the solution
MediumAI Engineering14 min read

How do temperature, top-p and other sampling parameters affect output?

722 views

The problem

Question presented to candidate: "When you call an LLM API you can set temperature, top-p and a few other sampling knobs. What does each one actually do to the output, and how would you set them for, say, data extraction versus brainstorming?"

What a strong answer should cover:

  • The model outputs logits for every token; sampling parameters only change how the next token is chosen from that distribution, not what the model knows
  • Temperature divides the logits before softmax: below 1 sharpens toward the top token, above 1 flattens and gives rare (often junk) tokens more mass; 0 means greedy
  • Truncation methods: top-k keeps a fixed number of candidates, top-p (nucleus) keeps the smallest set whose probability adds up to p, min-p keeps tokens above a fraction of the top token probability; the order of truncation and temperature matters
  • Frequency and presence penalties (and logit bias) edit logits based on what was already generated or on explicit token IDs, to reduce repetition or ban tokens
  • Practical settings: low or zero temperature for extraction, classification and code; moderate for chat; higher plus truncation for creative work; change one knob at a time; temperature 0 is not fully deterministic; newer reasoning-style models may reject these parameters

Code / implementation expected: Optional โ€” implementing temperature, top-p and penalties on a small logits vector and showing their effect is a strong signal.

  • temperature
  • top-p
  • sampling
  • inference

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

14 min read ยท 12 sections

Read the code

One logits vector through temperature, top-k, top-p, min-p and repetition penalties
// One fixed set of next-token logits, pushed through the sampling pipeline a
// serving engine runs on every step: penalties -> temperature -> softmax ->
// top-k / top-p / min-p truncation -> renormalise -> draw. The logits stand
// in for one forward pass of a model after the prompt "The weather today is".
const vocab = ["sunny", "cloudy", "rainy", "warm", "nice", "cold", "purple", "banana"];
const logits = [3.0, 2.5, 2.0, 1.5, 1.2, 0.8, -1.0, -2.5];
const JUNK = new Set(["purple", "banana"]);

function softmax(ls, T) {
  const m = Math.max(...ls.map(([, x]) => x));
  const e = ls.map(([w, x]) => [w, Math.exp((x - m) / T)]);
  const s = e.reduce((a, [, x]) => a + x, 0);
  return e.map(([w, x]) => [w, x / s]).sort((a, b) => b[1] - a[1]);
}

function distribution(o) {
  let l = vocab.map((w, i) => {                          // OpenAI-style penalties
    const c = (o.counts && o.counts[w]) || 0;
    return [w, logits[i] - c * (o.freq || 0) - (c > 0 ? o.pres || 0 : 0)];
  });
  if (!o.T) {                                            // temperature 0 = greedy
    const best = l.reduce((a, b) => (b[1] > a[1] ? b : a));
    return [[best[0], 1]];
  }
  // Truncation looks at the distribution at temperature T, unless the engine
  // is configured to truncate first and apply temperature last.
  let d = softmax(l, o.temperatureLast ? 1 : o.T);
  if (o.k) d = d.slice(0, o.k);                          // top-k: keep the k best
  if (o.p) {                                             // top-p: smallest set with mass >= p
    let acc = 0, n = 0;
    while (n < d.length && acc < o.p) acc += d[n++][1];
    d = d.slice(0, n);
  }
  if (o.minP) d = d.filter(([, p]) => p >= o.minP * d[0][1]); // min-p: relative to the top token
  const keep = new Set(d.map(([w]) => w));
  return softmax(l.filter(([w]) => keep.has(w)), o.T);   // renormalise survivors at T
}
const show = (d) => d.map(([w, p]) => w + "=" + p.toFixed(3)).join(" ");

for (const T of [0.2, 0.7, 1.0, 1.5, 3.0]) {
  const d = distribution({ T });
  const junk = d.filter(([w]) => JUNK.has(w)).reduce((a, [, p]) => a + p, 0);
  console.log("T=" + T.toFixed(1) + "  top3: " + show(d.slice(0, 3)) + " | P(purple or banana)=" + junk.toFixed(4));
}
console.log("T=0 (greedy) -> " + distribution({ T: 0 })[0][0]);

const cfgs = [
  ["T=1.0 top_k=3", { T: 1.0, k: 3 }],
  ["T=1.0 top_p=0.9", { T: 1.0, p: 0.9 }],
  ["T=3.0 top_p=0.9", { T: 3.0, p: 0.9 }],
  ["T=1.0 min_p=0.2", { T: 1.0, minP: 0.2 }],
  ["T=3.0 min_p=0.2", { T: 3.0, minP: 0.2 }],
  ["min_p=0.2, T=3 last", { T: 3.0, minP: 0.2, temperatureLast: true }],
];
console.log("candidates kept:");
for (const [name, o] of cfgs) {
  const d = distribution(o);
  console.log("  " + name.padEnd(20) + d.length + " tokens: " + d.map(([w]) => w).join(" "));
}

let seed = 42;
const rand = () => { seed = (seed * 48271) % 2147483647; return seed / 2147483647; };
function draw(d) {
  const r = rand();
  let acc = 0;
  for (const [w, p] of d) { acc += p; if (r < acc) return w; }
  return d[d.length - 1][0];
}
console.log("10000 seeded draws:");
for (const [name, o] of [["T=1.0", { T: 1.0 }], ["T=3.0", { T: 3.0 }], ...cfgs.slice(2, 3), ...cfgs.slice(4)]) {
  seed = 42;
  const d = distribution(o), tally = {};
  for (let i = 0; i < 10000; i++) { const w = draw(d); tally[w] = (tally[w] || 0) + 1; }
  const junk = (tally.purple || 0) + (tally.banana || 0);
  console.log("  " + name.padEnd(20) + "sunny=" + (tally.sunny || 0) + " distinct=" + Object.keys(tally).length + " junk=" + junk);
}

const counts = { sunny: 3, warm: 1 };      // already generated: "sunny sunny sunny warm"
for (const [name, o] of [["no penalty", {}], ["presence=0.5", { pres: 0.5 }], ["frequency=0.5", { freq: 0.5 }], ["both=0.5", { freq: 0.5, pres: 0.5 }]]) {
  const d = distribution({ T: 1.0, counts, ...o });
  console.log("penalty " + name.padEnd(14) + "top3: " + show(d.slice(0, 3)));
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 34 of 83 in AI engineering

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextMedium

How do you design human-in-the-loop approval for agent actions?

Continue