Pénalités presence et frequency
Combattre les répétitions
Les modèles de langage ont une tendance naturelle à se répéter — un même mot revient en boucle, une structure de phrase se reproduit à l’identique, ou un paragraphe entier est reformulé sans apport nouveau. Les paramètres presence_penalty et frequency_penalty offrent un contrôle fin sur ce comportement.
Presence penalty
La presence penalty applique une pénalité unique et fixe à chaque token qui est déjà apparu au moins une fois dans la réponse générée. Peu importe combien de fois le token a été utilisé — la pénalité est la même.
from mistralai import Mistral
import os
client = Mistral(api_key=os.getenv("MISTRAL_API_KEY"))
# Sans pénalité — le modèle peut se répéter
response = client.chat.complete(
model="mistral-large-latest",
messages=[{"role": "user", "content": "Listez 10 adjectifs pour décrire la mer."}],
presence_penalty=0.0
)
print("Sans pénalité :", response.choices[0].message.content)
# Avec presence penalty — encourage la diversité du vocabulaire
response = client.chat.complete(
model="mistral-large-latest",
messages=[{"role": "user", "content": "Listez 10 adjectifs pour décrire la mer."}],
presence_penalty=1.0
)
print("Avec pénalité :", response.choices[0].message.content)
Effet : le modèle est encouragé à utiliser des mots qu’il n’a pas encore employés, élargissant le vocabulaire de la réponse.
Plage de valeurs
- -2.0 à 2.0, défaut 0.0
- Valeur positive : pénalise les tokens déjà vus (plus de diversité)
- Valeur négative : favorise les tokens déjà vus (plus de répétition)
- Valeurs courantes en production : 0.0 à 1.5
Frequency penalty
La frequency penalty applique une pénalité cumulative qui augmente avec le nombre d’occurrences d’un token. Plus un token est répété, plus il est pénalisé.
# Sans pénalité de fréquence
response = client.chat.complete(
model="mistral-large-latest",
messages=[{"role": "user", "content": "Rédigez un paragraphe sur l'intelligence artificielle."}],
frequency_penalty=0.0
)
print("Sans pénalité :", response.choices[0].message.content)
# Avec frequency penalty — réduit les tokens très fréquents
response = client.chat.complete(
model="mistral-large-latest",
messages=[{"role": "user", "content": "Rédigez un paragraphe sur l'intelligence artificielle."}],
frequency_penalty=0.8
)
print("Avec pénalité :", response.choices[0].message.content)
Effet : les mots qui apparaissent souvent sont progressivement défavorisés. Chaque occurrence supplémentaire rend le token encore moins probable.
Plage de valeurs
- -2.0 à 2.0, défaut 0.0
- Valeur positive : pénalise de manière croissante les tokens fréquents
- Valeurs courantes en production : 0.0 à 1.0
Différence entre les deux
| Caractéristique | Presence penalty | Frequency penalty |
|---|---|---|
| Déclenchement | Dès la 1re occurrence | À chaque occurrence |
| Croissance | Fixe (même pénalité) | Cumulative (augmente) |
| Effet | Diversité du vocabulaire | Réduction des répétitions |
| Meilleur pour | Explorer de nouveaux sujets | Éviter les boucles de mots |
Combinaisons recommandées
# Chatbot — légère diversité, pas de répétitions
CONFIG_CHATBOT = {
"temperature": 0.7,
"presence_penalty": 0.3,
"frequency_penalty": 0.3
}
# Rédaction créative — vocabulaire riche, pas de boucles
CONFIG_CREATIF = {
"temperature": 0.9,
"presence_penalty": 0.8,
"frequency_penalty": 0.5
}
# Extraction de données — pas de pénalités (réponse exacte)
CONFIG_EXTRACTION = {
"temperature": 0.0,
"presence_penalty": 0.0,
"frequency_penalty": 0.0
}
# Résumé — un peu de diversité pour éviter le copier-coller
CONFIG_RESUME = {
"temperature": 0.3,
"presence_penalty": 0.2,
"frequency_penalty": 0.4
}
Cas concret : diagnostiquer les répétitions
def analyze_repetition(text: str) -> dict:
"""Analyse le taux de répétition d'un texte généré."""
words = text.lower().split()
total = len(words)
unique = len(set(words))
# Compter les mots qui apparaissent plus de 2 fois
from collections import Counter
counts = Counter(words)
repeated = {w: c for w, c in counts.items() if c > 2 and len(w) > 3}
return {
"total_mots": total,
"mots_uniques": unique,
"ratio_diversite": round(unique / total, 3) if total > 0 else 0,
"mots_repetes": dict(sorted(repeated.items(), key=lambda x: -x[1])[:10])
}
# Tester avec et sans pénalités
for fp in [0.0, 0.5, 1.0]:
response = client.chat.complete(
model="mistral-large-latest",
messages=[{"role": "user", "content": "Rédigez un long paragraphe sur les énergies renouvelables."}],
max_tokens=500,
frequency_penalty=fp
)
text = response.choices[0].message.content
stats = analyze_repetition(text)
print(f"frequency_penalty={fp} | Diversité: {stats['ratio_diversite']} | Répétés: {stats['mots_repetes']}")
Pièges à éviter
Valeurs trop élevées
Des pénalités supérieures à 1.5 produisent des textes étranges — le modèle évite tellement les mots courants qu’il choisit des alternatives inappropriées :
# MAUVAIS — pénalité trop forte
response = client.chat.complete(
model="mistral-large-latest",
messages=[{"role": "user", "content": "Expliquez le théorème de Pythagore."}],
presence_penalty=2.0,
frequency_penalty=2.0
)
# Résultat : texte décousu, mots rares mal employés
Ne pas combiner avec temperature haute
Des pénalités élevées combinées à une température haute produisent du texte quasi-aléatoire :
# À ÉVITER — trop de randomisation
{"temperature": 1.5, "presence_penalty": 1.5, "frequency_penalty": 1.5}
# CORRECT — ajuster un paramètre à la fois
{"temperature": 0.7, "presence_penalty": 0.5, "frequency_penalty": 0.3}
Points clés à retenir
- Presence penalty : pénalité fixe dès qu’un token est vu — élargit le vocabulaire
- Frequency penalty : pénalité cumulative proportionnelle à la fréquence — combat les boucles
- Les deux vont de -2.0 à 2.0, défaut 0.0
- Restez dans la plage 0.0 à 1.0 en production pour la plupart des cas
- Ne combinez pas des valeurs élevées avec une température haute
- Désactivez les pénalités pour l’extraction et la classification (où la répétition est acceptable)