Migration
Switch to Soup from other fine-tuning tools in one command. Soup automatically converts your existing config files.
Supported Tools
| Source | Config format | Command |
|---|---|---|
| LLaMA-Factory | YAML config | soup migrate --from llamafactory config.yaml |
| Axolotl | YAML config | soup migrate --from axolotl config.yml |
| Unsloth | Jupyter notebook | soup migrate --from unsloth finetune.ipynb |
Usage
# Convert LLaMA-Factory config to soup.yaml
soup migrate --from llamafactory llama3_lora_sft.yaml
# Convert Axolotl config
soup migrate --from axolotl axolotl_config.yml
# Convert Unsloth notebook (AST-only, no code execution)
soup migrate --from unsloth finetune.ipynb
# Preview without writing (dry-run)
soup migrate --from llamafactory config.yaml --dry-run
# Custom output path
soup migrate --from axolotl config.yml --output my-soup.yamlWhat Gets Mapped
Soup maps all major config fields automatically:
- Model:
model_name_or_path/base_model->base - Task:
stage/rl->task(pt->pretrain, rm->reward_model, sft/dpo/kto/ppo/grpo), with the refinements below - LoRA: rank, alpha, dropout, target modules, DoRA
- Training: epochs, lr, batch size, optimizer, scheduler, warmup, quantization
- Quantization and full fine-tuning: since v0.76.0 an unquantized source writes
quantization: noneexplicitly and a full fine-tune source writeslora.r: 0. HQQ and EETQ sources are supported - Data: dataset path, format, max length
- Output: output directory
When the task is not a plain SFT or DPO (v0.76.0)
An Axolotl rl:, a LLaMA-Factory pref_loss: or an Unsloth CPOTrainer loss with no Soup task now stops the migration with exit 1, naming the value, instead of writing a task: sft config. No file is written. (An unrecognised LLaMA-Factory stage: still falls back to sft.)
- Axolotl
rl:mapsdpo,ipo,kto,orpoandsimpoto the task of the same name, andgrpoandgdpototask: grpo.dpo,ipo,orpoandsimpoget thedpodata format,ktogetsktoandgrpogetsauto. Any other value is refused:Migration failed: No Soup task matches axolotl rl: ebft. Supported rl values are dpo, gdpo, grpo, ipo, kto, orpo, simpo. - LLaMA-Factory
pref_loss:is read only understage: dpo.sigmoidgivesdpo,ipogivesipo,orpogivesorpoandsimpogivessimpo.hinge,kto_pair, any other value, or a value that is not a string is refused:No Soup task matches LLaMA-Factory pref_loss: hinge. Supported pref_loss values are ipo, orpo, sigmoid, simpo.Under a stage other thandpothe stage's own task is kept. - Unsloth notebooks take the task from the trainer class:
SFTTrainertosft,DPOTrainertodpo,KTOTrainertokto,ORPOTrainertoorpo,GRPOTrainertogrpo,PPOTrainertoppo,RewardTrainertoreward_model,BCOTrainertobcoandOnlineDPOTrainertoonline_dpo. An online DPO notebook migrates with a warning and a placeholdertraining.online_dpo_judge: ollama://REPLACE-ME, because TRL's judge is a Python object with no string form; replace it, or settraining.reward_model.CPOTrainermigrates, tosimpo, only whenloss_type="simpo"is set on that trainer call or itsargs=config; any other CPO loss, or anargs=that cannot be read statically, stops the migration. - The last trainer decides. When a notebook builds several trainers, the task, output directory and hyperparameters come from the config passed to the last one, inline, named or positional, so an SFT warm-up before a GRPO stage no longer leaks its
num_train_epochsinto the GRPO config. Upstream names four public Qwen3 4B GRPO notebooks that used to inherittraining.epochs: 2. - IPython magics no longer break a notebook. Lines starting with
!or%(!pip install ...) are skipped;%%capture,%%time,%%timeitand%%prunlose only their header line and their body is still read; any other cell magic (%%bash,%%writefile) is skipped whole. A real syntax error is now reported with its code cell and line. - The output is validated with the config loader before it is written, and an Axolotl source with no adapter prints
No adapter specified for task 'sft' - full fine-tuning will be used (lora.r: 0); a LLaMA-Factory source withfinetuning_type: fulland an Unsloth notebook withfull_finetuning=Trueprint their own full-fine-tuning warning. A full fine-tune of a task other than SFT or embedding (DPO, pretraining, reward model) is refused.
If you migrated before v0.76.0, check the generated soup.yaml. Upstream's changelog lists what changed in the result: an unquantized source had no quantization line, so Soup loaded it as 4-bit QLoRA, and a full fine-tune source got LoRA r=64; Axolotl rl: orpo, ipo and simpo became task: sft with no warning; LLaMA-Factory pref_loss: ipo became task: dpo; an Unsloth CPO, reward-model, BCO or online DPO notebook became task: sft; and a warm-up trainer's epochs could leak into the final stage. If your source was bf16 or a full fine-tune, or used any of those trainers or losses, the run you got may not have been the run you meant. Regenerate and diff.
Unsupported Features
Soup will warn about features that don't have a direct equivalent:
- sample_packing (Axolotl) — not auto-mapped by
soup migrate; settraining.packing(ortraining.multipack) by hand after conversion - freeze training (LLaMA-Factory) — not auto-mapped; set
training.freeze_layersortraining.freeze_ratioby hand. Both keys are applied only bytask: sft(andtts) onbackend: transformerswithmodality: textand no layer streaming; any other combination is refused at config load (#1497, #1581) - use_rslora (Unsloth) — supported, but the key is nested:
training.lora.use_rslora - max_steps — Soup uses epochs; max_steps emitted as comment
- DeepSpeed / W&B — emitted as CLI flag comments
Security
- Input files are validated to be within the current working directory
- Unsloth notebooks are parsed via AST only — no code is executed
- Output paths are confined to the current directory
Soup is free and Apache-2.0. If it saved you a training run, starring the repo costs nothing and helps most. You can also fund the GPU time behind the work a 4 GB laptop cannot reach.