Pénalités presence et frequency
Mis à jour le 29 juillet 2026
Combattre les répétitions
Les modèles de langage ont une tendance naturelle à se répéter. Cela prend trois formes reconnaissables : un même mot qui revient en boucle sur un paragraphe, une structure de phrase qui se reproduit à l’identique d’une ligne à l’autre, ou un paragraphe entier reformulé sans apport nouveau. La température ne règle pas ce problème — augmenter la randomisation globale dégrade la cohérence sans garantir la variété lexicale. Les paramètres presence_penalty et frequency_penalty offrent un contrôle bien plus fin, à condition de comprendre ce qui les distingue.
Presence penalty : une pénalité fixe
La presence penalty applique une pénalité unique et fixe à chaque token déjà apparu au moins une fois dans la réponse générée. Peu importe qu’il ait été utilisé une fois ou quinze : la pénalité reste la même. L’effet est d’encourager le modèle à puiser dans des mots qu’il n’a pas encore employés, ce qui élargit le vocabulaire de la réponse. Demandez dix adjectifs pour décrire la mer et vous verrez la différence immédiatement — sans pénalité, les variations tournent autour de trois ou quatre champs sémantiques.
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)
Le paramètre accepte des valeurs de -2.0 à 2.0, avec 0.0 par défaut. Une valeur positive pénalise les tokens déjà vus et produit donc plus de diversité ; une valeur négative fait l’inverse et favorise la répétition, ce qui n’a d’usage que dans des cas très particuliers comme la génération de refrains ou de formules répétées. En production, on reste dans la plage 0.0 à 1.5.
Frequency penalty : une pénalité cumulative
La frequency penalty repose sur une mécanique différente : la pénalité est cumulative et croît avec le nombre d’occurrences du token. Plus un mot est répété, moins il devient probable à l’occurrence suivante. Là où la presence penalty ouvre le vocabulaire, celle-ci freine progressivement les mots qui reviennent trop, ce qui la rend particulièrement efficace contre les boucles sur les textes longs.
# 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)
Comme la précédente, elle va de -2.0 à 2.0 avec 0.0 par défaut, une valeur positive pénalisant de manière croissante les tokens fréquents. Sa plage utile en production est cependant plus étroite : 0.0 à 1.0, car son caractère cumulatif la rend plus agressive à valeur égale.
Le tableau suivant résume ce qui les sépare.
| 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 |
Des configurations par intention
En pratique, ces deux paramètres se règlent avec la température, en fonction de ce que produit l’application. Un chatbot demande une légère diversité et pas de répétitions, sans plus. La rédaction créative pousse la presence penalty pour enrichir le vocabulaire tout en gardant la frequency penalty modérée. L’extraction de données, elle, désactive tout : la répétition y est légitime, un même nom de champ doit pouvoir revenir dix fois. Le résumé occupe une position intermédiaire, avec juste ce qu’il faut de pénalité pour éviter le copier-coller du texte source.
# 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
}
Diagnostiquer avant de régler
Régler ces paramètres à l’oreille conduit vite à des ajustements arbitraires. Mesurez plutôt. La fonction ci-dessous calcule un ratio de diversité — mots uniques sur mots totaux — et isole les mots de plus de trois lettres apparaissant plus de deux fois, ce qui filtre les articles et les prépositions dont la répétition est normale. Lancez-la sur le même prompt avec trois valeurs de frequency_penalty et vous verrez le ratio grimper, puis plafonner : ce plafond marque la valeur au-delà de laquelle vous ne gagnez plus rien.
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']}")
Deux façons de tout gâcher
La première consiste à monter trop haut. Au-delà de 1.5, le modèle évite tellement les mots courants qu’il leur substitue des alternatives inappropriées : le texte devient décousu, truffé de termes rares mal employés. Sur une explication du théorème de Pythagore, des pénalités à 2.0 empêchent le modèle de répéter « côté » et « triangle » — c’est-à-dire exactement les mots dont la démonstration a besoin.
# 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
La seconde est de cumuler pénalités élevées et température haute. Chaque mécanisme ajoute sa part d’aléatoire au même processus de sélection, et leur superposition produit du texte quasi aléatoire. Comme pour temperature et top_p, la discipline consiste à ajuster un paramètre à la fois.
# À É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)