Retour au Blog
Blog

Affinage des LLM : Apprendre à l'IA à parler votre langue

Aug 17, 2025·8 min read·Shranya Mahna
#custom AI#domain-specific AI#fine-tuning LLMs#language models#personalized AI
Affinage des LLM : Apprendre à l'IA à parler votre langue

Partie 3 sur 5 : Personnaliser des modèles pré-entraînés

Bienvenue ! Dans notre dernier article, nous avons construit un système RAG qui donne à l'IA accès à vos informations spécifiques. Aujourd'hui, nous allons aller plus loin — nous allons modifier la façon dont un modèle d'IA pense et répond en l'affinant. Je vais utiliser un modèle open-source pour cet exemple de démonstration.

RAG vs Affinement : Quelle est la différence ?

Pensez-y de cette façon :

RAG c'est comme donner à quelqu'un un livre de référence. C'est toujours la même personne, mais maintenant elle a accès à des informations spécifiques pour répondre aux questions.

L'affinement c'est comme envoyer quelqu'un en formation spécialisée. Vous changez réellement la façon dont ils pensent et répondent en fonction de vos exigences spécifiques.

Quand devriez-vous affiner ?

L'affinement est puissant, mais ce n'est pas toujours nécessaire. Envisagez l'affinement quand :

  • Vous avez besoin que l'IA adopte un ton ou un style spécifique
  • Votre domaine utilise une terminologie ou des concepts spécialisés
  • Vous voulez des réponses cohérentes dans de nombreux scénarios différents
  • RAG ne vous donne pas la qualité de réponses dont vous avez besoin
  • Vous disposez de données d'entraînement suffisantes (généralement des centaines d'exemples)
  • Vous avez besoin que le modèle fonctionne hors ligne ou dans des environnements isolés

Configuration de votre environnement

Nous utiliserons Google Colab avec un GPU T4 pour ce didacticiel, mais vous pouvez l'adapter pour n'importe quel environnement compatible CUDA :

# Install required packages

!pip install bitsandbytes
import os import torch from datasets import Dataset from transformers import ( AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer, BitsAndBytesConfig ) from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training, PeftModel

Choisir le bon modèle

Pour ce didacticiel, nous utiliserons TinyLlama-1.1B, mais voici d'excellentes options pour différents besoins :

# Ultra-light models (good for experimentation)

# model_name = "distilgpt2"                          # 82M parameters

# model_name = "gpt2"                                # 124M parameters

# model_name = "EleutherAI/gpt-neo-125M"            # 125M parameters
# Small but capable models # model_name = "microsoft/DialoGPT-medium" # 355M parameters # model_name = "microsoft/DialoGPT-large" # 762M parameters model_name = "TinyLlama/TinyLlama-1.1B-Chat-v1.0" # 1.1B parameters - choosing this one # For production use (if you have more GPU memory) # model_name = "microsoft/phi-2" # 2.7B parameters # model_name = "stabilityai/stablelm-2-1_6b" # 1.6B parameters

Préparation de vos données d'entraînement

La clé d'un affinement réussi est la qualité des données d'entraînement. Voici comment nous le structurons :

# Sample dataset for MyNextDeveloper (MND)

data = {

"text": [

"User asks: Write a 3-bullet overview of MND.nAssistant: - Remote-first, founded 2022 in Mumbain- Staff augmentation + full-cycle web/API, UI/UX, AI/MLn- Agile/TDD, POSH culture, transparent pricing",

"User asks: Where is MND headquartered?nAssistant: Malabar Hill, Mumbai",

"User asks: What services does MND offer?nAssistant: Staff augmentation, API development, web development, UI/UX design, AI/ML solutions",

"User asks: What is MND's tech stack?nAssistant: Angular, React, Next.js, Node.js, Django, Python, Docker, AWS",

"User asks: What is MND's pricing model?nAssistant: Project pricing starting at $10,000 with hourly rates between $25 and $49",

"User asks: What is MND's mission?nAssistant: To solve the trust gap between startups and engineers by emphasizing empathy, communication, and transparency",

"User asks: What is MND's culture like?nAssistant: Agile practices, test-driven development, and POSH-compliant culture",

"User asks: When was MND founded?nAssistant: 2022"

]

}
# Convert to HuggingFace dataset dataset = Dataset.from_dict(data)

Principes clés pour les données d'entraînement :

  • Utilisez un formatage cohérent (notez le modèle « User asks: » et « Assistant: »)
  • Gardez les réponses factuelles et concises
  • Couvrez les informations les plus importantes sur votre domaine
  • La qualité plutôt que la quantité : 50 exemples parfaits valent mieux que 500 médiocres

Entraînement efficace avec LoRA et quantification

Au lieu d'affiner l'ensemble du modèle (ce qui nécessite une énorme mémoire GPU), nous utiliserons deux techniques d'efficacité :

