What's New
Six surfaces close v0.57 (adapters diff / merge / blame / branch) and turn adapter management into a real version-control + collaboration workflow.
soup adapters merge --strategy cmaes --eval <suite> --budget 1h— Sakana-style evolutionary search over LoRA merge weights. Pure-Python rank-mu CMA-ES (nocmadependency). Softmaxes N-1 logits onto the simplex, samples a population, keeps elite half, plateau-detects (3 generations without improvement →converged=True). Operator-suppliedeval_fnclosure; failures swallowed with sentinel score. Budget bounds reused from v0.57blame.parse_budget(60s..24h).soup_cli.utils.vector_bank— VeRA / VB-LoRA storage format.VectorBank = {shared random projection matrix P, per-user scaling vector v_u}— thousands of per-user adapters at MB-each instead of hundreds-of-MB per LoRA. Atomic JSON I/O + cwd containment + symlink rejection + 16 MiB cap.task='moe_lora_routing'— MoLE per-token gating over N task LoRAs. NewMoleGatingConfig(num_task_adapters [2,64] / hidden_dim / temperature / top_k); cross-validator rejects mlx backend.soup adapters pr <title> --base-sha <hex> --adapter <path> --eval <json>— GitHub-shaped PR rendering. PR = {base SHA, dataset diff, adapter weights, eval-delta report} → review-friendly Markdown with eval-delta tables + per-sample baseline/candidate diffs._md_table_escapeneutralises\|\n\r\tin cells.soup lock write / show / check— Shared run lockfile. Closure of(base_model_sha, dataset_sha, env_hash)→ committed to git so teams coordinate on reproducible training runs.soup lock checkexits 3 on drift;soup_version+created_atare advisory-only. Composes with v0.64soup env lock.soup adapters bisect <ckpt1> <ckpt2> ... --eval-command "..."— Binary search over training history. Operator supplies a shell template with{ckpt}placeholder (argv-list mode viashlex.splitaftershlex.quote(ckpt)— noshell=True). Probes both endpoints first, then ~log₂(n) midpoint probes. Exit 3 on BROKEN_AT. Composes with v0.66 influence-blame.
Install / Upgrade
pip install -U soup-cli==0.67.0Security
- Atomic disk writes (
tempfile.mkstemp + os.replace) for all new I/O surfaces via sharedpaths.atomic_write_text. - POSIX symlink rejection at every write boundary (TOCTOU defence).
- Size-cap before
json.loadonload_bank(16 MiB) andread_lock(1 MiB). - Subprocess in
soup adapters bisectuses argv-list mode (noshell=True); operator-supplied{ckpt}isshlex.quote-protected. - Closed allowlists wrapped in
frozenset/MappingProxyTypefor all v0.67.0 schemas. - Rich-markup escape on user-controlled fields in every renderer.
Known Limitations
- CMA-ES live eval-suite auto-wiring deferred to v0.67.1 — the CLI prints the validated plan today; operators inject
eval_fnvia the Python API. - VeRA / VB-LoRA
apply_bank_to_servedeferred to v0.67.1 — schema + atomic JSON I/O ship now; live multi-tenant serving via v0.22.0 multi-adapter surface lands in v0.67.1. - MoLE
build_gating_kerneldeferred to v0.67.1 — schema acceptstask='moe_lora_routing'; the live torch gating module lands in v0.67.1. soup adapters bisectassumes monotonic regression — non-monotonic histories produce undefined boundaries (does not crash).adapter_pris a renderer, not a publisher — pushing to a GitHub PR / issue comment is the v0.68.0 GitHub Action deliverable.soup.lockdoes NOT auto-computeenv_hash— operators runsoup env lock(v0.64) then pass the hash tosoup lock write.- CMA-ES
_LcgRngis a small in-tree LCG (no numpy at module top). Production randomness should inject a customeval_fn. cmaes_mergeweight cap —_MAX_ADAPTERS=16mirrors v0.57.0 adapter_merge.
Tests
+185 tests across 7 new files. Total: 11021 passed, 84 skipped.
🤖 Generated with Claude Code