LeetLLM
My PlanLearnGlossaryTracksPracticeBlog
LeetLLM

Your go-to resource for mastering AI & LLM systems.

Product

  • Learn
  • Glossary
  • Tracks
  • Practice
  • Blog
  • RSS

Legal

  • Terms of Service
  • Privacy Policy

© 2026 LeetLLM. All rights reserved.

All Topics
Your Progress
0%

0 of 196 articles completed

🛠️Computing Foundations0/9
Git, Shell, Linux for AIDocker for Reproducible AIPython for AI EngineeringNumPy and Tensor ShapesCUDA for ML TrainingMPS & Metal for ML on MacData Structures for AISQL and Data ModelingAlgorithms for ML Engineers
📊Math & Statistics0/9
Gradients and BackpropVectors, Matrices & TensorsLinear Algebra for MLAdam, Momentum, SchedulersProbability for Machine LearningBayesian Inference from EvidenceStatistics and UncertaintyDistributions and SamplingHypothesis Tests, Intervals, and pass@k
📚Preparation & Prerequisites0/13
Neural Networks from ScratchCNNs from ScratchTraining & BackpropagationSoftmax, Cross-Entropy & OptimizationRNNs, LSTMs, GRUs, and Sequence ModelingAutoencoders and VAEsThe Transformer Architecture End-to-EndLanguage Modeling & Next TokensFrom GPT to Modern LLMsPrompt Engineering FundamentalsCalling LLM APIs in ProductionFirst AI App End-to-EndThe LLM Lifecycle
🧮ML Algorithms & Evaluation0/15
Linear Regression from ScratchLogistic Regression and MetricsDecision Trees, Forests, and BoostingReinforcement Learning BasicsValidation and LeakageStatistical Learning and GeneralizationConformal Prediction and UncertaintyClustering and PCAProbabilistic Generative ModelsCore Retrieval AlgorithmsDecoding AlgorithmsExperiment Design and A/B TestingCausal Inference and CounterfactualsPyTorch Training LoopsDataset Pipelines and Data Quality
📦Production ML Systems0/6
Feature Engineering for Production MLBatch and Streaming Feature PipelinesGradient Boosted Trees in ProductionRanking and Recommendation SystemsForecasting and Anomaly DetectionMonitoring Predictive Models
🧪Core LLM Foundations0/8
The Bitter Lesson & ComputeBPE, WordPiece, and SentencePieceStatic to Contextual EmbeddingsPerplexity & Model EvaluationFile Ingestion for AIChunking StrategiesLLM Benchmarks & LimitationsInstruction Tuning & Chat Templates
🧰Applied LLM Engineering0/25
Dimensionality Reduction for EmbeddingsCoT, ToT & Self-Consistency PromptingFunction Calling & Tool UseMCP & Tool Protocol StandardsContext EngineeringPrompt Injection DefenseResponsible AI GovernancePrivacy-Preserving Machine LearningData Labeling and Human FeedbackEvaluating AI AgentsProduction RAG PipelinesHybrid Search: Dense + SparseReranking and Cross-Encoders for RAGRAG Evaluation for Reliable AnswersLLM-as-a-Judge EvaluationBias & Fairness in LLMsHallucination Detection & MitigationLLM Observability & MonitoringExperiment Tracking with MLflow and W&BPrompt Optimization with DSPyModel Versioning & DeploymentSemantic Caching & Cost OptimizationLLM Cost Engineering & Token EconomicsModel Gateways, Routing, and FallbacksDesign an Automated Support Agent
🎓Portfolio Capstones0/9
Capstone: Delivery ETA PredictionCapstone: Product RankingCapstone: Demand ForecastingCapstone: Image Damage ClassifierCapstone: Production ML PipelineCapstone: Document QACapstone: Eval DashboardCapstone: Fine-Tuned ClassifierCapstone: Reproducible ML Study
🧠Transformer Deep Dives0/8
Sentence Embeddings & Contrastive LossEmbedding Similarity & QuantizationScaled Dot-Product AttentionVision Transformers and Image EncodersPositional Encoding: RoPE & ALiBiLayer Normalization: Pre-LN vs Post-LNMechanistic InterpretabilityDecoding Strategies: Greedy to Nucleus
🧬Advanced Training & Adaptation0/17
Scaling Laws & Compute-Optimal TrainingPre-training Data at ScaleBuild GPT from Scratch LabJAX for PyTorch ResearchersContinued Pretraining for Domain ShiftSynthetic Data PipelinesSupervised Fine-Tuning PipelineMixed Precision TrainingDistributed Training: FSDP & ZeROLoRA & Parameter-Efficient TuningTraining Run OperationsReward Modeling from Preference DataRLHF & DPO AlignmentConstitutional AI & Red TeamingRLVR & Verifiable RewardsKnowledge Distillation for LLMsModel Merging and Weight Interpolation
🤖Advanced Agents & Retrieval0/16
Vector DB Internals: HNSW & IVFAdvanced RAG: HyDE & Self-RAGGraphRAG & Knowledge GraphsRAG Security & Access ControlStructured Output GenerationReAct & Plan-and-ExecuteGuardrails & Safety FiltersCode Generation & SandboxingComputer-Use / GUI / Browser AgentsHuman-in-the-Loop Agent ArchitectureAI Coding Workflow with AgentsAgent Memory & PersistenceAgent Failure & RecoveryRecursive Language Models (RLM)Multi-Agent OrchestrationCapstone: Production Agent
⚡Inference & Production Scale0/31
Inference: TTFT, TPS & KV CacheMulti-Query & Grouped-Query AttentionKV Cache & PagedAttentionPrefix Caching and Prompt CachingFlashAttention & Memory EfficiencyContinuous Batching & SchedulingScaling LLM InferenceModel Parallelism for LLM InferenceAccelerator Architecture Field GuideCorrect GPU Profiling and BenchmarkingGPU Kernel Performance Engineering LabGPU Parallel Primitives LabGPU Compilers and Kernel LanguagesGEMM From Naive CUDA to Tensor CoresLow-Precision GPU ProgrammingGPU Runtime Execution LabAI-Generated Kernel EngineeringModel Quantization: GPTQ, AWQ & GGUFLocal LLM DeploymentSLM Specialization & Edge DeploymentSpeculative DecodingLong Context Window ManagementMixture of Experts ArchitectureMamba & State Space ModelsReasoning & Test-Time ComputeAdvanced MLOps & DevOps for AIGPU Serving & AutoscalingGPU Failure OperationsDistributed Inference Data PlaneServing Benchmark EngineeringA/B Testing for LLMs
🏗️System Design Capstones0/9
Content Moderation SystemCode Completion SystemMulti-Tenant LLM PlatformLLM-Powered Search EngineVision-Language Models & CLIPMultimodal LLM ArchitectureDiffusion Models: Images & TextReal-Time Voice AI AgentReasoning Agent System Design
🎤AI Lab Interviewing0/4
AI Lab Coding Interview: Python SystemsAI Lab System Design InterviewAI Lab Behavioral InterviewAI Lab Technical Presentation
🔬Project Deep Dives0/17
Deep Dive - vLLMDeep Dive - SkyRLDeep Dive - FlashAttentionDeep Dive - FlashInferDeep Dive - DeepGEMMDeep Dive - NCCLDeep Dive - MegatronDeep Dive - DeepSpeedDeep Dive - RayDeep Dive - MLflowDeep Dive - PyTorchDeep Dive - TransformersDeep Dive - SGLangDeep Dive - slimeDeep Dive - DeepEPDeep Dive - TinkerDeep Dive - Light-PEFT
Back to Topics
LearnTransformer Deep DivesDecoding Strategies: Greedy to Nucleus
📝HardNLP Fundamentals

