Module 9 — Fusion des adaptateurs et export
Le modèle est affiné, mesuré, contrôlé. Reste à le rendre utilisable — pour un serveur d'inférence, pour Ollama sur un poste, pour un partage interne. Ce module couvre trois étapes indissociables : fusionner l'adaptateur dans les poids, convertir au format GGUF, publier proprement avec sa licence.
Fusion : quand faut-il fusionner, et quand ne pas le faire
Un modèle affiné par LoRA est en réalité deux fichiers : le modèle de base gelé et l'adaptateur. À l'inférence, chaque produit matriciel calcule d'abord le résultat avec les poids de base, puis y ajoute la contribution de l'adaptateur. Ce surcoût est modeste — quelques pour cent — mais il est constant.
La fusion consiste à écrire une bonne fois la matrice dans les poids de base. Une fois fusionné, le modèle se comporte exactement comme un modèle classique, sans adaptateur à charger, et l'on peut appliquer n'importe quel outil qui attend un modèle standard — dont les convertisseurs GGUF.
Deux cas où l'on ne fusionne pas. D'abord, quand on veut servir plusieurs adaptateurs avec un seul modèle de base (fin du module 5) : la fusion casse cette architecture. Ensuite, quand le modèle est en 4 bits (QLoRA) : la fusion dans un modèle quantifié abîme la qualité. Il faut alors recharger le modèle de base en bfloat16, y attacher l'adaptateur, fusionner, puis re-quantifier si besoin.
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
nom_base = "mistralai/Mistral-7B-Instruct-v0.3"
chemin_adapt = "./mistral-comptes-rendus/checkpoint-450"
# On recharge le modele de base en bfloat16 (PAS en 4 bits).
base = AutoModelForCausalLM.from_pretrained(
nom_base, torch_dtype=torch.bfloat16, device_map="cpu",
)
tokeniseur = AutoTokenizer.from_pretrained(nom_base)
# On attache l'adaptateur et on fusionne.
modele = PeftModel.from_pretrained(base, chemin_adapt)
modele = modele.merge_and_unload() # fusion definitive
# Sauvegarde standard.
modele.save_pretrained("./mistral-comptes-rendus-fusionne", safe_serialization=True)
tokeniseur.save_pretrained("./mistral-comptes-rendus-fusionne")
Le résultat est un dossier de 14 gigaoctets (pour un modèle de 7 milliards en bfloat16) que n'importe quel outil compatible transformers peut charger sans savoir qu'un adaptateur est passé par là.
Exporter au format GGUF
GGUF — Georgi Gerganov Unified Format — est le format binaire utilisé par llama.cpp et par Ollama pour servir un modèle de langage sur CPU ou sur GPU grand public. Il regroupe dans un seul fichier les poids quantifiés à un niveau choisi, le tokeniseur et les métadonnées.
La conversion se fait par le script convert_hf_to_gguf.py distribué avec llama.cpp :
# Clonage et compilation minimaux de llama.cpp.
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make -j
# Conversion du modele fusionne vers GGUF en fp16 (etape intermediaire).
python convert_hf_to_gguf.py ../mistral-comptes-rendus-fusionne \
--outfile ../mistral-comptes-rendus-f16.gguf \
--outtype f16
# Quantification finale, plusieurs niveaux disponibles.
./quantize ../mistral-comptes-rendus-f16.gguf \
../mistral-comptes-rendus-Q4_K_M.gguf Q4_K_M
Les niveaux de quantification courants et leur usage :
| Niveau | Taille (7B) | Qualité | Contexte typique |
|---|---|---|---|
Q8_0 | 7,2 Go | quasi identique à fp16 | serveur avec GPU modeste |
Q6_K | 5,5 Go | perte imperceptible | compromis qualité/place |
Q5_K_M | 4,8 Go | très bonne | par défaut Ollama |
Q4_K_M | 4,1 Go | bonne, léger écart | poste bureau, laptop |
Q3_K_M | 3,3 Go | perceptible | dépannage, gros modèles |
Pour notre modèle de comptes rendus déployé sur un poste avec 16 gigaoctets de mémoire vive, Q4_K_M est le point d'équilibre : environ 4 gigaoctets, une qualité indiscernable de fp16 dans 95 % des sorties.
Le déploiement Ollama
Ollama charge un GGUF via un Modelfile, l'équivalent d'un Dockerfile pour les modèles.
# Modelfile
FROM ./mistral-comptes-rendus-Q4_K_M.gguf
# Le gabarit de conversation doit correspondre au modele de base.
TEMPLATE """[INST] {{ .Prompt }} [/INST]"""
PARAMETER temperature 0.2
PARAMETER top_p 0.9
PARAMETER num_ctx 4096
PARAMETER stop "[INST]"
SYSTEM """Tu resumes une reunion en compte rendu structure."""
ollama create mistral-comptes-rendus -f Modelfile
ollama run mistral-comptes-rendus "..."
Le TEMPLATE doit correspondre au gabarit de conversation du modèle de base — c'est là qu'un chat template mal appliqué au module 2 se paie. Une consigne SYSTEM par défaut, une température basse (0,2) et une fenêtre de contexte adaptée à la longueur de séquence d'entraînement forment le socle raisonnable.
Publier sur le Hub
La publication sur huggingface.co prend une commande.
from huggingface_hub import HfApi
api = HfApi()
api.create_repo("notre-org/mistral-comptes-rendus", exist_ok=True)
api.upload_folder(
folder_path="./mistral-comptes-rendus-fusionne",
repo_id="notre-org/mistral-comptes-rendus",
repo_type="model",
)
Un fichier README.md accompagne obligatoirement le modèle. Il doit contenir la carte de modèle — quatre sections indispensables :
- modèle de base utilisé et lien vers sa page ;
- jeu de données d'affinage — origine, licence, taille ;
- usage prévu et exemples de code minimaux ;
- limitations connues et évaluations menées (module 10).
La licence du modèle de base : la question qu'on oublie
Un modèle affiné hérite des contraintes du modèle de base. Ignorer cette règle expose à un rappel juridique très concret.
| Modèle de base | Licence | Usage commercial |
|---|---|---|
Llama 3 | Meta Llama 3 Community License | oui, sauf plus de 700 millions d'utilisateurs actifs |
Mistral 7B | Apache 2.0 | oui, sans restriction |
Qwen2 7B | Tongyi Qianwen | oui, sous conditions |
Gemma 2 | Gemma Terms of Use | oui, avec clauses de conformité |
Falcon | Apache 2.0 | oui, sans restriction |
Deux règles pratiques. Si vous ne connaissez pas la licence de votre modèle de base, ne publiez rien tant que ce n'est pas clarifié. Si vous prévoyez un usage commercial, Mistral et Falcon sous Apache 2.0 sont les choix les plus simples juridiquement — beaucoup d'affinages commerciaux les préfèrent pour cette raison, et non pour leur qualité.
La licence du modèle est une chose, celle du jeu d'affinage en est une autre. Un modèle sous Apache 2.0 affiné sur des sorties d'un modèle commercial fermé peut violer les conditions d'usage de ce dernier (module 2). La carte de modèle doit expliciter les deux origines.
En résumé
- La fusion intègre l'adaptateur dans les poids de base ; on ne fusionne pas si l'on veut plusieurs adaptateurs, et jamais depuis un modèle quantifié.
- Le format
GGUFest la lingua franca pourllama.cppet Ollama ;Q4_K_Méquilibre qualité et place pour un déploiement grand public. - Un Modelfile Ollama transporte le gabarit de conversation, la consigne système, la température et la fenêtre de contexte.
- La carte de modèle publiée avec le poids est obligatoire ; la licence du modèle de base doit être vérifiée avant tout usage commercial.
Module suivant : évaluer proprement avant et après affinage, sans se raconter d'histoire.