Cheatsheet - Phase 4 : Fine-Tuning & Adaptation

Adapter un modèle générique à votre domaine spécifique

Formation IA Générative Open Source

← Retour à l'index

1. Matrice de Décision : FT vs RAG vs Prompting

Quand Fine-Tuner ?

Comparaison Coût-Performance

Approche Latence Coût Setup Coût Inférence Exactitude
Zero-Shot Prompting Normal Faible (~0€) Faible Moyenne
Few-Shot + RAG Moyen Moyen (~100€) Moyen Élevée
Fine-Tuning (LoRA) Rapide Élevé (~500€) Faible Très élevée
Full Fine-Tuning Très rapide Très élevé (~2000€) Élevé Maximale

Matrice Visuelle

Budget/Données │ Peu de données │ Données moyennes │ Beaucoup données ────────────────────┼─────────────────┼──────────────────┼───────────────── Budget zéro │ Zero-Shot │ Few-Shot │ (RAG++) Budget faible │ Few-Shot │ RAG │ LoRA+RAG Budget moyen │ RAG │ LoRA+Prompt │ LoRA Budget élevé │ LoRA │ LoRA Full │ Full FT

2. Préparation des Données

Format Alpaca (Instruction-Tuning)

{ "instruction": "Classe ce produit", "input": "Un téléphone noir durable", "output": "Catégorie: Électronique, Électronique/Téléphones" }

Format ShareGPT (Conversations)

{ "conversations": [ {"from": "human", "value": "Quelle est ta spécialité?"}, {"from": "gpt", "value": "Je suis expert en IA..."}, {"from": "human", "value": "Donne un exemple."}, {"from": "gpt", "value": "Par exemple..."} ] }

Format JSONL (Minimal)

{"prompt": "Résume ceci:", "completion": "Résumé..."} {"prompt": "Classe:", "completion": "Classe..."} {"prompt": "Génère:", "completion": "Contenu..."}

Checklist Qualité Données

Critère Target Vérification
Taille dataset 1K-100K exemples len(dataset)
Doublons <5% set(texts) size
Balance classes ±20% Counter(labels)
Longueur tokens 64-2048 tokenizer.encode()
Erreurs typo <2% spellchecker
Format cohérent 100% validation schema

Pipeline de Nettoyage Python

import json from collections import Counter def clean_dataset(jsonl_path): seen = set() cleaned = [] with open(jsonl_path) as f: for line in f: obj = json.loads(line) text = obj.get('prompt', '') + obj.get('completion', '') # Pas de doublon if text in seen: continue seen.add(text) # Pas vide if len(text) < 20: continue cleaned.append(obj) return cleaned

3. SFT : Supervised Fine-Tuning Basiques

Processus SFT Standard

Modèle Pré-entraîné ↓ Entraînement Supervisé (Input → Output attendu) ↓ Optimisation des poids pour prediction exacte ↓ Modèle Spécialisé

Hyperparamètres Typiques

Paramètre Recommandé Plage
learning_rate 5e-5 1e-5 à 1e-4
batch_size 16-32 4 à 128
num_epochs 3 1 à 10
warmup_ratio 0.1 0.05 à 0.2
weight_decay 0.01 0.0 à 0.1
max_grad_norm 1.0 0.5 à 2.0

Régularisation : Overfitting vs Underfitting

Overfitting (train_loss bas, eval_loss haut)

  • Réduire epochs
  • Augmenter weight_decay
  • Ajouter données
  • Utiliser Dropout

Underfitting (loss élevée partout)

  • Augmenter epochs
  • Réduire learning_rate
  • Vérifier données (doublon?)
  • Modèle trop petit

Early Stopping

from transformers import EarlyStoppingCallback trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, callbacks=[ EarlyStoppingCallback( early_stopping_patience=3, early_stopping_threshold=0.0 ) ] ) trainer.train()

4. Taxonomie PEFT (Parameter-Efficient FT)

Famille PEFT Complète

Méthode Paramètres à entraîner Mémoire Performance Cas d'usage
LoRA ~0.1-1% -60% Excellente Premier choix
QLoRA ~0.1% + quant -80% Très bonne Mémoire limitée
Adapters ~3-5% -40% Bonne Multi-tâches
Prefix Tuning ~0.1% -50% Moyenne Génération
IA3 ~0.01% -85% Variable Modèles 100B+

