8 Commits
Author SHA1 Message Date
Nynxz a0629f156f docs: add example image to readme & example workflow to match 2026-05-16 01:52:59 +10:00
NynxzandClaude Opus 4.7 026c1980ad Default to uni_pc + 20 steps
Empirical finding: uni_pc is the closest match to upstream's
UniPCMultistep (same algorithm, just comfy's port), but its multistep
polynomial extrapolation works against you at high step counts when
the per-step clamp_denoised non-linearity compounds. At 38 steps it
produced bad output; at ~20 steps it works well and is noticeably
closer to the HF Space than dpmpp_2m at 38.

The earlier "uni_pc produces bad output, route around it" framing was
wrong -- the real issue was step count, not the sampler. Updated the
README to reflect that, and bumped the example workflow.

UniPC is multistep so 15-25 steps is the typical range for flow
models; pushing past 25 starts to amplify any per-step error
accumulation through the polynomial fit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 01:59:42 +10:00
NynxzandClaude Opus 4.7 2ff2af8042 Honest README + dpmpp_2m default sampler
README:
- Dropped marketing voice and bold flourishes.
- Removed the "How it works (the surgery)" paper-length section. The
  short architecture pointer at the bottom tells the user where to look
  in the code; anything more belongs in the code, not the README.
- Removed the "math verified bit-exact" framing. The unit tests verify
  the math functions in isolation, not the end-to-end output, and
  presenting it like proof of fidelity was overclaiming.
- Removed the contradictory uni_pc recommendation that conflicted with
  the dpmpp recommendation a few lines later.
- New "Known limitations" section is honest about what differs from the
  HF Space (static vs dynamic shift, sampler choice) instead of burying
  those as a tooltip.
- Documented that image editing isn't supported.

Example workflow:
- Default sampler dpmpp_2m_sde -> dpmpp_2m. The SDE variant was a guess
  based on math theory about the clamp_denoised nonlinearity; empirical
  testing says dpmpp_2m matches the HF Space output more closely.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 23:59:55 +10:00
NynxzandClaude Opus 4.7 95353e80f5 Remove image-editing example workflow + docs
AsymFLUX.2-klein is a text-to-image model -- the upstream HF card lists
it as t2i and the `image=` kwarg on `PixelFlux2KleinPipeline.__call__`
is plumbing inherited from `Flux2KleinPipeline`, not a trained-for
capability. Output quality on reference-conditioned generation never
matched the t2i output, and shipping a workflow + docs for an
unsupported path is debt.

The model-side `/s` reference-token scaling was already dropped in the
cleanup commit. This commit removes the user-facing artifacts:

- example_workflows/asymflux2_edit.json (deleted)
- README "Image editing" section (deleted)

The historical `Support image editing` commit (922550b) stays in the
log -- anyone curious about the design can still read it there.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 23:43:36 +10:00
NynxzandClaude Opus 4.7 9ff7946a45 Switch example workflows to dpmpp_2m_sde + document why not uni_pc
Practical finding: uni_pc + simple produces poor output even though it
is algorithmically the same as upstream's UniPCMultistep. Cause is the
hard nonlinearity introduced by our clamp_denoised hook: x.clamp(-1, 1)
in RGB space puts a kink in denoised(sigma), and UniPC's multistep
polynomial extrapolation requires denoised(sigma) to be smooth. SDE
samplers (dpmpp_2m_sde, dpmpp_sde) average over the kink with per-step
noise injection and produce clean output.

Both example workflows now ship sampler=dpmpp_2m_sde, scheduler=simple.
README sampler section updated with the explanation + the
clamp_denoised=False workaround if the user wants to A/B against uni_pc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 22:54:55 +10:00
NynxzandClaude Opus 4.7 15865770ec Per-step Oklab gamut clamp on x0 (upstream clamp_denoised=True)
At low sigma, AsymFlow's `u_comp = (x_t_comp + s*u_a_comp) / sigma_clamped`
amplifies the orthogonal complement by ~3x at sigma=0.32 (our smallest
non-zero step), producing x0 magnitudes well outside the [-1, 1] gamut
that affine-normalised Oklab expects. Sampler accumulates this drift
over 38 steps → washed-out / oversaturated output.

`patch_clamp_denoised` registers a post-CFG hook that:
  1. Decodes the predicted x0 from Oklab to sRGB in [-1, 1]
  2. clamps to gamut
  3. Re-encodes back to Oklab

This matches upstream `pipeline_pixelflux2_klein` `clamp_denoised`. The
hook composes with our orthogonal CFG hook -- comfy chains post-CFG
functions in registration order; orthog applies first (refines the CFG
bias), then clamp pulls the result back to gamut.

- surgery: patch_clamp_denoised(model_patcher) using oklab_math
  decode/encode at the lakonik defaults (mean=(0.56, 0, 0.01), std=0.16);
  isfinite fallback to standard denoised on any numerical issue.
- apply_adapter: new `clamp_denoised` toggle (default True).
- Both example workflows ship with the toggle on.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 22:46:55 +10:00
NynxzandClaude Opus 4.7 922550be01 Support image editing (FLUX-Kontext-style reference conditioning)
- surgery.py: in the wrapped forward, divide ref_latents by `s` (the
  AsymFlow scale_buffer, ~2.4375) before handing them to comfy's flux2
  `_forward`. This matches upstream's `condition_hidden_states / s` step
  in `_AsymFlux2Transformer2DModel.forward` — without this, reference
  tokens reach `x_embedder` at ~2.4x the magnitude the model trained
  with and editing produces jank.
- example_workflows/asymflux2_edit.json: end-to-end edit workflow using
  comfy's stock `ReferenceLatent` node. Encoded source image attaches to
  positive conditioning; KSampler.latent_image stays as empty pixel
  latent (sampling from pure noise, not img2img).
- README: editing section with the wiring diagram and the two common
  mistakes (don't pipe encoded latent into KSampler.latent_image; don't
  attach reference to the negative branch).

Comfy's flux2 `_forward` already supports ref_latents and uses
`ref_index_scale=10.0` which matches upstream's
`_prepare_condition_latent_ids(scale=10)` for position IDs — no other
wiring needed on our side.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 22:29:04 +10:00
NynxzandClaude Opus 4.7 789526f05e Initial commit: native ComfyUI v3 nodes for pixel-space AsymFLUX.2-klein
Four nodes that run the LakonLab AsymFLUX.2-klein 9B model natively in
ComfyUI on top of a stock FLUX.2-klein-base-9B loaded via Load Diffusion
Model. No diffusers, no lakonlab package required.

- AsymFLUX2 Apply Adapter: patches a FLUX.2-klein MODEL into AsymFLUX.2 via
  ModelPatcher.add_object_patch (so the base model is never mutated):
  swaps img_in / final_layer.linear / final_layer.adaLN_modulation[1] to
  the adapter's 3ch x 16x16 patch shapes, attaches proj_buffer +
  scale_buffer, wraps diffusion_model.forward with AsymFlow calibration +
  velocity (orthogonal decomposition via proj_buffer), applies the
  rank-256 LoRA, sets a flux-shift of 17 (converted to comfy's mu=log(17)
  internally), overrides latent_format to a 3-channel pass-through, and
  registers an optional orthogonal CFG post-hook bit-exact equivalent to
  upstream guidance_jit (in velocity space for numeric stability).
- AsymFLUX2 Empty Pixel Latent: 1:1 3-channel pixel latent.
- AsymFLUX2 Oklab Encode / Decode: deterministic IMAGE <-> Oklab LATENT.

Math verified bit-exact against lakonlab.models.architectures.asymflow.
common.AsymFlowMixin.asymflow_velocity and gaussian_flow.guidance_jit on
synthetic inputs. The Oklab transform is a direct port of
OklabColorEncoder; the AsymFlow velocity uses the same s, k, and
proj_buffer subspace decomposition as upstream.

See PORTING.md for the architecture diff between the FLUX.2-klein base
and the AsymFLUX.2 adapter (full overwrites of img_in / final_layer +
extra proj/scale buffers + 116 rank-256 LoRA tensors on attn.to_out, ff,
ff_context, and the timestep MLP).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 22:00:01 +10:00