Decoding Strategies: Greedy to Nucleus

Compare decoding strategies for text generation: greedy, beam search, top-k, nucleus (top-p), temperature, repetition controls, and newer variants like min-p.

32 min read
Learning path
Step 102 of 196 in the full curriculum
Mechanistic InterpretabilityScaling Laws & Compute-Optimal Training

Personalize this lesson

Adapt explanations and teaching visuals to your background and preferred voice.

A status assistant has one small-looking decision: finish The canary status is without turning a plausible token into a misleading incident update. A transformer gives its decoder a score for every next token, not a sentence.

Once those scores exist, decoding decides what reaches the user, one token at a time. That decision trades reproducibility, variety, and serving cost.

Keep this running example in view. Treat each word below as a single token. One model step might look like this:

TokenProbabilityPlausible continuation
degraded0.45degraded
in0.30in recovery
on0.15on track
broken0.02rare status word
tail0.08the rest of the vocabulary, each token tiny

Greedy decoding writes degraded because it wins this step. A sampling policy might write in and continue into in recovery; on could lead to on track.

Same model, same prompt, different policy, different sentence. The decoder is choosing how much uncertainty to let through.

For top-p sampling at p = 0.90, the first three tokens reach exactly 0.45 + 0.30 + 0.15 = 0.90. Sampling then renormalizes that retained mass, so degraded, in, and on have probabilities 0.50, 0.333..., and 0.166....

The boundary matters: a cutoff that drops the token that reaches the threshold changes both candidate set and draw probabilities.

The earlier decoding algorithms lesson built stable softmax from raw next-token scores (logits) and covered baseline greedy, sampling, truncation, and beam mechanics. This lesson turns those mechanics into product decisions. We will predict a policy's next move, inspect a small implementation, then use its failure mode to choose a setting.

Speculative decoding is a serving trick that drafts tokens for the target model to verify. It isn't a sampling policy, so it doesn't replace the choices below.[1]Reference 1Fast Inference from Transformers via Speculative Decoding.https://arxiv.org/abs/2211.17192

Shared next-token mass for The canary status is: degraded 45 percent, in 30 percent, on 15 percent, tail 10 percent. Greedy emits only degraded. Beam width 3 keeps those three partials and drops the tail. Nucleus p equals 0.90 keeps degraded, in, and on, then samples inside that set after renormalizing.
Greedy commits to degraded. Beam width 3 keeps the same three prefixes as scored partials. Nucleus p=0.90 stops once the running sum hits 90 percent, then samples inside {degraded, in, on}.

Greedy decoding

Why can greedy decoding be bad even when it always picks the most likely next token?

Answer

The most likely next token is a local choice. It can lead the model into a generic or repetitive path even when a slightly less likely token would make the full answer more useful. In a status reply, that can mean writing "degraded." instead of entering "in recovery".

Greedy's weakness appears when a first-step winner leads to a weak continuation. Keep the same two leading tokens and give each a single continuation:

PathFirst tokenContinuationSequence probability
degraded .0.450.400.18
in recovery0.300.900.27

Argmax at step one writes degraded and never looks at the other prefix. Multiply each pair to inspect what that commitment hides: in recovery is the better two-token sequence.

greedy-can-miss-higher-scoring-sequence.py
1first_step = {"degraded": 0.45, "in": 0.30} 2continuations = {"degraded": {".": 0.40}, "in": {"recovery": 0.90}} 3 4greedy_first = max(first_step, key=first_step.get) 5path_probabilities = { 6 "degraded .": first_step["degraded"] * continuations["degraded"]["."], 7 "in recovery": first_step["in"] * continuations["in"]["recovery"], 8} 9highest_sequence = max(path_probabilities, key=path_probabilities.get) 10 11print(f"greedy first token: {greedy_first}") 12print(f"sequence probabilities: { {key: round(value, 3) for key, value in path_probabilities.items()} }") 13print(f"higher-probability sequence: {highest_sequence}") 14 15assert greedy_first == "degraded" 16assert highest_sequence == "in recovery" 17assert path_probabilities["in recovery"] > path_probabilities["degraded ."]
Local versus sequence score
1greedy first token: degraded 2sequence probabilities: {'degraded .': 0.18, 'in recovery': 0.27} 3higher-probability sequence: in recovery

The rule

Now name the policy. At each step, select the token with the highest probability:

wt=arg⁡max⁡wP(w∣w<t)w_t = \arg\max_{w} P(w | w_{<t})wt​=argmaxw​P(w∣w<t​)

The decoder scans the vocabulary, picks the winner, and commits. That costs O(V)O(V)O(V) per step: one pass over VVV candidates. There is no search or random draw. If the local winner starts a weak sentence, decoder has no route back.

Use greedy when variability is a bug: extraction, classification-style labels, or a tightly constrained status enum. Open-ended chat has a different objective.

Holtzman et al. show that maximum-likelihood decoding can drift toward bland, repetitive text, while human-written text often sits at higher perplexity than those high-likelihood beams.[2]Reference 2The Curious Case of Neural Text Degeneration.https://arxiv.org/abs/1904.09751 DeepSeek-R1 reported a similar failure on long reasoning traces: greedy decoding raised repetition and varied across checkpoints, which is why its published pass@1 setup samples instead.[3]Reference 3DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning.https://arxiv.org/abs/2501.12948

Beam search

Greedy keeps one prefix. Beam search keeps B scored prefixes and expands each of them. That extra memory is useful when a slightly weaker first token may unlock a stronger continuation.

Exact search considers the full vocabulary (or a very large candidate set) at every beam, then retains the top-B extended sequences. A cheaper pruned expansion lets each beam propose only its own top-BBB next tokens before global reselection. That shortcut can miss a high-scoring path that starts with a lower-ranked token, so it isn't exhaustive search.

Run width 2 on the same two-step status reply. Predict first: which prefix survives step one, and which full sequence should win after step two?

