Réponse courte
Rassemblez quelques centaines d’exemples de l’entrée et de la sortie exactes que vous voulez, puis entraînez un petit adaptateur LoRA par-dessus un modèle à poids ouverts gelé, avec les bibliothèques TRL et PEFT de Hugging Face. Gardez quelques exemples de côté et testez-y le modèle de base et le modèle adapté, pour voir si l’entraînement a aidé.
Question de suivi Comment savoir s’il a appris la bonne chose?
L’ajustement fin consiste à poursuivre l’entraînement d’un modèle sur vos propres exemples pour qu’il prenne une habitude : un format, un ton, un type de décision. Réentraîner chaque poids d’un modèle moderne demande du matériel sérieux, et c’est pourquoi la plupart des gens utilisent maintenant LoRA, pour Low-Rank Adaptation (adaptation de rang faible). Présentée par des chercheurs de Microsoft en 2021, la méthode gèle le modèle d’origine et entraîne une paire de petites matrices supplémentaires à côté de certaines de ses couches. Seules ces petites matrices changent. Pour GPT-3, les auteurs ont rapporté environ 10 000 fois moins de paramètres à entraîner qu’un ajustement fin complet et environ le tiers de la mémoire graphique, pour une qualité comparable.
Le résultat est un adaptateur : un fichier de quelques mégaoctets qui se pose par-dessus le modèle de base. Vous pouvez garder plusieurs adaptateurs pour un même modèle, les échanger ou en fusionner un avec le modèle pour l’utiliser plus rapidement. Comme le modèle de base reste intact, un entraînement raté ne vous coûte que du temps.
Quand LoRA est le bon outil
LoRA enseigne un comportement, pas des faits. Il est bon pour « toujours répondre selon cette structure », « classer ces billets à notre façon » ou « écrire comme notre centre d’assistance ». C’est un mauvais moyen de faire retenir à un modèle votre liste de prix ou vos politiques, qui changent; pour cela, donnez plutôt les documents au modèle au moment de la question. Un test utile : si un prompt soigné avec trois exemples vous mène déjà à 90 % du but, l’ajustement fin risque seulement d’ajouter des coûts. Si le modèle s’éloigne sans cesse d’un format dont vous avez besoin des milliers de fois par jour, un adaptateur peut aider, et il permet à un petit modèle peu coûteux de faire un travail qui exigerait autrement un grand modèle.
Un exemple complet, étape par étape
La tâche : transformer des notes de réunion en désordre en exactement trois lignes, Décision:, Responsable: et Échéance:. Le modèle de base est Qwen2.5-0.5B-Instruct, un petit modèle à poids ouverts qui tourne sur un portable et que Hugging Face utilise dans ses propres exemples d’entraînement. Deux bibliothèques font le travail : PEFT (Parameter-Efficient Fine-Tuning) crée l’adaptateur, et TRL (Transformer Reinforcement Learning) mène l’ajustement fin supervisé, ou SFT, c’est-à-dire l’apprentissage à partir de paires entrée-sortie.
1. Installer.
pip install "trl[peft]"
2. Écrire les données. Mettez environ 300 exemples dans train.jsonl et 40 autres dans test.jsonl, un par ligne, dans le format conversationnel prompt-réponse de TRL :
{"prompt": [{"role": "user", "content": "Notes : on s’entend pour déplacer le lancement, Sam vérifie la salle, il faut une réponse avant le vendredi 12"}], "completion": [{"role": "assistant", "content": "Décision: Déplacer la date du lancement\nResponsable: Sam\nÉchéance: Vendredi 12"}]}
Avec ce format, TRL calcule la perte d’entraînement seulement sur la réponse, si bien que le modèle apprend à écrire la réponse plutôt qu’à répéter vos notes. Écrivez les exemples à la main ou vérifiez-les tous : l’adaptateur copie vos erreurs aussi fidèlement que vos bonnes habitudes.
3. Entraîner.
from datasets import load_dataset
from peft import LoraConfig
from trl import SFTConfig, SFTTrainer
data = load_dataset("json", data_files={"train": "train.jsonl", "test": "test.jsonl"})
peft_config = LoraConfig(r=16, lora_alpha=32, lora_dropout=0.05, task_type="CAUSAL_LM")
args = SFTConfig(
output_dir="notes-lora",
learning_rate=2.0e-4,
num_train_epochs=3,
per_device_train_batch_size=4,
logging_steps=10,
)
trainer = SFTTrainer(
model="Qwen/Qwen2.5-0.5B-Instruct",
args=args,
train_dataset=data["train"],
eval_dataset=data["test"],
peft_config=peft_config,
)
trainer.train()
trainer.save_model("notes-lora")
Trois réglages comptent. r est le rang, la largeur des petites matrices : plus il est élevé, plus la capacité est grande et plus le fichier est gros. lora_alpha règle la force avec laquelle l’adaptateur agit sur le modèle. Le taux d’apprentissage de 2.0e-4 est environ dix fois celui que la documentation de TRL suggère pour un ajustement fin complet, parce que très peu de paramètres sont entraînés. save_model écrit seulement l’adaptateur, pas une copie du modèle.
À essayer : entraînez une fois avec 100 exemples et une fois avec 300, puis lancez le test ci-dessous sur les deux. Notez combien des 40 réponses de test réussissent chaque fois.
Comment savoir s’il a appris la bonne chose?
Testez-le sur des exemples qu’il n’a jamais vus, et comparez-le au modèle de départ. La baisse de la perte d’entraînement vous dit seulement que le modèle colle à votre fichier d’entraînement; elle ne vous dit pas qu’il se comportera bien avec les notes de lundi. C’est pourquoi 40 exemples sont restés dans test.jsonl. Voici un petit script qui fait tourner le modèle de base et le modèle adapté sur les mêmes prompts de test et vérifie le format :
import json
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
name = "Qwen/Qwen2.5-0.5B-Instruct"
tok = AutoTokenizer.from_pretrained(name)
base = AutoModelForCausalLM.from_pretrained(name)
tuned = PeftModel.from_pretrained(AutoModelForCausalLM.from_pretrained(name), "notes-lora")
def ask(model, messages):
text = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tok(text, return_tensors="pt")
out = model.generate(**inputs, max_new_tokens=80, do_sample=False)
return tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
def ok(answer):
lines = [l for l in answer.strip().splitlines() if l.strip()]
return [l.split(":")[0] for l in lines] == ["Décision", "Responsable", "Échéance"]
tests = [json.loads(line) for line in open("test.jsonl")]
for label, model in [("base", base), ("tuned", tuned)]:
print(label, sum(ok(ask(model, t["prompt"])) for t in tests), "/", len(tests))
Une vérification du format n’est que la moitié du test. Lisez au moins 20 réponses à côté des réponses attendues et marquez chacune comme juste ou fausse sur le fond : le responsable est-il la bonne personne, l’échéance est-elle celle des notes? Un résultat type, à titre d’illustration, pourrait être un modèle de base qui réussit la vérification du format 9 fois sur 40 et un adaptateur qui la réussit 38 fois, avec trois erreurs de fond que vous retraceriez ensuite jusqu’à des erreurs semblables dans vos données d’entraînement.
Vérifiez aussi ce que vous ne vouliez pas changer. Posez au modèle adapté quelques questions ordinaires hors de la tâche. S’il répond maintenant à tout en trois lignes, il a appris une leçon trop étroite; moins d’époques, un taux d’apprentissage plus faible ou quelques exemples généraux dans le mélange règlent habituellement le problème. Gardez le fichier de test et les résultats. La prochaine fois que vous ajouterez des données ou changerez un réglage, lancez le même test, et vous saurez si le nouvel adaptateur est vraiment meilleur.
Sources
- LoRA: Low-Rank Adaptation of Large Language Models — arXiv (Hu et al., Microsoft), 17 juin 2021
- PEFT Integration (TRL documentation) — Hugging Face (GitHub, huggingface/trl), 7 août 2026
- SFT Trainer (TRL documentation) — Hugging Face (GitHub, huggingface/trl), 7 août 2026