Vous utilisez GPT-4o et Claude via leurs API. Le coût par token est prévisible. La latence est acceptable. Mais vous vous heurtez sans cesse au même mur : le modèle ne comprend pas suffisamment bien votre domaine, et vous ne pouvez pas vous permettre de compter uniquement sur l’ingénierie de prompts pour résoudre le problème.
Le fine-tuning résout ce problème. Pas par magie. En montrant à un modèle 100 à 1 000 exemples de ce que vous attendez précisément qu’il fasse, puis en réentraînant ses poids pour qu’ils correspondent à vos spécificités. J’ai construit le classifieur de signaux de trading d’AlgoVesta sur Llama 3 8B affiné, et cela réduit nos coûts d’inférence de 70 % par rapport à GPT-4 tout en égalant la précision sur notre domaine.
Voici ce qui compte vraiment : la qualité des données prime sur la quantité, vous avez besoin d’une base de référence avant d’affiner, et le déploiement est l’étape où la plupart des gens échouent.
Quand le Fine-Tuning a Vraiment du Sens
Le fine-tuning n’est pas la réponse à « mon prompt ne fonctionne pas ». Corrigez d’abord le prompt. La chaîne de pensée (chain-of-thought), la récupération (retrieval) ou un message système résolvent généralement le problème pour 1/100ème du coût.
Affinez lorsque :
- Vous avez plus de 100 exemples étiquetés de votre tâche spécifique (moins n’aide pas beaucoup)
- Le comportement de base du modèle est proche mais pas tout à fait correct — vous ajustez, vous n’écrasez pas
- Vous avez besoin d’un format de sortie cohérent ou d’une terminologie spécifique au domaine que les modèles génériques peinent à gérer
- Le coût d’inférence ou la latence sont une contrainte stricte (les modèles plus petits et affinés surpassent les modèles génériques plus grands sur votre tâche)
Vous ne devriez PAS affiner si vous essayez d’ajouter des connaissances factuelles que le modèle n’a pas. Utilisez RAG à la place. Si vous essayez de rendre le modèle plus « utile » ou « amical », réécrivez votre prompt. Le fine-tuning n’est pas une greffe de personnalité.
Préparation des Données : le 80/20 du Processus
Passez le plus clair de votre temps ici. De mauvaises données ruinent tout en aval.
Votre ensemble d’entraînement nécessite : une entrée, une sortie attendue, et idéalement une étiquette de confiance (certains exemples sont plus représentatifs que d’autres). Pour la classification, c’est simple. Pour la génération (résumé de texte, rédaction d’e-mails), c’est plus compliqué — une entrée peut avoir plusieurs sorties correctes.
Le format dépend du modèle et du framework. L’API de fine-tuning d’OpenAI attend du JSONL :
{"messages": [{"role": "user", "content": "Classifiez ce signal de trading : MSFT a clôturé 3% au-dessus de la MA50"}, {"role": "assistant", "content": "bullish_breakout"}]}
{"messages": [{"role": "user", "content": "Classifiez ce signal de trading : TSLA a ouvert en baisse avec un volume élevé"}, {"role": "assistant", "content": "bearish_reversal"}]}
Si vous utilisez Hugging Face avec un modèle ouvert, le format dépend de votre framework (généralement la même structure, mais avec une sérialisation différente).
Avant de finaliser votre jeu de données :
- Auditez manuellement 50 exemples aléatoires. Vérifiez les erreurs d’étiquetage, les entrées peu claires ou les fuites de données (données de test accidentellement dans l’ensemble d’entraînement). J’ai trouvé que 12 % de notre premier jeu de données étaient mal étiquetés. Nous ne l’avons découvert qu’après que l’inférence ait échoué sur des cas limites connus.
- Divisez en 80/10/10 : entraînement/validation/test. Ne laissez pas les données de validation toucher l’entraînement. Les données de test doivent être entièrement séparées et utilisées uniquement à la toute fin.
- Équilibrez les classes si vous faites de la classification. Si 90 % de vos exemples sont « aucune action » et 10 % sont « acheter », le modèle apprendra à toujours prédire « aucune action ». Sur-échantillonnez la classe minoritaire ou utilisez des poids de classe pendant l’entraînement.
Choisir Votre Modèle de Base
Commencez par ce que vous connaissez. Si vous avez testé avec Claude, l’API de fine-tuning d’OpenAI est le chemin le plus simple. Anthropic ne propose pas encore de fine-tuning. Si le coût est critique, utilisez un modèle ouvert : Llama 3 8B ou Mistral 7B fonctionnent sur du matériel grand public et s’affinent en quelques heures au lieu de jours.
Le choix du modèle présente des compromis :
- OpenAI GPT-3.5 Turbo : environ 1,50 $ pour 1 million de tokens d’entraînement. Le plus rapide à mettre en production. Fonctionne sur leur infrastructure. Idéal si vous voulez affiner sans gérer le calcul.
- Llama 3 8B ou Mistral 7B : modèle gratuit, mais vous payez pour le calcul GPU. 0,24 $ à 0,50 $ par heure sur la plupart des fournisseurs cloud. Mieux si vous avez plus de 500 exemples et que vous souhaitez itérer. Le coût d’inférence tombe à presque zéro une fois déployé.
- Claude ou GPT-4 : modèles de base plus performants mais plus chers à affiner (si OpenAI le prend en charge) ou indisponibles (Anthropic). Ne commencez pas par là.
Je recommande de commencer avec GPT-3.5 Turbo si vous avez moins de 300 exemples. Utilisez Llama 3 8B si vous en avez plus de 500 et pouvez tolérer un modèle de base légèrement moins performant qui sera néanmoins excellent sur votre domaine après affinage.
Le Processus de Fine-Tuning Réel
Cela varie selon la plateforme, mais le schéma est identique.
Si vous utilisez l’API d’OpenAI :
import openai
openai.api_key = "votre-clé"
# Télécharger le fichier d'entraînement
response = openai.File.create(
file=open("training_data.jsonl", "rb"),
purpose="fine-tune"
)
file_id = response["id"]
# Lancer le job de fine-tuning
job = openai.FineTuningJob.create(
training_file=file_id,
model="gpt-3.5-turbo",
hyperparameters={"n_epochs": 3} # 3 passes sur vos données
)
print(f"Job ID : {job['id']}")
# Vérifier le statut
job_status = openai.FineTuningJob.retrieve(job["id"])
print(job_status["status"])
Pour Llama 3 sur Hugging Face, vous utiliseriez la bibliothèque transformers avec LoRA (Low-Rank Adaptation) pour n’affiner qu’un petit ensemble de paramètres au lieu du modèle complet — ce qui est considérablement plus rapide :
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b")
lora_config = LoraConfig(
r=8, # Dimension de rang faible
lora_alpha=32,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.05
)
model = get_peft_model(model, lora_config)
# Passer à votre boucle d'entraînement (HuggingFace Trainer ou personnalisé)
Les hyperparamètres sont importants : n_epochs (3 est standard), le taux d’apprentissage (généralement de 2e-5 à 5e-4) et la taille du lot (dépend de la mémoire de votre GPU). Commencez avec les valeurs par défaut. Ne cherchez pas à optimiser les performances avant d’avoir une base de référence.
Évaluation Avant le Déploiement
Votre perte d’entraînement diminuera. Cela ne signifie rien. Ce qui compte : le modèle affiné est-il plus performant sur des données qu’il n’a pas vues ?
Exécutez votre ensemble de test mis de côté sur le modèle de base et votre version affinée. Comparez la précision, le score F1 (pour la classification) ou le taux de correspondance exacte (pour les sorties structurées). Si l’amélioration est inférieure à 5 %, le fine-tuning n’a pas aidé — vous aviez probablement un problème de prompt ou de données à la place.
Testez manuellement les cas limites. Fournissez au modèle des exemples qui sont à la limite, intentionnellement ambigus, ou spécifiques au domaine d’une manière que vos données d’entraînement n’auraient peut-être pas couverte. Un score de précision de 90 % signifie qu’une prédiction sur dix est erronée. Sachez lesquelles.
Déploiement : Là Où Ça Casse Vraiment
Une fois affiné, votre modèle réside dans un point d’accès API ou sur votre matériel. Les erreurs critiques se produisent ici :
Vous ne gérez pas les versions de vos affinages. Vous déployez une nouvelle version en production et l’inférence échoue. Nommez-les : trading-signals-v1-20250115 inclut la date et la version. Gardez l’ancien point d’accès actif pendant 2 semaines en parallèle.
Vous ne testez pas le point d’accès de production avec des données fraîches. Votre ensemble de test datait du mois dernier. L’inférence réelle aujourd’hui rencontre des distributions différentes. Surveillez l’entropie de sortie, la latence et les taux d’erreur en production. Si la précision diminue, vos données ont dérivé.
Vous oubliez le coût de possession. Un modèle 8B affiné fonctionnant 24h/24 et 7j/7 sur un A100 coûte environ 700 $/mois. Un point d’accès GPT-3.5 Turbo mis en cache pour le même volume coûte environ 90 $. Faites le calcul avant de déployer.
Si vous déployez sur votre infrastructure, utilisez vLLM ou TensorRT pour l’optimisation de l’inférence. Vous réduirez la latence de 50 % et la mémoire GPU de 30 % par rapport à un déploiement transformers brut.
Votre Prochaine Étape
Rassemblez 150 à 200 exemples de votre tâche. Passez une semaine à les nettoyer et à les étiqueter. Ensuite, effectuez un fine-tuning peu coûteux sur GPT-3.5 Turbo d’OpenAI (coût d’environ 5 $). Comparez les sorties côte à côte avec le modèle de base. Cette expérience vous dira si le fine-tuning vaut le temps pour votre cas d’utilisation. La plupart du temps, un meilleur prompt ou RAG résout le problème. Mais quand ce n’est pas le cas, vous le saurez.