two-step-beam-search.py
1first_step = [("degraded", 0.45), ("in", 0.30), ("on", 0.15)] 2continuations = { 3 "degraded": [(".", 0.40)], 4 "in": [("recovery", 0.90)], 5 "on": [("track", 0.70)], 6} 7 8def keep_top(candidates, width): 9 return sorted(candidates, key=lambda item: item[1], reverse=True)[:width] 10 11step_one = keep_top(first_step, width=2) 12step_two = [] 13for prefix, prefix_prob in step_one: 14 for token, token_prob in continuations[prefix]: 15 step_two.append((f"{prefix} {token}", prefix_prob * token_prob)) 16 17winner = keep_top(step_two, width=2)[0] 18greedy = f"{first_step[0][0]} {continuations[first_step[0][0]][0][0]}" 19 20print(f"beam after step 1: {step_one}") 21print(f"beam after step 2: {[(text, round(prob, 3)) for text, prob in keep_top(step_two, width=2)]}") 22print(f"greedy path: {greedy}") 23print(f"beam winner: {winner[0]}") 24 25assert [token for token, _ in step_one] == ["degraded", "in"] 26assert greedy == "degraded ." 27assert winner[0] == "in recovery"
Width-2 beam recovers the better path
1beam after step 1: [('degraded', 0.45), ('in', 0.3)] 2beam after step 2: [('in recovery', 0.27), ('degraded .', 0.18)] 3greedy path: degraded . 4beam winner: in recovery

The result keeps degraded (0.45) and in (0.30) after step one, drops on (0.15), and returns in recovery at 0.27 after step two. Beam search recovered the path greedy discarded because it kept that second prefix alive.

Beam candidates can finish in two ways. An EOS token finalizes one early; hitting max_length finalizes every beam that is still active.

At the cutoff, compare completed and still-active candidates under the same score. A non-empty completed list can silently discard a truncated hypothesis that may be better.

Production decoders usually keep a finished flag on beams that remain in the active set and apply length normalization continuously, rather than only when a beam is moved aside.

Length penalty

Without a correction, longer sequences lose. Every extra token multiplies sequence probability by a value smaller than 1, making its log-probability more negative.

Google's Neural Machine Translation system divides sequence log-probability by a length term:

score(Y)=log⁡P(Y)(5+∣Y∣)α/6α\text{score}(Y) = \frac{\log P(Y)}{(5 + |Y|)^\alpha / 6^\alpha}score(Y)=(5+∣Y∣)α/6αlogP(Y)​

When α=0\alpha = 0α=0, denominator is 1 and you are back to raw log-probability. Larger α\alphaα reduces short-sequence bias.

Wu et al. first tried dividing by lengthα\text{length}^\alphalengthα and often landed near 0.60.60.6 to 0.70.70.7 on development data. The formula above is the later GNMT term.

In reported experiments they used α=0.2\alpha = 0.2α=0.2 with a separate coverage penalty β=0.2\beta = 0.2β=0.2 unless noted otherwise. Neither number is a universal default. Tune α\alphaα on validation data for your model, stopping rule, and metric.[4]Reference 4Google's Neural Machine Translation System: Bridging the Gap between Human and Machine Translation.https://arxiv.org/abs/1609.08144

The arithmetic below uses α=0.6\alpha = 0.6α=0.6 only to show ranking flip, not as a recommended setting. Watch which candidate wins before reading output.

beam-length-normalization.py
1def gnmt_score(log_probability, length, alpha=0.6): 2 penalty = ((5 + length) / 6) ** alpha 3 return log_probability / penalty 4 5short = {"text": "degraded.", "log_probability": -1.00, "length": 2} 6complete = {"text": "in recovery mode", "log_probability": -1.08, "length": 5} 7 8raw_choice = max([short, complete], key=lambda item: item["log_probability"])["text"] 9normalized_choice = max( 10 [short, complete], 11 key=lambda item: gnmt_score(item["log_probability"], item["length"]), 12)["text"] 13print(f"raw sequence score chooses: {raw_choice}") 14print(f"length-normalized score chooses: {normalized_choice}") 15 16assert raw_choice == "degraded." 17assert normalized_choice == "in recovery mode"
Length-normalized ranking
1raw sequence score chooses: degraded. 2length-normalized score chooses: in recovery mode

A summarization model with beam width 8 keeps returning clipped one-line outputs instead of complete summaries. Which scoring term do you inspect first?

Answer

Inspect length normalization or length penalty first. Without it, beam search over-rewards short sequences because every extra token lowers sequence probability, so the beam prefers prematurely ending outputs.

When a wider beam hurts

Beam search fits outputs with a constrained target meaning: translation, structured summarization, and some structured extraction. Open-ended chat is usually a poor fit. Holtzman et al. show that high-likelihood paths in open-ended generation are often generic and repetitive.[2]Reference 2The Curious Case of Neural Text Degeneration.https://arxiv.org/abs/1904.09751

There is a second warning even for machine translation. Meister et al. find that under a plain maximum a posteriori (MAP) objective, quality can drop as beam width grows. Searching farther into high-probability sequences can move you closer to a mode that is not the text people prefer.[5]Reference 5If Beam Search is the Answer, What was the Question?.https://arxiv.org/abs/2010.02650

Width also has a serving cost. A width-BBB search keeps up to BBB active continuations. Efficient runtimes batch those hypotheses and reorder their KV-cache state, but larger beams still increase decoder work and memory relative to greedy.

For how that cache sits in the inference pipeline, wait until that later chapter. The practical rule is simple: pay for a wide beam only when the task wants sequence search.

Temperature scaling

Beam search asks which sequence scores highest. Sampling asks a different question: how much uncertainty should survive at each step?

Return to The canary status is. The original probabilities are 0.45, 0.30, 0.15, 0.02, and 0.08. Temperature TTT changes their shape by acting on logits zzz before softmax:

P(wi)=exp⁡(zi/T)∑jexp⁡(zj/T)P(w_i) = \frac{\exp(z_i / T)}{\sum_j \exp(z_j / T)}P(wi​)=∑j​exp(zj​/T)exp(zi​/T)​

If you already have probabilities, renormalizing each individual Pi1/TP_i^{1/T}Pi1/T​ is equivalent. It is not equivalent if you first glue the tail into one bucket and then raise that bucket to 1/T1/T1/T.

The table and figure below aggregate the tail on purpose so you can compare five readable numbers across temperatures. A real decoder never aggregates the tail first; it divides each token's logit by TTT.

TokenT=0.3T = 0.3T=0.3T=1.0T = 1.0T=1.0T=1.5T = 1.5T=1.5
degraded0.7770.450.372
in0.2010.300.284
on0.0200.150.179
broken0.0000.020.047
tail0.0020.080.118
entropy HHH (bits, five buckets)0.881.852.06