1. Quantification (4-bit)

La quantification est une technique de compression utilisée pour rendre les grands modèles de langage (LLM) plus petits et plus rapides sans réduire considérablement la précision.

  • Normalement, les poids des LLM sont stockés sous forme de nombres à virgule flottante 32 bits (FP32).
  • La quantification réduit cette précision à 16 bits (FP16/BF16), 8 bits (INT8), 4 bits (INT4) ou moins.

👉 Exemple :

  • Un modèle avec 10 milliards de paramètres en FP32 nécessite ~40 Go de mémoire.
  • Si nous le quantifions à INT8 (8-bit) → il n'a besoin que de ~10 Go.
  • Si nous passons à INT4 (4-bit) → juste ~5 Go.

Pourquoi c'est utile ?

  • Permet aux modèles de fonctionner sur des GPU plus petits (ou même des CPU).
  • Accélère l'inférence.
  • Léger compromis sur la précision, mais souvent négligeable.
# Configure 4-bit quantization

bnb_config = BitsAndBytesConfig(

load_in_4bit=True,

bnb_4bit_quant_type="nf4",

bnb_4bit_use_double_quant=True,

bnb_4bit_compute_dtype=torch.float16

)
# Load model with quantization model = AutoModelForCausalLM.from_pretrained( model_name, quantization_config=bnb_config, device_map="auto", torch_dtype=torch.float16 )

2. LoRA (Low-Rank Adaptation)

LoRA est une méthode d'affinement efficace en paramètres (PEFT).

Normalement, pour affiner un énorme LLM (comme LLaMA-65B ou GPT-J), nous aurions besoin de centaines de Go de mémoire GPU. LoRA résout ce problème en :

  • Gelant les poids du modèle original.
  • Ajoutant des petites matrices entraînables (adaptateurs de faible rang) à l'intérieur des couches du modèle.
  • Pendant l'affinement, seules ces petites matrices sont mises à jour.

👉 Exemple :

  • L'affinement complet d'un modèle de 65B pourrait nécessiter ~1 To de mémoire GPU.
  • Avec LoRA, vous entraînez seulement quelques millions de paramètres → nécessite < 20 Go de mémoire GPU.

Pourquoi c'est utile ?

  • Rend possible l'affinement des énormes LLM sur du matériel grand public (1–2 GPU).
  • Facile de « fusionner » ou « dissocier » les adaptateurs → vous pouvez rapidement changer de tâche.
  • Atteint souvent une performance proche de l'affinement complet.
# Configure LoRA based on model architecture

if "TinyLlama" in model_name or "Llama" in model_name:

target_modules = ["q_proj", "k_proj", "v_proj", "o_proj"]

elif "gpt" in model_name.lower() or "DialoGPT" in model_name:

target_modules = ["c_attn", "c_proj"]

else:

