Handleiding voor LLM fine-tuning: LoRA, QLoRA, Unsloth, Axolotl
Automatische vertaling Dit artikel is automatisch vertaald vanuit de oorspronkelijke Engelse versie.
De meeste mislukkingen bij fine-tuning zijn beslissingsfouten. Een team gaat trainen voordat het heeft aangetoond dat prompting, retrieval of constrained decoding het probleem niet kan oplossen. Een ander team evalueert op de trainingsdistributie, of ontdekt pas na de training dat het artifact lastig te serven is.
Deze handleiding behandelt adaptation als een experiment met een operationele exit. We beginnen bij de beslissingsgrens en volgen daarna één pad door data, LoRA of QLoRA, task-specifieke evaluatie, export en serving.
Zie Fine-Tuning vs RAG vs Prompting voor de korte interventiebeslissing.
Moet je überhaupt fine-tunen?
Beslis voordat je GPU-uren besteedt of fine-tuning het juiste hulpmiddel is voor het probleem dat voor je ligt.
Fine-tuning versus RAG
Fine-tuning kan veranderen hoe een model domeintaal gebruikt, maar is een slecht update-mechanisme voor feiten die veranderen of moeten worden geciteerd. Retrieval en fine-tuning lossen verschillende delen van het probleem op en horen vaak in hetzelfde systeem thuis.
| Kenmerk | Fine-Tuning | RAG (Retrieval-Augmented Generation) |
|---|---|---|
| Kernfunctie | Past interne weights aan om skills, stijlen of gedrag aan te leren | Levert externe, actuele context tijdens inference |
| Geschikt voor | • Specifieke conversationele stijlen • Complex instruction following • Domeinspecifieke reasoning | • Snel veranderende data (nieuws, aandelenkoersen) • Hallucinations verminderen (grounding) • Bronnen citeren |
| Omgaan met kennis | Verandert statistisch gedrag in de weights; exact recall is niet gegarandeerd | Haalt records of passages op die kunnen worden bijgewerkt en geciteerd |
| Updatefrequentie | Voor updates is retraining vereist | Wordt onmiddellijk bijgewerkt met nieuwe documenten |
Fine-tuning versus prompt engineering
Moderne LLMs reageren goed op duidelijke prompts en voorbeelden. Test die opties voordat je in fine-tuning investeert.
| Aspect | Fine-Tuning | Prompt Engineering |
|---|---|---|
| Setupkosten | Hoog (data-curatie, GPU-compute, iteratie) | Laag (iteratieve promptverfijning) |
| Flexibiliteit | Vereist een nieuwe training- en releasecyclus | Verandert met de prompt |
| Format/stijl | Kan herhaald gedrag waarschijnlijker maken | Vaak voldoende voor stijl en eenvoudige formats |
| Latency | Kan herhaalde instructies verkorten | Hangt af van promptlengte en provider caching |
| Geschikt voor | Complex gedrag, distillation, kosten op schaal | Snelle iteratie, veranderende requirements |
[!TIP] Probeer eerst prompting Begin met een prompt en representatieve voorbeelden. Als alleen de outputsyntax onbetrouwbaar is, voeg dan constrained decoding toe voordat je de weights wijzigt.
Fine-tuning versus constrained decoding
Libraries zoals xgrammar en outlines beperken generation tot een JSON Schema, regular expression of grammar. Afhankelijk van de constraint en backend compileren ze een automaton of grammar en maskeren ze ongeldige volgende tokens. Er is geen weight update nodig.
Dit garandeert dat de output tot de ondersteunde outputtaal behoort. De garantie zegt niets over de vraag of de waarden waar, volledig of semantisch geschikt zijn. Een syntactisch geldige function call kan nog steeds het verkeerde klant-ID bevatten.
| Aspect | Constrained Decoding | Fine-Tuning |
|---|---|---|
| Setup | Direct—definieer schema, deploy | Vereist data-curatie, GPU-compute, iteratie |
| Garantie | Geldige syntax voor de ondersteunde constraint | Learned behavior; schema-compliance kan variëren |
| Flexibiliteit | Schema op elk moment wijzigen zonder retraining | Vast na de training |
| Latency | Lichte overhead (het model kan het schema “tegenwerken”) | Lager (het model produceert het format natuurlijk) |
| Geschikt voor | JSON, keuzes, grammars, tool-call-syntax | Herhaald taskgedrag dat het base model mist |
Een praktische volgorde:
- Begin met prompting en few-shot examples voor eenvoudige formatting.
- Voeg constrained decoding (
xgrammarofoutlines) toe wanneer de syntax inconsistent is. - Fine-tune pas wanneer je gedragsveranderingen nodig hebt die een schema niet kan afdwingen.
Snelle referentie: problemen koppelen aan oplossingen
| Uitdaging | Eerste mechanisme om te testen | Waarom? |
|---|---|---|
| Ontbrekende kennis | RAG | Models hallucinate facts. Retrieval levert grounded, actuele context |
| Verkeerd format of verkeerde toon | Prompt Engineering | Moderne models volgen stijlinstructies goed via few-shot examples |
| Ongeldige outputsyntax | Constrained decoding | Dwingt tijdens generation een ondersteund schema of grammar af |
| Herhaald falen op een task | Fine-tuning (SFT) | Leert van gecureerde input/output-examples |
| Mismatch in pairwise preferences | Preference optimization | Gebruikt chosen/rejected-examples nadat het taskgedrag meetbaar is |
| Latency/kosten op schaal | Distillation (SFT) | Trained een kleiner student model op outputs van een groter teacher model |
| Model kleiner maken | Quantization | Geen training—comprimeert weights (FP16→INT4) voor snellere inference |
Maak de businesscase meetbaar
Fine-tuning kan terugkerende prompt-tokens verminderen of ervoor zorgen dat een kleiner model het doel haalt, maar geen van beide besparingen is automatisch. Bereken het break-evenpoint met je eigen traffic en pricing:
[ \text{break-even requests} = \frac{\text{training + evaluation + deployment cost}} {\text{baseline cost/request} - \text{tuned cost/request}} ]
Als de noemer klein of negatief is, of gebaseerd is op een onbewezen kwaliteitsaanname, heeft het project nog geen economische onderbouwing.
[!TIP] De hybride setup Een veelvoorkomende architectuur is een kleiner, task-adapted model plus retrieval voor veranderende feiten. Behandel het grotere model met prompts als baseline en behoud het kleinere model alleen als het aan dezelfde task-specifieke quality- en safety-thresholds voldoet.
Types fine-tuning
Fine-tuning kent drie hoofdvormen. Ze verschillen in het soort data dat ze nodig hebben en in wat ze het model leren.
1. Continued pre-training (self-supervised)
Je traint het base model op meer raw text, waarbij de volgende token in elke sequence het training target vormt. Dat is self-supervised learning: de tekst levert zijn eigen targets, net als in de oorspronkelijke pretraining-run.
Wanneer gebruik je dit:
- Het domein bevat vocabulary die het base model nooit heeft gezien (medisch, juridisch, interne codebases).
- Je hebt grote hoeveelheden domain text, maar geen gelabelde (input, output)-paren.
- Het base model heeft moeite met domeinspecifieke terminologie.
Voorbeeld: trainen op miljoenen klinische notities zodat het model medische afkortingen, medicijnnamen en klinische workflows oppikt.
2. Supervised fine-tuning (SFT)
SFT traint op gelabelde (input, output)-paren. Je laat het model voor elke input exact de gewenste output zien.
Wanneer gebruik je dit:
- Je hebt een specifieke task met een schoon input/output-format.
- Je beschikt over kwalitatieve gelabelde data, zelfs als de hoeveelheid klein is.
- Je hebt voorspelbaar gedrag nodig voor een bekende inputvorm.
Voorbeeld: trainen op (beschrijving van SQL-query, SQL-code)-paren voor text-to-SQL.
{
"input": "Get all users who signed up last month",
"output": "SELECT * FROM users WHERE signup_date >= DATE_SUB(NOW(), INTERVAL 1 MONTH)"
}
3. Instruction tuning
Instruction tuning is een speciaal geval van SFT dat is ontworpen om models uiteenlopende instructies in natuurlijke taal te laten volgen. De trainingsdata bestaat uit (instruction, response)-paren voor veel verschillende tasks.
Wanneer gebruik je dit:
- Je wilt een general-purpose assistant bouwen (zoals ChatGPT of Claude).
- Het model moet uiteenlopende, open-ended verzoeken kunnen verwerken.
- Je bouwt een chatinterface.
Voorbeeld: trainen op duizenden diverse instructies zoals “Vat dit artikel samen”, “Schrijf een gedicht over X” en “Leg Y uit in eenvoudige bewoordingen.”
Vergelijking
| Aspect | Continued Pre-training | SFT | Instruction Tuning |
|---|---|---|---|
| Data | Raw text | (input, output)-paren | (instruction, response)-paren |
| Labels | Geen (unsupervised) | Task-specifiek | Diverse tasks |
| Doel | Domeinkennis | Specifiek taskgedrag | Elke instructie volgen |
| Datavolume | Meestal het grootste corpus | Bepaald door task coverage en error diversity | Meestal breder dan task-specifieke SFT |
[!NOTE] Wat mensen daadwerkelijk doen SFT en instruction tuning gebruiken hetzelfde next-token-objective; het onderscheid zit in de breedte en samenstelling van de dataset. Continued pre-training is een apart experiment en moet worden gevolgd door tests voor zowel domeinwinst als regressie van general capabilities.
De fine-tuning-pipeline in 7 stages
Fine-tuning is een pipeline, geen enkel commando. Elke stage kent eigen failure modes, en een overgeslagen stage wordt meestal later zichtbaar als een slecht model.
Elke stage bouwt voort op de vorige:
- Data preparation — Definieer de evaluatie-eenheid, split de data en clean en formatteer deze
- Model selection — Kies het juiste base model en laad de weights
- Training setup — Configureer hardware, hyperparameters en optimization strategy
- Fine-tuning — Voer SFT-, DPO- of ORPO-training uit
- Evaluation — Benchmark performance en valideer quality
- Deployment — Exporteer en serve je model
- Monitoring — Volg performance, onderhoud het model en itereer
[!WARNING] Data is de basis Training reproduceert systematische fouten in de voorbeelden. Inspecteer labels, leakage, coverage en policy compliance voordat je tijd besteedt aan optimizer sweeps.
Stage 1: Data preparation
Veel fine-tuning-projecten mislukken hier, niet tijdens de training. Moderne data prep is meer dan een regex over CSVs uitvoeren.
De data-pipeline in 5 stages
Tools zoals DataTrove en Distilabel kunnen op schaal helpen. Laat de failure taxonomy en het data contract het pipelineontwerp sturen; de toolkeuze volgt daaruit.
1. Ingestion en filtering
- Actie: verwijder refusals (“Ik kan dat niet beantwoorden”), corrupte UTF-8 en niet-doeltalen.
- Tools: Trafilatura voor extractie en fastText’s language-identification models voor language ID; de distributed
lid.176models herkennen 176 talen.
2. Beleid voor gevoelige data
- Actie: bepaal wat het model mag leren en redact, tokenize of sluit persoonlijke en vertrouwelijke velden uit waar nodig.
- Tools: Microsoft Presidio of scrubadub.
- Waarom: een detector is slechts één control; vereisten voor provenance, consent, retention, access en deletion blijven van toepassing.
3. Deduplicatie (MinHash LSH)
- Actie: verwijder near-duplicates zodat het model ze niet memoriseert.
- Tools: DataTrove verwerkt terabyte-scale data goed.
4. Synthetic augmentation, indien nodig
- Actie: gebruik een sterker teacher model (GPT-4o, DeepSeek-V3) om raw data om te schrijven naar schone instruction-response-paren.
- Tools: Distilabel.
- Validatie: sample teacher outputs, controleer ze met dezelfde rubric als human labels en houd synthetic en human-written slices gescheiden in de evaluatie.
5. Formatting
- Actie: converteer naar een standaardformat (Alpaca of ShareGPT).
Voorbeelden van dataformats
Alpaca-format (instruction-following):
{
"instruction": "Summarize the following text.",
"input": "The text to be summarized...",
"output": "This is the summary."
}
ShareGPT/ChatML-format (conversationeel):
{
"conversations": [
{ "from": "user", "value": "Hello, who are you?" },
{ "from": "assistant", "value": "I am a helpful AI assistant." }
]
}
Wat daadwerkelijk telt
- Coverage vóór volume. Voeg voorbeelden toe die verschillende failure modes vertegenwoordigen, niet herhalingen van de eenvoudige meerderheidscase.
- Cleanliness. Verwijder irrelevante tekst, normaliseer whitespace en houd formatting consistent.
- Balance. Behoud belangrijke zeldzame cases en rapporteer performance per slice.
- Separation. Split op source, user, document of time wanneer random row splits near-duplicates zouden laten lekken.
- Provenance. Leg voor elke datasetversie de source, license of permission, transformation history en deletion path vast.
Stage 2: Model selection en hardware
De keuze van het base model en inzicht in de GPU-floor bepalen wat je daadwerkelijk kunt trainen.
Begin met het kleinste base model dat de niet-onderhandelbare baseline checks al doorstaat. Controleer:
- license- en redistribution terms voor het beoogde product;
- language-, domain-, tool-use- en safety behavior vóór adaptation;
- compatibiliteit van tokenizer en chat template met de dataset;
- de maximale context en het truncation behavior dat echte voorbeelden vereisen;
- support in zowel het training framework als de beoogde serving engine.
Fine-tuning is een adaptation-stap, geen reparatie voor een ongeschikt base model. Als het model capabilities mist die de dataset niet afdekt, kies dan een ander base model voordat je meer epochs uitvoert.
Size de run, niet de marketingtier
Er bestaat geen blijvende tabel van “model size → GPU”. Peak memory verandert door weight precision, optimizer, trainable parameter count, sequence length, micro-batch size, activation checkpointing, attention implementation en framework overhead. Begin met een memory estimate en voer daarna een korte smoke test op maximum length uit met exact dezelfde stack.
| Memorycomponent | Full fine-tuning | LoRA | QLoRA |
|---|---|---|---|
| Base weights | Training precision | Frozen, meestal BF16/FP16 | Frozen, meestal 4-bit NF4 |
| Gradients | Alle trainable weights | Adapter weights | Adapter weights |
| Optimizer states | Alle trainable weights | Adapter weights | Adapter weights |
| Activations | Hangt bij elke methode af van batch en sequence length | Dezelfde afhankelijkheid | Dezelfde afhankelijkheid |
Het oorspronkelijke QLoRA-paper paste een 65B LLaMA model op één GPU van 48 GB in de specifieke setup van het paper. Dat resultaat is een bruikbare bovengrens, geen garantie dat elke huidige 70B-architectuur, contextlengte, kernel of trainer op hetzelfde device past.
Memory math
Voor een model met parameters vereisen alleen de weights ongeveer bytes in BF16/FP16 of bytes bij four-bit, vóór quantization metadata en runtime buffers. Full Adam-style training voegt gradients, optimizer states en vaak higher-precision master weights toe. LoRA vermijdt het grootste deel van de trainable-state memory; QLoRA verkleint daarnaast de footprint van de frozen base weights. Activations kunnen bij lange sequence lengths nog steeds domineren.
Gebruik deze workflow:
- Kies de langste sequence en micro-batch die je moet ondersteunen.
- Schat weights en trainable state, en houd headroom over voor activations en kernels.
- Voer één forward/backward step uit op maximum length.
- Noteer peak allocated en reserved memory.
- Schaal pas daarna batch size, rank, sequence length of het aantal GPUs op.
Stage 3: Training methods (PEFT en LoRA)
Full fine-tuning versus PEFT
Full fine-tuning (FFT) update elke weight, waardoor gradients en optimizer state met het volledige model meegroeien. De peak kan niet alleen uit het aantal parameters worden afgeleid, maar ligt veel hoger dan de memory die nodig is om de weights voor inference te laden.
Parameter-efficient fine-tuning (PEFT) traint slechts een kleine subset van de parameters en freezet de rest. De wiskunde wordt een stuk vriendelijker.
LoRA: het startpunt
LoRA (Low-Rank Adaptation) freezet een pre-trained matrix en representeert de geleerde update met twee kleinere matrices. Het oorspronkelijke paper motiveert dit met de hypothese dat nuttige adaptation-updates een lage intrinsic rank hebben.
Voor een frozen matrix leert LoRA:
De adapted layer is:
De adapter heeft trainable parameters in plaats van voor die matrix. Voor een square matrix van 4.096 breed met rank 16 betekent dat een reductie van 128× voor de matrix, niet 10.000× voor een willekeurig model. De claim van 10.000× in het LoRA-paper betrof een specifieke GPT-3 175B-configuratie die geselecteerde matrices adapteerde.
PEFT-methoden vergeleken
| Methode | Wat verandert | Kies dit wanneer |
|---|---|---|
| LoRA | Frozen base plus trainable updates met lage rank | Het base model comfortabel past en je kleine task-artifacts wilt |
| QLoRA | LoRA met de frozen base opgeslagen in 4-bit-formaat | Memory voor base weights de beperkende factor is |
| DoRA | Scheidt weight magnitude van een door LoRA geüpdatete richting | Een gemeten LoRA-baseline een quality gap laat dat extra complexiteit rechtvaardigt |
| Full fine-tuning | Alle model weights | PEFT het doel mist en de quality gain distributed training en volledige checkpoints rechtvaardigt |
Wanneer kies je welke methode?
- LoRA: begin hier. Snel, memory-efficient en goed ondersteund.
- QLoRA: wanneer hetzelfde LoRA-experiment niet past vanwege de frozen base weights.
- DoRA: nadat een apples-to-apples LoRA-vergelijking een nuttige gain laat zien.
- Full fine-tuning: pas nadat PEFT een geëvalueerde bottleneck is gebleken, niet slechts een aanname.
DoRA: weight-decomposed LoRA
DoRA (Weight-Decomposed Low-Rank Adaptation) scheidt de magnitude van elke weight vector van de richting ervan. Het DoRA-paper past een LoRA-update toe op de directionele component en leert de magnitude afzonderlijk.
Zo werkt het:
In plaats van weights als één geheel te behandelen, splitst DoRA pre-trained weights op in twee componenten:
- Magnitude — één trainable value per weight vector.
- Direction — een genormaliseerde vector die via low-rank matrices wordt geüpdatet.
In compacte column-wise notatie:
waarbij:
m= magnitude (trainable)- = de frozen directionele matrix
- = de geleerde low-rank directionele update
- = column-wise normalization
Wat je voor die extra structuur krijgt:
- Meer degrees of freedom dan bij standaard LoRA, omdat magnitude onafhankelijk kan veranderen.
- Betere resultaten dan LoRA in verschillende configuraties die door het paper van de auteurs worden gerapporteerd.
- Extra parameters en computation, dus de gain moet op jouw task en serving path worden geverifieerd.
Adapter merging voor multi-task learning
Met afzonderlijke adapters kan één frozen base meerdere tasks ondersteunen. Je kunt requests naar een adapter routen, meerdere adapters vanuit één engine serven wanneer dat wordt ondersteund, of offline een merged candidate maken. Merging kan interference veroorzaken; evalueer daarom het merged artifact in plaats van aan te nemen dat de source adapters probleemloos composeren.
Veelgebruikte merging-methoden:
- Concatenation — combineer adapterparameters en verhoog de effectieve rank. Snel en eenvoudig.
- Linear combination — gewogen som van adapters. Geeft je instelbare parameters.
- SVD — matrix decomposition voor merging. Flexibeler, maar trager.
Voorbeeld: één adapter voor summarization en een andere voor translation, samengevoegd tot één multi-task model.
Stage 4: Fine-tuning en preference alignment
SFT leert van demonstrations. Preference optimization leert daarentegen van vergelijkingen, zoals “chosen response A is beter dan rejected response B”. Gebruik dit alleen wanneer pairwise preference het juiste label voor de fout is; factual correctness en policy compliance vereisen vaak sterkere evaluators dan één algemene preference-score.
PPO-based RLHF
Het oorspronkelijke recept was een pipeline in drie stages:
- SFT — leer de task.
- Reward model — train op human preferences (chosen versus rejected).
- PPO (Proximal Policy Optimization) — reinforcement learning om de policy te optimaliseren.
De operationele kosten komen door de moving parts:
- Complex om te implementeren en te onderhouden.
- Duur — je traint meerdere models.
- On-policy sampling en reward optimization vereisen zorgvuldige stability- en reward-hacking-checks.
DPO
DPO (Direct Preference Optimization) verwijdert het expliciete reward model en de RL-loop. Het DPO-paper leidt een geparameteriseerd objective af voor reward maximization met een KL-divergence-constraint, zodat optimization kan plaatsvinden op basis van preference pairs in plaats van reinforcement learning:
{
"prompt": "Explain quantum computing",
"chosen": "Quantum computing uses qubits...", # Preferred response
"rejected": "Well, it's complicated..." # Non-preferred response
}
Wat er operationeel verandert:
- Eenvoudiger code path (geen afzonderlijk reward model en geen RL-loop).
- Een offline objective over preference pairs in plaats van on-policy reinforcement learning.
- Een reference policy of equivalente reference log probabilities in de standaardformulering.
DPO is eenvoudiger te prototypen dan een volledige PPO-pipeline, maar is geen automatische quality upgrade. Resultaten hangen af van de starting policy, pair quality, loss settings, length effects en het evaluation protocol. Vergelijk DPO met een SFT-checkpoint op dezelfde held-out preference- en task-suites.
ORPO
ORPO (Odds-Ratio Preference Optimization) combineert de SFT negative-log-likelihood loss met een odds-ratio penalty op rejected responses. Het verwijdert het afzonderlijke reference model en kan task learning en preference optimization in één run combineren.
Zo werkt het: ORPO gebruikt een gecombineerde loss die twee dingen tegelijk doet:
- Maximaliseert de likelihood van de chosen response (task learning).
- Penaliseert de rejected response met een odds-ratio-term (preference learning).
Relevante hyperparameters:
from trl import ORPOConfig
config = ORPOConfig(
learning_rate=8e-6, # Very low, as recommended by the ORPO paper
beta=0.1, # Controls strength of preference penalty
# ... other params
)
- Learning rate: het paper gebruikte lage rates in zijn experimenten; tune deze voor jouw model, batch en data in plaats van één waarde als regel over te nemen.
- Beta: bepaalt het gewicht van de preference term ten opzichte van de SFT term.
De trade-off:
- Eén trainingstage in plaats van twee.
- Geen reward model.
- Geen forward pass van een reference model.
- Een gekoppelde run: als task learning of preference behavior regressie vertoont, is er in dezelfde pipeline geen intermediate SFT-checkpoint om te inspecteren.
Kies op basis van het data- en evaluation design:
- Gebruik DPO wanneer je al een satisfactory SFT-checkpoint hebt en een eenvoudiger offline preference-experiment wilt uitvoeren.
- Test ORPO wanneer een reference-free objective in één stage past bij je data en operationele constraints.
- Gebruik PPO-based RLHF wanneer online sampling tegen een expliciet learned reward onderdeel van de requirement is en je reward exploitation kunt monitoren.
Geen van deze methoden is een default voor alle tasks. Houd een SFT-only baseline aan en rapporteer zowel task metrics als preference metrics.
Fine-tuning frameworks
Frameworks overlappen en veranderen snel. Kies op basis van de execution path die je moet ondersteunen, pin versions en houd de training configuration voldoende portable om buiten een notebook te kunnen reproduceren.
Unsloth — snelheid en memory efficiency
Unsloth integreert met Hugging Face trl en transformers en levert optimized kernels, checkpointing en quantized fine-tuning paths voor ondersteunde models.
- Custom Triton GPU kernels voor attention, RoPE en cross-entropy die PyTorch-overhead overslaan.
- Memory-efficient backprop die activations tijdens de backward pass recompute in plaats van ze in memory te houden.
- Fused operations die meerdere stappen samenvoegen (layer norm + linear en vergelijkbare operaties) tot afzonderlijke GPU-calls.
- 4-bit quantization rechtstreeks geïntegreerd in de QLoRA-path, met optimized dequantization.
[!IMPORTANT] Importvolgorde is belangrijk Volg de importvolgorde in het Unsloth-voorbeeld voor de versie die je pint. Unsloth past tijdens import patches toe; importeer het daarom vóór
trlentransformersom ontbrekende optimizations of version-specific errors te voorkomen.
# Correct order
from unsloth import FastLanguageModel # Must be first!
from trl import SFTTrainer
from transformers import TrainingArguments
# Avoid this order with Unsloth's patched path
from trl import SFTTrainer
from unsloth import FastLanguageModel
Geschikt voor: single-GPU training, prototyping, Colab-notebooks en iedereen die op de GPU-rekening let.
Gepubliceerde snelheids- en memory-cijfers variëren per model, sequence length, batch, precision en hardware. Benchmark tokens per second en peak memory in je eigen run in plaats van een headline ratio als frameworkeigenschap te behandelen.
Axolotl — config-driven training
# config.yaml - no code required
base_model: meta-llama/Meta-Llama-3-8B
adapter: qlora
lora_r: 32
lora_alpha: 16
datasets:
- path: data/my_data.jsonl
type: alpaca
sample_packing: true
Uitvoeren met: accelerate launch -m axolotl.cli.train config.yaml
Geschikt voor: declaratieve, reproduceerbare runs en ingebouwde launcher-opties voor distributed training. De config kan worden gereviewd, versioned en hergebruikt voor lokale en distributed runs.
Frameworkvergelijking
| Tool | Nuttig wanneer | Verifieer vóór je committeert |
|---|---|---|
| Unsloth | Je een optimized path voor een ondersteund model wilt met beknopte voorbeelden | Matrix voor model, GPU, quantization en distributed support |
| Axolotl | Je declarative configs en ingebouwde distributed recipes wilt | Exacte config schema en launcher voor de gepinde release |
| TRL | Je direct toegang wilt tot Hugging Face SFT- en preference-trainers | Datasetformat, chat template, loss masking en PEFT-integratie |
| Torchtune | Je PyTorch-native recipes en components wilt | Model recipe coverage en export compatibility |
Praktische demo: fine-tuning met Unsloth
Hier is een representatief trainingsfragment uit mijn repository unsloth-finetune-demo. De demo fine-tunet Nemotron-Nano voor function calling. Voor dit fragment laadt en formatteert de demo’s src/unsloth_demo/data.py de dataset; daarna maakt het training path de versioned train_dataset- en eval_dataset-objects aan.
Quick start
# Clone and setup
git clone https://github.com/slavadubrov/unsloth-finetune-demo.git
cd unsloth-finetune-demo
# Install with uv (recommended)
uv sync
# Run fine-tuning (quick test)
uv run finetune --max-samples 1000
Configuration
De interessante onderdelen staan in config.py:
# Model & Dataset
MODEL_NAME = "nvidia/Llama-3.1-Nemotron-Nano-4B-v1.1" # 4B params, 128K context
DATASET_NAME = "glaiveai/glaive-function-calling-v2" # 113K examples
# LoRA Configuration
LORA_R = 16 # Adapter capacity; tune against held-out results
LORA_ALPHA = 32 # Update scaling; alpha/r is the classic LoRA scale
MAX_SEQ_LENGTH = 4096
# Candidate modules for this Llama-family model
LORA_TARGET_MODULES = [
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",
]
[!NOTE] De alpha-to-rank-ratio
alpha/rschaalt de klassieke LoRA-update.alpha = 2ris een gebruikelijke startheuristiek in documentatie van sommige tools, geen stabiliteitsgarantie. Sweep rank, alpha, learning rate en target modules pas nadat de data en baseline zijn vastgelegd.
Core training code
from unsloth import FastLanguageModel
from trl import SFTConfig, SFTTrainer
# Load model with 4-bit quantization
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="nvidia/Llama-3.1-Nemotron-Nano-4B-v1.1",
max_seq_length=4096,
load_in_4bit=True,
)
# Add LoRA adapters
model = FastLanguageModel.get_peft_model(
model,
r=16,
lora_alpha=32,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
use_gradient_checkpointing="unsloth", # Lower activation memory; extra compute
)
# The preceding data step must create these versioned dataset objects.
# Each row has the chat messages and tool schemas expected by current TRL.
# Train with the current TRL configuration surface.
trainer = SFTTrainer(
model=model,
processing_class=tokenizer,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
args=SFTConfig(
output_dir="outputs/nemotron-function-calling",
max_length=4096,
packing=True,
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
learning_rate=2e-4,
num_train_epochs=3,
bf16=True,
),
)
trainer.train()
Fine-tuning met Axolotl
[!NOTE] Demo komt eraan Ik werk aan een hands-on Axolotl-demo. Tot die tijd is de Accelerate n-D Parallelism Guide van Hugging Face een goede referentie voor multi-GPU-trainingstrategieën.
Voor config-first en distributed setups maakt Axolotl de workflow reproduceerbaar:
# axolotl_config.yaml
base_model: meta-llama/Meta-Llama-3-8B
model_type: LlamaForCausalLM
# QLoRA configuration
load_in_4bit: true
adapter: qlora
lora_r: 32
lora_alpha: 16
lora_dropout: 0.05
lora_target_modules:
- q_proj
- k_proj
- v_proj
- o_proj
- gate_proj
- up_proj
- down_proj
# Dataset
datasets:
- path: data/training_data.jsonl
type: alpaca
# Training settings
sequence_len: 4096
sample_packing: true # Benchmark with your length distribution
micro_batch_size: 2
gradient_accumulation_steps: 4
learning_rate: 0.0002
num_epochs: 3
# Current Axolotl key; verify support on the pinned release
bf16: true
attn_implementation: flash_attention_2
Training uitvoeren:
axolotl train axolotl_config.yaml
Stage 5: Evaluation
Bevries het evaluation contract vóór de eerste run. Vergelijk minimaal het tuned checkpoint met exact dezelfde untuned base, dezelfde prompt, decoding settings en tool environment. Rapporteer aggregate quality pas nadat je de failure slices hebt gecontroleerd die het project moest verbeteren.
Volg vier groepen:
- Target task: exact match, execution success, human rubric of een andere uitkomst die aan de use case is gekoppeld.
- Regression: general abilities en eerder ondersteunde task slices die door adaptation kunnen verslechteren.
- Safety en policy: refusals, data leakage, prompt injection of domeinspecifieke constraints.
- Operations: latency, throughput, memory, artifact size en kosten bij de beoogde serving configuration.
Geautomatiseerde benchmarks
Gebruik lm-evaluation-harness voor relevante gestandaardiseerde tasks, niet als vervanging voor de product evaluation:
lm_eval --model hf \
--model_args pretrained=./outputs/merged-model \
--tasks hellaswag,arc_easy,mmlu \
--batch_size 8
LLM-as-judge
Voor subjectieve quality kan een groter model helpen met scoring, maar kalibreer dit tegen door mensen gereviewde voorbeelden en houd de identiteit van de candidate verborgen:
judge_prompt = """
Rate this response from 1-5 on:
- Relevance
- Accuracy
- Formatting
Response: {model_output}
Expected: {ground_truth}
"""
Domeinspecifieke evaluatie
Houd echte voorbeelden apart per source, user, document of time, zodat near-duplicates niet over de split kunnen lekken. Valideer bij function calling de volledige trajectory: tool selection, arguments, execution result, recovery en final response. Rapporteer confidence intervals of paired win/loss counts wanneer de sample klein is, en inspecteer elke regressie in een kritieke slice.
Stage 6: Deployment en outputformats
Kies het artifact op basis van serving engine en rollback plan, niet alleen op basis van file size:
1. LoRA-adapter
uv run finetune # Saves ~100-500MB adapter
- Grootte: evenredig aan targeted modules, rank, layers en dtype; vaak veel kleiner dan de base.
- Geschikt voor: development, versioned task adapters en engines die LoRA rechtstreeks ondersteunen.
- Bonus: je kunt adapters wisselen zonder het base model opnieuw te downloaden.
2. Merged model
uv run finetune --merge # Creates a standalone full model
- Grootte: ongeveer die van het volledige base checkpoint bij de gekozen output precision.
- Geschikt voor: engines of distribution paths die de adapter niet afzonderlijk ondersteunen.
- Trade-off: groter artifact en tragere rollout; eenvoudiger laden van één model.
3. GGUF-format
uv run finetune --gguf q4_k_m # Creates ~2-4GB quantized model
- Grootte: afhankelijk van het model; voor Q4-varianten ongeveer four-bit weights plus metadata.
- Geschikt voor: CPU-inference, Ollama, llama.cpp en edge deployment.
- Opties:
q4_k_m(kleiner),q5_k_m(meer weight fidelity),q8_0(groter en hogere fidelity). Meet na conversion de impact op de task.
Stage 7: Serving en monitoring
Met vLLM
# Serve the base and expose a PEFT adapter as a model name. This parser and
# template pair is for a Llama 3.1-compatible function-calling adapter.
vllm serve nvidia/Llama-3.1-Nemotron-Nano-4B-v1.1 \
--enable-lora \
--lora-modules function-calling=./outputs/adapter \
--enable-auto-tool-choice \
--tool-call-parser llama3_json \
--chat-template examples/tool_chat_template_llama3.1_json.jinja \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 4096
Query via de OpenAI-compatible API:
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="dummy")
response = client.chat.completions.create(
model="function-calling",
messages=[{"role": "user", "content": "Book a flight to Tokyo"}],
tools=[
{
"type": "function",
"function": {
"name": "book_flight",
"description": "Book a flight to a city.",
"strict": True,
"parameters": {
"type": "object",
"properties": {
"destination": {"type": "string"},
},
"required": ["destination"],
"additionalProperties": False,
},
},
}
],
tool_choice="auto",
)
De tool-calling guide van vLLM vereist auto tool choice en een parser die bij het model past; gebruik de compatible chat template van het model wanneer de tokenizerconfiguratie er geen levert. Met tool_choice="auto" vereisen constrained arguments bovendien strict: true op ten minste één function (en moet vLLM’s strict-tool-calling-setting zijn ingeschakeld, wat de default is); gebruik een strict-compatible parameters schema. Zonder die opt-in extraheert vLLM calls uit raw text, waardoor de arguments malformed kunnen zijn of het schema kunnen schenden.
Met Ollama (lokaal)
# Create Modelfile
echo 'FROM ./outputs/unsloth-nemotron-function-calling-gguf/model-q4_k_m.gguf' > Modelfile
# Import to Ollama
ollama create my-function-model -f Modelfile
# Run
ollama run my-function-model
Met llama.cpp (CPU)
./llama-cli -m ./outputs/model-q4_k_m.gguf \
-p "What's the weather in Tokyo?" \
--ctx-size 4096
Monitor het released model
De lifecycle stopt niet bij een gezonde training loss. Leg de base-model revision, tokenizer en chat template, adapter hash, datasetversie, trainingconfiguratie en evaluation report vast als één release-unit. Monitor in production task success, invalid outputs, policy failures, latency en input drift met dezelfde slices als offline. Houd het vorige artifact loadable en definieer vóór de launch een rollback threshold.
Belangrijkste conclusies
- Fine-tune pas nadat een untuned baseline en failure taxonomy laten zien dat weight adaptation het probleem adresseert.
- Retrieval beheert veranderende evidence; constrained decoding beheert syntax; geen van beide wordt door SFT vervangen.
- LoRA reduceert trainable state. QLoRA comprimeert daarnaast de frozen base weights. Schrijf QLoRA-memorycijfers niet toe aan LoRA.
- Data coverage, split integrity, provenance en loss masking zijn belangrijker dan het kopiëren van een modieuze optimizerconfiguratie.
- DPO, ORPO en PPO-based RLHF zijn verschillende experimental designs, geen quality ladder met één universele default.
- Evalueer target behavior, regressions, safety en operations tegen hetzelfde base model.
- Kies vóór de training tussen adapter-, merged- of GGUF-output op basis van serving- en rollbackrequirements.
Referenties
Papers en research
- LoRA: Low-Rank Adaptation of Large Language Models
- QLoRA: Efficient Finetuning of Quantized LLMs
- DoRA: Weight-Decomposed Low-Rank Adaptation
- DPO: Direct Preference Optimization
- ORPO: Odds Ratio Preference Optimization
- PPO: Proximal Policy Optimization Algorithms — OpenAI, 2017
Tools voor dataverwerking
- DataTrove — Hugging Face dataverwerking op schaal
- Distilabel — Synthetic data generation (Argilla)
- Trafilatura — Extractie en crawling van webtekst
- fastText language identification — distributed
lid.176-models voor 176 talen - Microsoft Presidio — PII-detectie en anonymization
- scrubadub — Python-library voor PII-removal
Constrained decoding
Training frameworks
- Unsloth — Optimized fine-tuning framework
- Axolotl — Config-driven training en distributed launchers
- TRL — Hugging Face SFT- en preference-training-library
- Torchtune — PyTorch-native fine-tuning-library
Inference en deployment
- vLLM LoRA adapters — Serve één of meer adapters met het base model
- vLLM tool calling — Stem auto tool choice, parser, chat template en request schema af op het model
- Ollama — Lokale LLM-runner voor Mac/Windows/Linux
- llama.cpp — CPU/GPU-inference met GGUF-format
Evaluation
- lm-evaluation-harness — Gestandaardiseerde LLM-benchmarking door EleutherAI
Guides en resources
- Demo Repository — Praktisch fine-tuning-voorbeeld
- LLM Fine-Tuning. Theoretical Intuition and Practical Implementation — Research notebook in NotebookLM
- Accelerate n-D Parallelism Guide — Hugging Face-strategieën voor multi-GPU-training