Aller au contenu principal

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éristiquePresence penaltyFrequency penalty
DéclenchementDès la 1re occurrenceÀ chaque occurrence
CroissanceFixe (même pénalité)Cumulative (augmente)
EffetDiversité du vocabulaireRéduction des répétitions
Meilleur pourExplorer 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)