Aller au contenu principal

Ancrer les Réponses dans les Sources et Réduire les Hallucinations

Mis à jour le 29 juillet 2026

Le problème des hallucinations en production

Une hallucination est une réponse factuellement fausse mais formulée avec l’assurance d’une réponse juste, et c’est précisément cette assurance qui la rend dangereuse. Un chatbot de support qui invente une procédure envoie l’utilisateur dans une impasse ; un assistant juridique qui cite un article de loi inexistant expose votre client ; un outil médical qui recommande un mauvais dosage crée un risque réel. Dans les trois cas, rien dans la forme de la réponse ne signale le problème.

Le grounding (ancrage) répond à ce risque en contraignant le modèle à fonder ses réponses exclusivement sur des sources vérifiées. Associé au système de citations vu dans les leçons précédentes, il constitue un filet de sécurité à plusieurs mailles : le prompt cadre le comportement attendu, le parsing des citations permet de le vérifier, et le pipeline décide quoi faire des réponses qui ne passent pas le contrôle.

Le system prompt, première ligne de défense

Un prompt vague produit un ancrage vague. Il faut donc énoncer les règles comme un cahier des charges : périmètre des sources, formule exacte à employer en cas d’absence d’information, interdiction de compléter avec les connaissances générales, obligation de citer, et traitement des contradictions entre sources.

system_prompt = """
Vous êtes un assistant documentaire spécialisé.

RÈGLES ABSOLUES :
1. Répondez UNIQUEMENT à partir des sources fournies via les références.
2. Si l'information n'est pas dans les sources, répondez :
   "Cette information ne figure pas dans les sources disponibles."
3. Ne complétez JAMAIS avec vos connaissances générales.
4. Citez chaque affirmation avec la référence correspondante.
5. Si deux sources se contredisent, mentionnez les deux versions.
"""

Ce prompt ne garantit pas l’absence d’hallucinations, et il faut le dire clairement à vos parties prenantes : il en réduit considérablement la fréquence. Les modèles Mistral, entraînés pour le grounding, respectent ces consignes avec un taux de conformité élevé, mais un taux élevé n’est pas un taux de cent pour cent, d’où les étapes suivantes.

Vérifier l’ancrage après coup

La fonction validate_grounding transforme une intuition — « cette réponse a-t-elle l’air sourcée ? » — en mesure. Elle parcourt les chunks de la réponse, additionne la longueur du texte d’un côté, compte les citations et les sources distinctes de l’autre, puis en dérive une densité exprimée en citations pour mille caractères. Une réponse de deux mille signes ne portant qu’une seule référence devient alors immédiatement suspecte, là où l’œil humain l’aurait laissée passer.

from mistralai.models import TextChunk, ReferenceChunk


def validate_grounding(response, min_citations=1):
    """Vérifie que la réponse est ancrée dans les sources."""
    content = response.choices[0].message.content

    text_length = 0
    citation_count = 0
    cited_refs = set()

    for chunk in content:
        if isinstance(chunk, TextChunk):
            text_length += len(chunk.text)
        elif isinstance(chunk, ReferenceChunk):
            citation_count += 1
            cited_refs.update(chunk.reference_ids)

    # Vérifications
    checks = {
        "has_citations": citation_count >= min_citations,
        "citation_count": citation_count,
        "unique_sources": len(cited_refs),
        "text_length": text_length,
        "citations_per_1000_chars": round(
            citation_count / max(text_length / 1000, 1), 1
        )
    }

    checks["is_grounded"] = checks["has_citations"]
    return checks


result = validate_grounding(final_response, min_citations=2)
if not result["is_grounded"]:
    print("ALERTE : Réponse potentiellement non ancrée !")
    print(f"  Citations trouvées : {result['citation_count']}")

Repérer les affirmations sorties du périmètre

Compter les citations ne dit pas si le texte entre deux citations reste fidèle aux sources. detect_ungrounded_claims s’attaque à ce point aveugle avec une heuristique lexicale simple : la réponse est découpée en phrases, les mots de plus de cinq caractères de chaque phrase sont confrontés à la concaténation des snippets, et toute phrase dont moins de trente pour cent des mots-clés apparaissent dans les sources est signalée. Sur un assistant documentaire, ce sont typiquement les phrases de « culture générale » ajoutées par le modèle qui remontent en tête de la liste des suspects.

