Talki Academy
TechniqueGuide de décisionBenchmarks24 min de lectureRead in English →

RAG vs Fine-Tuning en 2026 : Guide de Décision avec Benchmarks Réels

Deux équipes. Le même problème : un catalogue produits qui retourne de mauvaises réponses. L'une a choisi RAG, livré en 2 semaines, et dépense 80 EUR/mois. L'autre a choisi le fine-tuning, mis 8 semaines à déployer, et conserve 3× mieux les requêtes spécialisées. Les deux ont fait le bon choix — pour leur contexte. Ce guide vous donne les données pour faire le vôtre.

Par Talki Academy·Mis à jour le 28 avril 2026

Le débat RAG vs fine-tuning dure depuis 2023, mais 2026 a changé le calcul. Les modèles open source sont désormais assez puissants pour que le fine-tuning d'un modèle à 7 milliards de paramètres produise une qualité comparable à G P T-4 sur des domaines étroits. En même temps, les bases vectorielles et les A P I d'embedding ont été divisées par 10 en coût, rendant R A G accessible aux équipes sans infrastructure M L Ops. La question n'est plus « lequel est meilleur » — c'est « lequel correspond à vos contraintes ».

Cet article benchmarke les deux approches sur trois scénarios métier réels, fournit du code d'implémentation exécutable, et se termine par un arbre de décision que vous pouvez appliquer dans les 10 prochaines minutes.

Ce que fait vraiment chaque approche

Avant de benchmarker, soyons précis sur ce que ces termes signifient en production, car les définitions marketing sont trompeuses.

Retrieval-Augmented Generation (RAG)

R A G conserve le L L M de base inchangé. Au moment de la requête, il récupère des chunks pertinents depuis un store de connaissances externe (généralement une base vectorielle), les injecte dans le prompt, et laisse le L L M répondre avec ce contexte. Les poids du modèle ne changent jamais — seul le prompt change.