Read the columns as a prediction about variance. At T=0.3T = 0.3T=0.3, sampling usually still writes degraded; at T=1.5T = 1.5T=1.5, on and even broken are in play.

As T→0T \to 0T→0, the draw collapses toward greedy. As T→∞T \to \inftyT→∞, it approaches uniform over the vocabulary.

As a separate edge case, zero is not a valid divisor. Route temperature=0 to deterministic decoding instead of sending it through sampling math.

temperature-reshapes-probability.py
1from math import log2 2 3probs = [0.45, 0.30, 0.15, 0.02, 0.08] 4 5def temperature_from_probs(values, temperature): 6 if temperature <= 0: 7 raise ValueError("temperature must be > 0; use greedy decoding for temperature=0") 8 weights = [value ** (1.0 / temperature) for value in values] 9 total = sum(weights) 10 return [weight / total for weight in weights] 11 12def entropy_bits(values): 13 return -sum(value * log2(value) for value in values if value > 0) 14 15low_t = temperature_from_probs(probs, 0.3) 16high_t = temperature_from_probs(probs, 1.5) 17print("T=0.3:", [round(value, 4) for value in low_t]) 18print("T=1.5:", [round(value, 4) for value in high_t]) 19print("entropy bits:", round(entropy_bits(low_t), 3), round(entropy_bits(probs), 3), round(entropy_bits(high_t), 3)) 20 21assert round(low_t[0], 4) == 0.7766 22assert round(high_t[0], 4) == 0.3724 23assert entropy_bits(low_t) < entropy_bits(probs) < entropy_bits(high_t) 24 25try: 26 temperature_from_probs(probs, 0.0) 27except ValueError as error: 28 print("zero temperature:", error)
Temperature reshapes five buckets
1T=0.3: [0.7766, 0.201, 0.0199, 0.0, 0.0025] 2T=1.5: [0.3724, 0.2842, 0.179, 0.0467, 0.1177] 3entropy bits: 0.883 1.854 2.061 4zero temperature: temperature must be > 0; use greedy decoding for temperature=0
Three bar charts of the same five tokens after temperature. At T 0.3, degraded holds 77.7 percent and entropy is 0.88 bits. At T 1.0 the original mass is 45, 30, 15, 2, and 8 percent with entropy 1.85 bits. At T 1.5 the mass flattens to 37.2, 28.4, 17.9, 4.7, and 11.8 percent with entropy 2.06 bits.
The same five buckets after $P_i^{1/T}$ renormalization. Entropy rises from 0.88 bits at $T=0.3$ to 2.06 bits at $T=1.5$ as mass leaves `degraded`.

Dividing logits by T<1T < 1T<1 stretches differences, so the top token takes more mass. Dividing by T>1T > 1T>1 compresses those differences. Temperature is a global sharpness knob.

Temperature sees neither retrieved evidence nor factual support, and it leaves the tail in play. Put a temperature sweep beside task metrics, not in their place:

Evaluation sliceTemperature candidatesWhat to measure
Code generation0.0, 0.2, 0.5Tests passed, format validity, diversity
Factual QA / status lookup0.0, 0.2, 0.5Grounded accuracy and unsupported claims
General chat / runbook assistance0.3, 0.7, 1.0Helpfulness, repetition, policy adherence
Creative writing / descriptions0.7, 1.0, 1.3Diversity and coherence

Why should one global temperature be questioned in evaluation?

Answer

Different endpoints tolerate different variance. Status lookup and rollback eligibility prioritize grounded accuracy; creative drafting may value variety. Evaluate sampler settings per task slice rather than accepting a single preset without measurements.

Top-k sampling

Temperature still leaves the whole vocabulary in play. Top-k sampling, popularized for neural story generation, keeps only the kkk most probable tokens, then renormalizes and samples.[6]Reference 6Hierarchical Neural Story Generation.https://arxiv.org/abs/1805.04833

On the canary-status step, k=2k = 2k=2 keeps degraded and in, then drops on, broken, and the tail. Their 0.45 and 0.30 weights become 0.60 and 0.40 after renormalization.

The fixed count is both top-k's appeal and its weakness. Ask how peaked each context is before choosing kkk:

ContextDistribution shapeCandidate kkk values to evaluate
The rollback runbook saysPotentially peaked1, 3, 10
The incident summary shouldPotentially flatter10, 30, 50
The servicePrompt-dependentMeasure rather than assume

When the distribution is peaked, k=50k = 50k=50 drags in dozens of irrelevant tail tokens. A high temperature can give that tail enough mass to be drawn.

When distribution is flat, k=10k = 10k=10 can cut off valid continuations. The count ignores confidence, which is why later methods moved to a dynamic cutoff.

Why does top-k fail differently on peaked and flat distributions?

Answer

Top-k always keeps the same number of tokens. On a peaked distribution, a large k admits irrelevant tail tokens. On a flat distribution, a small k cuts off valid alternatives. The fixed count ignores how confident the model is.

top-k-vs-top-p-survivors.py
1def top_k_tokens(tokens_and_probs, k): 2 ranked = sorted(tokens_and_probs, key=lambda item: item[1], reverse=True) 3 return [token for token, _ in ranked[:k]] 4 5def top_p_tokens(tokens_and_probs, p): 6 kept = [] 7 cumulative = 0.0 8 for token, probability in sorted(tokens_and_probs, key=lambda item: item[1], reverse=True): 9 kept.append(token) 10 cumulative += probability 11 if cumulative >= p: 12 break 13 return kept 14 15distribution = [ 16 ("degraded", 0.45), 17 ("in", 0.30), 18 ("on", 0.15), 19 ("paused", 0.04), 20 ("held", 0.03), 21 ("broken", 0.02), 22 ("rollback", 0.01), 23] 24 25assert top_k_tokens(distribution, 2) == ["degraded", "in"] 26assert top_p_tokens(distribution, 0.8) == ["degraded", "in", "on"]

Nucleus (top-p) sampling

Top-k with k=50k = 50k=50 keeps fifty tokens even when two are plausible or when hundreds deserve a look. Nucleus sampling, also called top-p, changes the question from “how many?” to “how much mass?”

It keeps adding highest-probability tokens until cumulative mass reaches threshold ppp.[2]Reference 2The Curious Case of Neural Text Degeneration.https://arxiv.org/abs/1904.09751

Using the same canary-status table, p=0.80p = 0.80p=0.80 includes degraded, in, and on (cumulative 0.90) and excludes broken plus the tail. If degraded had 0.85, nucleus would be one token.

Vp={w(1),…,w(m)},m=min⁡{j:∑i=1jP(w(i))≥p}V_p = \{w_{(1)}, \ldots, w_{(m)}\}, \qquad m = \min \left\{j : \sum_{i=1}^{j} P(w_{(i)}) \ge p \right\}Vp​={w(1)​,…,w(m)​},m=min{j:i=1∑j​P(w(i)​)≥p}