Critères de Sélection

5. LoRA en Détail

Mathématique LoRA

h = W₀x + ΔWx = W₀x + BAx où: - W₀ = poids original (gelé, non-entraîné) - B ∈ ℝ^(d_out × r) - A ∈ ℝ^(r × d_in) - r = rang << min(d_out, d_in)

Hyperparamètres LoRA

Paramètre Recommandé Effet
r (rank) 8-16 Plus haut = plus flexible, plus mémoire
lora_alpha 16-32 Scaling, souvent 2×rank
lora_dropout 0.05 Régularisation, evite overfitting
target_modules ["q_proj", "v_proj"] Où appliquer LoRA

Target Modules par Modèle

# LLaMA / Mistral target_modules = ["q_proj", "v_proj"] # Qwen target_modules = ["c_attn"] # Phi-2 target_modules = ["q_proj", "v_proj", "dense"] # Complet (attention + FFN) target_modules = ["q_proj", "v_proj", "k_proj", "up_proj", "down_proj"]

Configuration LoRA Complète

from peft import LoraConfig, get_peft_model from transformers import AutoModelForCausalLM lora_config = LoraConfig( r=8, lora_alpha=16, lora_dropout=0.05, bias="none", task_type="CAUSAL_LM", target_modules=["q_proj", "v_proj"], inference_mode=False ) model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B") model = get_peft_model(model, lora_config) print(model.print_trainable_parameters())

Fusion et Sauvegarde

# Après entraînement, fusionner poids model = model.merge_and_unload() # Sauvegarder le modèle fusionné (optionnel) model.save_pretrained("./final_model") tokenizer.save_pretrained("./final_model") # Charger normal comme n'importe quel modèle from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("./final_model")

6. QLoRA : 4-Bit + LoRA

Architecture QLoRA

Modèle 70B (140GB) sans quantization ↓ Quantization 4-bit (10GB) ↓ LoRA adapters (100MB) ↓ Total: ~10.1GB (vs 140GB!) ↓ Fine-tune sur 24GB GPU

Types de Quantization

Format Taille Précision Qualité
FP32 100% 32-bit Parfaite
BF16/FP16 50% 16-bit Excellente
INT8 25% 8-bit Très bonne
NF4 25% 4-bit normalisé Bonne
INT4 25% 4-bit Acceptable

Code QLoRA Complet

from transformers import AutoModelForCausalLM, BitsAndBytesConfig from peft import LoraConfig, get_peft_model # Config quantization bnb_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_use_double_quant=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.bfloat16 ) # Charger modèle quantifié model = AutoModelForCausalLM.from_pretrained( "meta-llama/Llama-2-70b", quantization_config=bnb_config, device_map="auto" ) # Appliquer LoRA lora_config = LoraConfig( r=16, lora_alpha=32, target_modules=["q_proj", "v_proj"], lora_dropout=0.05, bias="none", task_type="CAUSAL_LM" ) model = get_peft_model(model, lora_config) print(model.print_trainable_parameters())

Double Quantization

7. TRL & SFTTrainer

Transformer Reinforcement Learning Stack

TRL (Transformer Reinforcement Learning) ├── SFTTrainer (Supervised Fine-Tuning) ├── DPOTrainer (Direct Preference Opt) ├── PPOTrainer (Reinforcement Learning) └── Utilities (Data, Models, Training)

Configuration SFTTrainer

