In plain English
Fine-tuning an open LLM by hand means stitching together a lot of moving parts: load the base model, tokenize your dataset, apply the right chat template, wire up LoRA or QLoRA, set the optimizer and learning-rate schedule, shard everything across GPUs, log metrics, and save checkpoints. Each piece is a chance to make a quiet mistake that ruins the run.

Axolotl is an open-source tool that turns all of that into a single configuration file. You write a YAML file that says which model, which dataset, and which method (plain supervised fine-tuning, LoRA, QLoRA, or preference training), and Axolotl runs the whole training job for you — including across multiple GPUs. It is a wrapper around the standard Hugging Face training stack, so it is not reinventing training; it is packaging the proven pieces behind one clean config.
Think of it like a recipe card versus cooking from instinct. Cooking by hand, you might nail it once but never reproduce it exactly. A written recipe — exact ingredients, exact steps — means anyone on your team can run the same dish and get the same result. Axolotl's YAML is that recipe card for a fine-tuning run: hand it to a teammate or a CI server, and they get the same model you did.
Why it matters
The hard part of fine-tuning is rarely the idea. It is the dozens of small, error-prone details between your dataset and a trained model. Axolotl exists to absorb that plumbing so you spend your effort on the things that actually decide quality: the data and the method.
- Reproducibility. A run is fully described by one text file you can commit to git. Six months later you can re-run the exact job, diff two configs to see what changed, and trust that 'it worked on my machine' means it works everywhere.
- Fewer silent mistakes. Getting the chat template and loss masking right by hand is a classic footgun — train on the wrong tokens and the model learns the wrong thing while loss still looks fine. Axolotl handles common dataset formats and templates for you.
- Multi-GPU without the pain. Sharding a model across several GPUs (via DeepSpeed or FSDP) is fiddly to set up correctly. Axolotl exposes it as a few config lines instead of a deep distributed-training project.
- Method coverage in one place. Full fine-tuning, LoRA, QLoRA, and preference/RLHF-style training all live behind the same config schema, so switching approaches is a config edit, not a rewrite.
Who cares most? Teams and individuals fine-tuning open-weight models (Llama, Qwen, Mistral, and friends) who want runs they can repeat, review, and hand off. If you are tuning a closed model through a provider API, that provider already hides this plumbing — Axolotl is for the self-hosted, open-weight world where you own the training loop. It is a popular workhorse precisely because it makes that world feel almost as turnkey as a hosted API, without giving up control.
How it works
Axolotl sits on top of the Hugging Face ecosystem. Your YAML config is the input; from it, Axolotl assembles and runs a real training job using libraries you would otherwise call yourself — Transformers for the model, PEFT for LoRA/QLoRA adapters, bitsandbytes for quantization, TRL for preference training, and DeepSpeed or FSDP for multi-GPU sharding.
The config is the whole interface
Almost everything you would normally write in Python becomes a field in the YAML. A trimmed-down config gives the shape of it: pick a base model, point at a dataset, choose the method, and set the core hyperparameters.
base_model: meta-llama/Llama-3.1-8B
# Method: 4-bit QLoRA (load_in_4bit + adapter: lora)
load_in_4bit: true
adapter: lora
lora_r: 16
lora_alpha: 32
lora_dropout: 0.05
# Dataset: a known format Axolotl knows how to template
datasets:
- path: tatsu-lab/alpaca
type: alpaca
# Core training hyperparameters
sequence_len: 2048
micro_batch_size: 2
gradient_accumulation_steps: 4
num_epochs: 3
learning_rate: 0.0002
optimizer: adamw_bnb_8bit
output_dir: ./outThe type: alpaca line is doing quiet, important work: it tells Axolotl how each dataset row maps onto a prompt and a response so the model trains on the answer tokens, not the instruction tokens. Axolotl ships handling for several common dataset shapes, so you usually do not write tokenization or templating code at all.
Running it
Once the config exists, the run is one command. The same command scales to multiple GPUs through an accelerate launch, because the distributed setup is also described in config rather than in your code.
# Single command, single config file
axolotl train qlora-example.yaml
# Same job across multiple GPUs (config controls the sharding)
accelerate launch -m axolotl.cli.train qlora-example.yamlWhat the config actually covers
It helps to see the config as four groups of decisions. Almost every field you will touch falls into one of these buckets, which maps neatly onto the choices any fine-tuning job has to make.
| Config area | What it decides | Example fields |
|---|---|---|
| Model | Which base model and how it is loaded | base_model, load_in_4bit, load_in_8bit |
| Method | Full fine-tune vs adapter, and adapter shape | adapter, lora_r, lora_alpha, lora_target_modules |
| Data | Which dataset and how rows become prompts | datasets, type, sequence_len, chat_template |
| Training | The optimization knobs and hardware use | learning_rate, num_epochs, micro_batch_size, deepspeed |
This is why switching methods is cheap. Going from a memory-hungry full fine-tune to a lightweight QLoRA run is mostly flipping load_in_4bit on and setting adapter: lora — the model, data, and most training fields stay put. The same config skeleton stretches from a tiny experiment on one GPU to a serious multi-GPU job.
Axolotl vs hand-written code vs other tools
Axolotl is not the only way to fine-tune an open model. The honest trade-off is control vs convenience vs reproducibility, and different tools sit at different points on that line.
- One YAML describes the whole run
- Built-in multi-GPU (DeepSpeed/FSDP)
- Great for reproducible team workflows
- Less flexible than raw code for odd cases
- You call Transformers/PEFT/TRL yourself
- Total flexibility for custom logic
- Every detail is your responsibility
- Easy to make silent, hard-to-find mistakes
- Some optimize single-GPU speed/memory
- Some add a no-code web UI
- Different defaults and dataset formats
- Pick the one matching your workflow
A common comparison is Axolotl vs Unsloth. They solve overlapping problems differently: Unsloth focuses on squeezing maximum speed and minimum memory out of a single GPU, while Axolotl focuses on config-driven, reproducible, and multi-GPU runs. They are not strictly rivals — some teams prototype quickly with one and run scaled, repeatable jobs with the other. The right pick depends on whether your bottleneck is one-GPU efficiency or team-wide reproducibility across more hardware.
Common pitfalls
Axolotl removes a lot of plumbing mistakes, but a config-driven tool has its own failure modes. Most trouble comes from the config being valid yet not describing what you actually meant.
- Wrong dataset
type. If your data does not match the format you declared, rows get templated incorrectly and the model trains on the wrong tokens. Always sanity-check a few tokenized samples before committing to a long run. - Mismatched chat template. Fine-tune with one template, then serve with a different one, and quality collapses at inference time. Keep the chat template consistent between training and deployment.
- Out-of-memory surprises.
sequence_len,micro_batch_size, and whether you use 4-bit loading dominate memory. If a run OOMs, lower these or enable QLoRA before reaching for more GPUs. - Copy-pasting a whole example without reading it. Example configs carry opinionated defaults (learning rate, epochs, target modules). Skim every field — a default that suits a 70B model may overfit a small one. Watch for overfitting signs.
- Forgetting it is still real training. A clean config does not guarantee a good model. You still need good data, sane hyperparameters, and an honest evaluation afterward.
Going deeper
Once the basic config flow clicks, the useful next steps are mostly about scale, data, and method depth.
Multi-GPU and sharding. For models too big to fit on one card, you point the config at a DeepSpeed (ZeRO) or FSDP setup. These shard the model weights, gradients, and optimizer state across GPUs so the job fits in aggregate memory. Axolotl exposes this as configuration, but understanding why you are using ZeRO stage 2 vs 3, or FSDP, is what lets you debug an OOM on a large run.
Sample packing and sequence length. To use GPU time efficiently, Axolotl can pack multiple short examples into one sequence up to sequence_len. This speeds training but interacts subtly with loss masking and attention boundaries, so it is worth understanding before you trust the throughput gains on a quality-sensitive run.
Beyond plain SFT. The same config schema reaches into preference training (DPO and related RLHF-style methods) via the underlying TRL library. That means the jump from instruction tuning to preference optimization is, again, mostly a config change — though the data you need (preference pairs, not just instruction-response rows) is fundamentally different, which is the real work.
Where to go next. Solidify the fundamentals the tool sits on: full fine-tuning vs PEFT to understand the methods, dataset preparation because data quality outranks every config knob, and the cost breakdown so a multi-GPU run does not surprise you on the bill. The durable lesson: Axolotl makes runs reproducible and repeatable, but it cannot make a bad dataset good — the config is only as valuable as the data and evaluation behind it.
FAQ
What is Axolotl used for?
Axolotl is an open-source tool for fine-tuning open-weight LLMs from a single YAML config. You describe the model, dataset, and method (full fine-tuning, LoRA, QLoRA, or preference training) and it runs the whole job, including across multiple GPUs, so runs are reproducible and easy to hand off.
Does Axolotl support LoRA and QLoRA?
Yes. You select the method in the config: set adapter: lora for LoRA, and add load_in_4bit: true to turn it into QLoRA. Full fine-tuning and preference/RLHF-style training are also available through the same config schema, so switching method is mostly a config edit.
Axolotl vs Unsloth — which should I use?
They overlap but optimize for different things. Unsloth focuses on maximum speed and minimum memory on a single GPU, while Axolotl focuses on config-driven, reproducible, multi-GPU runs. Choose based on whether your bottleneck is one-GPU efficiency or team-wide reproducibility across more hardware.
Do I need to write Python to use Axolotl?
Mostly no. The training job is described in a YAML file and launched with a single command, so you usually avoid writing tokenization, templating, or training-loop code. You still benefit from understanding the underlying concepts, but day-to-day work is editing config, not code.
Can Axolotl train across multiple GPUs?
Yes. Multi-GPU sharding via DeepSpeed (ZeRO) or FSDP is configured in the YAML and launched through an accelerate command. That is one of its main draws over single-GPU-focused tools: scaling to more hardware is a config change rather than a distributed-training project.