Here w(i)w_{(i)}w(i)​ are sorted by decreasing probability. After truncation, divide each kept probability by kept mass so nucleus sums to 1.

nucleus-renormalization.py
1def nucleus_distribution(tokens_and_probs, threshold): 2 kept = [] 3 mass = 0.0 4 for token, probability in sorted(tokens_and_probs, key=lambda item: item[1], reverse=True): 5 kept.append((token, probability)) 6 mass += probability 7 if mass >= threshold: 8 break 9 return [(token, round(probability / mass, 3)) for token, probability in kept] 10 11tokens = [("degraded", 0.45), ("in", 0.30), ("on", 0.15), ("broken", 0.02)] 12nucleus = nucleus_distribution(tokens, threshold=0.8) 13print("renormalized nucleus:", nucleus) 14 15assert nucleus == [("degraded", 0.5), ("in", 0.333), ("on", 0.167)] 16assert round(sum(probability for _, probability in nucleus), 3) == 1.0
Nucleus renormalization
1renormalized nucleus: [('degraded', 0.5), ('in', 0.333), ('on', 0.167)]

At fixed p=0.90p = 0.90p=0.90, survivor count is a function of distribution shape, not a hidden constant:

Sorted probabilitiesSmallest prefix reaching 0.90Survivors
0.92, 0.04, 0.02, 0.01, 0.010.921
0.45, 0.30, 0.15, 0.07, 0.030.45 + 0.30 + 0.15 = 0.903
0.22, 0.19, 0.17, 0.15, 0.13, 0.08, 0.060.946

Real nucleus size also depends on model, tokenizer, prompt, and temperature. The threshold stays fixed; candidate count moves with confidence.

The long-tail failure at high TTT

Top-p has a failure mode to measure at high temperatures (T>1T > 1T>1). Flattening gives many weak tokens enough combined mass to enter the cumulative set.

A p=0.9p = 0.9p=0.9 nucleus can therefore get large even when no individual tail token is a good next word. That is one motivation for confidence-scaled cutoffs such as min-p.

Why can top-p admit too much tail at high temperature?

Answer

High temperature flattens the distribution, so many weak tokens gain enough combined probability mass to enter the cumulative top-p set. The nucleus can become large even though many individual tokens are poor choices.

temperature-expands-a-nucleus.py
1from math import exp 2 3def probabilities(logits, temperature): 4 weights = [exp(logit / temperature) for logit in logits] 5 total = sum(weights) 6 return [weight / total for weight in weights] 7 8def nucleus_size(probs, threshold): 9 mass = 0.0 10 for index, probability in enumerate(sorted(probs, reverse=True), start=1): 11 mass += probability 12 if mass >= threshold: 13 return index 14 15logits = [4.0, 2.0, 1.0, 0.0, -0.5, -1.0] 16focused = nucleus_size(probabilities(logits, 0.7), threshold=0.9) 17flattened = nucleus_size(probabilities(logits, 1.5), threshold=0.9) 18print(f"nucleus size at T=0.7: {focused}") 19print(f"nucleus size at T=1.5: {flattened}") 20 21assert focused == 1 22assert flattened == 3 23assert flattened > focused
Temperature changes nucleus size
1nucleus size at T=0.7: 1 2nucleus size at T=1.5: 3

Beyond nucleus: min-p

Top-p asks how many ranked tokens are needed to cover a chosen mass. Min-p asks a different question: is each token strong enough relative to the best token? Keep tokens whose probability is at least a fraction ρ\rhoρ of that peak.

A dominant top token sets a high bar; a weak top token lowers it. The cutoff follows relative confidence, not a fixed cumulative sum. Nguyen et al. (ICLR 2025 oral) define the kept set as:[7]Reference 7Turning Up the Heat: Min-p Sampling for Creative and Coherent LLM Outputs.https://arxiv.org/abs/2407.01082

Vmin⁡-p={w:P(w)≥ρ⋅max⁡vP(v)}V_{\min\text{-}p} = \{w : P(w) \geq \rho \cdot \max_v P(v)\}Vmin-p​={w:P(w)≥ρ⋅maxv​P(v)}

If the top token has probability 0.80 and ρ=0.1\rho = 0.1ρ=0.1, anything below 0.08 is dropped. If the top token has only 0.05, the bar falls to 0.005, so more alternatives survive.

ScenarioTop-p (p=0.9p = 0.9p=0.9)Min-p (ρ=0.1\rho = 0.1ρ=0.1)
Model confident (Pmax⁡=0.80P_{\max} = 0.80Pmax​=0.80)Keeps enough tokens to reach 90% mass, which can still include a long tailKeeps only tokens with P≥0.08P \ge 0.08P≥0.08
Model uncertain (Pmax⁡=0.05P_{\max} = 0.05Pmax​=0.05)Still targets 90% cumulative massLowers the cutoff to P≥0.005P \ge 0.005P≥0.005
High temperature (T=1.5T = 1.5T=1.5)Flattened tails can enter the nucleusRelative cutoff can trim more of that tail

Use the figure as a prediction test. On a peaked split, which rule should keep the fewest candidates? On a flatter split, which rule should expand its set? The same token names make the three answers easy to compare.

Survivor matrix for the same five named tokens plus a tail bucket. On a peaked 72/20/5/2/1 split, top-k equals 3 keeps degraded, in, and on, while top-p 0.90 and min-p 0.10 both stop after degraded and in. On a flatter 40/20/15/11.5/3.5 plus 10 percent tail split, top-k still keeps three tokens, top-p keeps five, and min-p keeps four because paused sits below the 4.0 percent relative cutoff.
On the peaked split, top-p and min-p both drop `on`. On the flatter split, top-k still stops at three tokens while top-p keeps five and min-p keeps four, because `paused` sits below the 4.0% relative cutoff.

Run the small implementation after making that prediction. It returns survivors before any renormalization, so the threshold is visible in isolation.

min-p-tracks-the-peak.py
1def min_p_tokens(tokens_and_probs, rho): 2 max_probability = max(probability for _, probability in tokens_and_probs) 3 threshold = rho * max_probability 4 return [token for token, probability in tokens_and_probs if probability >= threshold] 5 6confident = [("degraded", 0.80), ("in", 0.09), ("broken", 0.01)] 7uncertain = [("degraded", 0.05), ("in", 0.04), ("on", 0.03)] 8 9assert min_p_tokens(confident, rho=0.1) == ["degraded", "in"] 10assert min_p_tokens(uncertain, rho=0.1) == ["degraded", "in", "on"]

Min-p is a newer truncation heuristic to evaluate, not a settled replacement for nucleus sampling. Nguyen et al. propose it for the high-temperature tail that top-p can admit.[7]Reference 7Turning Up the Heat: Min-p Sampling for Creative and Coherent LLM Outputs.https://arxiv.org/abs/2407.01082