from trl import SFTTrainer, SFTConfig sft_config = SFTConfig( output_dir="./results", num_train_epochs=3, per_device_train_batch_size=4, per_device_eval_batch_size=4, learning_rate=5e-5, lr_scheduler_type="cosine", warmup_steps=100, gradient_accumulation_steps=4, max_seq_length=2048, # Logging logging_steps=10, save_steps=100, eval_steps=50, evaluation_strategy="steps", # Distributed ddp_find_unused_parameters=False, report_to=["wandb"] ) trainer = SFTTrainer( model="mistralai/Mistral-7B", train_dataset=train_dataset, eval_dataset=eval_dataset, args=sft_config, peft_config=lora_config ) trainer.train()

Intégration Weights & Biases

# Logging automatique export WANDB_PROJECT="fine-tuning" export WANDB_ENTITY="my-entity" # Dans SFTConfig report_to=["wandb"], wandb_project="fine-tuning" # Métriques tracées automatiquement: # - train_loss, eval_loss # - learning_rate # - epoch # - temps execution

8. DPO : Direct Preference Optimization

Formule DPO

L_DPO = -E[log σ(β log(π(y_w|x)/π_ref(y_w|x)) - β log(π(y_l|x)/π_ref(y_l|x)))] où: - y_w = réponse préférée (chosen) - y_l = réponse rejetée (rejected) - β = coefficient température (0.1 typique) - π = modèle à optimiser - π_ref = modèle de référence

Format Données DPO

{ "prompt": "Comment faire un gâteau?", "chosen": "Mélanger farine, œufs... C'est savoureux!", "rejected": "Je ne sais pas comment faire un gâteau." }

Avantages vs RLHF

Aspect DPO RLHF
Reward Model Non requis Requis
Stabilité Très bonne Difficile
Complexité Faible Élevée
Performance Comparable Légèrement meilleure
Temps setup Rapide (~1 semaine) Lent (~2 semaines)

Code DPOTrainer

from trl import DPOTrainer, DPOConfig dpo_config = DPOConfig( output_dir="./dpo_results", per_device_train_batch_size=4, num_train_epochs=3, learning_rate=5e-5, beta=0.1, # Température de contraste max_seq_length=2048 ) trainer = DPOTrainer( model="mistralai/Mistral-7B", train_dataset=train_dataset, eval_dataset=eval_dataset, args=dpo_config, peft_config=lora_config ) trainer.train()

9. RLHF en Pratique

Pipeline RLHF Complet

Phase 1: SFT Modèle Base + Démonstrations → Modèle SFT Phase 2: Reward Model Modèle SFT + Comparaisons humaines → Reward Model Phase 3: PPO Modèle SFT + Reward Model → Modèle Aligné

Hyperparamètres PPO

Paramètre Typique Description
learning_rate 1e-5 Très faible pour stabilité
batch_size 64-128 Large pour stabilité
mini_batch_size 8-16 Pour gradient updates
ppo_epochs 4 Iterations par batch
cliprange 0.2 PPO clipping parameter
gamma 0.99 Discount factor

Code PPOTrainer

from trl import PPOTrainer, PPOConfig ppo_config = PPOConfig( model_name="mistralai/Mistral-7B", learning_rate=1e-5, batch_size=128, mini_batch_size=16, ppo_epochs=4, gradient_accumulation_steps=8 ) trainer = PPOTrainer( config=ppo_config, model=model, ref_model=ref_model, tokenizer=tokenizer, train_dataset=train_dataset, data_collator=data_collator ) # Boucle d'entraînement for epoch in range(3): for step, batch in enumerate(train_dataloader): # Générer réponses response_tensors = trainer.generate(**batch) # Scorer avec reward model rewards = reward_model.score(response_tensors) # PPO update stats = trainer.step(batch, response_tensors, rewards) print(f"Step {step}: Loss = {stats['loss']}")

Complexité RLHF

10. ORPO, SimPO, KTO (Méthodes 2025-2026)

Nouvelle Génération d'Alignment

Méthode Année Approche Avantages
ORPO 2024 SFT + Odds Ratio loss Une étape, stable, efficace
SimPO 2024 Contrastive + preference Très stable, rapide
KTO 2025 Theoretic optimal alignment Performance maximale

ORPO (Odds Ratio Preference Optimization)

L_ORPO = L_SFT + λ * L_OR où L_OR = -E[log σ(log odds(y_w|x) - log odds(y_l|x))] odds(y|x) = P(y|x) / (1 - P(y|x))

Code ORPO

from trl import ORPOConfig, ORPOTrainer orpo_config = ORPOConfig( output_dir="./orpo_results", per_device_train_batch_size=4, num_train_epochs=3, learning_rate=5e-5, lambda_=0.1, # Poids du loss OR max_seq_length=2048 ) trainer = ORPOTrainer( model="mistralai/Mistral-7B", args=orpo_config, train_dataset=train_dataset, eval_dataset=eval_dataset, peft_config=lora_config ) trainer.train()

Comparaison des Approches d'Alignment

Méthode │ Étapes │ Reward Model │ Stabilité │ Performance ─────────────┼────────┼──────────────┼───────────┼──────────── Prompting │ 0 │ Non │ Très haute│ Basse SFT │ 1 │ Non │ Très haute│ Moyenne DPO │ 1 │ Non │ Très haute│ Haute ORPO │ 1 │ Non │ Très haute│ Haute SimPO │ 1 │ Non │ Très haute│ Très haute RLHF │ 3 │ Oui │ Basse │ Maximale KTO │ 1 │ Non │ Très haute│ Maximale

11. Model Merging

Stratégies de Fusion

Méthode Complexité Qualité Cas d'usage
Simple Average Très faible Faible Quick experiments
TIES-Merge Faible Bonne Multiple fine-tunes
DARE Moyen Très bonne Combiner LoRAs
Passthrough Moyen Excellente LoRA selective merge
Gradient-based Élevée Maximale Research/optimisation

mergekit Configuration

# config.yaml pour mergekit models: - model: base/Mistral-7B parameters: weight: 1.0 - model: finetune/medical-lora parameters: weight: 0.5 - model: finetune/legal-lora parameters: weight: 0.3 merge_method: ties base_model: base/Mistral-7B parameters: normalize_weights: true threshold: 0.05 # Exécution mergekit-cli merge config.yaml ./merged_model

DARE (Drop And REscale)

# DARE merge pour LoRAs import torch def dare_merge(base_weight, delta, scaling_factor=1.0): """ Fusionner avec probabilité dropout + rescaling """ # Dropout aléatoire des changements mask = torch.bernoulli(torch.ones_like(delta) * 0.7) # Rescaling pour compenser delta_scaled = delta * mask / (1 - 0.3) # Fusion merged = base_weight + scaling_factor * delta_scaled return merged

Fusion de Multiples LoRAs

# Fusionner plusieurs LoRAs dans un seul from peft import LoraConfig # Charger base model model = AutoModelForCausalLM.from_pretrained("mistral-7b") # Fusion séquentielle for lora_path in ["lora_medical", "lora_legal", "lora_code"]: peft_model = PeftModel.from_pretrained(model, lora_path) model = peft_model.merge_and_unload() # Sauvegarder modèle fusionné model.save_pretrained("./merged_expert_model")

12. Continued Pre-Training

Quand faire CPT?

CPT vs Fine-Tuning

Aspect CPT Fine-Tuning
Données requises Très élevées (100GB+) Modérées (10GB)
Temps entraînement Très long (mois) Court (heures/jours)
Coût Très élevé (10k€+) Moyen (100€-1k€)
Vocabulaire Peut créer tokens Utilise existant
Performance Maximale dans domaine Très bonne

Pipeline CPT

# 1. Préparer corpus domaine corpus_files = glob.glob("./medical_data/*.txt") dataset = load_dataset("text", data_files=corpus_files) # 2. Configuration pré-entraînement training_args = TrainingArguments( output_dir="./cpt_model", num_train_epochs=1, per_device_train_batch_size=16, gradient_accumulation_steps=4, learning_rate=5e-4, warmup_steps=10000, logging_steps=100, save_steps=5000, max_steps=100000 ) # 3. Entraînement trainer = Trainer( model=model, args=training_args, train_dataset=dataset, data_collator=DataCollatorForLanguageModeling( tokenizer=tokenizer, mlm=False ) ) trainer.train()

13. Multi-Task & Instruction Tuning

Approche Multi-Task

Dataset 1 (Q&A médicale) Dataset 2 (Summarization légale) Dataset 3 (Code generation) ↓ Unified format (instruction) ↓ Single model trained on all ↓ Généralisation améliorée

Format Instruction Unifiée

# Tous les datasets au format Alpaca { "instruction": "Répondre à une question médicale", "input": "Qu'est-ce que l'hypertension?", "output": "L'hypertension est l'élevation de la pression artérielle..." } { "instruction": "Résumer ce texte légal", "input": "Article 1234 du code civil...", "output": "Résumé : ..." } { "instruction": "Générer du code Python", "input": "Fonction qui calcule Fibonacci", "output": "def fibonacci(n): ..." }

Avantages Multi-Task

Data Mixing Strategies

Stratégie Description Cas d'usage
Round-robin Alterner entre datasets Datasets petits/équilibrés
Proportional Mix selon taille Datasets non-équilibrés
Stratified Sampling par classe Classes déséquilibrées
Curriculum Facile → difficile Données très hétérogènes

14. Évaluation de Fine-Tuning

Benchmarks Standard

Benchmark Type Taille Domaine
MMLU Multiple choice QA 15,908 questions 57 sujets (généraliste)
HumanEval Code generation 164 problèmes Python
GSM8K Math reasoning 8,500 problèmes Mathématiques grade 8
TruthfulQA Véracité réponses 817 questions Fact accuracy
BBH Raisonnement difficile 23 tâches Cognition complexe

LLM-as-Judge Evaluation

def evaluate_with_judge(model, test_cases, judge_model="gpt-4"): """Évaluer réponses avec un modèle judge""" results = [] for case in test_cases: # Générer réponse response = model.generate(case["prompt"]) # Évaluer avec judge eval_prompt = f""" Question: {case['prompt']} Réponse: {response} Réponse de référence: {case['reference']} Note cette réponse sur 5 critères : 1. Exactitude (1-5) 2. Complétude (1-5) 3. Clarté (1-5) 4. Utilité (1-5) 5. Respect des consignes (1-5) Fournis notation JSON.""" scores = judge_model.evaluate(eval_prompt) results.append(scores) return average_scores(results)

Métriques Automatiques

Métrique Usage Plage Meilleur
BLEU Traduction, n-gram overlap 0-100 Plus haut
ROUGE-L Résumé, LCS 0-1 Plus haut
BERTScore Similarité sémantique 0-1 Plus haut
Perplexity Qualité modèle LM 0-∞ Plus bas

Framework Evaluation Complet

from datasets import load_dataset from evaluate import load def full_evaluation(model, tokenizer, benchmark_name="mmlu"): """Pipeline complet évaluation""" dataset = load_dataset(f"json", data_files=f"{benchmark_name}.json") # Métriques accuracy = load("accuracy") bleu = load("bleu") predictions = [] references = [] for example in dataset["test"]: pred = model.generate(example["question"]) predictions.append(pred) references.append(example["answer"]) # Calcul acc_score = accuracy.compute( predictions=predictions, references=references ) return { "accuracy": acc_score["accuracy"], "benchmark": benchmark_name }

15. Axolotl : Framework Unifié YAML

Configuration Axolotl Complète

base_model: mistralai/Mistral-7B model_type: AutoModelForCausalLM tokenizer_type: AutoTokenizer # Data datasets: - path: data/train.jsonl type: alpaca split: train - path: data/eval.jsonl type: alpaca split: eval # Training learning_rate: 5e-5 num_epochs: 3 micro_batch_size: 4 gradient_accumulation_steps: 4 max_seq_length: 2048 warmup_ratio: 0.1 lr_scheduler: cosine weight_decay: 0.01 # LoRA peft: adapter: lora lora_r: 8 lora_alpha: 16 lora_dropout: 0.05 target_modules: [q_proj, v_proj] bias: none # Distributed distributed_backend: nccl ddp_timeout: 3600 # Logging output_dir: ./axolotl_outputs logging_steps: 10 save_steps: 100 eval_steps: 50 report_to: wandb # GPU device_map: auto bf16: true

Lancement Axolotl

# Installation pip install axolotl # Single GPU axolotl train config.yaml # Multi-GPU accelerate launch -m axolotl.cli.train config.yaml # Inference axolotl inference config.yaml \ --prompt "Your question here" # Merge LoRA axolotl merge_lora config.yaml

Avantages Axolotl

16. Unsloth : Fine-Tuning Accéléré

Optimisations Unsloth

Optimisation Speedup Mémoire Compatibilité
Flash Attention 2 1.3-1.5× 0% Ampere+
RoPE optimization 1.2× 0% All
Memory efficient LoRA 1.2× -30% All
Fused ops 1.5× 0% CUDA compatible
Combined 2-2.5× -60% Ampere+

Installation et Usage

# Installation (GPU specific) pip install unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git # Ou pour RTX 3090, 4090 pip install unsloth[colab] @ git+https://github.com/unslothai/unsloth.git # Usage - remplacer chargement modèle from unsloth import FastLanguageModel max_seq_length = 2048 dtype = None # Auto-detect load_in_4bit = True model, tokenizer = FastLanguageModel.from_pretrained( model_name = "unsloth/mistral-7b", max_seq_length = max_seq_length, dtype = dtype, load_in_4bit = load_in_4bit, ) # Ajouter LoRA model = FastLanguageModel.get_peft_model( model, r = 16, lora_alpha = 16, lora_dropout = 0.05, target_modules = ["q_proj", "v_proj"], bias = "none", use_gradient_checkpointing = True, )

Modèles Supportés (Optimisés)

Modèle Paramètres Speedup Support
Llama-2 7B, 13B, 70B 2.5× Complet
Mistral 7B 2.3× Complet
Phi 2, 2.5 2.1× Complet
Qwen 7B, 14B 2.2× Complet

17. Cloud GPU Providers : Comparatif

Fournisseurs Principaux 2026

Provider GPU Premium Coût/h H100 Setup Support
RunPod H100, A100, RTX 4090 $3.50 Instants Excellent
Lambda Labs H100, A100 $4.00 Minutes Très bon
Vast.ai Marché $2.50 Rapide Bon
AWS SageMaker P4d (H100) $12.99 Lent Excellent
GCP Vertex A100, L4 $8.00 Moyen Bon

Estimation de Coûts

# Fine-tuning 7B model sur 10k examples # Temps estimé: 2-4 heures # Scenario 1: RTX 4090 ($3.50/h, RunPod) hours = 3 cost = 3.5 * hours # $10.50 # Scenario 2: H100 ($3.50/h, RunPod) hours = 1.5 cost = 3.5 * hours # $5.25 # Scenario 3: Local GPU RTX 3090 (~$2.50/h electricity) hours = 5 cost = 2.5 * hours # $12.50

RunPod Setup

# 1. Créer compte RunPod.io # 2. Obtenir API key # 3. Script Python pour lancer job import runpod endpoint_id = runpod.create_endpoint( name="fine-tuning-mistral", image="runpod/pytorch:latest", gpu_count=1, volume_in_gb=50, container_disk_in_gb=100 ) # 4. Exécuter training result = runpod.run_job( endpoint_id, input={ "command": "python /workspace/train.py" } )

Recommandations Provider

18. DeepSpeed & FSDP : Distributed Training

Stratégies Distributed Training

Stratégie Data Parallel Model Parallel Overhead Cas d'usage
DDP Oui Non 5-10% 1-8 GPUs
DeepSpeed ZeRO-1 Oui Non 5-10% Optimiseur sharding
DeepSpeed ZeRO-2 Oui Partial 10-15% Optimiseur + gradients
DeepSpeed ZeRO-3 Oui Oui 15-25% Full model sharding
FSDP Oui Oui 15-25% PyTorch native

Configuration DeepSpeed

# ds_config.json { "train_batch_size": 128, "train_micro_batch_size_per_gpu": 4, "gradient_accumulation_steps": 8, "optimizer": { "type": "AdamW", "params": { "lr": 5e-5, "betas": [0.9, 0.95], "eps": 1e-8, "weight_decay": 0.01 } }, "scheduler": { "type": "WarmupDecay", "params": { "warmup_min_lr": 0, "warmup_max_lr": 5e-5, "warmup_num_steps": 1000, "total_num_steps": 100000 } }, "zero_optimization": { "stage": 2, "offload_optimizer": { "device": "cpu", "pin_memory": true } }, "activation_checkpointing": { "partition_activations": true, "cpu_checkpointing": false } } # Lancer avec DeepSpeed deepspeed --num_gpus=8 train.py \ --deepspeed ds_config.json

FSDP Configuration

# Transformer config + FSDP from torch.distributed.fsdp import FullyShardedDataParallel as FSDP from torch.distributed.fsdp.wrap import size_based_auto_wrap_policy # Auto wrap small layers auto_wrap_policy = size_based_auto_wrap_policy( min_num_params=100_000_000 # 100M ) # Wrap modèle model = FSDP( model, auto_wrap_policy=auto_wrap_policy, sharding_strategy=ShardingStrategy.FULL_SHARD ) # Entraîner normalement optimizer.zero_grad() loss.backward() optimizer.step()

19. Export & Conversion de Modèles

Pipeline Complet Export

Modèle Fine-Tuné (FP32/BF16) ↓ 1. Merge LoRA → Modèle complet ↓ 2. Quantization (optionnel) → GGUF/GPTQ ↓ 3. Conversion format → GGML, ONNX, TensorRT ↓ 4. Upload Hugging Face Hub ↓ 5. Serve (vLLM, Ollama, TGI)

Fusion et Export LoRA

from peft import AutoPeftModelForCausalLM from transformers import AutoTokenizer # Charger modèle + LoRA model = AutoPeftModelForCausalLM.from_pretrained( "path/to/lora/checkpoint", device_map="auto", torch_dtype=torch.bfloat16 ) # Fusionner et décharger merged_model = model.merge_and_unload() # Sauvegarder merged_model.save_pretrained("./final_model") AutoTokenizer.from_pretrained("path/to/base/model").save_pretrained("./final_model")

Conversion GGUF (pour Ollama)

# 1. Convertir en GGUF python ./llama.cpp/convert.py \ ./final_model \ --outfile ./model.gguf \ --outtype q4_k_m # 4-bit K-quant # 2. Tester localement avec Ollama ollama create custom-model -f Modelfile # Modelfile contenu: FROM ./model.gguf:latest PARAMETER temperature 0.7 PARAMETER top_k 50 PARAMETER top_p 0.95 # 3. Servir ollama run custom-model "Votre prompt"

Upload Hugging Face Hub

from huggingface_hub import HfApi, ModelCard from datetime import datetime # Authentification hf_api = HfApi() # Créer Model Card card = ModelCard.from_template( template_path="model_card_template.md", model_id="username/custom-model", metrics=[{"name": "accuracy", "value": 0.92}] ) # Upload hf_api.upload_folder( folder_path="./final_model", repo_id="username/custom-model", repo_type="model", commit_message=f"Fine-tuned model - {datetime.now().isoformat()}" ) # Rendre public hf_api.update_repo_visibility( repo_id="username/custom-model", private=False )

Formats de Sortie

Format Taille Vitesse Compatibilité
FP32 100% Normal Universelle
BF16 50% Rapide GPU moderne
GGUF 25% Très rapide Ollama, CPU
GPTQ 25% Rapide GPU spécifiques
TorchScript 50% Rapide Production PyTorch

20. Vision Fine-Tuning

Modèles de Vision Spécialisés

Modèle Type Fine-Tuning Cas d'usage
Stable Diffusion Génération d'images DreamBooth, LoRA Images personnalisées
LLaVA Vision + Langage Full SFT, LoRA Vision understanding
CLIP Image-Text matching Contrastive learning Retrieval, classification
InternVL Multimodal Instruction tuning Comprendre images + texte

Stable Diffusion LoRA

from diffusers import StableDiffusionPipeline from peft import LoraConfig, get_peft_model # Charger modèle pipe = StableDiffusionPipeline.from_pretrained( "runwayml/stable-diffusion-v1-5" ) # Appliquer LoRA à l'UNet unet = pipe.unet lora_config = LoraConfig( r=32, lora_alpha=64, target_modules=["to_q", "to_v"], lora_dropout=0.05 ) unet = get_peft_model(unet, lora_config) # Fine-tuner sur dataset custom # ... training loop ... # Générer avec LoRA with torch.no_grad(): image = pipe( prompt="a photo of a dog in style XYZ", num_inference_steps=50 ).images[0]

LLaVA Fine-Tuning

# Format données vision instruction { "image": "path/to/image.jpg", "conversations": [ { "from": "human", "value": "Qu'est-ce que tu vois dans cette image?" }, { "from": "gpt", "value": "Je vois un chien en train de courir..." } ] } # Fine-tune avec LLaVA python -m llava.train.train \ --model_name_or_path lmsys/llava-v1-7b \ --data_path ./vision_data.json \ --image_folder ./images \ --output_dir ./llava_ft \ --num_train_epochs 3 \ --per_device_train_batch_size 4 \ --per_device_eval_batch_size 4

Production Best Practices