What's new across v0.71 to v0.77

One page for everything that shipped since the v0.71 install split, newest first. The current flagship, layer streaming, has its own pages: Layer streaming for the mechanism and the measured numbers, Scaling a streaming run for architectures, batches, resume and the disk tier, Layer streaming disk tier for the direct-I/O reader added in v0.76.0, Streaming a Mixture-of-Experts base for the DeepSeek-V3 family added in v0.77.0, Preference losses over streaming for DPO, ORPO, SimPO and KTO, and Validation on hardware we do not own for what the method does at 8B through 72B on someone else's cards.

Every line below names the release it shipped in. Where a number is quoted it was measured; where none is quoted, none was measured.

The v0.77 line

  • v0.77.0 refuses what v0.76 warned about. Upstream gave it no codename and titled it with a sentence: "what v0.76 warned about is now refused". The 31 staged fields (the 29 v0.76.0 warned about, and two staged after it) set away from their defaults, data.remove_unused_columns: true, training.quantization: 4bit or 8bit on a task that never quantises, and soup ab --beta now stop the load or the command, and so do fourteen of the fifteen settings on upstream's list that v0.76 accepted without a word and never applied (the fifteenth, a malformed KTO label, drops the row at data load), so a config that loaded on v0.76 can stop loading: run soup doctor --config soup.yaml before you upgrade. Python 3.10 is no longer supported (>=3.11,<3.14, so 3.13 is), AWQ and GPTQ export are removed, and on soup serve, /v1/tools/python and /v1/tools/bash answer 401 without --tool-auth-token on every bind, loopback included; pin soup-cli[train]<0.77 to keep Python 3.10, AWQ and GPTQ export need v0.76.x and its [awq] or [gptq] extra, and 0.76.x receives security fixes only, until 0.78.0. training.gradient_checkpointing now reaches the trainer, so grpo, ipo, bco, reward_model and online_dpo train with checkpointing off at the default false. DPO, ORPO, SimPO and KTO train natively on Apple Silicon (backend: mlx, Soup's own loop on TRL's objectives), MLX text SFT gains DoRA, eval_steps, the loss watchdog and seeded runs, and lora.use_rslora is now applied on MLX and Unsloth, where it was ignored. Layer streaming reaches DeepSeek-V3-family MoE models, with Kimi-K2-Base and -Instruct admitted behind a field-by-field check verified on CPU with a tiny K2-shaped checkpoint only (nothing has been trained on K2 itself); soup ship --require-provenance checks evidence against what it was stamped with; and GRPO can score with an LLM judge, training.reward_fn: judge_rank (task: grpo only; prompts and completions are sent to the judge host you configure). Some finished runs trained something other than their config said, among them a dpo, ipo or grpo run resumed from a checkpoint: the Re-run table. 151 of the 226 pull requests came from 44 people outside the maintainer, in the release body's count. No security advisory is published with it, the preprint is unchanged, and the catalog is 171 recipes. The release page.

