main
2
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1be05ad7d2 |
v1.1.0: Unify NRS on a single v-space path (EPS/V/X0) + X0 support; defaults 2/4/0.5 (#44)
## Summary
Collapses the experimental three-mode EPS switch
(`current`/`identity`/`true_v`) into a single, mathematically-correct
v-prediction-space path used by **all** variance-preserving
parameterizations — EPS, v-pred, and x0.
The sampler hook delivers `cond`/`uncond` as `x - x0` for every VP
parameterization, so NRS recovers the true velocity `v = (cond -
A)/factor` (with `A = x·σ²/(σ²+1)`, `factor = σ/√(σ²+1)`), runs its
geometry in v-space, and inverts exactly on return. This replaces the
prior EPS-only affine that operated on the wrong input space.
## Version: 1.1.0
MINOR, not a patch: this adds **X0 (sample) prediction support** — a new
backward-compatible capability — and **changes the default parameters**
(2/5/0.75 → 2/4/0.5). The node interface is unchanged (`eps_mode` never
shipped in 1.0.0), so it is **not** breaking/MAJOR. `pyproject.toml` and
`NRS/nodes_NRS.py __version__` are bumped to `1.1.0` in this PR; the
registry publish is triggered by the merge/release process, not by this
branch.
## Changes
- **`NRS/nodes_NRS.py`**: two-branch conversion — FLOW/CONST operated
natively (identity); all VP types (EPS/V/X0, UNKNOWN→VP) share one
true-v-space transform. Implements X0 (removes the
`NotImplementedError`). Removes `eps_mode` from every method and the
`nrs()` call. New defaults **skew 2 / stretch 4 / squash 0.5**.
- **`scripts/negative_rejection_steering_script.py`** (Forge/A1111):
removes the `eps_mode` test radio, process args, XYZ axis, and
extra-param; reverts `patch()` to 4 args; defaults 2/4/0.5.
- **`tests/test_pred_type.py`**: rewritten for the unified path — FLOW
is the sole native branch; EPS/V/X0/UNKNOWN all run the algebra.
- **`README.md`**: rewrites the V-Space step (now covers EPS/v-pred/x0
identically; flow-matching stays native) and updates the default to
2/4/0.5.
- **`CHANGELOG.md`**: `[1.1.0]` entry.
- **`pyproject.toml` / `NRS/nodes_NRS.py`**: version bumped 1.0.0 →
1.1.0.
## Rationale
Empirical A/B on an EPS checkpoint showed the true-v path is weakly
dominant: equal in normal ranges, burn-resistant at the failure edge,
and unlocks an on-style high-detail regime via squash (squash becomes a
detail/steering knob because the offset `A` is unscaled).
## Validation
- 39 passed / 9 skipped locally (torch tests skip; CI runs them).
Branch-coverage gate passed on push.
- ⚠️ **v-pred and x0 in v-space are math-validated but not yet
image-validated** — recommend a spot-check on a v-pred checkpoint before
merge/release.
|
||
|
|
d4ff852491 |
PR-2: pack-aware per-stream NRS routing + degeneracy tripwire (#36)
## What Fixes NRS on MiniMax H3 (and any sampler that packs multiple streams). ComfyUI hands the cfg hook a **flat packed latent** `[B,1,N]` whose `dim=1` is a singleton, so every NRS reduction runs over a size-1 axis and the projection geometry collapses — Skew becomes a silent no-op, Stretch degenerates to elementwise CFG, Squash to a Stretch-reverter (proven to float precision in Phase 0). This PR unpacks the flat pack into its real channels-first per-stream tensors, runs the **unchanged** NRS geometry per stream, then repacks. ## Changes (`NRS/nodes_NRS.py`) - Guarded `import comfy.utils as _comfy_utils` (module still imports with no ComfyUI present) + `import math`. - Module-level pure-Python `_unpack_latents`/`_pack_latents` fallbacks matching ComfyUI's pack contract (each stream reshaped to `(B,1,-1)` and concatenated on the last dim; unpack slices `prod(shape[1:])` per stream). - Extracted `_apply_guidance(...)` — the per-stream geometry pipeline (sigma reshape → `_convert_to_v_space` → dot/proj/stretch/skew/squash → `_finalize_from_v_space`), **byte-for-byte identical** to the prior inline math. - Rewired `nrs()`: read `args["model"].latent_shapes`; when present with `len>1`, unpack cond/uncond/input per stream (comfy-preferred, pure-Python fallback), map `_apply_guidance`, repack; otherwise the single-stream path is the **exact prior behavior** (regression no-op for SDXL etc.). - Permanent **degeneracy tripwire**: warns once per `patch()` if any routed stream still has a singleton reduction axis — the silent-failure class that cost the original Skew investigation days. ## Why this is safe - Single-stream models are a verified byte-for-byte no-op (two regression tests compare against a manually-computed `_apply_guidance`). - Not H3 fingerprinting: any multi-stream packed sampler (LTXV AV variants) benefits; older ComfyUI without the API falls through cleanly. - Verified against the real 18MB H3 capture (not committed): unpack→repack is bit-exact for cond/uncond/x_orig; streams recover as `[1,24,72,38,22]` (video) / `[1,32,2,405]` (audio); per-stream guidance produces large live deviations where the flat pack was near-degenerate — Skew is alive again. ## Tests New `tests/test_pack_split.py` (9 tests, real-torch via a module-scoped isolation harness that restores the mock afterward): round-trip pack/unpack, single- & multi-stream fallback regression, tripwire fires/doesn't-fire, per-stream reduced shapes, and non-degenerate-vs-degenerate rejection. - `uvx ruff check .` → All checks passed! - `uvx --with torch pytest -q` → **33 passed** (24 existing + 9 new) Breaking for H3 outputs only. Baseline preserved at tag `pre-flow`. |