What's New
Two of the most under-served axes in fine-tuning land as first-class trainers: unlearning (NPO / SimNPO / RMU — the legal-liability axis upstream TRL avoids) and knowledge editing (ROME / MEMIT / AlphaEdit — research-coded everywhere, productized nowhere). Hospital data teams handling a GDPR deletion request, labs patching factual errors without retraining, and security teams responding to a CSAM/PII leak all get a CLI workflow that composes with the existing Registry + eval-gate + diagnose surface.
Schema-only release: live trainer + kernel wiring lands in v0.61.1 (matches the established v0.50.0 / v0.52.0 / v0.53.0 stub-then-live cadence).
task='unlearn'+ NPO / SimNPO / RMU.training.unlearn_methodselects the backend;data.forget_set(rows to unlearn) +data.retain_set(capability anchors) validated at schema-load.UnlearnTrainerWrapperstub accepts forward-compat kwargs so v0.61.1 wiring is purely additive.soup eval unlearning <run-id> --benchmark tofu|muse|wmdp— three orthogonal scores on the project's OK / MINOR / MAJOR taxonomy: Forget Quality (pre/post forget-loss ramp), Model Utility (retain accuracy preserved), PrivLeak (MIA AUC distance from 0.5). Bundled TOFU mini-fixture; MUSE + WMDP loaders v0.61.1.soup edit set --base <m> --method rome|memit|alphaedit --subject "..." --target "..." [--plan-only]— surgical locate-and-edit. Per-method default MLP layer.--plan-onlyvalidates + prints the resolvedEditPlanand exits 0 today; without it the CLI surfaces the deferred-liveNotImplementedErrorat exit code 3 (distinct from validation rejection exit 2).- Sequential edit governor + norm-blowup detection. Auto-switches ROME → AlphaEdit at edit-count threshold (default 10) AND on detected Frobenius blowup. Refuses further edits past the max cap or after BLOWUP via
GovernedEditErrorso callers can distinguish governance refusals from other failures. soup edit diff <before-run> <after-run> --probes p.jsonl— knowledge-injection diff visualizer. FrozenDiffReport; probe-file loader is cwd-contained, symlink-rejected, size-capped (16 MiB / 1000 rows / 4096-char per prompt with WARNING-log truncation). Shape + table renderer ship now; live before/after generation v0.61.1.
Install / Upgrade
pip install --upgrade soup-cli
soup version # should print v0.61.0Security
- TOCTOU
lstat-before-write on every operator-supplied path via sharedpaths.atomic_write_texthelper. load_evidence_file+load_probescwd-contained +os.lstat + S_ISLNKrejection (CRITICAL: rejected BEFORErealpath, which would silently resolve symlinks — CI caught this on POSIX).- Frozen dataclasses for every report/plan surface;
EditGovernorcounters declared as real fields (slots-safe,asdict/replacecompatible). run_unlearn_evaldistinguishes "missing key → neutral OK" from "present-but-invalid → ValueError" so operator typos surface instead of silently scoring OK.registry_idvalidated BEFORE the deferred attach so a crafted null-byte / oversize id can't crash the v0.61.1 hook.- Exit-code policy:
eval unlearningexits 2 on MAJOR (CI gate);edit setexits 3 on deferred-liveNotImplementedError(distinct from exit 2 = validation rejection). importlib.resourcesfor TOFU fixture path (zipapp / namespace-package safe).- Test count: 9446 → 9571 (+125 net).
Known Limitations
- Every live wiring (NPO/SimNPO/RMU loss kernels, ROME/MEMIT/AlphaEdit closed-form updates,
UnlearnTrainerWrapper.setup) deferred to v0.61.1 — schema accepts every flag today so soup.yaml written now works the moment v0.61.1 ships. - MUSE + WMDP fixtures NOT bundled (only TOFU mini-set); operators wanting MUSE / WMDP today supply pre-computed evidence JSON via
--evidence. soup edit diffis shape-only — live model loading + before/after generation lands in v0.61.1.- Registry-attach for edited models is plan-only — v0.61.1 wires the
parent_adapterlineage write. EditGovernoris single-process (no SQLite persistence).- Norm-blowup detection depends on operator-supplied
norm_delta— v0.61.1's liveapply_editwill compute + thread it through. - Unlearn task gated to non-mlx (mlx-lm doesn't expose per-token logp scoring needed for NPO / SimNPO).
apply_editdoes not consultEditGovernorautomatically — v0.61.1 wires the optionalgovernor: EditGovernorkwarg.
Full release notes: .claude/CLAUDE.md v0.61.0 entry.
🤖 Generated with Claude Code