LLM Sampling Parameters
Temperature, Top-p, Top-k, and Other Generation Controls
Understanding Token Generation
Large Language Models generate text one token at a time. At each step, the model outputs a probability distribution over all possible next tokens (typically 32,000–100,000+ tokens in the vocabulary). Sampling parameters control how the next token is selected from this distribution, directly affecting the creativity, coherence, and predictability of outputs.
Understanding these parameters is essential for fine-tuning model behavior for different use cases—from deterministic code generation to creative writing.
The Token Generation Process
- Forward Pass: Input tokens are processed through the transformer layers
- Logits: The model outputs raw scores (logits) for each vocabulary token
- Softmax: Logits are converted to a probability distribution (sums to 1.0)
- Sampling: Parameters modify this distribution and select the next token
- Repeat: The selected token is appended, and the process repeats
Temperature
Temperature scales the logits before softmax, controlling the "sharpness" of the probability distribution. It's the most commonly adjusted parameter.
# Temperature scaling formula
P(token_i) = exp(logit_i / T) / Σ exp(logit_j / T)
Where T = temperature
- T < 1.0: Sharpens distribution (more deterministic)
- T = 1.0: No change (default)
- T > 1.0: Flattens distribution (more random)
- T → 0: Approaches greedy decoding (always pick highest probability)
T = 0.0–0.3
Highly deterministic. Best for code generation, data extraction, factual Q&A. Nearly identical outputs each run.
T = 0.5–0.7
Balanced. Good for most tasks—summaries, explanations, technical writing. Some variety, mostly coherent.
T = 0.8–1.2
Creative. Good for brainstorming, storytelling, poetry. More diverse but may include errors.
⚠️ Warning: Temperature > 1.5 often produces incoherent output. Use extreme values only for specific creative applications.
Top-p (Nucleus Sampling)
Top-p dynamically selects the smallest set of tokens whose cumulative probability exceeds
the threshold p. Only tokens in this "nucleus" are considered for sampling.
# Top-p algorithm
1. Sort tokens by probability (descending)
2. Compute cumulative probability
3. Keep tokens until cumulative prob ≥ p
4. Renormalize remaining probabilities
5. Sample from this reduced set
Example (top_p = 0.9):
Token Prob Cumulative
"the" 0.40 0.40 ✓
"a" 0.25 0.65 ✓
"an" 0.15 0.80 ✓
"this" 0.10 0.90 ✓ (threshold)
"that" 0.05 0.95 ✗ (excluded)
"one" 0.03 0.98 ✗
...
top_p = 0.9–0.95
Most common range. Eliminates low-probability "noise" tokens while preserving reasonable alternatives.
top_p = 1.0
Disabled (all tokens considered). Equivalent to temperature-only sampling.
💡 Key Insight: Top-p adapts to context. When the model is confident (one token has very high probability), nucleus is small. When uncertain, nucleus is larger. This makes it more robust than fixed top-k.
Top-k Sampling
Top-k simply keeps only the k highest-probability tokens and samples from them.
It's simpler than top-p but less adaptive.
# Top-k algorithm
1. Sort tokens by probability (descending)
2. Keep only the top k tokens
3. Renormalize their probabilities
4. Sample from this set
Example (top_k = 3):
Token Prob
"the" 0.40 ✓ (kept)
"a" 0.25 ✓ (kept)
"an" 0.15 ✓ (kept)
"this" 0.10 ✗ (excluded)
"that" 0.05 ✗
...
| top_k Value | Effect | Use Case |
|---|---|---|
| k = 1 | Greedy decoding (always pick top token) | Maximum determinism |
| k = 10–50 | Balanced variety | General tasks |
| k = 100+ | Wide variety (similar to high temperature) | Creative generation |
| k = 0 or disabled | All tokens considered | Rely on temperature/top-p only |
Other Important Parameters
max_tokens
Maximum number of tokens to generate. Prevents runaway generation and controls costs.
# Common settings
max_tokens=256 # Short responses (summaries, answers)
max_tokens=1024 # Medium responses (explanations)
max_tokens=4096 # Long responses (articles, code)
stop / stop_sequences
Strings that halt generation when encountered. Essential for structured outputs.
stop=["\n\n", "###", "", "Human:"]
# Stops when any of these appear in output
frequency_penalty
Reduces the probability of tokens proportionally to how often they've appeared. Range: -2.0 to 2.0 (positive = less repetition).
# Adjusted logit = logit - frequency_penalty * token_count
frequency_penalty=0.0 # No penalty (default)
frequency_penalty=0.5 # Mild reduction of common tokens
frequency_penalty=1.0 # Strong anti-repetition
presence_penalty
Flat penalty for any token that has appeared (regardless of count). Encourages new topics rather than just avoiding repetition.
# Adjusted logit = logit - presence_penalty * (1 if token appeared else 0)
presence_penalty=0.0 # No penalty (default)
presence_penalty=0.6 # Encourage topic diversity
seed
Fixed random seed for reproducible outputs. When combined with temperature=0, produces deterministic results.
seed=42 # Same seed + same input = same output (mostly)
# Note: Not all providers guarantee perfect reproducibility
Recommended Parameter Combinations
| Use Case | temperature | top_p | frequency_penalty | Notes |
|---|---|---|---|---|
| Code Generation | 0 | 1.0 | 0 | Deterministic, reproducible |
| Data Extraction | 0 | 1.0 | 0 | Consistent JSON/structured output |
| Summarization | 0.3 | 0.95 | 0 | Low variance, factual |
| Chatbot / Assistant | 0.7 | 0.9 | 0.3 | Natural, varied responses |
| Creative Writing | 0.9 | 0.95 | 0.5 | Diverse, surprising |
| Brainstorming | 1.0 | 1.0 | 0.7 | Maximum variety |
⚠️ Don't Combine: Adjusting both temperature and top_p simultaneously can have unpredictable effects. OpenAI recommends changing one or the other, not both.
API Examples
OpenAI
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Write a haiku about Python"}],
temperature=0.8,
top_p=0.95,
max_tokens=100,
frequency_penalty=0.3,
presence_penalty=0.0,
stop=["\n\n"],
seed=42
)
Anthropic (Claude)
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
messages=[{"role": "user", "content": "Write a haiku about Python"}],
temperature=0.8,
top_p=0.95,
max_tokens=100,
stop_sequences=["\n\n"]
)
# Note: Claude doesn't support frequency/presence penalty
Local (Ollama / vLLM)
import requests
response = requests.post("http://localhost:11434/api/generate", json={
"model": "llama3.2",
"prompt": "Write a haiku about Python",
"options": {
"temperature": 0.8,
"top_p": 0.95,
"top_k": 40,
"num_predict": 100,
"stop": ["\n\n"]
}
})
Debugging & Optimization Tips
- Outputs too repetitive? Increase frequency_penalty (0.3–0.7) or raise temperature slightly.
- Outputs too random/incoherent? Lower temperature (0.3–0.5) and use top_p=0.9.
- Need reproducibility? Set temperature=0 and use a fixed seed. Note: not 100% guaranteed across API versions.
- Generation stops early? Check for implicit stop sequences or increase max_tokens.
- Generation too long? Add explicit stop sequences or reduce max_tokens.
- Testing prompts? Start with temperature=0 for consistent debugging, then tune for production.
Related Topics
Test Your Knowledge
Score 8/10 or higher to pass
You need to be logged in to take this quiz.
Login to Continue