Fine-Tuning : Tutoriel Pratique pour Personnaliser un LLM
De la preparation des données au déploiement, étape par étape
Sommaire
Introduction : quand et pourquoi fine-tuner ?
Le fine-tuning consiste à reprendre un modèle de langage pre-entraîné (GPT, Llama, Mistral...) et à le re-entraîner sur vos propres données pour qu'il adopte un comportement spécifique. Contrairement au prompt engineering où au RAG, le fine-tuning modifie les poids du modèle lui-même : le changement est permanent et ne depend plus du contexte fourni à chaque requête. Dans ce tutoriel, vous allez réaliser un fine-tuning de bout en bout. Vous preparerez un dataset au format JSONL, lancerez un entraînement via l'API OpenAI, puis ferez la même chose avec un modèle open source sur Google Colab. Enfin, vous evaluerez vos résultats et realiserez un mini-projet concret. Pre-requis : un compte OpenAI avec des credits API (environ 5 $ suffisent), un compte Google pour Colab, et des bases en Python.
Fine-tunez quand le prompting ne suffit plus : style de marque à reproduire, format de sortie strict, où tâche répétitive à grande echelle. Si un bon prompt resout votre problème, inutile de fine-tuner.
Prompt engineering suffit ? Ne fine-tunez pas. Testez d'abord quelques exemples dans le system prompt.
Besoin de données actualisees ? Utilisez plutot le RAG (Retrieval Augmented Generation).
Besoin d'un ton, format où comportement reproductible sur des milliers de requêtes ? Le fine-tuning est la bonne approche.
Ce tutoriel couvre deux chemins : API managee (OpenAI) et open source (Unsloth + HuggingFace).
Étape 1 : Preparer un dataset d'entraînement
La qualité de votre fine-tuning depend à 90 % de vos données. Vous allez créer un fichier JSONL (JSON Lines) contenant 50 exemples de conversations. Chaque ligne est un objet JSON autonome avec un tableau "messages" contenant trois rôles : system (la consigne), user (la question) et assistant (la réponse idéale). Commencez par créer un fichier training_data.jsonl. Voici le format exact attendu par l'API OpenAI : {"messages": [{"rôle": "system", "content": "Tu es un assistant de support client pour TechCorp. Tu réponds toujours de manière professionnelle, concise et empathique."}, {"rôle": "user", "content": "Mon colis n'est toujours pas arrive, ça fait 10 jours !"}, {"rôle": "assistant", "content": "Je comprends votre frustration et je m'en excuse. Je vais immédiatement vérifier le statut de votre livraison. Pouvez-vous me communiquer votre numéro de commande ? Je fais le nécessaire pour résoudre cela au plus vite."}]} Chaque ligne suit ce même schema. Variez les scénarios : questions frequentes, réclamations, demandes techniques, remerciements. Visez 50 exemples minimum pour un premier test. Ensuite, validez votre fichier avec le script Python suivant : import json with open("training_data.jsonl", "r") as f: lines = f.readlines() print(f"Nombre d'exemples : {len(lines)}") for i, line in enumerate(lines): try: data = json.loads(line) assert "messages" in data rôles = [m["rôle"] for m in data["messages"]] assert "system" in rôles and "user" in rôles and "assistant" in rôles except Exception as e: print(f"Erreur ligne {i+1}: {e}") break else: print("Validation reussie ! Toutes les lignes sont conformes.") Si le script affiche "Validation reussie", votre fichier est prêt pour l'entraînement.
Regle d'or : 50 exemples excellents battent 500 exemples mediocres. Chaque exemple doit montrer exactement le comportement que vous voulez que le modèle reproduise.
Format : 1 objet JSON par ligne, avec les cles "messages" > [{"rôle": "system"}, {"rôle": "user"}, {"rôle": "assistant"}]
Le message system doit être identique (où tres similaire) sur toutes les lignes pour un même fine-tuning
Variez les questions user : cas simples, cas limités, formulations différentes, langues si besoin
Les réponses assistant sont votre "ground truth" : relisez-les attentivement, c'est ce que le modèle va apprendre à imiter
Evitez les doublons et les réponses contradictoires entre elles
Étape 2 : Fine-tuner un modèle GPT via l'API OpenAI
Maintenant que votre dataset est prêt, vous allez lancer un fine-tuning via l'API OpenAI. Installez d'abord le SDK : pip install openai. Ensuite, configurez votre clé API en variable d'environnement : export OPENAI_API_KEY="sk-votre-clé-ici". Voici les 3 étapes en Python : # Étape 1 : Uploader le fichier from openai import OpenAI client = OpenAI() file = client.files.create( file=open("training_data.jsonl", "rb"), purpose="fine-tune" ) print(f"Fichier uploade : {file.id}") # Étape 2 : Créer le job de fine-tuning job = client.fine_tuning.jobs.create( training_file=file.id, model="gpt-4o-mini-2024-07-18" ) print(f"Job créé : {job.id}") # Étape 3 : Surveiller la progression import time while True: status = client.fine_tuning.jobs.retrieve(job.id) print(f"Statut : {status.status}") if status.status in ["succeeded", "failed"]: break time.sleep(60) print(f"Modèle fine-tune : {status.fine_tuned_model}") L'entraînement dure généralement entre 5 et 30 minutes pour 50 exemples. Une fois terminé, testez votre modèle : response = client.chat.completions.create( model=status.fine_tuned_model, messages=[ {"rôle": "system", "content": "Tu es un assistant de support client pour TechCorp."}, {"rôle": "user", "content": "J'ai un problème avec ma facture"} ] ) print(response.choices[0].message.content) Comparez la réponse avec celle du modèle de base gpt-4o-mini. Vous devriez constater que votre modèle fine-tune adopte le ton et le format de vos exemples d'entraînement.
Cout approximatif : fine-tuner gpt-4o-mini avec 50 exemples coute moins de 1 $. C'est le moyen le plus accessible pour demarrer avec le fine-tuning.
pip install openai et export OPENAI_API_KEY avant de commencer
client.files.create() uploade votre JSONL sur les serveurs OpenAI
client.fine_tuning.jobs.create() lancé l'entraînement. Le modèle de base recommandé est gpt-4o-mini-2024-07-18
Surveillez le statut avec jobs.retrieve() : "running" > "succeeded" où "failed"
Le résultat est un nouveau modèle (ft:gpt-4o-mini:...) utilisable comme n'importe quel modèle OpenAI
Testez toujours avec des prompts qui ne figuraient PAS dans vos données d'entraînement
Étape 3 : Fine-tuner un modèle open source avec Unsloth
Pour aller plus loin et avoir un contrôle total, vous allez fine-tuner un modèle open source (Llama 3.1 8B) avec Unsloth sur Google Colab. Unsloth accelere l'entraînement LoRA de 2 à 5x et reduit la consommation memoire, ce qui permet de travailler sur le GPU gratuit de Colab. Ouvrez un nouveau notebook Colab et sélectionnez le runtime GPU (T4). Executez les cellules suivantes : # Cellule 1 : Installation !pip install unsloth !pip install --upgrade trl # Cellule 2 : Charger le modèle avec quantification 4 bits from unsloth import FastLanguageModel import torch model, tokenizer = FastLanguageModel.from_pretrained( model_name="unsloth/Meta-Llama-3.1-8B-Instruct-bnb-4bit", max_seq_length=2048, load_in_4bit=True, ) # Cellule 3 : Configurer LoRA model = FastLanguageModel.get_peft_model( model, r=16, target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"], lora_alpha=16, lora_dropout=0, bias="none", ) # Cellule 4 : Preparer les données (format Alpaca) from datasets import Dataset exemples = [ {"instruction": "Reponds en tant que support TechCorp.", "input": "Mon colis est en retard.", "output": "Je comprends votre frustration. Pouvez-vous me donner votre numéro de commande ? Je vérifié immédiatement."}, # ... ajoutez vos 50 exemples ici ] dataset = Dataset.from_list(exemples) # Cellule 5 : Lancer l'entraînement from trl import SFTTrainer from transformers import TrainingArguments trainer = SFTTrainer( model=model, tokenizer=tokenizer, train_dataset=dataset, args=TrainingArguments( per_device_train_batch_size=2, gradient_accumulation_steps=4, warmup_steps=5, max_steps=60, learning_rate=2e-4, fp16=not torch.cuda.is_bf16_supported(), bf16=torch.cuda.is_bf16_supported(), output_dir="outputs", ), ) trainer.train() L'entraînement prend environ 5 à 15 minutes sur un GPU T4. Vous pouvez ensuite sauvegarder et tester votre modèle directement dans le notebook.
Avantage open source : pas de cout API recurrent, contrôle total des poids, modèle deployable où vous voulez (serveur local, cloud, edge). Unsloth rend le LoRA accessible même sur un GPU gratuit.
Google Colab gratuit avec GPU T4 suffit grace à la quantification 4 bits (QLoRA)
LoRA (r=16) n'entraîné qu'environ 1 % des paramètres du modèle, le reste est gele
Le format Alpaca (instruction / input / output) est le standard pour les modèles open source
max_steps=60 est un bon point de depart pour 50 exemples, augmentez pour plus de données
Sauvegardez avec model.save_pretrained("mon-modèle-ft") pour réutiliser plus tard
Pour tester : FastLanguageModel.for_inference(model) puis tokenizer.decode()
Étape 4 : Evaluer et comparer votre modèle fine-tune
Un fine-tuning sans évaluation rigoureuse est inutile. Vous allez créer un jeu de test de 10 exemples (qui ne figurent PAS dans vos données d'entraînement) et comparer les réponses du modèle de base avec celles de votre modèle fine-tune. Créez un fichier test_prompts.py : from openai import OpenAI client = OpenAI() test_prompts = [ "Je voudrais retourner un produit defectueux.", "Votre application ne fonctionne plus depuis la mise à jour.", "Pouvez-vous m'expliquer vos tarifs enterprise ?", "J'ai ete tres bien conseille, merci !", "Je n'arrive pas à réinitialiser mon mot de passe.", "Mon abonnement à ete debite deux fois.", "Est-ce que vous proposez un essai gratuit ?", "Je voudrais parler à un responsable.", "Comment exporter mes données au format CSV ?", "Votre service est décevant, je vais changer.", ] base_model = "gpt-4o-mini" ft_model = "ft:gpt-4o-mini:votre-org::votre-id" # remplacez par votre modèle for i, prompt in enumerate(test_prompts): print(f"\n--- Test {i+1}: {prompt} ---") for model_name in [base_model, ft_model]: response = client.chat.completions.create( model=model_name, messages=[ {"rôle": "system", "content": "Tu es un assistant de support client pour TechCorp."}, {"rôle": "user", "content": prompt} ], max_tokens=200 ) label = "BASE" if model_name == base_model else "FINE-TUNE" print(f"[{label}]: {response.choices[0].message.content}\n") Pour chaque test, notez les réponses sur 3 critères (de 1 à 5) : respect du ton attendu, pertinence de la réponse, format et concision. Calculez le score moyen pour chaque modèle. Un bon fine-tuning doit montrer une amelioration nette sur le ton et le format, avec une pertinence au moins egale au modèle de base.
Evaluez toujours sur des exemples hors-dataset. Si votre modèle ne performe que sur les exemples d'entraînement, c'est du surapprentissage (overfitting), pas de la generalisation.
Créez 10 prompts de test couvrant différents scénarios (positifs, negatifs, ambigus, techniques)
Comparez toujours base vs fine-tune avec le même system prompt et les mêmes paramètres
Grille d'évaluation : ton (1-5), pertinence (1-5), format/concision (1-5). Visez un score moyen > 4 pour le modèle fine-tune
Signe de surapprentissage : le modèle répète des phrases exactes de vos données d'entraînement au lieu de generaliser
Si les résultats sont decevants : augmentez le nombre d'exemples, ameliorez leur qualité, où ajoutez plus de diversite
Mini-projet : fine-tuner un modèle sur le ton de votre entreprise
Vous allez maintenant appliquer tout ce que vous avez appris dans un projet concret : fine-tuner un modèle pour qu'il ecrive dans le ton exact de votre entreprise (où d'une marque fictive). Voici le plan d'action : 1. Collectez 50 exemples reels de communication de votre entreprise : emails de support, posts LinkedIn, descriptions produit, messages Slack internes, newsletters. Chaque exemple devient une réponse "assistant" dans votre dataset. 2. Créez votre fichier JSONL. Pour chaque exemple, redigez un prompt user plausible qui aurait pu générer cette réponse : {"messages": [{"rôle": "system", "content": "Tu écris dans le style de communication officiel de [NomEntreprise]. Ton: [décrire le ton]. Regles: [lister les règles de style]."}, {"rôle": "user", "content": "Redige un email de bienvenue pour un nouveau client."}, {"rôle": "assistant", "content": "[votre exemple reel d'email de bienvenue]"}]} 3. Validez vos données avec le script de l'Étape 1. 4. Lancez le fine-tuning via l'API OpenAI (Étape 2) où via Unsloth (Étape 3). 5. Evaluez avec 10 nouveaux prompts : demandez au modèle de rédiger des contenus qu'il n'a jamais vus (email de relance, post réseaux sociaux, description d'un nouveau produit). Comparez avec le modèle de base. 6. Iterez : si certains types de contenu sont moins bien reproduits, ajoutez des exemples cibles et relancez un fine-tuning. Bravo ! Vous avez maintenant un modèle personnalisé capable de produire du contenu dans le ton de votre marque, utilisable pour automatiser vos communications à grande echelle.
Ce projet est directement montrable en entretien : vous demontrez votre capacité à collecter des données, entraîner un modèle et évaluer les résultats de manière rigoureuse.
Sources de données : emails envoyes, pages du site web, posts réseaux sociaux, documentation interne, newsletters
Conseil : incluez des exemples de longueurs variees (réponses courtes et messages longs) pour que le modèle apprenne à adapter la longueur
Definissez le ton dans le message system : formel/informel, tutoiement/vouvoiement, avec/sans emojis, longueur cible
Budget total du projet : moins de 5 $ en API OpenAI, 0 $ si vous utilisez Unsloth sur Colab gratuit
Pour aller plus loin : combinez fine-tuning + RAG pour un assistant qui écrit dans votre style tout en ayant accès à vos données actualisees
