Configuration
Soup uses a single YAML config file for all settings. Run soup init to generate one.
Reproducibility and full fine-tuning (v0.73.0)
Two training keys landed in v0.73.0. Both are config keys, not CLI flags.
training:
seed: 1234 # weight init of new params, data order, dropout
data_seed: 7 # optional: vary data order while holding init fixed
lora:
r: 0 # 0 means no adapter: full fine-tuning, dense checkpointseed and data_seed are the first seed knobs in the project's history: before this every run trained at seed 42 with no way to change it, so "run this twice with a different seed" was impossible. Both default to unset rather than to 42, deliberately, because an unset seed has to keep reproducing two different historical defaults (the trainer's 42 and the multipack sampler's 0) and a plain 42 would have silently re-ordered every existing multipack run. A boolean is refused by name, since seed: true would otherwise become seed 1.
The honest scope: the seed reaches the trainer arguments on supervised runs only, so setting it on a DPO run parses and does nothing. On a streamed run it additionally seeds the adapter initialisation for all five streaming tasks, which is why a streamed run is bit-reproducible from a seed while a resident 4-bit one still is not.
lora.r: 0 selects full fine-tuning: no adapter is built, and the run writes a dense checkpoint rather than a LoRA. Rank 0 was chosen because three parts of the codebase already read it as "no adapter" and because r: 0 used to crash, so no config that worked before changes meaning. It is refused with a named message alongside a non-transformers backend, a non-text modality, any quantisation, Spectrum, LISA, layer streaming, or any LoRA-shaped option, and it refuses rather than running a no-op if your freeze settings leave nothing trainable.
Config Structure
base: meta-llama/Llama-3.1-8B-Instruct # HuggingFace model ID (required)
task: sft # Training task
# backend: unsloth # 2-5x faster (pip install "soup-cli[fast]")
# modality: text # text, vision, or audio
data:
train: ./data/train.jsonl # Path to training data
format: alpaca # Data format (auto-detected if omitted)
val_split: 0.1 # Validation split ratio
max_length: 2048 # Max sequence length (64-1048576)
# image_dir: ./data/images # For vision modality
# audio_dir: ./data/audio # For audio modality
training:
epochs: 3
lr: 2e-5
batch_size: auto # auto or integer
quantization: 4bit # none, 4bit, 8bit
# quantization_aware: false # Enable QAT
# optimizer: adamw_8bit
# gradient_checkpointing: true
# stream_layers: false # Train or align a model bigger than VRAM (v0.72, BETA)
# stream_source: auto # auto | ram | disk
# stream_buffers: 2 # 2-8
lora:
r: 64
alpha: 16
dropout: 0.05
# target_modules: auto # Auto-detected per model
# use_dora: false # Weight-decomposed LoRA
output: ./outputLayer streaming keys
These turn on layer streaming, which trains a model larger than your VRAM by keeping the frozen base out of the card entirely. They are config keys, not CLI flags: there is deliberately no --stream-layers.
| Key | Values | Default | Notes |
|---|---|---|---|
stream_layers | true / false | false | BETA. Only enable it if the model does not fit resident; streaming trades time for memory |
stream_source | auto / ram / disk | auto | auto takes RAM when the base fits and falls back to an NVMe tier; ram refuses instead of falling back; disk forces NVMe |
stream_buffers | 2 to 8 | 2 | VRAM buffers in the pool. 2 is double-buffering; 1 cannot overlap load with compute, so it is refused |
stream_vram_probe | true / false | false | v0.73.1. Decide the fit by measuring one real forward and backward at your shape, instead of predicting it. task: sft only. Costs 1 to 5 seconds, and cannot overrule a prediction more than 4x over budget |
stream_disk_kind | nvme / ssd / hdd | (unset) | v0.73.3. Override the detected media type behind the disk tier. nvme forces the tier on, ssd and hdd force it off. The override prints beside what was actually detected, and deliberately carries no measured rate, so a later refusal can never cite a reading you overrode |
stream_vram_override | bytes | (unset) | v0.73.1. Replaces the free-VRAM figure the pre-flight checks against, in either direction. It changes the yardstick, not the check: an override below real free VRAM still refuses a config that would otherwise fit |
Setting any of these while stream_layers is false is refused, because the knobs would silently do nothing.
stream_vram_probe and stream_vram_override are not interchangeable, and the difference is the point. stream_vram_probe is a measurement: it runs the step and reads the peak. stream_vram_override is an assertion you are making about how much VRAM is really available, which is what you need when the pre-flight cannot see the truth, as under a per-process memory cap in a hosted notebook.
Streaming also constrains keys you already set: quantization must be none or 4bit, batch_size must be a concrete number rather than auto, and task must be one of sft, dpo, orpo, simpo and kto (kto additionally needs batch_size of 2 or more). Scaling a streaming run covers sizing, the VRAM pre-flight and the disk tier; Preference losses over streaming covers the four alignment tasks.
Templates
Soup includes 21 built-in templates:
soup init --template chat # Conversational fine-tune
soup init --template code # Code generation
soup init --template medical # Domain expert
soup init --template reasoning # GRPO reasoning (DeepSeek-R1 style)
soup init --template vision # Vision/multimodal fine-tune
soup init --template audio # Audio/speech fine-tune
soup init --template kto # KTO unpaired preference
soup init --template orpo # ORPO (no reference model)
soup init --template simpo # SimPO length-normalized preference
soup init --template ipo # IPO regularized preference
soup init --template bco # BCO binary classifier preference (v0.40)
soup init --template rlhf # Full RLHF pipeline (SFT -> RM -> PPO)
soup init --template pretrain # Continued pre-training on raw text
soup init --template moe # MoE fine-tuning (ScatterMoE LoRA)
soup init --template longcontext # 128k+ context fine-tuning
soup init --template embedding # Sentence embedding fine-tuning
soup init --template tool-calling # Function / tool-calling fine-tune (v0.25)Four more are regulation-shaped (compliance pack, v0.71.35). Each is a valid training config on a license-clean Apache-2.0 base plus header comments naming that regime's exact commands, because Soup's compliance controls are CLI flags and commands rather than config keys:
soup init --template hipaa # Protected Health Information
soup init --template soc2 # SOC 2 Trust Services Criteria
soup init --template eu-ai-act # EU AI Act Annex XI/XII
soup init --template sr-11-7 # SR 11-7 Model Risk ManagementTask-Specific Config Keys
| Key | Tasks | Description |
|---|---|---|
dpo_beta | DPO | DPO beta parameter |
kto_beta | KTO | KTO beta parameter |
orpo_beta | ORPO | ORPO beta parameter |
simpo_gamma | SimPO | SimPO gamma parameter |
cpo_alpha | SimPO | CPO alpha parameter |
ipo_tau | IPO | IPO tau parameter |
grpo_beta | GRPO | GRPO beta parameter |
num_generations | GRPO | Number of generations per prompt |
reward_fn | GRPO, PPO | Reward function (accuracy/format/path.py) |
reward_model | PPO | Path to reward model |
ppo_epochs | PPO | PPO training epochs |
ppo_clip_ratio | PPO | PPO clip ratio |
ppo_kl_penalty | PPO | PPO KL penalty |
loraplus_lr_ratio | All | LoRA+ learning rate ratio |
use_galore | All | Enable GaLore optimizer |
moe_lora | All | Target MoE expert layers |
moe_aux_loss_coeff | All | Router load-balancing loss |
use_liger | All | Liger Kernel fused ops |
use_flash_attn | All | FlashAttention v2/v3 |
use_ring_attention | All | Ring FlashAttention |
rope_scaling_type | All | RoPE scaling (linear/dynamic/yarn/longrope) |
neftune_alpha | All | NEFTune noisy embeddings (0-50) |
packing | SFT | Sample packing for efficiency |
curriculum | All | Enable curriculum learning |
curriculum_metric | All | Sort metric (length) |
curriculum_buckets | All | Number of difficulty buckets (1-20) |
loss_watchdog | All | Enable loss watchdog |
loss_watchdog_threshold | All | Loss spike threshold (≤100) |
loss_watchdog_patience | All | Patience before stopping (≤1000) |
freeze_layers | All | Freeze bottom N layers (≤1000) |
freeze_ratio | All | Freeze ratio of layers |
embedding_loss | Embedding | Loss function |
embedding_pooling | Embedding | Pooling strategy |
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.