def detect_ungrounded_claims(response_text, source_snippets):
    """Détecte les phrases qui ne correspondent à aucun snippet."""
    import re

    # Découper la réponse en phrases
    sentences = re.split(r'[.!?]+', response_text)
    sentences = [s.strip() for s in sentences if len(s.strip()) > 20]

    # Concaténer tous les snippets en un seul texte
    all_sources = " ".join(source_snippets).lower()

    suspicious = []
    for sentence in sentences:
        # Extraire les mots-clés significatifs (> 5 chars)
        keywords = [
            w.lower() for w in sentence.split()
            if len(w) > 5
        ]
        # Vérifier la couverture
        matches = sum(1 for kw in keywords if kw in all_sources)
        coverage = matches / max(len(keywords), 1)

        if coverage < 0.3:  # Moins de 30 % de mots-clés trouvés
            suspicious.append({
                "sentence": sentence,
                "coverage": round(coverage, 2)
            })

    return suspicious

Assembler un pipeline de confiance

En production, ces vérifications ne restent pas des scripts d’analyse : elles deviennent une porte que la réponse doit franchir avant d’atteindre l’utilisateur. La classe GroundedRAG matérialise cette porte. Elle génère la réponse citée, la valide, et en mode strict la rejette purement et simplement si l’ancrage est insuffisant, en retournant un statut explicite plutôt qu’un texte douteux. Le score de confiance agrège trois signaux — présence de citations, diversité des sources, densité — pour que votre interface puisse afficher un niveau de fiabilité ou router les cas faibles vers une relecture humaine.

class GroundedRAG:
    """Pipeline RAG avec ancrage et validation."""

    def __init__(self, client, model="mistral-large-latest"):
        self.client = client
        self.model = model

    def query(self, question, references, strict=True):
        """Exécute une requête RAG avec validation d'ancrage."""

        # 1. Générer la réponse avec citations
        response = self._generate_with_citations(
            question, references
        )

        # 2. Valider l'ancrage
        grounding = validate_grounding(response, min_citations=1)

        # 3. En mode strict, rejeter les réponses non ancrées
        if strict and not grounding["is_grounded"]:
            return {
                "status": "rejected",
                "reason": "Réponse insuffisamment ancrée dans les sources",
                "grounding_score": grounding
            }

        # 4. Retourner la réponse validée
        return {
            "status": "ok",
            "response": response,
            "grounding_score": grounding,
            "confidence": self._compute_confidence(grounding)
        }

    def _compute_confidence(self, grounding):
        """Calcule un score de confiance basé sur l'ancrage."""
        score = 0.0
        if grounding["has_citations"]:
            score += 0.4
        if grounding["unique_sources"] >= 2:
            score += 0.3
        if grounding["citations_per_1000_chars"] >= 1.0:
            score += 0.3
        return round(score, 2)

Suivre l’ancrage dans la durée

Un pipeline ancré le jour de sa mise en production peut se déliter ensuite, parce que la base documentaire vieillit, parce qu’un prompt a été retouché ou parce que le trafic se déplace vers des sujets mal couverts. Les cinq indicateurs ci-dessous se calculent directement à partir des sorties de validate_grounding et méritent un tableau de bord permanent : c’est leur dérive, plus que leur valeur absolue, qui vous alerte.

MétriqueCe qu’elle mesure
Taux de citationsPourcentage de réponses contenant au moins une citation
Densité de citationsNombre moyen de citations par 1000 caractères
Diversité des sourcesNombre moyen de sources distinctes par réponse
Taux de rejetPourcentage de réponses rejetées pour ancrage insuffisant
Score de confiance moyenÉvolution du score de confiance dans le temps

Points clés à retenir

  • Le grounding contraint le modèle à répondre uniquement à partir de sources vérifiées
  • Le system prompt strict est la première ligne de défense contre les hallucinations
  • La validation post-génération vérifie programmatiquement l’ancrage de chaque réponse
  • Combinez ces stratégies dans un pipeline de confiance à plusieurs niveaux
  • Monitorez les métriques de grounding en continu pour détecter les dégradations