A later critical reanalysis reports that min-p did not reliably improve quality-diversity tradeoffs against commonly used samplers in its experiments, and disputes broad adoption claims.[8]Reference 8Min-p, Max Exaggeration: A Critical Analysis of Min-p Sampling in Language Modelshttps://arxiv.org/abs/2506.13681

Treat any published setting, including DeepSeek-R1's temperature 0.6 with top-p 0.95 pass@1 configuration, as an experiment input for that model, not a preset for yours.[3]Reference 3DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning.https://arxiv.org/abs/2501.12948

MethodThresholdAdapts to distribution shape?Main tradeoff
Top-kFixed kkk tokensNoSimple, but rigid
Top-pFixed ppp cumulative massPartlyDynamic, but can admit a long tail
Min-pρ×Pmax⁡\rho \times P_{\max}ρ×Pmax​YesRelative cutoff; compare empirically with top-p

Repetition penalty

When a generated answer loops, the sampler is reusing tokens that remain too attractive:

"The deploy rolled back. The deploy rolled back. The deploy rolled..."

CTRL introduced penalized sampling: discount logits of tokens already in the generated list. Keskar et al. reported that near-greedy sampling with θ≈1.2\theta \approx 1.2θ≈1.2 balanced truthful generation against repetition in their experiments.[9]Reference 9CTRL: A Conditional Transformer Language Model for Controllable Generation.https://arxiv.org/abs/1909.05858

Their original rule scales the logit of a seen token through a temperature multiplier θ\thetaθ. Modern runtimes expose related variants; inspect the transform instead of inferring it from the name.

Common runtimes such as Hugging Face Transformers expose a related sign-aware processor.

For a repeated token, divide a positive logit by the penalty and multiply a negative logit by it. Both move down in preference rather than toward zero. See RepetitionPenaltyLogitsProcessor.

The function below mirrors that runtime behavior:

sign-aware-repetition-penalty.py
1def apply_repetition_penalty(logits, generated_ids, penalty=1.2): 2 if penalty <= 0: 3 raise ValueError("penalty must be positive") 4 adjusted = list(logits) 5 for token_id in set(generated_ids): 6 if adjusted[token_id] > 0: 7 adjusted[token_id] /= penalty 8 else: 9 adjusted[token_id] *= penalty 10 return adjusted 11 12logits = [2.4, -0.5, 0.7] 13penalized = apply_repetition_penalty(logits, generated_ids=[0, 1], penalty=1.2) 14print("original logits:", logits) 15print("penalized logits:", [round(value, 3) for value in penalized]) 16 17assert penalized[0] < logits[0] 18assert penalized[1] < logits[1] 19assert penalized[2] == logits[2]
Sign-aware repetition penalty
1original logits: [2.4, -0.5, 0.7] 2penalized logits: [2.0, -0.6, 0.7]

Token 0 was positive, so the penalty divides it (2.4 / 1.2 = 2.0). Token 1 was negative, so the penalty multiplies it (-0.5 × 1.2 = -0.6). Token 2 never appeared, so its logit stays unchanged.

A naive “divide every seen logit” rule would move -0.5 toward zero and make that token more likely. The sign branch is the important detail.

Frequency and presence penalties

A different pair of controls changes how often a token has appeared:

logitadjusted=logit−α⋅count(token)−β⋅1[count(token)>0]\text{logit}_{\text{adjusted}} = \text{logit} - \alpha \cdot \text{count}(\text{token}) - \beta \cdot \mathbb{1}[\text{count}(\text{token}) > 0]logitadjusted​=logit−α⋅count(token)−β⋅1[count(token)>0]

The frequency penalty α\alphaα grows with each reuse: five copies of a token cost 5α5\alpha5α. The presence penalty β\betaβ is a one-time hit after first appearance, which pushes the model off a topic rather than off a word.

Exact formulas and defaults vary by stack. Neither knob repairs a missing fact. They only make already-seen tokens less attractive.

Combining strategies in production

At each generation step, a production system may stack several logit transforms, then branch into deterministic or stochastic selection. Before reading the diagram, predict where a temperature=0 request should go.

Diagram showing Raw logits, Penalties and masks, T = 0?, and yes.
Raw logits, Penalties and masks, T = 0?, and yes.
  1. Start with raw logits.
  2. Apply processors such as penalties, banned-token masks, or forced-token constraints.
  3. If the policy is deterministic, take argmax on the adjusted logits.
  4. If the policy samples, warp with temperature, then truncate with top-k, top-p, or min-p, then draw.

That list is a conceptual path, not a universal contract. Exact order is implementation-specific.

Some stacks apply temperature before truncation; others place temperature later. Don't memorize one canonical chain. Know that these controls are layered transforms, and read the stack you are shipping.

You move a chat product to a new inference engine and outputs change even though temperature and top-p stayed the same. What sampler detail do you verify first?

Answer

Verify the exact order of penalties, masks, temperature, truncation, and sampling. There is no universal sampler order across frameworks, so the same knobs can behave differently when those transformations are applied in a different sequence.

Use the next figure as a dry run of that stack. degraded already appeared in the prompt, so a 1.2 penalty drops it from 2.4 to 2.0, below in at 2.1. Greedy now emits in.

After softmax, the penalized logits are approximately in 0.404, degraded 0.365, on 0.164, and broken 0.067. A p=0.90p = 0.90p=0.90 nucleus keeps the first three (cumulative 0.933) and drops broken.

The illustrated sample is on, inside the nucleus but not the mode. That is the point of a sampling path: its draw need not be argmax.

Sampler stack on four canary-status logits. Raw scores rank degraded 2.4 above in 2.1, on 1.2, and broken 0.3. A 1.2 repetition penalty on already-emitted degraded drops it to 2.0, so greedy argmax emits in. After softmax, top-p 0.90 keeps in 0.404, degraded 0.365, and on 0.164, drops broken 0.067, and the illustrated sample lands on on.
After the penalty, greedy emits `in`. Top-p 0.90 still keeps `degraded` and `on`; the illustrated draw is `on`, not the mode.

Runnable code uses that same conceptual order: penalty, then a greedy branch at temperature 0, otherwise temperature plus nucleus sampling.

random.Random(0) makes the sampled token reproducible in this lesson.

