Repetition Penalties › Combining Penalties with Sampling Strategies
Language AI HandbookAll chapters Repetition Penalties › Combining Penalties with Sampling StrategiesOne section · Sections in this chapter7 / 13 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
In practice, repetition penalties work alongside temperature, top-k, and nucleus sampling. The interactions between these components matter for understanding and tuning generation quality. Each technique operates at a different stage of the logit-to-token pipeline, and applying them in the correct order is essential for the intended behavior.
The typical processing order is well-defined and follows a natural logic:
- Get raw logits from the model's final layer
- Apply repetition/frequency/presence penalties to adjust logit values for previously used tokens
- Apply temperature scaling to control distribution sharpness (dividing logits by temperature)
- Apply top-k or nucleus truncation to limit candidates to the most promising tokens
- Sample from the resulting distribution
This order is not arbitrary. Repetition penalties should be applied before temperature because the penalty magnitudes are calibrated for logit-scale values. If you apply temperature first (which rescales all logits), the same penalty value would have a different effective strength depending on the temperature used. Applying penalties first ensures consistent behavior regardless of temperature.
Similarly, sampling truncation (top-k or nucleus) should come after penalties because the penalties change which tokens are most competitive. If you truncated first, then applied penalties, you might inadvertently keep penalized tokens in the candidate set while excluding better alternatives. Applying penalties before truncation ensures the truncation operates on the post-penalty distribution, correctly identifying the best candidates after repetition is accounted for.
def generate_with_combined_strategies(
model,
tokenizer,
prompt,
repetition_penalty=1.0,
frequency_penalty=0.0,
presence_penalty=0.0,
temperature=1.0,
top_p=0.9,
max_tokens=50,
):
"""
Generate text combining multiple penalty types with sampling strategies.
"""
input_ids = tokenizer.encode(prompt, return_tensors="pt")
generated_ids = input_ids[0].tolist()
prompt_length = len(generated_ids)
token_counts = {}
for _ in range(max_tokens):
with torch.no_grad():
outputs = model(torch.tensor([generated_ids]))
logits = outputs.logits[0, -1, :].clone()
# Track tokens generated so far (excluding prompt)
generated_so_far = generated_ids[prompt_length:]
generated_set = set(generated_so_far)
# Count occurrences
for token_id in generated_so_far:
token_counts[token_id] = token_counts.get(token_id, 0) + 1
# Apply repetition penalty
if repetition_penalty != 1.0:
for token_id in generated_set:
if logits[token_id] > 0:
logits[token_id] = logits[token_id] / repetition_penalty
else:
logits[token_id] = logits[token_id] * repetition_penalty
# Apply frequency penalty
if frequency_penalty > 0:
for token_id, count in token_counts.items():
logits[token_id] = logits[token_id] - frequency_penalty * count
# Apply presence penalty
if presence_penalty > 0:
for token_id in generated_set:
logits[token_id] = logits[token_id] - presence_penalty
# Apply temperature
logits = logits / temperature
# Apply nucleus sampling
sorted_logits, sorted_indices = torch.sort(logits, descending=True)
cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=0), dim=0)
sorted_indices_to_remove = cumulative_probs > top_p
sorted_indices_to_remove[1:] = sorted_indices_to_remove[:-1].clone()
sorted_indices_to_remove[0] = False
indices_to_remove = sorted_indices_to_remove.scatter(
0, sorted_indices, sorted_indices_to_remove
)
logits[indices_to_remove] = float("-inf")
# Sample
probs = F.softmax(logits, dim=0)
next_token = torch.multinomial(probs, num_samples=1).item()
generated_ids.append(next_token)
if next_token == tokenizer.eos_token_id:
break
return tokenizer.decode(generated_ids, skip_special_tokens=True)Prompt: 'Here are some ideas for improving productivity:' ======================================================================
No penalties: Here are some ideas for improving productivity: Show Me The Details First off, let's talk about how much time I spend on Twitter. I know you're not the only one who's tired of being told that you shouldn't spend more time on Twitter than you should. I know that I want to see my tweets read more and more frequently. This is something ----------------------------------------------------------------------
Repetition only (θ=1.2): Here are some ideas for improving productivity: "Don't make a bunch of extra widgets just to get stuff done. Put them on top and do it well." – Gary Dewey, YouTube Engineer (not long ago). Stop making some arbitrary split-screen widget with no taskbar or multitasking effects that makes your life feel like shit for hours at the least! New features: V ----------------------------------------------------------------------
Frequency only (α=0.5): Here are some ideas for improving productivity: Show Me The Details: Show me what you need to get done at work. Make it very clear where the project is being held, and how productive that piece of information will be for a change in your life or career! Focus on one thing per task group; focus more often than not (with less distraction) On each separate activity specific ----------------------------------------------------------------------
Presence only (β=0.8): Here are some ideas for improving productivity: Show Me The Details: Show me what you need to get done at work. Make it very clear where the project is being done, where you're being done and where you're going. Show people the value that you have created. Show people the benefits of your work. Show them how to spend their money. This all comes ----------------------------------------------------------------------
Combined (θ=1.1, α=0.3): Here are some ideas for improving productivity: "Don't make a bunch of extra widgets just to get stuff done. Put them on top and do it well." – Gary Dewey, YouTube Engineer (not long ago). Stop making some arbitrary split-screen widget with no taskbar or multitasking effects that makes your life feel like shit for hours at the least! New features: V ----------------------------------------------------------------------
Comparing the outputs reveals how each penalty type shapes generation. Without penalties, the model may fall into repetitive patterns. Repetition penalty alone provides uniform discouragement of repeated tokens. Frequency penalty creates graduated pressure that builds as tokens accumulate, while presence penalty encourages the model to continuously introduce new vocabulary. The combined approach balances these effects, often producing the most natural-sounding output by gently discouraging repetition without forcing unnatural word choices.
You can also combine penalties with n-gram blocking for a hybrid approach: the probabilistic penalties soften the probability distribution to make repetition less attractive, while n-gram blocking provides a hard guarantee against the most egregious exact repetitions. This combination is particularly effective for tasks like abstractive summarization, where you want rich vocabulary diversity but also need to ensure the summary does not copy entire sentences from the source document.