Qu’est-ce que le fine-tuning ?
Le fine-tuning consiste à ré-entraîner un modèle d’IA pré-entraîné (comme GPT-3.5, LLaMA ou Mistral) sur vos propres données pour l’adapter à un cas d’usage spécifique. Au lieu de partir de zéro, vous exploitez les connaissances déjà acquises par le modèle et vous les affinez avec vos exemples. Résultat : un modèle qui comprend votre domaine, votre ton, votre vocabulaire métier et vos formats de sortie.
Exemples de cas d’usage courants : un chatbot de service client qui connaît vos produits et vos politiques, un modèle qui rédige des rapports dans le style de votre entreprise, un assistant qui répond en wolof ou dans un mélange français-wolof naturel, un classifieur de tickets de support adapté à votre activité.
Prérequis techniques
Avant de commencer, assurez-vous d’avoir les éléments suivants :
# Python 3.8 ou supérieur
python3 --version
# Installer les bibliothèques nécessaires
pip install openai # Pour le fine-tuning via l'API OpenAI
pip install transformers # Pour le fine-tuning local avec Hugging Face
pip install datasets # Pour charger et préparer les données
pip install peft # Pour le fine-tuning efficace (LoRA)
pip install bitsandbytes # Pour la quantification (économiser la VRAM)
pip install accelerate # Pour l'entraînement distribué
pip install wandb # Pour le suivi des expériences (optionnel)
Méthode 1 : Fine-tuning avec l’API OpenAI
C’est la méthode la plus simple. Vous n’avez pas besoin de GPU — OpenAI gère l’infrastructure. Vous payez uniquement pour l’entraînement et l’utilisation du modèle fine-tuné.
Étape 1 : Préparer les données d’entraînement
OpenAI attend un fichier JSONL (JSON Lines) où chaque ligne est une conversation complète au format chat. Voici le format requis :
# Fichier : training_data.jsonl
# Chaque ligne est un objet JSON avec un tableau "messages"
{"messages": [{"role": "system", "content": "Tu es l'assistant commercial de TechSenegal, une entreprise de vente de matériel informatique à Dakar. Tu réponds en français, tu connais tous les produits et tu donnes les prix en FCFA."}, {"role": "user", "content": "Quel est le prix du MacBook Air M2 ?"}, {"role": "assistant", "content": "Le MacBook Air M2 est disponible chez TechSenegal à 850 000 FCFA pour la version 8 Go RAM / 256 Go SSD, et à 1 050 000 FCFA pour la version 16 Go RAM / 512 Go SSD. Nous offrons une garantie de 12 mois et la livraison gratuite à Dakar. Souhaitez-vous passer commande ?"}]}
{"messages": [{"role": "system", "content": "Tu es l'assistant commercial de TechSenegal, une entreprise de vente de matériel informatique à Dakar. Tu réponds en français, tu connais tous les produits et tu donnes les prix en FCFA."}, {"role": "user", "content": "Vous faites des réparations ?"}, {"role": "assistant", "content": "Oui, TechSenegal dispose d'un atelier de réparation à Dakar Plateau, ouvert du lundi au samedi de 8h30 à 18h. Nous réparons ordinateurs portables, desktops, imprimantes et tablettes. Le diagnostic est gratuit et prend 24 à 48 heures. Pour les réparations, les tarifs commencent à 15 000 FCFA selon le type d'intervention. Voulez-vous prendre rendez-vous ?"}]}
{"messages": [{"role": "system", "content": "Tu es l'assistant commercial de TechSenegal, une entreprise de vente de matériel informatique à Dakar. Tu réponds en français, tu connais tous les produits et tu donnes les prix en FCFA."}, {"role": "user", "content": "Avez-vous des PC portables à moins de 300 000 FCFA ?"}, {"role": "assistant", "content": "Bien sûr ! Voici nos PC portables à moins de 300 000 FCFA :
1. Lenovo IdeaPad 1 (Celeron N4020, 4 Go RAM, 128 Go SSD) — 185 000 FCFA
2. HP 245 G9 (AMD Ryzen 3, 8 Go RAM, 256 Go SSD) — 275 000 FCFA
3. Acer Aspire 3 (Intel i3-1215U, 8 Go RAM, 256 Go SSD) — 295 000 FCFA
Le HP 245 G9 offre le meilleur rapport qualité-prix pour un usage bureautique et web. Souhaitez-vous plus de détails sur l'un de ces modèles ?"}]}
Vous avez besoin d’au minimum 10 exemples, mais 50 à 100 exemples donnent de bien meilleurs résultats. Règle d’or : la qualité des exemples est plus importante que la quantité.
Étape 2 : Valider et uploader les données
import openai
import json
# Configurer la clé API
openai.api_key = "sk-votre-cle-api"
# Valider le format du fichier avant upload
def validate_jsonl(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
for i, line in enumerate(f):
try:
data = json.loads(line)
assert "messages" in data, f"Ligne {i+1}: clé 'messages' manquante"
for msg in data["messages"]:
assert "role" in msg, f"Ligne {i+1}: clé 'role' manquante"
assert "content" in msg, f"Ligne {i+1}: clé 'content' manquante"
assert msg["role"] in ["system", "user", "assistant"], f"Ligne {i+1}: rôle invalide '{msg['role']}'"
except json.JSONDecodeError:
print(f"Ligne {i+1}: JSON invalide")
return False
print(f"✓ Fichier valide : {i+1} exemples")
return True
validate_jsonl("training_data.jsonl")
# Uploader le fichier
file_response = openai.files.create(
file=open("training_data.jsonl", "rb"),
purpose="fine-tune"
)
print(f"Fichier uploadé : {file_response.id}")
# Sortie : file-abc123...
Étape 3 : Lancer le fine-tuning
# Créer le job de fine-tuning
ft_job = openai.fine_tuning.jobs.create(
training_file=file_response.id,
model="gpt-3.5-turbo", # Modèle de base
hyperparameters={
"n_epochs": 3, # Nombre de passes sur les données
"batch_size": 1, # Taille du batch (auto par défaut)
"learning_rate_multiplier": 1.8 # Taux d'apprentissage
},
suffix="techsenegal-assistant" # Suffixe pour identifier votre modèle
)
print(f"Job créé : {ft_job.id}")
print(f"Statut : {ft_job.status}")
# Suivre la progression
import time
while True:
job = openai.fine_tuning.jobs.retrieve(ft_job.id)
print(f"Statut : {job.status}")
if job.status in ["succeeded", "failed"]:
break
time.sleep(60) # Vérifier toutes les minutes
# Récupérer le nom du modèle fine-tuné
if job.status == "succeeded":
model_name = job.fine_tuned_model
print(f"Modèle prêt : {model_name}")
# Sortie : ft:gpt-3.5-turbo:techsenegal-assistant:abc123
Étape 4 : Utiliser le modèle fine-tuné
# Utiliser votre modèle personnalisé
response = openai.chat.completions.create(
model="ft:gpt-3.5-turbo:techsenegal-assistant:abc123", # Votre modèle
messages=[
{"role": "system", "content": "Tu es l'assistant commercial de TechSenegal."},
{"role": "user", "content": "Je cherche un écran pour le graphisme, budget 200 000 FCFA"}
],
temperature=0.7,
max_tokens=500
)
print(response.choices[0].message.content)
# Le modèle répondra dans le style et avec les connaissances
# spécifiques à TechSenegal que vous lui avez enseignés
Coût estimé du fine-tuning OpenAI : environ 8$ pour 100 000 tokens d’entraînement sur GPT-3.5-turbo. L’utilisation du modèle fine-tuné coûte environ 2x le prix du modèle de base.
Méthode 2 : Fine-tuning local avec Hugging Face et LoRA
Cette méthode vous donne un contrôle total sur le processus et le modèle reste sur votre infrastructure. Elle nécessite un GPU (au minimum 8 Go de VRAM avec LoRA, ou un compte Google Colab Pro).
Étape 1 : Préparer l’environnement
# Sur Google Colab (GPU T4 gratuit) ou machine locale avec GPU
!pip install transformers datasets peft bitsandbytes accelerate trl
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
from datasets import Dataset
from trl import SFTTrainer, SFTConfig
# Vérifier la disponibilité du GPU
print(f"GPU disponible : {torch.cuda.is_available()}")
print(f"GPU : {torch.cuda.get_device_name(0)}")
print(f"VRAM : {torch.cuda.get_device_properties(0).total_mem / 1e9:.1f} Go")
Étape 2 : Charger le modèle de base avec quantification
# Configuration de la quantification 4-bit (réduit la VRAM nécessaire)
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True
)
# Charger Mistral 7B (ou LLaMA 2 7B, Falcon 7B, etc.)
model_name = "mistralai/Mistral-7B-Instruct-v0.2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map="auto"
)
# Préparer le modèle pour l'entraînement en précision réduite
model = prepare_model_for_kbit_training(model)
print(f"Modèle chargé : {model_name}")
print(f"Paramètres : {model.num_parameters() / 1e9:.1f} milliards")
Étape 3 : Configurer LoRA
LoRA (Low-Rank Adaptation) permet de fine-tuner un modèle en ne modifiant qu’une petite fraction de ses paramètres. Au lieu de modifier les 7 milliards de paramètres de Mistral, LoRA n’en entraîne que 5 à 10 millions — ce qui réduit drastiquement la VRAM et le temps d’entraînement.
# Configuration LoRA
lora_config = LoraConfig(
r=16, # Rang de la décomposition (8-64)
lora_alpha=32, # Facteur de mise à l'échelle
target_modules=[ # Couches à adapter
"q_proj", "k_proj", "v_proj", "o_proj", # Attention
"gate_proj", "up_proj", "down_proj" # FFN
],
lora_dropout=0.05, # Dropout pour la régularisation
bias="none",
task_type="CAUSAL_LM"
)
# Appliquer LoRA au modèle
model = get_peft_model(model, lora_config)
# Afficher le nombre de paramètres entraînables
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
total_params = sum(p.numel() for p in model.parameters())
print(f"Paramètres entraînables : {trainable_params:,} / {total_params:,}")
print(f"Pourcentage : {100 * trainable_params / total_params:.2f}%")
# Sortie typique : 0.06% des paramètres — c'est la magie de LoRA !
Étape 4 : Préparer le dataset
# Préparer les données au format Mistral Instruct
training_examples = [
{
"instruction": "Quel est le prix du MacBook Air M2 ?",
"response": "Le MacBook Air M2 est disponible chez TechSenegal à 850 000 FCFA (8 Go/256 Go) et 1 050 000 FCFA (16 Go/512 Go). Garantie 12 mois, livraison gratuite à Dakar."
},
{
"instruction": "Vous faites des réparations d'ordinateurs ?",
"response": "Oui, notre atelier à Dakar Plateau est ouvert lun-sam 8h30-18h. Diagnostic gratuit (24-48h). Tarifs à partir de 15 000 FCFA selon l'intervention."
},
# ... ajoutez 50-100 exemples
]
def format_instruction(example):
"""Formater au format Mistral Instruct"""
return f"""[INST] {example['instruction']} [/INST] {example['response']}"""
# Créer le dataset
formatted_data = [{"text": format_instruction(ex)} for ex in training_examples]
dataset = Dataset.from_list(formatted_data)
print(f"Dataset : {len(dataset)} exemples")
print(f"Exemple : {dataset[0]['text'][:200]}...")
Étape 5 : Lancer l’entraînement
# Configuration de l'entraînement
training_config = SFTConfig(
output_dir="./mistral-techsenegal",
num_train_epochs=3,
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
learning_rate=2e-4,
weight_decay=0.01,
warmup_steps=10,
logging_steps=10,
save_steps=50,
fp16=True,
max_seq_length=512,
dataset_text_field="text",
)
# Créer le trainer et lancer l'entraînement
trainer = SFTTrainer(
model=model,
train_dataset=dataset,
args=training_config,
tokenizer=tokenizer,
)
print("Début du fine-tuning...")
trainer.train()
print("Fine-tuning terminé !")
# Sauvegarder le modèle LoRA (seulement ~20-50 Mo)
trainer.save_model("./mistral-techsenegal-lora")
print("Modèle sauvegardé dans ./mistral-techsenegal-lora")
Étape 6 : Tester le modèle fine-tuné
# Charger et tester le modèle
from peft import PeftModel
# Recharger le modèle de base + adaptateur LoRA
base_model = AutoModelForCausalLM.from_pretrained(
model_name, quantization_config=bnb_config, device_map="auto"
)
model = PeftModel.from_pretrained(base_model, "./mistral-techsenegal-lora")
# Fonction de génération
def ask(question, max_tokens=300):
prompt = f"[INST] {question} [/INST]"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=max_tokens,
temperature=0.7,
top_p=0.9,
do_sample=True
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
return response.split("[/INST]")[-1].strip()
# Test
print(ask("Avez-vous des imprimantes laser ?"))
print("---")
print(ask("Quels sont vos délais de livraison à Saint-Louis ?"))
print("---")
print(ask("Je veux un PC pour le montage vidéo, budget 500 000 FCFA"))
Bonnes pratiques pour le fine-tuning
La qualité des données prime sur la quantité. 50 exemples de haute qualité, bien rédigés et variés, donneront de meilleurs résultats que 500 exemples médiocres ou répétitifs. Chaque exemple doit illustrer le comportement exact que vous attendez du modèle.
Diversifiez vos exemples. Couvrez tous les types de questions que le modèle recevra en production. Si votre chatbot reçoit des questions sur les prix, les horaires, le SAV, les comparatifs et les réclamations, incluez des exemples pour chaque catégorie.
Évaluez systématiquement. Gardez 20% de vos données en jeu de test. Après le fine-tuning, comparez les réponses du modèle sur ces exemples avec les réponses attendues. Mesurez la pertinence, la précision factuelle et le ton.
Itérez progressivement. Commencez avec un petit dataset, testez, identifiez les faiblesses, ajoutez des exemples ciblés, et relancez le fine-tuning. Chaque itération améliore le modèle sur les cas problématiques.
Attention au surapprentissage (overfitting). Si le modèle récite vos exemples mot pour mot au lieu de généraliser, réduisez le nombre d’époques ou augmentez le dropout. Avec LoRA, 2-3 époques suffisent généralement.
Coûts et comparaison des approches
Fine-tuning OpenAI API : le plus simple, pas besoin de GPU, coût modéré (~8$ pour 100K tokens d’entraînement). Inconvénient : vous dépendez d’OpenAI et le modèle reste sur leurs serveurs.
Fine-tuning local avec LoRA : contrôle total, modèle privé, mais nécessite un GPU (Google Colab Pro à 10$/mois ou GPU cloud à partir de 0.5$/heure sur RunPod ou Vast.ai). L’adaptateur LoRA ne fait que 20-50 Mo.
Fine-tuning complet (full) : meilleurs résultats potentiels mais nécessite beaucoup plus de ressources (40+ Go de VRAM pour un modèle 7B). Rarement justifié pour la majorité des cas d’usage.
Pour la plupart des entreprises au Sénégal, le fine-tuning via l’API OpenAI est le point de départ recommandé. Une fois que votre cas d’usage est validé et que vous voulez plus de contrôle ou réduire les coûts à long terme, migrez vers un modèle open source fine-tuné localement.