penalty-then-sample.py
1import math 2import random 3 4def apply_repetition_penalty(logits, generated_ids, penalty=1.2): 5 adjusted = list(logits) 6 for token_id in set(generated_ids): 7 if adjusted[token_id] > 0: 8 adjusted[token_id] /= penalty 9 else: 10 adjusted[token_id] *= penalty 11 return adjusted 12 13def softmax(logits): 14 peak = max(logits) 15 weights = [math.exp(logit - peak) for logit in logits] 16 total = sum(weights) 17 return [weight / total for weight in weights] 18 19def nucleus_sample(logits, threshold, rng): 20 probs = softmax(logits) 21 ranked = sorted(enumerate(probs), key=lambda item: item[1], reverse=True) 22 kept = [] 23 mass = 0.0 24 for index, probability in ranked: 25 kept.append((index, probability)) 26 mass += probability 27 if mass >= threshold: 28 break 29 tokens, weights = zip(*kept) 30 return rng.choices(tokens, weights=weights, k=1)[0] 31 32def sample_next_token(logits, generated_ids, temperature, top_p, rng): 33 logits = apply_repetition_penalty(logits, generated_ids, penalty=1.2) 34 if temperature == 0: 35 return max(range(len(logits)), key=lambda index: logits[index]) 36 scaled = [logit / temperature for logit in logits] 37 return nucleus_sample(scaled, threshold=top_p, rng=rng) 38 39logits = [2.4, 2.1, 1.2, 0.3] 40generated_ids = [0] 41rng = random.Random(0) 42 43greedy_id = sample_next_token(logits, generated_ids, temperature=0, top_p=0.9, rng=rng) 44sampled_id = sample_next_token(logits, generated_ids, temperature=1.0, top_p=0.9, rng=rng) 45names = ["degraded", "in", "on", "broken"] 46print(f"greedy token: {names[greedy_id]}") 47print(f"sampled token: {names[sampled_id]}") 48 49assert greedy_id == 1 50assert names[greedy_id] == "in" 51assert sampled_id == 2 52assert names[sampled_id] == "on"
Penalty then greedy or nucleus
1greedy token: in 2sampled token: on

With seed 0, the sampled path lands on on, matching the figure. Nucleus sampling can redraw the mode or another kept token.

on is one legal draw from this nucleus, not a second deterministic answer.

Evaluation configurations

Evaluation sliceTemperature candidatesSampler candidatesRepetition-penalty candidatesGoal
Code generation0.0, 0.2, 0.5Greedy, top-p=0.951.0, 1.05Tests and format validity
Factual QA0.0, 0.2, 0.5Greedy, top-p=0.91.0, 1.05Grounded accuracy
Chat0.3, 0.7, 1.0Top-p=0.9, min-p=0.11.0, 1.1Helpfulness and repetition
Creative writing0.7, 1.0, 1.3Top-p=0.95, min-p=0.051.0, 1.1Diversity and coherence
Published DeepSeek-R1 pass@1 setting0.6Top-p=0.95Not reportedOne evaluation configuration[3]Reference 3DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning.https://arxiv.org/abs/2501.12948

The first four rows are candidate sweeps, not recommended defaults. Compare them on held-out prompts. The right settings depend on model, tokenizer, task, and measured failure costs.

Choosing a policy by task

Choose a policy from the output contract, not from a favorite knob. First decide how much output variance the endpoint can tolerate and which failures cost most. Then compare candidates on task metrics, repetition, format validity, and latency.

StrategyDeterministic?Adapts to context?Candidate evaluation fit
GreedyYesNoExtraction, classification
Beam searchYesNoTranslation, summarization
Top-kNoNoSimple truncation baseline
Top-pNoYes, by cumulative massGeneral generation
Min-pNoYesConfidence-scaled truncation to compare with top-p
TemperatureModifierModifierControls global diversity
Rep penaltyModifierModifierSuppresses repeated-token reuse

The first five rows choose how candidates are searched or sampled. Temperature and repetition penalty modify that choice. A modifier can improve one symptom while making another worse, so evaluate the stack together.

What to check before moving on

Use these pass bars as predictions you can defend from examples, not as settings to memorize.

DecisionPass bar
Greedy vs samplingYou can name one task where greedy is the right default and one where it will likely sound degenerate.
Beam searchYou can explain why beam width can help translation yet hurt open-ended chat, and when length penalty matters.
TemperatureYou can connect lower or higher temperature to the actual shape change in one worked probability distribution.
Top-k vs top-p vs min-pYou can choose which truncation rule better fits a peaked distribution and which better fits a flat one.
Penalty knobsYou can explain when repetition, frequency, and presence penalties solve style loops versus when they don't touch factual errors.
Production choiceYou can defend one sampler stack for factual QA, one for code, and one for creative chat under a real latency or quality goal.
Implementation bugsYou can name two runtime mistakes that change outputs even when the visible knobs look the same.

Common failures and fixes

Beam search made chat sound robotic

Answers became safer and more repetitive after you increased beam width. Inspect the objective first: beam search is pushing toward a most likely overall continuation, which is often generic in open-ended dialogue.

Keep beam search for translation or tightly grounded summarization, where several candidate paths can help. For chat, switch back to sampling and tune temperature plus truncation against a quality and latency target.

Temperature tweak didn't fix hallucinations

You lowered temperature, but the model still states wrong facts confidently. Temperature changes distribution sharpness, not factual grounding. If the model lacks evidence, a wrong continuation can still be high probability.

Keep decoding conservative for factual tasks, but fix retrieval, prompt grounding, or output constraints. Temperature is not a truth knob.

High temperature plus top-p pulled in nonsense tail tokens

Creative mode started producing weird fragments or off-topic words. Higher temperature flattened the distribution, so top-p admitted a long tail of individually weak candidates.

Lower temperature, tighten top-p, or test min-p. Min-p makes the cutoff track strength of the best token instead of only cumulative mass.

Fixed top-k clipped valid options

Outputs stayed narrow on creative prompts and erratic on factual prompts with the same k. Top-k uses the same cutoff in every shape: too small in flat contexts and too large in peaked ones.

Treat top-k as a simple baseline. Compare top-p or min-p when candidate-set size should react to model confidence.

Same knobs changed behavior after a runtime swap

Another engine gives different outputs even with matching documented settings. Sampler order, defaults, or special cases such as temperature=0 can differ across implementations.

Inspect the actual sampler path and log intermediate logits if needed. Validate representative prompts before blaming model weights.

temperature=0 was sent through the sampling math directly

The runtime crashes, returns NaNs, or behaves inconsistently when someone sets temperature to zero. The implementation divided logits by zero instead of treating temperature=0 as a greedy special case.

Handle temperature=0 explicitly as deterministic decoding. Keep sampling path only for temperatures greater than zero.

Truncated probabilities no longer sum to one

Logged or returned survivor probabilities sum to less than one after truncation. Tail probabilities were set to zero, but downstream code still expects a normalized distribution. Some sampling APIs accept unnormalized nonnegative weights; metrics and probability contracts expect normalized probabilities.

Mask logits with negative infinity and run softmax again, or divide surviving probabilities by remaining mass before returning them.

Practice drill

