Aller au contenu principal

Self-consistency : multiples raisonnements

Self-consistency : multiples raisonnements

La self-consistency est une technique qui consiste à générer plusieurs réponses indépendantes au même prompt, puis à sélectionner la réponse la plus fréquente ou la plus cohérente. Elle améliore significativement la fiabilité des réponses, en particulier pour les tâches de raisonnement logique et mathématique.

Le problème qu’elle résout

Un LLM peut donner une réponse différente à chaque appel, même avec le même prompt. Certaines de ces réponses sont correctes, d’autres non. La self-consistency exploite cette variabilité : si le modèle arrive à la même conclusion par plusieurs chemins de raisonnement différents, cette conclusion est probablement correcte.

Implémentation de base

from openai import OpenAI
from collections import Counter

client = OpenAI()

def self_consistency(prompt: str, system: str = "",
                     n: int = 5, model: str = "gpt-5.3") -> dict:
    """Génère n réponses et retourne la plus fréquente."""
    responses = []

    for _ in range(n):
        response = client.responses.create(
            model=model,
            instructions=system + "\nRaisonne étape par étape, puis donne "
                         "ta réponse finale après '>>> RÉPONSE :'",
            input=prompt,
            temperature=0.7  # Température > 0 pour la diversité
        )
        responses.append(response.output_text)

    # Extraire les réponses finales
    answers = []
    for r in responses:
        if ">>> RÉPONSE :" in r:
            answer = r.split(">>> RÉPONSE :")[-1].strip()
            answers.append(answer)

    # Vote majoritaire
    if answers:
        counter = Counter(answers)
        best_answer, count = counter.most_common(1)[0]
        return {
            "answer": best_answer,
            "confidence": count / len(answers),
            "all_answers": dict(counter),
            "total_responses": len(answers)
        }
    return {"answer": None, "confidence": 0}

Exemple concret : classification

system = """Tu es un classificateur de sentiment.
Analyse le texte et raisonne étape par étape.
Donne ta réponse finale après '>>> RÉPONSE :' parmi :
positif, négatif, neutre"""

texte = "Le produit est correct mais la livraison a pris 3 semaines."

result = self_consistency(texte, system, n=7)
print(f"Sentiment : {result['answer']}")
print(f"Confiance : {result['confidence']:.0%}")
print(f"Distribution : {result['all_answers']}")
# Exemple de sortie :
# Sentiment : négatif
# Confiance : 57%
# Distribution : {'négatif': 4, 'neutre': 3}

Version parallèle avec asyncio

Pour réduire la latence, envoyez les requêtes en parallèle :

import asyncio
from openai import AsyncOpenAI

async_client = AsyncOpenAI()

async def self_consistency_async(prompt: str, system: str = "",
                                  n: int = 5) -> dict:
    """Version asynchrone de la self-consistency."""

    async def single_call():
        response = await async_client.responses.create(
            model="gpt-5.3",
            instructions=system + "\nRaisonne puis donne ta réponse "
                         "après '>>> RÉPONSE :'",
            input=prompt,
            temperature=0.7
        )
        return response.output_text

    # Lancer toutes les requêtes en parallèle
    tasks = [single_call() for _ in range(n)]
    results = await asyncio.gather(*tasks)

    # Extraire et voter
    answers = []
    for r in results:
        if ">>> RÉPONSE :" in r:
            answers.append(r.split(">>> RÉPONSE :")[-1].strip())

    counter = Counter(answers)
    best, count = counter.most_common(1)[0] if answers else (None, 0)

    return {
        "answer": best,
        "confidence": count / len(answers) if answers else 0,
        "distribution": dict(counter)
    }

Quand utiliser la self-consistency

Cas d'usage Utile ? Pourquoi
Classification Oui Réponse discrète, vote simple
Raisonnement mathématique Oui Multiples chemins vers la bonne réponse
Extraction d'entités Oui Consensus sur les entités détectées
Rédaction créative Non Pas de "bonne" réponse unique
Résumé de texte Partiel Utile pour les faits clés, pas le style

Optimiser le rapport coût/fiabilité

  • n = 3 : minimum viable pour un vote majoritaire
  • n = 5 : bon compromis coût/fiabilité
  • n = 7-11 : pour les décisions critiques
  • Seuil de confiance : si la confiance est inférieure à 60 %, escaladez vers un humain ou un modèle plus puissant
result = self_consistency(question, system, n=5)

if result["confidence"] < 0.6:
    # Pas de consensus clair, escalader
    result = self_consistency(question, system, n=9, model="gpt-5.4")

Mise en pratique

  1. Implémentez la fonction self_consistency avec la version asynchrone
  2. Testez-la sur 10 questions de classification de sentiment
  3. Comparez la précision avec n=1 (appel unique) vs n=5
  4. Mesurez le gain de fiabilité et le surcoût

Points clés à retenir

  • La self-consistency génère plusieurs réponses et vote pour la meilleure
  • Utilisez une température > 0 pour obtenir de la diversité
  • Efficace pour les tâches avec une réponse discrète (classification, calcul)
  • Inutile pour les tâches créatives sans bonne réponse unique
  • Parallélisez les appels avec asyncio pour limiter la latence