22 of the 28 pull requests in this release came from 11 people outside the maintainer.
Thank you: the Contributors section below names each of them and what they found or built.
v0.77.1 is a cut of main after v0.77.0, not a backport: it carries every pull request merged since that tag. The fixes that matter most are three. soup data commands no longer write their output over their own input. soup plan and soup apply now refuse the configs soup train refuses. And the README's Docker example works again. Nothing in v0.77.0 is taken back; coming from v0.76.x or older, read the v0.77.0 notes first, because a config that loaded on v0.76 can stop loading on v0.77, and run:
soup doctor --config soup.yamlFixes that matter
soup datacommands no longer overwrite their input when--outputnames it. Eighteen commands used to write their result over one of their own inputs and exit 0; the original could not be recovered. Each now compares its outputs with its inputs before it reads anything, and refuses the same file under any spelling: the same string,./x,sub/../x, the absolute path, a case variant on a case-insensitive file system, a hard link or a symlink. The message names both paths and says what to change, for example--output './d.jsonl' is the same file as the input 'd.jsonl'; choose a different --output. An output that is a different file works as before, and default output names are unchanged.decontaminate,toxicity,langdetect,piiandeducational(#2245, closes #2225). Their default output names (clean.jsonl,toxicity.jsonl,langdetect.jsonl,pii.jsonl,educational.jsonl) used to replace an input of the same name.decontaminatealso compares--outputwith--benchmark-file. On Windows a trailing space or dot,::$DATAand a junction are refused too. Exit code 1.- Thirteen more (#2261, refs #2226):
lint,doctorandtopics(the JSON report replaced the dataset),from-traces(the preference pairs, often an empty file, replaced the trace file),canary insert,sample,dedup,filter,convert,merge,active-sample,augmentandevolve(the result replaced the input). A default output name that the input already has is refused too:merged.jsonl,prefs.jsonl,active_samples.jsonl,augmented.jsonl.canary insertalso refuses a--manifestthat is the dataset or the--output; before, the dataset write replaced the manifest that had just been written, and the only record of the inserted secrets was lost. Exit code 1, exceptlint(3) andaugmentandevolve(2), which keep the code of their other path errors. soup data cleanalready refused this and is unchanged.
soup planandsoup applyrefuse the configssoup trainrefuses (#2242). They checked only for unknown keys, so a config with a staged field set (training.early_stop_patience: 5), a refused deprecated value (data.remove_unused_columns: true) or any other schema error got a plan (exit 0), andsoup applyandsoup apply --dry-runaccepted it. Both commands now exit 1 with theConfig validation error:linessoup trainprints for the same file, write no plan, and leave an existing state file unchanged (so it is not marked applied). A valid config plans and applies as before. This is the gap the v0.77.0 notes said was open.- The README's Docker example works again (#2244, closes #2229).
docker runwithout-tgivessoup traina stdin that is not a terminal, and since v0.77.0 such a run needs--yes; the README example exited 3. It now passes--yes, and the four translations follow. - Five statements about v0.77.0 now match the code (#2244). They were wrong in the v0.77.0 CHANGELOG,
SECURITY.md,docs/backends-and-ops.mdand the README What's New; no behaviour changed, the only source edits are two comments.soup doctor --config: the System, GPU, System Resources and Dependencies tables still print first; what moved is theAll checks passed!line. The config is checked before it, and a refused, missing or unreadable config exits2without it. The text had said the config is checked "before the environment summary".- A KTO row whose
labelis not a boolean, atrue/false-style string or exactly-1,0or1is dropped with a warning (soup trainnames the first such row and stops only when none is left;soup data validate --min-valid-fraction 1.0exits2). It is not refused at load, as the text listed it; the README says fourteen silently ignored settings are refused, not fifteen. - A
dpooripoterm under asimpoororpoprimary trains (since #1828), against an adapter-off reference; only with full fine-tuning, which has no adapter to switch off, does it still stop at the first step, with a message that names the fix. The #1785 entry had said it always stopped. - Telemetry: as released, nothing is sent. The bundled analytics key is a placeholder, so an opted-in command prints
Notice: telemetry is not yet live.and makes no network request. Only an operator's ownSOUP_POSTHOG_KEY(and optionally an HTTPSSOUP_POSTHOG_ENDPOINT) gives one HTTPS POST at command exit; the payload list now names every field it carries. - Which commands refuse a staged field or a deprecated value:
soup trainexits1,soup doctor --configexits2,soup recipes verify --configandsoup ship --configexit3.soup planandsoup applydid not (fixed above).
What's New
- GRPO trains natively on Apple Silicon.
task: grpowithbackend: mlxwas refused at config load; Soup's own MLX loop now generatesnum_generationscompletions per prompt from the current policy, scores them with the built-inaccuracyorformatfunction and takes one policy-gradient step per update. The objective is the one the transformers path trains on TRL 0.29.1 (loss_type: dapo, group-scaled scores,epsilon0.2, one iteration, token-level importance sampling, a k3 KL against the base model withtraining.grpo_beta), every setting is recorded inadapter_config.json, and held-out prompts are scored once after training asval_reward. A non-finite loss or gradient skips the update. Trytask: grpo,backend: mlx,reward_fn: accuracy. This is the dense baseline, step 1 of #1976 (#2182 by @dryn85-max). soup infer --backend mlx. Native text LoRA adapters and MLX base models load and generate without Torch or PEFT, through a shared strict loader that checks every adapter name, shape and finite value and refuses unsupported tasks, controls, targets and variants. Dense and genuine 4-bit bases are covered, and base-only generation works. Part 1 of #1986;soup chatis scoped separately (#2121 by @Amix29).soup ship --progress jsonl. Versionedstart,progress,endanderrorevents on stderr, with explicit identities for noise-floor repeats and a fixedexecution_abortedcode when a group aborts. It is opt-in: ordinary output, stdout and exit codes are unchanged; in JSONL mode an unexpected exception becomes exit 1 with start/error events and no traceback (#2171 by @kok-o).- Unknown config keys get better hints. A key written the way another library names it now names the Soup field:
learning_ratesuggestslr,num_train_epochssuggestsepochs,training.lerning_ratesuggeststraining.lrrather than an unrelated field. The suggestion cutoff is 0.65 in every section. "use X" is for those names and one-edit typos of them; a name that is only similar gets the "did you mean" ranking, andper_device_eval_batch_size,per_gpu_eval_batch_size,eval_batch_size,warmup_stepsandwarmup_step, which have no Soup counterpart, get a sentence saying so at the top level and undertraining:alike. The hints are diagnostics; the schema still decides what loads (closes #2099; #2138 by @Nari-Ab). - Two reads of a streamed routed expert per step instead of three (experimental).
build_streamed_model(..., two_read_experts=True)keeps the decoder checkpoint but no longer fetches routed experts in its replay: the forward and the expert's own backward read each expert once, and the router reuses the forward's top-k choice while its scores stay differentiable. It needs theper_expertlayout and reaches DeepSeek-V3-family bases only. It is API only, off by default: there is no config field, flag or default change. A forward hook on a two-read layer, its MoE block or its routed experts is refused with an error. On CPU the losses and gradients equal the resident model's bit for bit; no hardware speed record is part of this release (#2158 by @Batyrkhantzy111).
Also fixed
- Streamed LoRA on an untied embedding or head saves and resumes. The adapter saves with PEFT's defaults and resumes through Trainer or
load_adapterwith every tensor kept; reloads keep the runtime's device map; DPO's reference adapter can attach through the streaming wrappers (completes item 1 of #1048; #2159 by @kok-o). - Building a streamed fused-expert MoE no longer asks the CPU for each full expert tensor. The skeleton is built on
meta, but each MoE layer first created its expert tensor on the CPU (15 GB for DeepSeek-V3, 22.5 GB for Kimi K2 in bf16) before moving it; on Linux with strict overcommit, a small machine, or Windows with too little page file this failed withDefaultCPUAllocator: can't allocate memoryornot enough memory. Every CPU request of 1 MiB or more is now made onmeta; a model that registers a buffer that large is built the old way with the buffer named in a warning. Closes #2154 (#2157 by @ybai08). /v1/tools/pythonreports what failed. A timeout istimed_out: truewithexit_code: 124and no output; other process failures carry their stdout, stderr and exit code withtimed_out: false(output overflow isexit_code: 1); every HTTP 401 from the tool routes carriesWWW-Authenticate: Bearer. Closes #2194 (#2204 by @Nari-Ab).soup profile --gpuand the MCPprofiletool know the RTX 30-series laptop GPUs.--gpu "rtx3060 laptop"was "Unknown GPU", and the laptop 3060 has 6 GB, not the desktop card's 12; each part now has its own entry with NVIDIA's memory, the names the driver reports resolve to it, and a size written as a word ("A100 40GB") reaches the matching entry (#2144 by @abdulwaarith0).- Adapter commands name the missing dependency.
soup adapters checkand the others reported corrupt weights when numpy or safetensors was missing; read-only operations now ask for numpy, and merge and arithmetic for numpy and safetensors (closes #2056; #2141 by @Nari-Ab). soup eval gatehandles a malformed suite. Malformed YAML and non-mapping roots ([],false,0,"") exit 3 with a file-specific message; before, malformed YAML and a list or scalar root exited 1 with a bareError: TypeErrororParserErrorline, and an empty root such as[]exited 3 with a generic validation message;soup train --gateexits 1 and the training callbacks keep their fatal-failure policy (#1878, reported by @taljeon; #1895 by @Nari-Ab).soup exportcleans up after a failed step. The temporary.soup_merge_tmp_<adapter>/directory is removed when llama.cpp is not found, a clone or install fails, or the merge dies while saving, for the gguf, onnx, tensorrt, bitnet and gguf-ud paths; before, a multi-gigabyte directory was left next to the adapter. It removes only a directory that export created: one that was already there is left alone, and the output says so (#1464 by @ShivanshShukla in #2164).- Spike recovery hints are written safely. They refuse symbolic-link targets and are replaced atomically, which keeps other hard links and the previous hint when the write fails, without consuming an attempt (#2169 by @Nari-Ab).
- Langfuse zero scores are kept.
soup ingest --source langfuse --logsdropped scores of0,0.0andfalse; they now reach the thumbs-down signal and preference-pair construction. Only a missing or null score falls back torating(closes #1856; #1871 by @akkupratap323). - A malformed model file no longer stops the estimate. A model's
config.jsonthat is malformed, or states a figure no model has, is treated as an unreadableconfig.jsonby the VRAM pre-flight,soup plan,soup profileand the MCPprofiletool (soup profileprices a guessed shape and says so;soup planrecords that it could not price the run); a malformed.safetensorsheader is skipped and the parameter count comes fromconfig.json(approximate); andsoup infer --backend mlxrefuses a malformed native adapter'sadapter_config.jsonwith a message naming the file. - A mixture-of-experts model known only by its cached
config.jsonis priced with all its experts, not as a dense model of a few billion parameters; the estimate's note says the count is approximate. - Names from a config or a command line reach the terminal cleaned.
soup profileprints the LoRA target modules, andsoup adapters bisectthe checkpoint ids, with control characters and bidi marks removed.soup infer --backend mlxnames the one option it refuses (--task,--batch-sizeor--cuda-graphs).
Changed
- One peak-VRAM estimate for
soup train's pre-flight,soup profile, the MCPprofiletool andsoup plan. They priced the same run with two formulas in two units, and neither charged the logits and loss chain that decides long, large-vocabulary runs. All four now use one estimate that reads the model'sconfig.jsonand safetensors headers (never the weights) and prices weights, adapters, gradients, optimizer state, activations, logits, the 4-bit dequantization copy and overhead, calibrated on 39 measured runs (benchmarks/gate-2049-resident-vram.md). Details under Behaviour changes (#2146 by @abdulwaarith0). - External programs are started by an absolute path found on
PATH(#2205), and on Windows the current directory is left out of the program search (#2213). Both under Behaviour changes. training.curriculum_dynamicis documented as telemetry. Its weights are logged tocurriculum_history.jsonlforsoup runs curriculum-curveand do not change which samples a batch contains; the schema descriptions, reference entries and training guide now say so. Behaviour is unchanged (#2142 by @Nari-Ab).
Tests, records and benchmarks
- A measurement record for selective attention checkpointing of streamed NF4 (Mistral-7B, one RTX 3090 on Windows, five alternating pairs per comparison). Only saving Q/K/V/O at sequence length 2048 met the pre-registered rule: 3.1% less measured time, interval 3.0% to 3.4%; the other three arms were inconclusive or slower. The installer is benchmark-only and nothing in
soup trainuses it (closes #2050; #2161 by @Shutaru). - The
stream_loss_chunk_vramharness runs each arm in a process of its own, because only the first arm per process got the RAM tier. It is step 1 of #1693's order: the rerun and the chunked-charge fix follow (#2151 by @ybai08). - The test suite passes under pytest 9.2.0, released after the cut: a Windows-path test no longer leaves
os.fstatandos.namefaked while pytest reads its capture file (closes #2286, reported by @abdulwaarith0; the test change comes from #2284 by @Nari-Ab). - A fresh-process streaming test now imports this tree's
soup_cliand has a timeout (#2208 by @ybai08); the GGUF progress test no longer fails on a machine with a real~/.soup/llama.cpp(closes #2198; #2207 by @Nari-Ab); effective vision and audio checkpointing is covered by 28 offline cases (closes the last item of #797; #2180 by @SauravMukherjee44); the atomic writers are pinned to stage their temporary file in the destination directory, with a mutation check per writer (closes #2178; #2179 by @SauravMukherjee44).
The preprint (DOI 10.5281/zenodo.21771064) is
unchanged: no number it states was re-measured or corrected, and its measurements stay scoped to
the Soup versions it names. The opt-in two-read routed experts, saving a streamed LoRA on an
untied embedding or head, and the benchmark-only selective attention checkpointing record are
outside what it measured.
Behaviour changes to know
- A script that wrote a
soup dataresult over its own input now fails.soup data dedup d.jsonl -o d.jsonl(orsample,filter,convert,merge,pii,toxicityand the rest listed above) used to exit 0 and replaced.jsonl; it now exits non-zero before reading anything. If you wanted an in-place edit, write to a new file and rename it.soup data cleanalready refused this. soup planandsoup applynow refuse whatsoup trainrefuses (#2242), with exit 1 and no state written. A pipeline that planned a config containing a staged field, a refused deprecated value or any schema error will now stop atsoup plan; delete the line the message names (runsoup doctor --config soup.yamlto see them all). With several unknown keys, every line of the message is now indented, assoup trainprints it.- Soup starts external programs by an absolute path found on
PATH(#2205).nvidia-smi,sysctl, the disk-probe tools,git,ollama, the llama.cpp binaries,trtllm-build,docker, the Modal CLI,gh,sshandscp(RunPod and Lambda controllers), the code-sandbox tools,accelerateforsoup train --gpusand thesoup adapters bisect --eval-commandprogram now run by the absolute path found in an absolutePATHdirectory. Empty and relativePATHentries (.,bin, and on Windows\binorC:bin) are not searched, and neither is the current directory. If a tool is only in the current directory or in a relativePATHentry, Soup no longer finds it: put its directory onPATHas an absolute path, or give the tool's path. Related edges: on Windows a set but emptyPATHEXTfalls back to.COM;.EXE;.BAT;.CMD;soup adapters bisectexits 2 before the first probe when its--eval-commandprogram is not onPATH(and when the checkpoint id fills in the program name, a name not onPATHcounts as a failed probe); the macOS code sandbox runssandbox-execfrom/usr/bin/sandbox-execonly; a llama.cpp checkout given as--llama-cpp .runs its binaries by absolute path;soup train --cloud lambdarefuses anoutputwith a part that starts with-, as--cloud runpodalready did; and both controllers stop before launching with "OpenSSH ssh and scp must be installed and on PATH" when they are missing. - On Windows, a program that is only in the current directory is no longer started by bare name (#2213), by
soupor by the programs it starts, eval scripts and the scripts behind a customreward_fnincluded.soupsetsNoDefaultCurrentDirectoryInExePath=1for itself when it is not set. A value you already set is kept, and any non-empty value,0included, already leaves the current directory out, so no setting brings the old search back. To run a program from the current directory, give its path (./tool.exe, or an absolute path in quotes) or put the directory onPATHas an absolute path.soup adapters bisect --eval-commandis split with POSIX shell rules, in which a backslash is an escape, so a Windows path there takes forward slashes or quotes;.\tool.exewould reach the program as.tool.exe. - The VRAM pre-flight prices runs differently (#2146). Inside the range its estimate was fitted on (dense models of 3B and below on one 6 GB card),
soup train's pre-flight now refuses some long-sequence, large-vocabulary runs and some runs without gradient checkpointing that it let through, and--allow-oom-attemptstill launches them. Outside that range (a larger model, a mixture-of-experts model,mediumorselectivecheckpointing,use_ligeroruse_cut_ce,backend: unsloth; none of these is among the 39 measured runs) a run that does not fit gets the estimate as a warning, with a footnote that it may overstate the peak, and starts, unless its weights, the CUDA context, its adapters and the gradients of the parameters it trains (plus their optimizer state for the AdamW optimizers, unless GaLore replaces the optimizer onsft,ttsorpretrain) alone are more than the card holds, which is refused there too (--allow-oom-attemptlaunches it). The shippedlongcontexttemplate (an 8B model at 131,072 tokens) is outside the range, and its header says how to turn onuse_liger.soup profile's numbers change and its JSON gains the exact bytes per term, the fit verdict, where the model's shape came from andgradient_checkpointing_tier(off,full,mediumorselective);gradient_checkpointingstays the config's own value. Reading a Hub model's shape can now reach the Hub from the pre-flight,soup profileandsoup plan(which prints a dim line before it does), and writes itsconfig.jsoninto the Hugging Face cache, unlessHF_HUB_OFFLINEorTRANSFORMERS_OFFLINEis set;soup applycompares hashes only and does not read the model; the MCPprofiletool reads only a local directory or the local cache. A Hub model with no readableconfig.jsonis priced from a shape guessed from its name.soup planrecordspeak_vram_gb: nullwith apeak_vram_reasonwhen it cannot price the run, instead of a fixed 8.0 GB; an older state file still loads.gradient_checkpointingis priced as the trainer applies it:autoresolves on the card assftdoes,selectiveis priced as no checkpointing (an upper bound), and tasks other thansftandttscheckpoint fully. Tasks without an LM head (classifier,reranker,cross_encoder,embedding,reward_model) are charged no logits. /v1/tools/pythonanswers differently on failure (#2204). A caller that treated every non-success as a timeout will now seetimed_out: falsefor ordinary failures, with the process output in the reply; a timeout still reportstimed_out: true, now withexit_code: 124and no output.
Install / Upgrade
pip install -U soup-cli # or: pipx upgrade soup-cli
soup --version # soup v0.77.1
soup doctor --config soup.yaml # before the first run of an existing config- From v0.77.0: nothing to change in a valid
soup.yaml. A Windows setup that relied on a tool in the current directory, and a script that wrote asoup dataresult over its input, need the changes described above. - From v0.76.x or older: read the v0.77.0 notes first. Python 3.10 stays on v0.76.x (
pip install "soup-cli[train]<0.77"); AWQ and GPTQ export were removed in v0.77.0. - Docker:
docker pull ghcr.io/makazhanalpamys/soup:0.77.1(alsolatest); the host driver must support CUDA 12.8.
Security
This release tightens how external programs are started. Upgrading is enough; the one visible effect on a setup is described under Behaviour changes.
Known Limitations
New in this release:
- The pre-flight's estimate was fitted on dense models of 3B and below on one 6 GB card (
benchmarks/gate-2049-resident-vram.md). No model of 7B or more, no mixture-of-experts model, nomediumorselectivetier, no fused loss and no Unsloth run was measured, so for those it warns and starts instead of refusing. A model known only by its cachedconfig.jsonis counted from that file (approximate for a mixture-of-experts one). - A distill
soup.yamlwithtraining.minillm_enabled: true,training.minillm_teacher_mix_ratio: 0and notraining.minillm_on_policyloads only undersoup train --minillm-on-policy, which sets the field before validation.soup planandsoup applyhave no such flag, so they refuse that config (minillm_enabled with minillm_on_policy=false requires minillm_teacher_mix_ratio > 0). Writetraining.minillm_on_policy: truein the YAML. soup data persona-mixstill writes over its--promptsinput when--outputnames it.mix,forge,generate,gen-magpie,recipeandcanary checkhave not been checked yet. Both are tracked in #2226.- MLX GRPO is the dense baseline:
quantization: 8bit,lora.r: 0, custom or ensemblereward_fnsettings and non-text modalities are refused at load, and--resumeis refused because only the adapter is saved (#1976). Native MLX inference covers text LoRA adapters only;soup chaton MLX is open (#1986, #2123). two_read_expertshas no hardware speed record yet; its scope is discussed in #2170.
Carried over from v0.77.0:
task: simpoon the transformers backend cuts a prompt longer thandata.max_length // 2tokens even when the whole row would fit, until #1196 lands (#1185).training.fast_lorais verified on CPU (float32 and float64 against peft) only; no speedup is claimed (#792).training.stream_loss_chunkhas not been measured on a GPU and its peak-VRAM table is still open (#1693).training.stream_recomputeis SFT only;autoworks on the RAM tier only, gains nothing on a read-bound disk tier, and at a high VRAM fill it is slower.- Kimi K2 admission is verified on CPU with a tiny K2-shaped checkpoint only; nothing has been trained on K2. Its tokenizer needs
--trust-remote-codeandpip install tiktoken. Resident K2 loads are refused at load, and Kimi-K2-Thinking and Kimi-K2-Instruct-0905 have no supported route yet (#2104). stream_expert_layout: per_expertcovers the DeepSeek-V3 family only and costs step time (about 2x to 2.7x on Moonlight-16B); a non-NVMe cache volume is warned about (#2170).- After upgrading, the first pinned layer-streamed run re-shards into a new
<slug>@<commit>cache slot; the old slot stays on disk and nothing names or removes it (#2196). - The RunPod controller has not been run against a real RunPod account yet (#2098); local input files are not uploaded.
soup export --format ggufstill clones llama.cppb5270, which cannot convert Qwen3.5; it refuses before cloning and names--llama-cpp <dir>(#1911).- Base-revision binding covers the transformers backend; Unsloth and MLX loads, and local or cached-path hints, are not bound yet (#1902).
lora.rank_pattern/alpha_patternare refused on MLX and Unsloth until those trainers apply them (MLX: #1996).freeze_layers/freeze_ratiowith LoRA need a list oflora.target_modules; a regex,all-linear,lora.target_parametersand VeRA are refused when the model is built (#2201).soup merge --low-memoryrefuses adapters it cannot reproduce exactly (DoRA,modules_to_save, rank or alpha patterns, embedding adapters) and names the regular merge instead.soup serve's/v1/tools/pythonis unavailable (501) on Windows and on Linux with Python 3.11, as/v1/tools/bashalready was.- On MLX,
task: preferencestays refused (#2202). - Still open from v0.76.0: fields that reach no consumer outside the staged table (#1814),
soup doctor --configcoverage (#1815), config-error wording (#1816) and vague messages for rows of an unknown shape (#1818). - Layer streaming remains BETA and opt-in;
--cuda-graphsremains experimental.
Fixed since v0.77.0 and no longer limits: the 22.5 GB CPU commit while a full-size Kimi K2 is set up (#2154) and the empty stderr of a failing /v1/tools/python call (#2194).
Contributors
Grouped by person, in order of merged pull requests; each line says what they found or built.
- Nariman Abdikarim (@Nari-Ab), 7: unknown-key hints that know other libraries' parameter names (#2138);
soup eval gateexits 3 on a malformed suite (#1895, reported by @taljeon); adapter commands name the missing dependency (#2141);/v1/tools/pythonfailure diagnostics andWWW-Authenticate(#2204); safe spike recovery hints (#2169); thecurriculum_dynamictelemetry contract (#2142); the GGUF progress test isolated from a developer's own converter (#2207); the Windows-path test change that keeps the suite green on pytest 9.2.0 (from #2284) - Yang Bai (@ybai08), 3: the streamed fused-expert MoE build without a CPU allocation first (#2157); the
stream_loss_chunk_vramharness with one process per arm (#2151); the fresh-process streaming test on this tree (#2208) - Nurkhan Esenbek (@kok-o), 2: save and resume of streamed LoRA on an untied embedding or head (#2159);
soup ship --progress jsonl(#2171) - Abdulwaarith Zakariyya (@abdulwaarith0), 2: the single peak-VRAM estimate and its calibration on 39 runs (#2146); the RTX 30-series laptop GPUs (#2144); the pytest 9.2.0 diagnosis and fix (#2286)
- Saurav Mukherjee (@SauravMukherjee44), 2: vision and audio checkpointing coverage (#2180); the atomic-writer destination-directory pin (#2179)
- dryn85-max (@dryn85-max), 1: native GRPO on Apple Silicon (#2182)
- AmixDigital (@Amix29), 1: native MLX inference,
soup infer --backend mlx(#2121) - Batyrkhan (@Batyrkhantzy111), 1: two reads of a streamed routed expert per step (#2158)
- Aditya Pratap Singh (@akkupratap323), 1: Langfuse zero scores kept as negative feedback (#1871)
- Shivansh Shukla (@ShivanshShukla), 1:
soup exportremoves its temporary merge directory on failure (#2164) - Shutaru (@Shutaru), 1: the selective attention checkpointing measurement for streamed NF4 (#2161)
Reports that led to fixes in this release: @taljeon (#1878), @abdulwaarith0 (#2286).
Full list
Every change, with its issue and pull request, is in
CHANGELOG.md; its [0.77.1] section lists the same changes. Compare with the previous release: v0.77.0...v0.77.1.