Create one decoding audit table for three production routes: a factual status answer, a creative incident narrative, and code completion. Each route has a different cost for variance, so run its experiment separately instead of letting one global preset decide.

  1. Pick baseline settings for temperature, top-p or top-k, repetition penalty, and stop conditions.
  2. Write two failure examples per route: one too deterministic, one too random or unsupported.
  3. Compare outputs under at least three setting changes, then mark accuracy, diversity, latency, and parseability.
  4. Choose one launch setting per route and write the rollback trigger that would force you to change it.

Finish by recording an evaluation-backed decoding policy for each task, model, and tokenizer. The record should explain which failure the setting is meant to prevent and which measurement would make you revisit it.

Complete the lesson

Mastery Check

Answer every question, then check your score. Score 75% or higher to mark this lesson complete.

1.At the first step, P(degraded) = 0.45 and P(in) = 0.30. The only continuations have P(.) = 0.40 after degraded and P(recovery) = 0.90 after in. Which result demonstrates the greedy trap?

Correct answer: degraded ., because greedy commits to the highest first-step token and evaluates no alternate continuation.

Greedy chooses degraded from the first-step probabilities, but its sequence probability is 0.45 x 0.40 = 0.18. The alternative scores 0.30 x 0.90 = 0.27, showing that the locally strongest token need not begin the strongest full sequence.

2.At a beam search max-length cutoff, two hypotheses already ended with EOS while three are still active. How should the simplified decoder choose its return value?

Correct answer: Finalize the active hypotheses as truncated candidates and compare them with the EOS-completed hypotheses under the same sequence score.

EOS completion and max-length truncation are two ways a candidate can enter the final set. Ignoring either group changes the search result. A production decoder should also retain a finished or truncated flag and apply its configured length normalization consistently.

3.A chatbot repeats the same closing tokens several times. You want the penalty on each token to grow with every reuse. Which control matches that objective?

Correct answer: Frequency penalty, because its subtraction scales with token count.

A frequency penalty subtracts an amount proportional to the token's count, so repeated reuse becomes progressively less attractive. A presence penalty applies one flat deduction after the token has appeared at least once.

4.With top_k=10, a creative assistant misses many plausible continuations, while a factual assistant admits weak tail tokens. What explains both symptoms?

Correct answer: Fixed k ignores distribution shape; compare an adaptive truncation rule.

Top-k always retains the same number of candidates. Ten can be too few when probability is spread across many valid creative choices and too many when a factual distribution is concentrated in only a few plausible tokens.

5.A min-p sampler with rho = 0.1 sees probabilities degraded: 0.80, in: 0.09, on: 0.07, and broken: 0.01. Which tokens survive before renormalization?

Correct answer: degraded and in, because both clear the 0.08 threshold before renormalization.

Min-p sets its cutoff to rho x P_max. Here that's 0.1 x 0.80 = 0.08. The probabilities 0.80 and 0.09 meet the cutoff, while 0.07 and 0.01 do not.

6.After a runtime migration, identical nonzero sampler settings produce different candidate probabilities, and temperature=0 produces NaNs. Which audit addresses both symptoms?

Correct answer: Audit processor order and defaults, and route T=0 directly to argmax.

Engines can apply penalties, masks, temperature, and truncation in different orders or with different defaults, which changes candidate probabilities. Temperature zero must bypass division and stochastic sampling and use deterministic argmax handling.

7.A factual bot is accurate at temperature 0.2 and top_p 0.95. After only temperature rises to 1.3, it samples wrong policy continuations. What's the likely decoding cause?

Correct answer: Temperature flattened the distribution, admitting weaker tokens to top-p.

A temperature above 1 compresses logit differences and spreads probability toward weaker candidates. A wide top-p nucleus can then include more of those candidates, increasing factual variance even though the model and grounding are unchanged.

8.Four tokens have probabilities A=0.45, B=0.30, C=0.15, and D=0.10. With top_p=0.8, which distribution is sampled after truncation?

Correct answer: A, B, C with probabilities 0.50, 0.333, and 0.167.

A and B total only 0.75, so C must be included to reach the 0.8 threshold. Their retained mass is 0.90, and dividing each probability by 0.90 gives approximately 0.50, 0.333, and 0.167.

9.A team serves both narrow-target translation and open-ended creative chat. Which evaluation plan matches their different generation goals?

Correct answer: Evaluate beam search for translation and truncation-based sampling for creative chat.

Translation has a constrained target meaning, so retaining several high-probability sequence paths can improve the final result. Creative chat has many acceptable continuations, and wider beams can over-optimize generic high-likelihood text, so sampling is the more appropriate candidate to evaluate.

10.A low-temperature runbook assistant confidently gives the wrong rollback policy because retrieval supplied no runbook evidence. What should be changed first?

Correct answer: Fix retrieval or constraints; decoding can't supply missing evidence.

Temperature and truncation control which modeled continuations are selected, not whether the model has reliable evidence. If a wrong continuation is already highly probable, making decoding more deterministic can preserve the error rather than correct it.

10 questions remaining.

Next Step
Continue to Scaling Laws & Compute-Optimal Training

You can now turn residual-stream logits into a deliberate next-token policy. That policy still samples from a trained distribution. Next, scaling laws ask how to spend parameters, data, and compute so the distribution you decode from is worth the budget.

PreviousMechanistic Interpretability
Share this article
XFacebookLinkedInBlueskyRedditHacker NewsEmail
References

Fast Inference from Transformers via Speculative Decoding.

Leviathan, Y., Kalman, M., & Matias, Y. · 2023 · ICML 2023

https://arxiv.org/abs/2211.17192

The Curious Case of Neural Text Degeneration.

Holtzman, A., et al. · 2020 · ICLR 2020

https://arxiv.org/abs/1904.09751

DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning.

DeepSeek Team · 2025

https://arxiv.org/abs/2501.12948

Google's Neural Machine Translation System: Bridging the Gap between Human and Machine Translation.

Wu, Y., et al. · 2016

https://arxiv.org/abs/1609.08144

If Beam Search is the Answer, What was the Question?.

Meister, C., Cotterell, R., & Vieira, T. · 2020 · EMNLP 2020

https://arxiv.org/abs/2010.02650

Hierarchical Neural Story Generation.

Fan, A., Lewis, M., & Dauphin, Y. · 2018 · ACL 2018

https://arxiv.org/abs/1805.04833

Turning Up the Heat: Min-p Sampling for Creative and Coherent LLM Outputs.

Nguyen, et al. · 2025 · ICLR 2025 Oral

https://arxiv.org/abs/2407.01082

Min-p, Max Exaggeration: A Critical Analysis of Min-p Sampling in Language Models

Schaeffer, R., Kazdan, J., & Denisov-Blanch, Y. · 2025

https://arxiv.org/abs/2506.13681

CTRL: A Conditional Transformer Language Model for Controllable Generation.

Keskar, N. S., et al. · 2019

https://arxiv.org/abs/1909.05858

Discussion

Questions and insights from fellow learners.

Discussion loads when you reach this section.