Dix façons de réduire les hallucinations sans retouche fine
Boucles d’ancrage, de contraintes, de récupération et d’évaluation qui réduisent les faits inventés dans les réponses générées.
Ce guide reconstitue le processus allant des matières premières à un système fonctionnel pour : 10 façons de réduire les hallucinations de l’IA sans affiner son modèle. L’accent est mis sur des étapes opérationnelles, des vérifications explicites et du code que vous pouvez intégrer directement dans un dépôt sans devoir deviner l’intention derrière lui. Pour une vue d’ensemble, définissez les entrées, le responsable de chaque étape ainsi que les critères d’achèvement avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans avoir à deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe d’un environnement de démonstration à des environnements partagés.
Le problème de base
Lorsque vous travaillez sur le Problème de base, notez d’abord les exigences : entrées requises, signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système. Mémorisez les instructions stables du système ainsi que les schémas des outils. Envoyer à nouveau un préambule identique est une cause fréquente de gaspillage.
const response = await client.responses.create({
model: "gpt-5",
input: `
Where is order #48291?
`
});
console.log(response.output_text);
Customer
↓
AI Agent
↓
Order System
↓
Actual Order State
↓
AI Agent
↓
Response
1. Fournir un meilleur contexte au modèle
Lorsque vous travaillez sur la section « Donnez un meilleur contexte au modèle », notez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations apportées ultérieurement. Mémorisez les instructions du système stables ainsi que les schémas des outils. Envoyer à nouveau un préambule identique est une cause fréquente de surconsommation.
{
"orderId": "48291",
"status": "SHIPPED",
"carrier": "FedEx",
"trackingNumber": "784512963",
"estimatedDelivery": "2026-08-25"
}
const context = {
order: {
id: "48291",
status: "SHIPPED",
carrier: "FedEx",
trackingNumber: "784512963",
estimatedDelivery: "2026-08-25"
}
};
const response = await client.responses.create({
model: "gpt-5",
input: `
Answer the customer using only the supplied order information.
Context:
${JSON.stringify(context, null, 2)}
Customer:
Where is my order #48291?
`
});
Le schéma
Lorsque vous travaillez sur ce modèle, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables aux scripts volumineux. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Cachez les instructions du système stables ainsi que les schémas des outils. Envoyer à nouveau un préambule identique est une cause fréquente de gaspillage.
Bad:
Customer → LLM → Answer
Better:
Customer
↓
Retrieve state
↓
Build context
↓
LLM
↓
Answer
Lorsque vous travaillez sur ce modèle, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de l’environnement de démonstration à des environnements partagés.
2. Récupérer avant de générer
- « Récupérer avant de générer » fonctionne le mieux lorsqu’il est considéré comme une surface mesurable. Capturez un transcript parfait, un cas d’échec et la note de réversion avant d’élargir le périmètre. Conservez les configurations en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Fixez des limites de tokens par tour et par session. Les outils agents élargissent lourdement le contexte ; des plafonds stricts empêchent que les démonstrations ne se transforment en factures inattendues.
Customer Question
↓
Retrieve
↓
Rank
↓
Build Context
↓
LLM
↓
Answer
const results = await vectorStore.search({
query: customerQuestion,
topK: 10
});
const relevant = results
.filter(item => item.score > 0.8)
.slice(0, 5);
const context = relevant
.map(item => item.content)
.join("\n\n");
const answer = await generateAnswer(
customerQuestion,
context
);
3. Réduire le bruit contextuel
- « Réduire le bruit contextuel » fonctionne le mieux lorsqu’il est considéré comme une donnée mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez en même temps le parcours optimal et celui de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure. Fixez un budget de tokens par tour et par session : les outils agents élargissent de manière importante le contexte ; des plafonds stricts empêchent que les démonstrations se transforment en factures inattendues.
20 retrieved documents
+
15 previous messages
+
10 previous tool responses
+
customer profile
+
product catalog
+
order history
+
promotion metadata
Available Information
↓
Relevance Filtering
↓
Metadata Filtering
↓
Ranking
↓
Deduplication
↓
Context Compression
↓
LLM
const context = results
.filter(x => x.score >= 0.82)
.filter(x => x.metadata.category === "returns")
.filter(x => x.metadata.region === customer.region)
.sort((a, b) => b.score - a.score)
.slice(0, 5)
.map(x => x.content);
4. Utiliser un graphique de connaissances pour des faits structurés
- L’utilisation d’un graphe de connaissances pour les faits structurés fonctionne le mieux lorsqu’il est considéré comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’échec doit pointer vers une seule responsabilité plutôt que vers un processus embrouillé. Fixez des limites de tokens par tour et par session. Les outils agents élargissent lourdement le contexte ; des plafonds stricts empêchent que les démos ne se transforment en factures inattendues.
- L’utilisation d’un graphe de connaissances pour les faits structurés fonctionne le mieux lorsqu’il est considéré comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe d’une démo à des environnements partagés.
Customer
│
└── PLACED → Order
│
├── CONTAINS → Product
│
├── PAID_BY → Payment
│
├── FULFILLED_BY → Warehouse
│
└── SHIPPED_BY → Carrier
Order #48291
↓
FULFILLED_BY
↓
Warehouse #17
MATCH (o:Order {id: "48291"})
-[:FULFILLED_BY]->
(w:Warehouse)
RETURN w.id, w.name, w.location;
{
"orderId": "48291",
"warehouse": {
"id": "WH-17",
"name": "Delhi Fulfillment Center",
"location": "Delhi"
}
}
Without structured knowledge:
User → LLM
↓
Guess
With Knowledge Graph:
User
↓
Entity Identification
↓
Graph Traversal
↓
Verified Relationship
↓
Context
↓
LLM
5. Réponses fondées sur des preuves
Pour la section 5, « Réponses fondées sur des preuves », définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Gardez la configuration en dehors du code de l’application : les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système. Préférez des sorties structurées avec validation de schéma plutôt que du texte libre lorsque l’étape suivante consiste en du code ou une appel à outil.
{
"answer": "Your order is being fulfilled by Warehouse WH-17.",
"confidence": 0.98,
"evidence": [
{
"type": "order_record",
"source": "orders_db",
"orderId": "48291"
},
{
"type": "warehouse_relationship",
"source": "knowledge_graph",
"warehouseId": "WH-17"
}
]
}
For every factual claim:
1. Identify supporting evidence.
2. Use only available evidence.
3. Never invent a source.
4. If evidence is unavailable, say so.
5. Clearly distinguish facts from inference.
if (result.confidence < 0.7) {
return escalateToHuman(result);
}
LLM → Answer
LLM
↓
Answer
↓
Evidence
↓
Confidence
↓
Decision
6. Fournir des outils à l’agent plutôt que de le laisser deviner
Pour le point 6 : donnez aux agents des outils plutôt que de les laisser deviner. Définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu, sans avoir à deviner l’état caché. Documentez conjointement le parcours normal et les scénarios de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations ultérieures. Préférez des sorties structurées avec validation de schéma plutôt que du texte libre lorsque l’étape suivante consiste en du code ou une appel à un outil.
const tools = [{
name: "get_refund_status",
description: "Retrieve the current refund status for an order",
parameters: {
type: "object",
properties: {
orderId: {
type: "string"
}
},
required: ["orderId"]
}
}];
Customer
↓
LLM
↓
get_refund_status()
↓
Payment System
↓
Actual Refund State
↓
LLM
↓
Customer
7. Valider les entrées et les sorties des outils
Pour 7. Valider les entrées et les sorties des outils, il faut définir les entrées, le responsable de l’étape ainsi que les critères d’arrêt avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Préférer des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Préférer des sorties structurées avec validation de schéma à du texte libre lorsque l’étape suivante consiste en du code ou une appel d’outil. Pour 7. Valider les entrées et les sorties des outils, il faut définir les entrées, le responsable de l’étape ainsi que les critères d’arrêt avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrer les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite des factures inattendues lorsque le processus passe d’un environnement de démonstration à des environnements partagés.
{
"orderId": "48291",
"amount": "one hundred",
"currency": "dollars"
}
{
"orderId": "48291",
"amount": 100,
"currency": "USD"
}
import { z } from "zod";
const RefundRequest = z.object({
orderId: z.string(),
amount: z.number().positive(),
currency: z.enum(["USD", "EUR", "GBP", "INR"])
});
const refundRequest = RefundRequest.parse(
modelOutput
);
if (refundRequest.amount > order.total) {
throw new Error(
"Refund amount exceeds order total"
);
}
LLM
↓
Schema Validation
↓
Business Validation
↓
Permission Check
↓
Execute
↓
Response Validation
↓
Accept / Retry / Escalate
8. Séparer les faits de la réflexion
Lorsque vous travaillez sur le point 8. Séparer les faits de la réflexion, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de maintenir l’honnêteté des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système. Mémorisez les instructions stables du système ainsi que les schémas des outils. Envoyer à nouveau un préambule identique est une cause fréquente de gaspillage de ressources.
{
"facts": [
"Order 48291 is shipped",
"Order 48291 is fulfilled by Warehouse WH-17",
"Warehouse WH-17 is currently operating"
],
"reasoning": [
"The order is likely to remain on schedule"
],
"conclusion": "The order is currently expected to arrive on time."
}
Was the fact wrong?
OR
Was the reasoning wrong?
FACT
→ Order shipped
FACT
→ Estimated delivery: Aug 25
INFERENCE
→ Delivery is currently expected on schedule
9. Apprendre des exécutions réussies et échouées
Lorsque vous travaillez sur la section 9 « Apprendre des exécutions réussies et échouées », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations apportées ultérieurement. Mémorisez les instructions du système stables ainsi que les schémas des outils. Envoyer à nouveau un préambule identique est une cause fréquente de surconsommation des ressources.
{
"orderId": "48291",
"status": "PROCESSING",
"cancelable": true
}
cancel_order(48291)
{
"success": true,
"cancellationId": "CAN-83921"
}
{
"task": "Cancel order",
"orderState": "PROCESSING",
"action": "cancel_order",
"result": "SUCCESS",
"cancellationId": "CAN-83921"
}
New Request
↓
Find Similar Successful Execution
↓
Retrieve Relevant Pattern
↓
Check Current Order State
↓
Generate Action
↓
Validate
↓
Execute
Attempt 1
↓
cancel_order()
↓
Rejected: Order already shipped
↓
Agent retrieves shipping information
↓
Explains cancellation is unavailable
Execute
↓
Observe
↓
Evaluate
↓
Store Experience
↓
Improve Future Context
10. Évaluer chaque modification
Lors de l’étape 10 « Évaluer chaque modification », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle garantit l’honnêteté des modifications ultérieures du code. Préférez des unités petites et testables plutôt que des scripts volumineux. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité et non un processus complexe. Cachez les instructions du système stables ainsi que les schémas des outils. Envoyer à nouveau un préambule identique est une cause fréquente de gaspillage. Lors de l’étape 10 « Évaluer chaque modification », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle garantit l’honnêteté des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de l’environnement de démonstration à des environnements partagés.
[
{
"question": "Where is order 48291?",
"expected": "SHIPPED"
},
{
"question": "Which warehouse fulfills order 48291?",
"expected": "WH-17"
},
{
"question": "Can order 48291 be cancelled?",
"expected": false
}
]
Answer Accuracy
Groundedness
Retrieval Precision
Tool Selection Accuracy
Tool Success Rate
Task Success Rate
Recovery Rate
Hallucination Rate
Latency
Cost
Before After
Answer Accuracy 72% 95%
Groundedness 69% 97%
Tool Success 81% 98%
Hallucination Rate 17% 3%
Change
↓
Test
↓
Measure
↓
Compare
↓
Improve
Assembler tout cela
La méthode « Assembler tout cela » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Fixez des limites budgétaires par tour et par session. Les outils agents élargissent de manière importante le contexte ; des plafonds stricts empêchent que les démonstrations se transforment en factures inattendues.
┌──────────────────┐
│ Knowledge Graph │
└────────┬─────────┘
│
┌────────▼─────────┐
│ RAG / Search │
└────────┬─────────┘
│
Customer → Intent → Context Engine → LLM
↑ │
│ ▼
Memory Tool Selection
↑ │
│ ▼
│ Validation
│ │
│ ▼
│ Real Systems
│ │
│ ▼
└─────── Feedback
│
▼
Evaluation
La leçon plus importante
« The Bigger Lesson » fonctionne le mieux lorsqu’il est considéré comme une surface mesurable. Recueillez un exemple réussi, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez en même temps le parcours optimal et celui de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’une mise en forme ultérieure. Fixez un budget de tokens par tour et par session : les outils agents élargissent de manière importante le contexte ; des plafonds stricts empêchent que les démonstrations se transforment en factures inattendues.
Le LLM n’est qu’une partie du système
The LLL n’est qu’une partie du système et fonctionne le mieux lorsqu’il est considéré comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’erreur doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Fixez un budget de tokens par tour et par session. Les outils agents élargissent fortement le contexte ; des plafonds stricts empêchent que les démos ne se transforment en factures inattendues. The LLL n’est qu’une partie du système et fonctionne le mieux lorsqu’il est considéré comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démo aux environnements partagés.
┌───────────────────┐
│ Knowledge + RAG │
└─────────┬─────────┘
↓
Customer → Context → LLM → Tools → Real World
↑ ↓ ↓
Memory Reasoning Validation
↑ ↓
└──── Feedback
↓
Evaluation
Pensée finale
En guise de conclusion, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système. Préférez des sorties structurées avec validation de schéma plutôt que du texte libre lorsque l’étape suivante consiste en du code ou une appel à outil.
Liste de contrôle opérationnelle
La liste de contrôle opérationnelle est la plus efficace lorsqu’elle est considérée comme une surface mesurable. Recueillez un enregistrement type, un cas d’échec et une note de réversion avant d’élargir le périmètre. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définissez des vérifications de succès et refusez toute exécution partielle silencieuse.
Budget de tokens par tour et par session. Les outils agents élargissent le contexte de manière importante ; des plafonds stricts empêchent que les démos ne se transforment en factures inattendues.
Ajoutez un test de fonctionnement qui met à l’épreuve le parcours critique dans le CI en utilisant des fixtures, et non des API payantes en temps réel, chaque fois que le budget le permet.
Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le parcours passe de la démo aux environnements partagés.
Budget de tokens par tour et par session. Les outils agents élargissent le contexte de manière importante ; des plafonds stricts empêchent que les démos ne se transforment en factures inattendues.
Au préalable de promouvoir l’ensemble technologique, figez les versions, conservez une transcription exemplaire pour le parcours critique, et vérifiez les étapes de réversion. Les environnements partagés nécessitent des limites de débit, des contrôles d’attribution et un responsable clair pour la rotation des secrets. Préférez une fiabilité sans faille à des démos brillantes mais ponctuelles.
Note de lot pour d3bfab080c19 : éviter de placer les clés du fournisseur dans le répertoire, fixer une limite pour les tokens par session, et stocker les transcriptions à côté des fichiers d’évaluation afin que les remplacements ultérieurs de modèles restent comparables.