target_modules = ["q_proj", "v_proj"]
lora_config = LoraConfig( r=8, # Rank of adaptation lora_alpha=16, # LoRA scaling parameter target_modules=target_modules, lora_dropout=0.05, bias="none", task_type="CAUSAL_LM" ) # Apply LoRA to the model model = get_peft_model(model, lora_config) model.print_trainable_parameters()

Nous n'entraînons que 0,2 % des paramètres !

Entraînement du modèle

# Tokenize the data

def tokenize_function(examples):

tokenized_inputs = tokenizer(

examples["text"],

truncation=True,

padding="max_length",

max_length=512,

return_tensors="pt"

)

# Create labels by copying input tokens

tokenized_inputs["labels"] = tokenized_inputs["input_ids"].clone()

return tokenized_inputs
# Split dataset train_dataset = dataset.select(range(8)) eval_dataset = dataset.select(range(8, 11)) # Apply tokenization train_dataset = train_dataset.map(tokenize_function, batched=True) eval_dataset = eval_dataset.map(tokenize_function, batched=True) # Configure training training_args = TrainingArguments( output_dir="./mnd-finetune-outputs", num_train_epochs=5, per_device_train_batch_size=4, per_device_eval_batch_size=4, gradient_accumulation_steps=2, warmup_steps=10, learning_rate=3e-4, weight_decay=0.01, logging_steps=1, save_steps=30, eval_strategy="steps", eval_steps=15, save_total_limit=2, load_best_model_at_end=True, fp16=True, report_to=None # Disable wandb logging ) # Create trainer and start training trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, tokenizer=tokenizer, ) print("Starting training...") trainer.train() # Save the adapter adapter_dir = "./mnd-finetune-outputs/final_adapter" model.save_pretrained(adapter_dir) tokenizer.save_pretrained(adapter_dir)

Test du modèle affiné

def load_model_for_inference():

"""Load the fine-tuned model for inference"""

# Load base model

base_model = AutoModelForCausalLM.from_pretrained(

model_name,

quantization_config=bnb_config,

device_map="auto",

torch_dtype=torch.float16

)

# Load the fine-tuned adapter

model = PeftModel.from_pretrained(base_model, adapter_dir)

model = model.merge_and_unload()

# Load tokenizer

tokenizer = AutoTokenizer.from_pretrained(adapter_dir)

return model, tokenizer

def generate_response(model, tokenizer, prompt, max_length=256, temperature=0.7):

"""Generate response for a given prompt"""

formatted_prompt = f"User asks: {prompt}nAssistant:"

inputs = tokenizer.encode(formatted_prompt, return_tensors="pt")

inputs = inputs.to(model.device)

with torch.no_grad():

outputs = model.generate(

inputs,

max_length=max_length,

temperature=temperature,

top_p=0.9,

do_sample=True,

pad_token_id=tokenizer.eos_token_id,

repetition_penalty=1.1

)

response = tokenizer.decode(outputs[0], skip_special_tokens=True)

assistant_response = response.split("Assistant:")[-1].strip()

return assistant_response

# Load fine-tuned model and test

model, tokenizer = load_model_for_inference()

test_prompts = [

"What makes MND different from other development companies?",

"Can you tell me about MND's team?",

"What is the company culture at MND?"

]

for prompt in test_prompts:

response = generate_response(model, tokenizer, prompt)

print(f"Q: {prompt}")

print(f"A: {response}n")

Google Colab

Voici le lien Google Colab pour cet article que vous pouvez exécuter en un clic : lien

Les vrais coûts

Contrairement aux API commerciales, vos coûts sont principalement :

  1. Configuration initiale : Temps GPU pour l'entraînement
  2. Stockage : Poids du modèle (~4 Go pour TinyLlama avec adaptateurs LoRA)
  3. Inférence : Votre propre matériel ou instances GPU cloud

Pour un petit modèle comme TinyLlama, vous pouvez exécuter l'inférence sur :

  • Google Colab (niveau gratuit avec limitations)
  • AWS t3.medium avec GPU (~0,05 $/heure)
  • Votre propre matériel (RTX 3060 ou mieux)

Meilleures pratiques d'expérience réelle

1. Commencez petit et montez en échelle Commencez par distilgpt2 ou gpt2 pour tester vos données et votre processus, puis passez à des modèles plus grands.

2. Surveillez le surapprentissage Avec de petits ensembles de données, les modèles peuvent mémoriser plutôt que d'apprendre. Surveillez votre perte d'évaluation.

3. La cohérence de formatage est critique Le format exact de vos données d'entraînement est très important. Soyez cohérent avec la ponctuation, l'espacement et la structure.

4. Testez avec des questions non vues Testez toujours avec des questions non incluses dans vos données d'entraînement pour assurer la généralisation.

5. Sauvegardez des points de contrôle réguliers L'entraînement peut être interrompu. Sauvegardez fréquemment et testez les points de contrôle intermédiaires.

Pièges courants et solutions

Problème : Le modèle génère du texte répétitif ou dénué de sens Solution : Baissez le taux d'apprentissage, augmentez la régularisation ou améliorez la qualité des données d'entraînement

Problème : Le modèle oublie les connaissances générales Solution : Incluez quelques exemples généraux dans vos données d'entraînement ou utilisez un modèle de base plus grand

Problème : Les réponses sont trop génériques Solution : Rendez vos exemples d'entraînement plus spécifiques et détaillés

Problème : Problèmes de mémoire GPU Solution : Réduisez la taille du batch, utilisez une quantification plus agressive ou le checkpointing de gradient

Combinaison avec RAG

Voici la partie puissante : vous pouvez combiner votre modèle affiné avec RAG pour le meilleur des deux mondes :

  1. Affinez pour la compréhension du domaine, le ton et les connaissances générales de l'entreprise
  2. Utilisez RAG pour les informations actuelles, les documents spécifiques ou les spécifications techniques détaillées

Cela vous donne un modèle qui « pense » comme votre entreprise mais peut accéder aux informations à jour.

Et après ?

Dans notre prochain article, nous allons complètement personnaliser — construire un modèle de langage à partir de zéro, entièrement le vôtre, fonctionnant sur votre matériel avec vos données.

L'affinement des modèles open-source vous donne un contrôle sans précédent sur votre assistant IA. Vous pouvez vous assurer qu'il comprend votre domaine, parle avec votre voix et n'envoie jamais vos données à des tiers. Avec les techniques d'efficacité modernes comme LoRA et la quantification, c'est plus accessible que jamais.

L'avenir de l'IA n'est pas seulement d'utiliser le modèle de quelqu'un d'autre — c'est de rendre l'IA vraiment vôtre.


À venir : Article 4 — « Construire votre propre modèle de langage : petit mais puissant »