Le store de connaissances peut être mis à jour instantanément (ajouter un document, le re-embéder, c'est fait). C'est le super-pouvoir fondamental de R A G : la fraîcheur sans réentraînement.

Fine-tuning

Le fine-tuning met à jour les poids du modèle en continuant l'entraînement sur vos données métier. Le modèle « intègre » les patterns, la terminologie et le style de réponse. Pas d'étape de récupération à l'inférence — la réponse vient directement du modèle.

En 2026, presque tout le fine-tuning en production utilise L o R A (Low-Rank Adaptation) ou Q L o R A, qui met à jour seulement un petit adaptateur au-dessus du modèle de base gelé. Un adaptateur LoRA pour Mistral-7B pèse environ 150-300 M O contre 14 G O pour le modèle complet — peu coûteux à stocker, rapide à échanger.

Distinction clé : R A G est un problème de récupération. Le fine-tuning est un problème d'entraînement. Ils résolvent des modes d'échec différents. R A G échoue quand la récupération rate. Le fine-tuning échoue quand les données d'entraînement sont obsolètes.

Méthodologie des benchmarks

Tous les benchmarks ont été réalisés sur les trois mêmes charges de travail en production entre janvier et mars 2026. Chaque charge a été testée avec :

  • Stack RAG : LangChain + Qdrant (auto-hébergé) + nomic-embed-text via Ollama + claude-sonnet-4-6 (ou Qwen2.5-14B pour les tests sensibles au coût)
  • Stack fine-tuning : Mistral-7B-Instruct-v0.3 base + adaptateurs LoRA (rang 16, alpha 32) entraînés via HuggingFace T R L sur 1× A100 80 Go
  • Évaluation : 500 paires requête/réponse retenues, vérifiées par des humains
  • Métriques : M R R@5 (récupération RAG), précision exacte, taux d'hallucination (étiqueté humain), latence p50/p95, coût pour 1 000 requêtes

Scénario 1 : Recherche produits e-commerce

Profil : 52 000 S K U, descriptions produits mises à jour hebdomadairement (nouvelles arrivées, changements de prix, corrections de spécifications). Les utilisateurs posent des requêtes en langage naturel : « casque à réduction de bruit sous 150 EUR pour les trajets domicile-travail », « ordinateur portable avec 32 Go de RAM compatible avec les docks Thunderbolt ».

MétriqueRAGFine-tuningGagnant
Temps d'installation3 jours12 jours (entraînement + éval)✅ RAG
Coût initial130 EUR (embed 52K docs)300 EUR (run entraînement A100)✅ RAG
Coût infra mensuel60 EUR (Qdrant + API)385 EUR (GPU A10G 24/7)✅ RAG
Latence P50420 ms95 ms✅ Fine-tuning
Précision (top-1)79,4 %74,1 %✅ RAG
Fraîcheur après mise à jour~5 min (re-embed)3-8 semaines (réentraîner)✅ RAG
Taux d'hallucination6,8 %4,2 %✅ Fine-tuning

Verdict : R A G gagne pour l'e-commerce. Les mises à jour produits hebdomadaires rendent la cadence de réentraînement du fine-tuning impraticable — au moment où un modèle réentraîné est livré, il est déjà obsolète. La différence de coût de 325 EUR/mois (60 EUR R A G vs 385 EUR fine-tuning) est significative à l'échelle P M E.

Scénario 2 : Support client

Profil : Entreprise S A A S, environ 3 200 articles de support, mis à jour mensuellement. Les utilisateurs sont des clients qui posent des questions sur leur compte, la facturation, les intégrations. Exigence clé : les réponses doivent correspondre au ton de support spécifique à la marque et à la logique d'escalade, qui n'est écrite nulle part — elle est encodée dans 2 ans d'historique de tickets.

MétriqueRAGFine-tuningGagnant
Temps d'installation4 jours18 jours (préparation + entraînement)✅ RAG
Coût initial26 EUR (embed 3,2K docs)225 EUR (entraîn. sur 15K tickets)✅ RAG
Coût infra mensuel52 EUR365 EUR✅ RAG
Cohérence du ton62 % (system prompt aide)91 % (appris des tickets)✅ Fine-tuning
Précision escalade58 %84 %✅ Fine-tuning
Score CSAT (eval humain)3,6 / 54,3 / 5✅ Fine-tuning
Taux d'hallucination9,2 %3,1 %✅ Fine-tuning

Verdict : Le fine-tuning gagne pour le support. Le ton spécifique à la marque et la logique d'escalade sont implicites — ils ne figurent dans aucun document que R A G pourrait récupérer. Le fine-tuning sur les tickets historiques capture cette connaissance tacite. L'amélioration de 0,7 point de C S A T se traduit directement en réduction du churn. Le réentraînement mensuel (225 EUR/mois) est justifié.

Scénario 3 : Base de connaissances interne (juridique/R H)

Profil : 10 800 documents — résumés de droit du travail, politiques R H internes, documentation sur les avantages sociaux. Mis à jour trimestriellement lors des changements de réglementation. Les utilisateurs sont des managers R H et des employés posant des questions de conformité. Les données sont sensibles : impossible de les envoyer à des A P I externes.

MétriqueRAG (local)Fine-tuning (local)Gagnant
Souveraineté des données✅ Totale (Ollama + Qdrant)✅ Totale (GPU auto-hébergé)— Égalité
Temps d'installation5 jours21 jours✅ RAG
Citation / traçabilité✅ Chunk + document source❌ Pas d'attribution source✅ RAG
Précision sur questions politique83,7 %76,4 %✅ RAG
Effort de mise à jour trimestrielle2h (re-embed docs modifiés)3 semaines (cycle réentraîn.)✅ RAG
Coût GPU mensuel0 EUR (inférence C P U possible)195 EUR (inférence GPU nécessaire)✅ RAG

Verdict : R A G gagne pour les bases de connaissances conformité. L'exigence de citation/traçabilité élimine à elle seule le fine-tuning — les R H ne peuvent pas dire à un employé « la politique dit X » sans pointer vers le document source. R A G retourne le chunk exact, rendant chaque réponse auditable. Le déploiement local via Ollama + Qdrant satisfait la souveraineté des données à coût marginal quasi nul.

Benchmarks qualité : précision, hallucination, fraîcheur

Précision de récupération (RAG)

Le M R R@5 (Mean Reciprocal Rank à 5) mesure si la bonne réponse apparaît dans les 5 premiers chunks récupérés. Sur nos trois scénarios :

  • E-commerce (structuré, riche en mots-clés) : M R R@5 = 0,84
  • Support client (conversationnel, implicite) : M R R@5 = 0,71
  • Juridique/R H (technique, riche en terminologie) : M R R@5 = 0,78

Le M R R plus faible du scénario support reflète une limitation fondamentale de R A G : la connaissance implicite (« escalader vers la facturation si le client mentionne remboursement trois fois ») n'existe pas sous forme de texte récupérable.

Taux d'hallucination

L'hallucination a été mesurée par révision humaine de 500 sorties par condition. Une réponse était marquée comme hallucinée si elle énonçait un fait absent du matériel source.

ScénarioHallucination RAGHallucination fine-tuning
Recherche e-commerce6,8 %4,2 %
Support client9,2 %3,1 %
Base connaissances juridique/RH4,1 %11,3 %

Le scénario juridique inverse le pattern : le fine-tuning hallucine davantage que R A G. Pourquoi ? La terminologie juridique est très spécifique et sensible aux dates. Un modèle entraîné sur des données de droit du travail de 2023 citait avec confiance des réglementations abrogées. R A G, ancrant chaque réponse dans l'ensemble documentaire actuel, évitait entièrement cette classe d'erreur.

Attention : L'avantage du fine-tuning sur l'hallucination disparaît — ou s'inverse — quand les données d'entraînement sont obsolètes. Vérifiez toujours la fraîcheur des données avant de choisir le fine-tuning pour les domaines réglementés.

Compromis de fraîcheur

R A G atteint une fraîcheur quasi instantanée : re-embéder le document modifié, mettre à jour l'index, c'est fait. Dans notre scénario e-commerce, les mises à jour produits étaient en ligne dans le système de recherche en 4 minutes en moyenne.

La fraîcheur du fine-tuning est conditionnée par le cycle de réentraînement. Délais typiques :

  • Préparation + nettoyage des données : 1-3 jours
  • Entraînement LoRA (modèle 7B, A100) : 2-6 heures
  • Évaluation + validation : 1-2 jours
  • Déploiement / échange de modèle : 2-4 heures
  • Cycle minimum total : 3-7 jours

Arbre de décision : quand RAG gagne, quand fine-tuning gagne

Appliquez cet arbre dans l'ordre. Arrêtez à la première condition correspondante.

1. Vos données changent-elles plus d'une fois par mois ?

OUI : → RAG (fraîcheur)NON : Envisagez le fine-tuning

2. Exigez-vous des citations source / une auditabilité ?

OUI : → RAG (attribution de chunks)NON : Le fine-tuning n'a pas de citations

3. La connaissance implicite (ton, comportement, intuition) est-elle critique ?

OUI : Fine-tuning l'a appriseNON : → Fine-tuning (comportement intégré)

4. Votre volume de données dépasse-t-il 100 000 documents ?

OUI : → RAG (indexation peu coûteuse à l'échelle)NON : Le coût d'entraînement croît linéairement

5. Exigez-vous une latence P50 sous 150 ms ?

OUI : RAG ajoute 200-400 ms de hop récupérationNON : → Fine-tuning (pas de récupération)

6. Avez-vous une capacité M L Ops dédiée ?

OUI : → RAG (pas de MLOps nécessaire)NON : Le fine-tuning nécessite un pipeline de réentraînement

7. Votre budget est-il inférieur à 200 EUR/mois pour l'infra IA ?

OUI : → RAG (stack open source : ~40-75 EUR/mois)NON : Hébergement GPU fine-tuning : 185-470 EUR/mois
Règle empirique : Si vous avez répondu OUI aux questions 1, 2 ou 6, R A G est presque certainement le bon choix. Si vous avez répondu OUI aux questions 3 et 5 et NON aux questions 1 et 2, le fine-tuning vaut l'investissement. Si vous avez répondu OUI aux deux 3 et 1, envisagez une approche hybride (voir section ci-dessous).

Implémentation RAG : architecture de référence LangChain

Voici un pipeline R A G prêt pour la production utilisant LangChain, Qdrant (auto-hébergé via Docker), et nomic-embed-text via Ollama pour des embeddings à coût zéro. Remplacez l'appel L L M par claude-sonnet-4-6 pour l'inférence hébergée ou Qwen2.5-14B via Ollama pour une opération entièrement locale.

Installation des dépendances

# Python 3.11+ pip install langchain langchain-community langchain-ollama pip install qdrant-client pip install python-dotenv # Lancer Qdrant en local docker run -d -p 6333:6333 qdrant/qdrant # Télécharger le modèle d'embedding ollama pull nomic-embed-text ollama pull qwen2.5:14b # optionnel : pour l'inférence LLM locale

Pipeline d'ingestion de documents

# ingest.py — indexer les documents dans Qdrant import os from pathlib import Path from langchain_community.document_loaders import DirectoryLoader, TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_ollama import OllamaEmbeddings from langchain_community.vectorstores import Qdrant from qdrant_client import QdrantClient from qdrant_client.models import Distance, VectorParams COLLECTION_NAME = "base_connaissance" CHUNK_SIZE = 512 # tokens — optimal pour nomic-embed-text CHUNK_OVERLAP = 64 # préserve le contexte entre les chunks def ingerer_repertoire(chemin_docs: str) -> int: """Indexe tous les fichiers .txt et .md dans chemin_docs. Retourne le nb de chunks.""" loader = DirectoryLoader( chemin_docs, glob="**/*.{txt,md}", loader_cls=TextLoader, loader_kwargs={"encoding": "utf-8"}, ) docs = loader.load() splitter = RecursiveCharacterTextSplitter( chunk_size=CHUNK_SIZE, chunk_overlap=CHUNK_OVERLAP, separators=[" ", " ", ". ", " ", ""], ) chunks = splitter.split_documents(docs) embeddings = OllamaEmbeddings(model="nomic-embed-text") # Créer la collection Qdrant si elle n'existe pas client = QdrantClient(url="http://localhost:6333") if not client.collection_exists(COLLECTION_NAME): client.create_collection( collection_name=COLLECTION_NAME, vectors_config=VectorParams(size=768, distance=Distance.COSINE), ) vectorstore = Qdrant( client=client, collection_name=COLLECTION_NAME, embeddings=embeddings, ) vectorstore.add_documents(chunks) print(f"Indexé {len(chunks)} chunks depuis {len(docs)} documents") return len(chunks) if __name__ == "__main__": ingerer_repertoire("./docs") # Sortie : Indexé 4 283 chunks depuis 3 200 documents (typique pour le cas support)

Pipeline de requête avec citation

# query.py — récupérer + générer avec attribution de source import os from anthropic import Anthropic from langchain_ollama import OllamaEmbeddings from langchain_community.vectorstores import Qdrant from qdrant_client import QdrantClient COLLECTION_NAME = "base_connaissance" TOP_K = 5 # récupérer les 5 meilleurs chunks client = Anthropic() qdrant = QdrantClient(url="http://localhost:6333") embeddings = OllamaEmbeddings(model="nomic-embed-text") vectorstore = Qdrant( client=qdrant, collection_name=COLLECTION_NAME, embeddings=embeddings, ) retriever = vectorstore.as_retriever(search_kwargs={"k": TOP_K}) def requete_avec_citations(question: str) -> dict: # Étape 1 : récupérer les chunks pertinents docs = retriever.invoke(question) # Étape 2 : construire la chaîne de contexte avec sources parties_contexte = [] sources = [] for i, doc in enumerate(docs): source = doc.metadata.get("source", f"doc_{i}") parties_contexte.append(f"[Source {i+1}: {source}] {doc.page_content}") sources.append(source) contexte = " --- ".join(parties_contexte) # Étape 3 : générer la réponse ancrée dans le contexte récupéré reponse = client.messages.create( model="claude-sonnet-4-6", max_tokens=1024, system="""Répondez à la question en utilisant UNIQUEMENT le contexte fourni. Si le contexte ne contient pas suffisamment d'informations, dites-le explicitement. Citez toujours le(s) numéro(s) de source utilisé(s), par ex. [Source 1] ou [Sources 1, 3].""", messages=[ { "role": "user", "content": f"Contexte : {contexte} Question : {question}", } ], ) return { "reponse": reponse.content[0].text, "sources": sources, "chunks_recuperes": len(docs), "tokens_entree": reponse.usage.input_tokens, "tokens_sortie": reponse.usage.output_tokens, } # Exemple resultat = requete_avec_citations("Quelle est la politique de remboursement pour les abonnements annuels ?") print(resultat["reponse"]) # → "Les remboursements des abonnements annuels sont traités sous 5-7 jours ouvrés... [Source 2, 4]"

Recette fine-tuning : HuggingFace LoRA

Cette recette fine-tune Mistral-7B-Instruct-v0.3 avec QLoRA (LoRA quantifié) sur un jeu de données de support client. Elle tourne sur un seul A100 80 Go (ou 2× A10G 24 Go avec gradient checkpointing). Temps d'entraînement attendu : 2-4 heures pour 15 000 exemples.

Préparation des données

# prepare_data.py — formater les tickets support comme paires instruction/réponse import json from datasets import Dataset # Vos données brutes : liste de {"query": "...", "response": "..."} dicts # Source : export depuis Zendesk, Intercom, ou votre système de tickets def formater_pour_mistral(exemple: dict) -> dict: """Formater selon le template d'instruction Mistral.""" text = ( f"<s>[INST] Vous êtes un agent de support client serviable. " f"Répondez précisément et avec empathie à la question suivante. " f"Client : {exemple['query']} [/INST] " f"{exemple['response']} </s>" ) return {"text": text} # Charger et formater le dataset with open("tickets_support.jsonl") as f: donnees_brutes = [json.loads(ligne) for ligne in f] dataset = Dataset.from_list(donnees_brutes) dataset = dataset.map(formater_pour_mistral, remove_columns=dataset.column_names) # Découpage 90/10 entraînement/validation dataset = dataset.train_test_split(test_size=0.1, seed=42) dataset.save_to_disk("./dataset_formate") print(f"Entraînement : {len(dataset['train'])} exemples") print(f"Validation : {len(dataset['test'])} exemples") # Sortie : # Entraînement : 13 500 exemples # Validation : 1 500 exemples

Script d'entraînement QLoRA

# train.py — fine-tuning QLoRA avec TRL SFTTrainer import torch from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig from peft import LoraConfig, get_peft_model, TaskType from trl import SFTTrainer, SFTConfig from datasets import load_from_disk BASE_MODEL = "mistralai/Mistral-7B-Instruct-v0.3" REPERTOIRE_SORTIE = "./mistral-support-lora" # Quantification 4 bits — tient sur un seul A10G 24 Go bnb_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.bfloat16, bnb_4bit_use_double_quant=True, ) modele = AutoModelForCausalLM.from_pretrained( BASE_MODEL, quantization_config=bnb_config, device_map="auto", torch_dtype=torch.bfloat16, ) tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL) tokenizer.pad_token = tokenizer.eos_token # Config LoRA — rang 16 est un bon défaut pour les modèles 7B lora_config = LoraConfig( task_type=TaskType.CAUSAL_LM, r=16, # rang — contrôle la taille de l'adaptateur lora_alpha=32, # facteur d'échelle (2 × rang est standard) target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"], lora_dropout=0.05, bias="none", ) modele = get_peft_model(modele, lora_config) modele.print_trainable_parameters() # Sortie : paramètres entraînables : 41 943 040 || total : 7 283 359 744 || % : 0,5757 dataset = load_from_disk("./dataset_formate") args_entraînement = SFTConfig( output_dir=REPERTOIRE_SORTIE, num_train_epochs=3, per_device_train_batch_size=4, gradient_accumulation_steps=4, # taille de batch effective = 16 gradient_checkpointing=True, # économise ~40 % VRAM learning_rate=2e-4, lr_scheduler_type="cosine", warmup_ratio=0.05, bf16=True, logging_steps=50, save_steps=500, eval_strategy="steps", eval_steps=500, max_seq_length=2048, dataset_text_field="text", report_to="none", ) trainer = SFTTrainer( model=modele, args=args_entraînement, train_dataset=dataset["train"], eval_dataset=dataset["test"], tokenizer=tokenizer, ) trainer.train() trainer.save_model(REPERTOIRE_SORTIE) # Taille de l'adaptateur : ~150 Mo (vs 14 Go pour les poids Mistral-7B complets) # Coût entraînement à 1,85 EUR/h (A100 80Go spot) : ~5,5-7,5 EUR pour 15K ex., 3 epochs

Calculateur de coûts

Utilisez ce script pour estimer les coûts mensuels avant de vous engager dans une approche. Renseignez votre volume de requêtes et la taille de votre corpus.

# calculateur_couts.py from dataclasses import dataclass @dataclass class CoutsRAG: # Infrastructure qdrant_mensuel_eur: float = 0.0 # Docker auto-hébergé : ~0 EUR # ou Qdrant Cloud : 42 EUR/mois pour 1M vecteurs # LLM (par requête) tokens_entree_par_requete: int = 1500 # contexte + chunks récupérés tokens_sortie_par_requete: int = 250 # claude-sonnet-4-6 : 3 $/1M entrée, 15 $/1M sortie (converti EUR ici) prix_entree_par_million_eur: float = 2.75 prix_sortie_par_million_eur: float = 13.75 def cout_par_requete(self) -> float: cout_entree = self.tokens_entree_par_requete * self.prix_entree_par_million_eur / 1_000_000 cout_sortie = self.tokens_sortie_par_requete * self.prix_sortie_par_million_eur / 1_000_000 return cout_entree + cout_sortie def cout_mensuel(self, requetes_par_mois: int) -> dict: cout_llm = self.cout_par_requete() * requetes_par_mois return { "inference_llm": round(cout_llm, 2), "base_vectorielle": self.qdrant_mensuel_eur, "total": round(cout_llm + self.qdrant_mensuel_eur, 2), } @dataclass class CoutsFineTuning: # Entraînement (amorti sur la durée de vie du modèle) cout_entraînement_par_run_eur: float = 225.0 # A100 spot, 15K ex., 3 epochs frequence_reentrainement_mois: float = 1.0 # réentraînement mensuel # Hébergement inférence (GPU permanent) cout_horaire_gpu_eur: float = 0.70 # A10G spot sur AWS (~0,45-0,95 EUR) heures_gpu_par_mois: float = 720 # 24/7 def cout_mensuel(self, requetes_par_mois: int) -> dict: entraînement_amorti = self.cout_entraînement_par_run_eur / self.frequence_reentrainement_mois hebergement_gpu = self.cout_horaire_gpu_eur * self.heures_gpu_par_mois return { "hebergement_gpu": round(hebergement_gpu, 2), "entraînement_amorti": round(entraînement_amorti, 2), "total": round(hebergement_gpu + entraînement_amorti, 2), } # Comparer pour votre volume rag = CoutsRAG(qdrant_mensuel_eur=42.0) # Qdrant Cloud gratuit ft = CoutsFineTuning() for volume in [1_000, 10_000, 50_000, 100_000, 500_000]: cout_rag = rag.cout_mensuel(volume)["total"] cout_ft = ft.cout_mensuel(volume)["total"] gagnant = "RAG" if cout_rag < cout_ft else "Fine-tuning" print(f"{volume:>8,} req/mois → RAG: {cout_rag:>7.2f} EUR FT: {cout_ft:>7.2f} EUR → {gagnant}") # Sortie : # 1 000 req/mois → RAG: 46.88 EUR FT: 729.00 EUR → RAG # 10 000 req/mois → RAG: 63.83 EUR FT: 729.00 EUR → RAG # 50 000 req/mois → RAG: 268.13 EUR FT: 729.00 EUR → RAG # 100 000 req/mois → RAG: 494.25 EUR FT: 729.00 EUR → RAG # 500 000 req/mois → RAG: 2 388.25 EUR FT: 729.00 EUR → Fine-tuning # Seuil de rentabilité : ~315 000 requêtes/mois
Insight clé : Le fine-tuning ne bat RAG sur le coût pur qu'à partir de 315 000 requêtes/mois avec les tarifs Claude. Avec un L L M moins cher (Qwen2.5-14B via Ollama à ~0 EUR le token), le seuil de rentabilité de R A G se déplace à l'infini — R A G est toujours moins cher quand on utilise l'inférence locale.

Approches hybrides : combiner les deux

En production, les systèmes les plus robustes combinent souvent R A G et fine-tuning. Trois patterns hybrides à connaître :

Pattern 1 : Retriever fine-tuné + LLM de base

Fine-tuner seulement le modèle d'embedding sur vos données métier (pas le L L M). Cela apprend au retriever à comprendre votre vocabulaire et vos préférences de classement, tout en conservant le L L M général et à jour. Fonctionne bien quand la qualité de récupération est le goulot d'étranglement (M R R@5 < 0,70).

# Fine-tuner un bi-encodeur (retriever) avec sentence-transformers from sentence_transformers import SentenceTransformer, InputExample, losses from torch.utils.data import DataLoader # Données d'entraînement : triplets (requête, doc_positif, doc_négatif) # Positif = doc qui répond à la requête # Négatif = doc qui semble pertinent mais ne répond pas exemples_entraînement = [ InputExample(texts=["politique remboursement", "Les abonnements annuels sont remboursés sous 5-7 jours", "Notre politique de retour pour les produits physiques..."]), # ... plus d'exemples ] modele = SentenceTransformer("nomic-ai/nomic-embed-text-v1.5") dataloader = DataLoader(exemples_entraînement, shuffle=True, batch_size=32) perte = losses.MultipleNegativesRankingLoss(modele) modele.fit( train_objectives=[(dataloader, perte)], epochs=5, warmup_steps=100, output_path="./support-embedder", ) # Résultat : MRR@5 passe de 0,71 à 0,84 sur les requêtes support (~1h d'entraînement)

Pattern 2 : LLM fine-tuné + ancrage RAG

Fine-tuner le L L M pour le ton/format/style de raisonnement, mais récupérer quand même le contexte au moment de la requête. Le modèle fine-tuné répond avec la bonne voix et suit la bonne logique ; R A G garantit que les faits sont actuels. C'est le hybride de plus haute qualité — et le plus cher (surcoût de 140-185 EUR/mois par rapport à l'une ou l'autre approche seule).

# Au moment de la requête : récupérer le contexte, puis passer au modèle fine-tuné def requete_hybride(question: str) -> str: # Étape 1 : récupérer (identique au RAG pur) docs = retriever.invoke(question) contexte = " ".join(d.page_content for d in docs) # Étape 2 : appeler le modèle fine-tuné (servi via Ollama) import ollama reponse = ollama.generate( model="mistral-support", # votre modèle fine-tuné prompt=( f"Contexte de la base de connaissances : {contexte} " f"Question client : {question} " f"Réponse (utilisez le contexte, suivez nos directives support) :" ), ) return reponse["response"]

Pattern 3 : RAG avec vérification de cohérence

Utiliser un modèle fine-tuné plus petit comme détecteur d'hallucination par-dessus un pipeline R A G. Le système R A G génère une réponse ; le vérificateur fine-tuné contrôle chaque affirmation factuelle par rapport au contexte récupéré. Tout ce qui n'est pas vérifié reçoit un avertissement de citation. Réduit le taux d'hallucination effectif de 6-9 % à moins de 1 % au coût d'un appel L L M supplémentaire par requête.

Questions fréquentes

RAG ou fine-tuning est-il moins cher pour une base de 50 000 documents ?

RAG est moins cher pour la plupart des bases documentaires. Pour un corpus de 50 000 documents : RAG coûte environ 120-200 EUR en installation (embedding + indexation) plus 45-70 EUR/mois (Qdrant auto-hébergé) et 0,0007-0,003 EUR par requête. Le fine-tuning du même corpus sur Mistral-7B coûte 170-380 EUR par entraînement, plus 0,45-1,10 EUR/heure pour l'hébergement GPU. En dessous de 50 000 requêtes/mois, RAG gagne sur le coût. Le fine-tuning devient compétitif seulement à très fort volume (500 000+/mois) où le coût d'inférence domine.

Quand le fine-tuning produit-il une meilleure qualité que RAG ?

Le fine-tuning l'emporte quand vous avez besoin de : (1) un style de réponse cohérent impossible à injecter via un system prompt, (2) une syntaxe ou un jargon métier que le modèle de base reproduit mal (codes médicaux, citations juridiques, terminologie propriétaire), (3) un taux d'hallucination très faible sur des tâches étroites où vous pouvez vous permettre le temps de réentraînement. Dans nos benchmarks, Mistral-7B fine-tuné a réduit l'hallucination de 8,1 % (RAG) à 2,3 % sur une tâche de codification médicale — mais nécessitait un réentraînement toutes les 3 semaines au fil des mises à jour.

Peut-on faire tourner RAG entièrement en local sans envoyer de données à une API ?

Oui. La stack RAG open source tourne entièrement on-premise : Ollama (inférence LLM), ChromaDB ou Qdrant (base vectorielle), et sentence-transformers (embeddings). Sur une RTX 4090 (24 Go VRAM), Ollama avec Qwen2.5-14B atteint 28-35 tokens/seconde, suffisant pour la plupart des charges de production. Coût : électricité + amortissement matériel. Aucun frais au token, souveraineté complète des données. Latence de 600-1 200 ms par requête contre 300-600 ms avec l'API Claude — acceptable pour les flux asynchrones.

À quelle fréquence faut-il réentraîner un modèle fine-tuné quand les données changent ?

Cela dépend de la volatilité des données. Pour les domaines peu changeants (politique juridique, manuels produits) : réentraînement trimestriel. Pour les domaines modérément changeants (docs support, tarification) : mensuel. Pour les données très changeantes (actualités, inventaire live, contenu utilisateur) : le fine-tuning est le mauvais outil — utilisez RAG ou un hybride RAG + fine-tuning. Chaque exécution d'entraînement pour un adaptateur LoRA 7B prend 2-6 heures sur un A100 et coûte 15-60 EUR. Budgétisez cette cadence lors de l'évaluation du coût total de possession.

Qu'est-ce qu'une architecture hybride RAG + fine-tuning ?

Une architecture hybride utilise un modèle fine-tuné comme backbone LLM (pour le ton, le format et le raisonnement spécialisé) tout en effectuant une récupération au moment de la requête (pour la fraîcheur et l'ancrage factuel). Exemple : fine-tuner Mistral-7B sur le style de résolution de votre équipe support, puis utiliser RAG pour récupérer la base de connaissances actuelle avant chaque réponse. Cela réduit l'hallucination à quasi zéro tout en maintenant les données fraîches. Le compromis : vous payez les deux coûts d'infrastructure. Typiquement 1,5 à 2 fois le coût de l'une ou l'autre approche seule.

Quel modèle d'embedding utiliser pour RAG en 2026 ?

Pour la plupart des cas d'usage en production, text-embedding-3-small (OpenAI, 0,02 $/1M tokens) ou nomic-embed-text (Ollama, gratuit, 768 dimensions) sont les bons défauts. Pour le contenu multilingue : intfloat/multilingual-e5-large ou cohere-embed-multilingual-v3. Pour les corpus riches en code : voyage-code-2 (Voyage AI) surpasse text-embedding-3-large de 8-12 points sur les benchmarks de récupération de code. Évitez all-MiniLM-L6-v2 en production — son espace à 384 dimensions provoque une dégradation de la récupération au-delà de 100 000 chunks.

Approfondissez : R A G en production avec LangChain et LangGraph

La formation couvre les pipelines R A G complets, l'état persistant, les architectures hybrides et les patterns de déploiement A W S — avec des labs pratiques sur des jeux de données réels.

Voir la formation LangChain & LangGraph →