The v0.76 line

  • v0.76.1 is a backport patch, and the bundled DPO examples train again. On v0.76.0, task: dpo, ipo, bco and preference failed inside trl, after the model had loaded, on examples/data/dpo_sample.jsonl, examples/data/chat_preferences.jsonl and any dataset written the same way (a string prompt beside chosen / rejected message lists that repeat the user turn). The dpo and kto converters now hand the trainer every preference row in one layout, and a row that cannot be written that way is dropped at load with a reason that names the field, so a dataset can shrink at load, with a warning, never silently. The one fix that touches a finished run: on those same rows, reward_model "no longer trains on a text with the question in it twice" (verified on v0.76.0; the code that produced it is unchanged at every earlier tag the audit read, back to v0.40.0), so re-train such a reward model if it matters to you. Every YAML file Soup reads now goes through one loader with a 100-level nesting limit, an expansion limit and a size cap per reader, so a soup.yaml over 1 MiB or nested deeper than 100 levels stops the load with one line naming the file: run soup doctor --config soup.yaml first, as for v0.76.0. Soup declares typer>=0.15.4, so upgrading upgrades an older Typer or names the conflict; data.train: teknium/OpenHermes-2.5 loads from the Hub instead of failing with Data file not found; and the audit log masks the values of --slack-url and --discord-url (lines already in the log were not rewritten until v0.77.0, which masks them once, the next time the log is written). Upstream's README and performance docs now print the 8B NF4 figure with its clock beside the post-#331 row, measured by @umran666 (#1103), and the two are not directly comparable. All seven changes are maintainer pull requests; there is no security advisory and no gate record, the preprint is unchanged, and test files go from 875 to 883. The release page.
  • v0.76.0 stops the load on settings that never took effect. Upstream gave it no codename and titled it with a sentence: "settings Soup accepted and never applied now stop the load". Dozens of combinations that loaded on v0.75 are now refused with a message that names the field and what to change, and 29 declared-but-unread fields warn at load, with upstream saying that v0.77 will refuse them. (It did: they are refused at load since v0.77.0.) Run soup doctor --config soup.yaml before you train. 490 pull requests were merged between v0.75.0 shipping and the v0.76.0 tag, 418 of them from 80 people outside the maintainer. The release page; the refusals and warnings.
  • The exit codes of eleven gate and verdict commands moved to 0 pass, 2 gate failure, 3 usage or input error (soup ship, soup expect, soup eval gate, soup lock check and seven more). A CI step that tests for the old number, such as exit 1 from soup eval gate, now passes a failing gate. The table of what moved.
  • Validation loss is evaluated on the transformers backend for the first time. data.val_split held rows out on every run and no trainer on the transformers backend evaluated them; training.eval_steps is new. grpo, ppo and online_dpo no longer hold rows out, so every row trains. Every GRPO variant now applies grpo_beta, so an existing variant config will not reproduce an earlier run.
  • Dozens of fixes mean a run you already finished may have been wrong, most of them with a normal-looking loss curve: packing that trained prompt tokens, doubled BOS tokens, distillation gradients scaled by accumulation, GRPO rewards that scored every correct answer 0.0, Online DPO labels from a judge that could not rank a pair, and more. The Re-run this table lists them with upstream's wording and pull request numbers.
  • New commands: soup adapters check and audit, soup bench train and bench infer, soup data clean, soup rewind and soup recipes verify. Sigstore keyless signing is a real backend for soup adapters sign and soup attest emit (shipped in v0.76.0; upstream's tests mock the signer). soup export --format awq|gptq and soup quantize --to awq|gptq are deprecated, with removal tracked for v0.77. (Removed in v0.77.0.)
  • Layer streaming: the disk tier reads on a background thread through direct I/O and can stripe across NVMe drives, measured on one RTX 5070 Laptop with a synthetic store and with every caveat on its page. A post-repair row for the 8B configuration was recorded by @umran666 on a different 4 GB laptop (#1103) and is printed with its clock beside the older row, on Layer streaming; upstream's reading is that the raw 1.74x gain is the clock, not a speedup.
  • Security: no new advisory. The supported version for security fixes is now 0.76.x. (Since v0.77.0, 0.76.x receives security fixes only, until 0.78.0.) On a loopback bind soup ui keeps its token out of sessionStorage and uses an HttpOnly cookie, and third-party plugin code loads only after soup plugins enable.
  • Counts at the tag: 170 recipes (9 added, 6 removed), 78 top-level commands, 29 command groups, 37 extras, 24 optimizer names, and 20 values in the data.format list.

The v0.75 line

  • v0.75.2 is a security patch with one change in it, and nobody outside the maintainer wrote it. Several outbound endpoint checks refused plain http to a remote host but accepted any https URL, including one naming a private, link-local or reserved IP address, so a configuration file that set a judge URL could make the machine that ran it POST to an internal HTTPS service addressed by IP. It is advisory GHSA-9f49-hqpf-c849, rated medium and reported by an outside contributor, affecting 0.3.0 through 0.75.1. soup data generate --api-base, the vLLM provider, judge URLs, eval-gate suites, soup ship --judge-model, training.online_dpo_judge (now checked when the config loads) and the Web UI chat proxy now refuse such an address on both schemes; loopback still works and http://0.0.0.0 is no longer local. There is nothing to re-run and nothing to rotate; a config that names a private, link-local or reserved IP address fails loudly and should name a hostname instead. Hostnames are still not resolved. No measurement and no gate record; the preprint is unchanged.
  • v0.75.1 is a security and correctness backport, and the first release in four that nobody outside the maintainer wrote. It is the fix for advisory GHSA-63h4-gvp4-r26g, rated high, covering eight issues across 0.7.0 to 0.75.0, with three credentials to rotate: the Hugging Face token was resolved for every hub and handed to ModelScope or Modelers, OPENAI_API_KEY went as a Bearer token to any https judge host whatever it was, and credential option values were written to the audit log. Four fixes mean something you already ran was lost, and the sharpest is that a layer-streamed LoRA adapter saved on peft 0.21 or newer is a 40-byte file holding zero tensors, with nothing raised at save time and no way to recover it. Also: soup runs clean --keep-weights did the opposite on Click 8.1 and deleted whole checkpoints, Modal runs lost their outputs with the container, and Ctrl+C during a Lambda submit could leave the paid instance running. No gate record and the preprint is unchanged, both stated by upstream rather than left implicit.
  • v0.75.0 is the release where MLX started honouring the config it had been accepting. Training options were validated by the schema, documented in these pages and read by nothing on backend: mlx (upstream counts six, and its fix entries name eight settings), so the same soup.yaml trained a different recipe on Apple Silicon than on a CUDA box: response-only masking reached nothing, so every MLX run trained on the prompt; the optimizer, scheduler, warmup ratio and weight decay were dropped, so every run built a bare AdamW at a constant learning rate; max_grad_norm clipped nowhere; and gradient accumulation and checkpointing silently took mlx-lm's defaults. All 60 of its pull requests came from outside the maintainer, by 22 people, and fourteen of its fixes mean a finished run was wrong. Breaking: an unknown config key now refuses the load at the deadline v0.74.0 named, and grpo_variant: gspo is the published sequence-level objective rather than a column-centering heuristic, so existing gspo configs will not reproduce prior runs. Validation loss was computed on every backend and thrown away; it is now its own series, with an un-evaluated step recording NULL rather than a fabricated zero. (Corrected in v0.76.0: on the transformers backend the held-out split was never evaluated at all until v0.76.0.) torch>=2.6.0 closes the limitation v0.74.0 published rather than hid. Also here: inference prompts stop sending a doubled BOS across soup chat, serve, infer, bench, diff, ship, diagnose and advise; soup ingest --source langfuse --pull fetches traces live; soup doctor --config names the settings your backend does not read; Web UI read endpoints and SSE require authentication; and four recipes take the catalog to 167. Opt-in, hardware-only telemetry is wired behind SOUP_TELEMETRY=1, and as shipped it sends nothing. No maintainer gate: three contributor records landed instead, one of them a gate that failed and was published as written.

The v0.74 line

  • v0.74.0 found the frozen base being loaded in fp32 the whole time. A LoRA run freezes the base, so its only job is to hold the checkpoint's own numbers, and all three supervised load paths passed no dtype at all: measured on an H100 with Llama-3.1-8B and LoRA, peak memory falls from 48,241 MiB to 18,658 MiB, 2.59x on an unchanged config, with the same defect standing in twelve more trainers. 116 of the release's 120 pull requests came from outside the maintainer, by 25 people, and ten of its fixes mean a run you already finished was wrong, starting with unknown config keys that were silently dropped. The training stack moves to Transformers 5.16.1, TRL 0.29 and PEFT 0.20, so pip install "soup-cli[train,mlx]" resolves for the first time; the free notebook tier could not stream at all until now, for a second reason after v0.73.1's; layer streaming admits a tenth architecture and stops keeping an untied embedding and LM head both resident; and soup mcp serve gains sse and http transports behind a mandatory bearer token, with gated execution refused over a listener. Breaking: soup serve exits 2 rather than warning on a non-loopback host without --tool-auth-token, and the SGLang backend finally obeys --trust-remote-code. No new throughput was measured; the two new records are a second-box VRAM verification and a partial Apple Silicon gate.

The v0.73 line: borrowed hardware

  • v0.73.3 was a contributor release. All 24 pull requests came from outside the maintainer, from eight contributors, five of them appearing for the first time, and what they found was four flags that the schema validated, the docs described, and nothing read. Two findings are the project's signature failure shape: assistant-only loss masking built its label mask from a tokenizer mapping's key strings, so a run trained on zero tokens behind a normal-looking loss curve, and on Apple Silicon quantization: 4bit was silently rewritten to none because device detection did not know MLX. The one new capability is that soup mcp serve --allow-execute stopped being a reserved gate and now runs a planned training or export behind a single-use, server-generated confirmation token, taking the server from 16 tools to 18. Also here: the soup ship noise floor is measured in the judge task modes rather than metric alone, soup env check flags an installed package that violates Soup's own declared bounds, and layer streaming stops refusing a fast virtio disk as if it were a spinning one. No new measurement was made and no benchmark record was added, which upstream states rather than leaves implicit.
  • v0.73.2 repaired the release gate itself. Two of soup ship's behavioural suites ranked by the wrong thing, so a stub answering every item correctly scored 0.000 and an 8B naming the right tool 40 times out of 40 scored 0.225. A whole failure direction, a model that refuses everything, had no detector until mini_over_refusal joined as the eighth bundled suite. New CLI flag soup ship --noise-floor N measures what the instrument itself can resolve before any delta is called significant. Any verdict issued before this release is suspect, and a stored --baseline is on a different scale.
  • v0.73.1 repaired the GPU tier most people actually have. bf16 was assumed on every CUDA card in fourteen places, so every pre-Ampere card (T4, P100, V100, GTX 16xx) failed on every task, not only on streaming. The same release caught the streaming VRAM pre-flight under-predicting at long sequence, against a contract that says it never does, and shipped training.stream_vram_probe. Three more classes of finished-but-wrong run were closed: MLX adapters that loaded as a silent no-op, backend: mlx never dispatching to MLX at all, and periodic checkpoints under use_fsdp2_compile still loading dead.
  • v0.73.0 is the release that came out of three days on an 8x H100 box. It repaired the NF4 gradient defect that only a resident reference could have found, plus four backends that had never executed once: the multi-GPU launcher, DeepSpeed with LoRA, SGLang serving and the Liger kernel. Two capabilities are new, both config keys: training.seed and full fine-tuning as lora.r: 0. Python narrows to 3.10 through 3.12 (3.11 through 3.13 since v0.77.0). Six fixes mean a completed run of yours may be wrong, including a supervised path that silently capped every run at 1024 tokens and a soup ship gate whose suites scored zero on a capable model. The changelog and the re-run list. (v0.73.0)

The v0.72 line: layer streaming

  • Validated on hardware nobody here owns. Three borrowed days on an 8x H100 box, the first machine able to hold a resident reference for a model worth streaming, so the correctness check that had only ever run on 3-layer fixtures finally ran against real checkpoints. The streamed forward is exact against a matched resident reference at 8B, 14B, 32B and 72B; peak VRAM stays flat from 3,397 MiB to 4,845 MiB while the model grows fourfold; the 4 GB laptop's headline, measured on v0.72.2 before the repair, reproduces at a median 113.00 tok/s against its 119.6; and a streamed model converges indistinguishably from a resident one over five paired runs. It also found a defect: in NF4 above roughly 165 MiB per decoder layer, the backward produced silently wrong gradients while the forward stayed exact and the loss looked healthy. That affects 32B and up, was present in every release from v0.72.0 to v0.72.4, and is repaired in v0.73.0, gated at both affected sizes against a control that reproduced it. The whole record.
  • DPO, ORPO, SimPO and KTO run against a streamed base. Streaming used to mean supervised fine-tuning only. DPO's reference model is the same streamed base with its adapters switched off, so it costs no extra weights: on a 365M-parameter synthetic fixture, streamed DPO peaked at 0.914x the streamed SFT peak, where forcing a real second instance in the same harness cost 730.44 MB, exactly one copy of them. All four are bit-exact against a resident run of the same loss. The reference is free in memory, not in time: DPO reads the layer stack 1.52x as often per step. KTO needs batch_size of 2 or more. (v0.72.4)
  • A packaging defect that predates the release: six preference trainers passed a field TRL removed across several of its own versions, so soup train with task: orpo could fail at import on a fresh install. The dependency bound was settled by constructing all six configs against each candidate version rather than by reading source, and a contract test now calls the real setup() for all six. The first bound shipped too tight, and the reason is worth keeping: some of those config classes had moved into TRL's experimental namespace while still being re-exported publicly with the field intact, and a relocation read as a removal. Constructing the object is what distinguishes the two; reading a diff is not. Corrected in v0.73.0, which widens support to trl>=0.14.0,<0.29 (since moved: v0.74.0 requires trl>=0.29.0,<1.0.0) behind a capability-probe layer rather than a version table, verified by constructing and training all six on three different trl versions. (v0.72.4)
  • The measurement records behind the whole v0.72 line are published in the repository's benchmarks directory, failures and discarded numbers included, and the work has a preprint: 10.5281/zenodo.21771064, summarised on the paper page. (v0.72.4)
  • soup doctor --disk reports the detected media type, because the streaming disk tier needs NVMe and refuses a SATA SSD, a spinning disk, or media it cannot identify rather than guessing. Opt-in, because the probe costs about 9 seconds cold and 2.4 seconds warm. (v0.72.3)
  • [mcp] is pinned below 2.0. The MCP SDK's 2.0.0 removed an API soup mcp serve round-trips through, which broke its round-trip tests for anyone installing fresh. (v0.72.3. Since lifted: v0.74.0 requires mcp>=1.10.0,<3 and picks the API by probing the server constructor rather than reading a version string, so both majors work.)
  • soup adapters arithmetic --rank N: mixed-rank LoRA algebra is exact rather than refused. Stacking the factors reproduces the sum of deltas by construction, and an SVD truncates to the rank you ask for. (v0.72.0)

The v0.71 line: lean install and live wiring

  • soup reward synth golds.jsonl -o reward.py plus soup reward stress: Reward Forge. Synthesize a deterministic verifier from your gold outputs, refusing to emit a degenerate one, then attack it with empty, padded, repetitive and sentinel-spam junk to prove it cannot be gamed. (v0.71.40 and v0.71.41)
  • soup ship --emit-evidence plus --config soup.yaml plus --push owner/repo#N: the verdict becomes CI for weights, a provenance-bound gate you commit and render on every PR. (v0.71.39)
  • The soup ship regression leg grew teeth: answer-extraction scoring over seven bundled offline suites (MMLU, arithmetic, tool-call, JSON, safety and more), not fifteen substring-matched trivia prompts. Verdicts can flip, because the old gate reported false negatives. (v0.71.38)
  • soup data dedup --semantic plus topics, canary and train --replay: Data Moat II, a semantic layer over your data plus tools for what a fine-tune forgets and leaks. (v0.71.36)
  • soup init --template hipaa|soc2|eu-ai-act|sr-11-7 plus soup card and soup ci init: the compliance pack. A regulation-shaped config, a provenance-carrying model card, and a PR gate that blocks a merge on DON'T SHIP. (v0.71.35)
  • soup export --format gguf is validated end to end on Windows (q4_0, q4_k_m, q8_0, f16, plus an Ollama round-trip), fixing four bugs including an export that downgraded your CUDA torch. (v0.71.35)
  • soup adapters arithmetic "coder + 0.5*math - toxic": task-vector algebra over LoRAs. Add, scale, and actually negate a delta rather than performing the no-op a naive coefficient gives. (v0.71.34)
  • training.lisa_enabled: LISA re-samples which layers train every N steps, reaching for full fine-tune quality without a full fine-tune's memory. Since measured at 3B and 8B: it beats full fine-tuning on held-out loss, and it trains an 8B on one 80 GB card where full fine-tuning cannot run at all, but it costs more memory than LoRA rather than less (1.22x at 3B, 1.51x at 8B, both measured before v0.74.0 stopped loading a frozen LoRA base in fp32, so the real gap is wider). The numbers. (v0.71.34)
  • soup train with task: asr plus soup infer --task asr: Whisper fine-tuning with built-in WER and CER. Tiny and base fit a 4 GB card. (v0.71.32)
  • soup train with task: online_dpo plus soup data best-of-n and evolve: an LLM judge in the loop across training and data. (v0.71.31)
  • task: grpo plus training.prm_reward: a Process Reward Model grades every reasoning step, the o1-era process-supervision signal. (v0.71.30)
  • soup shrink --drop-ratio 0.25: depth-prune the least-useful layers, distill-heal the damage, and get a SHIP / DON'T-SHIP perplexity verdict. (v0.71.29)
  • soup mcp serve: drive Soup from Claude Code, Cursor, Cline or Continue. Stdio only when it shipped; sse and http transports arrived in v0.74.0. (v0.71.28)
  • soup data doctor and soup data lint: 8 chat-template checks including the "never stops generating" EOS bug, plus a preference-data linter. Pre-flight, zero GPU. (v0.71.27)
  • --reward-hack-mitigation kl_control|pid_lagrangian: detect reward hacking mid-run and self-correct by raising KL, shaping the reward and rolling back, instead of only halting. (v0.71.26)
  • soup ship: one SHIP / DON'T-SHIP verdict fusing a task win with no catastrophic forgetting. Exit 0 or 2 for CI. (v0.71.25)
  • soup recipes use whisper-tiny-asr: Whisper ASR and the 2026 model families (Qwen 3.5 and 3.6, DeepSeek-V4, GLM-5.1, Kimi K2.6, MiniMax M3). (v0.71.24 and v0.71.32. The catalog is 170 recipes at v0.76.0, 171 at v0.77.0. Since removed: the Mistral Large 3 recipe v0.71.24 added, mistral-large-3-sft, because Mistral publishes that model without a config.json, which AutoConfig cannot read (#1398).)
  • soup spectrum scan --top-percent 50: rank layers by singular-value SNR and fine-tune only the high-signal ones, with no model load. (v0.71.23)

See also

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.