Skip to content

Releases: HowDidTheCatGetSoFat/mflux-cv

0.18.39-CV

Choose a tag to compare

@fxd0h fxd0h released this 08 Aug 19:48

New model

  • Microsoft Lens (Turbo) (mflux-generate-lens): first MLX-native implementation of the 3.8B dual-stream MMDiT with GPT-OSS 20B multi-layer text features and the FLUX.2 VAE, requested upstream in #424. Encoder vendored from mlx-lm with no new dependency (bit-identical to the original, frozen harmony template, 97-token offset), 48-block denoiser loading the community checkpoint at full tensor coverage, ~0.1 s/step denoising at 512x512 in 4 steps. Weights resolve from the community mirrors, since the Microsoft originals were withdrawn. Turbo only for now; base Lens and seed-parity against the ComfyUI reference are the follow-ups. (#61)

Full details in the CHANGELOG.

0.18.38-CV

Choose a tag to compare

@fxd0h fxd0h released this 08 Aug 17:00

Fixes

  • Qwen-Image 4-bit no longer accumulates quantization noise across steps (upstream #484): at uniform q4, more steps made output grainier, not better (flat-field sigma 5.06 to 16.07 from 4 to 50 steps on Qwen-Image-2512). Bisection traced the whole effect to the adaLN modulation producers: -q 4 now keeps the 60 img_mod_linear layers at 8-bit (~1.8 GB extra), restoring the global-q8 noise floor exactly (sigma 1.10/1.37 at 20/50 steps vs 1.15/1.31 for full q8). Same protected-layer choice as upstream #420, so saves interoperate; qwen-edit and qwen-image-flash inherit the fix. Stored quantized models now reconstruct at the exact per-layer bits and group size inferred from the saved shapes, so mixed saves round-trip pixel-identically and uniform saves load exactly as before. (#60)

Full details in the CHANGELOG.

0.18.37-CV

Choose a tag to compare

@fxd0h fxd0h released this 07 Aug 20:07

Fixes

  • Klein edit references are encoded at their own aspect-preserved size (upstream #385): references were resized to the output dimensions, stretching them whenever aspects differed. Each reference now keeps its own size, capped near 1MP preserving aspect and snapped to multiples of 16 by center-crop, matching diffusers. All three Klein edit goldens validated, including the 9b-kv variant. (#57)
  • Flash follow-ups: --base-model survives qwen CLI resolution, and Flash through the edit CLI no longer double-applies CFG. (#56)
  • mlx floor raised to 0.32.0 on macOS (upstream #489): mlx below 0.32.0 silently corrupts quantized_matmul past 32768 input rows. Reproduced before porting: whole result garbage at 40000 rows on 0.31.0, exact on 0.32.0. (#58)

Project

  • Trusted publishing (OIDC) for PyPI releases, gated behind the PYPI_TRUSTED_PUBLISHING repository variable until the PyPI side is configured. The manual publish path keeps working unchanged. (#59)

0.18.36-CV

Choose a tag to compare

@fxd0h fxd0h released this 07 Aug 02:25

🎨 New Features

  • nvidia/Qwen-Image-Flash (--model qwen-image-flash / qwen-flash): NVIDIA's DMD2 4-step distillation of Qwen-Image, with a transformer byte-identical to Qwen-Image-2512, so the 20B Qwen goes from minutes to about 24 seconds of denoising (768x768, q8, M5 Max; peak 40.78 GB). CFG is internalized per the model card: guidance is forced to 1.0, the per-step negative transformer pass is skipped entirely (halving per-step cost), and --guidance/--negative-prompt are declared conditional so the runtime warnings and mflux-capabilities report them correctly. The static shift-3 schedule is expressed through the existing sigma schema (base shift == max shift == ln 3), producing exactly [1.0, 0.9, 0.75, 0.5, 0.0] at any resolution. The qwen CLI also now resolves --model (it previously ignored it). (#55)

🐛 Fixes

  • Golden-image comparator: atol defaults to 2 (upstream #467/#491): the hardcoded atol=0 collapsed tolerance to exact-match on near-black pixels, flagging visually identical dark references. Overridable via MFLUX_IMAGE_ALLCLOSE_ATOL, mirroring the rtol knob. (#52)
  • --no-metadata (upstream #437): opt out of embedding generation parameters (EXIF UserComment and friends) in the output image. Default unchanged; independent of --metadata, which additionally writes the JSON sidecar. (#53)
  • flux README no longer references nonexistent tools/ scripts (upstream #411): the inpaint section gives real mask guidance and the outpaint section uses the shipped ImageUtil helpers, snippet executed and verified. (#54)

0.18.35-CV

Choose a tag to compare

@fxd0h fxd0h released this 04 Aug 16:28

🐛 Fixes

  • --base-model <alias> with no --model crashed with an error blaming the vae: from_name returned a differently shaped config depending on which keyword named the model, handing back model_name=None through the base_model keyword; every FLUX initializer read that None as the weights path and the failure surfaced as No root_path and no download_url for component: vae on a fully cached repository. The alias now resolves to its own table entry, so both keywords yield the same config shape, and the loader reports a missing root path once, up front, as the whole-model condition it is (components satisfied by direct download URLs or per-component path overrides are exempt). Field-reported with the full diagnosis; regression tests cover every base alias in AVAILABLE_MODELS. Offered upstream as #501. (#46)
  • ComfyUI-format LoRAs (tensors named lora_A/lora_B with no trailing .weight) matched nothing in every family except FLUX.1: matching is exact string equality and every suffix pattern outside flux ends in .weight, so a correct adapter died with "No LoRA layers were applied". The matcher now accepts the bare spelling for every .weight pattern centrally, closing the gap in flux2, qwen, z-image, ernie, ideogram4 and krea2 at once, and the zero-match error names the key endings it saw against what the mapping expects, so a naming-format mismatch (or a file of full-weight .diff deltas) reads as what it is. Field-reported with a working patch and a fixed-seed A/B; the fix lands one level below the patch. Offered upstream as #505. (#49)
  • mflux-capabilities hardening from the late review round: a mapping default whose keys collide when stringified now raises instead of publishing an incomplete record, and the conditional/mapping regression tests pin more of the contract. (#47)

0.18.34-CV

Choose a tag to compare

@fxd0h fxd0h released this 02 Aug 13:09

🎨 New Features

  • mflux-capabilities: a machine-readable contract of what each CLI actually honours (from the #357 discussion, with the #498 evidence base). Downstream tools transcribe capability tables from --help, and --help overstates: some models read options and discard them. The dump is self-healing by construction, with no hand-maintained registry to rot: commands come from the installed console scripts, options and parser_defaults from each CLI's live build_parser() (the idiom extracted across all 27 generate CLIs), and the honoured/ignored/conditional classification is the same constant the runtime warnings read, so dump and warnings cannot disagree. Output: JSON (default), YAML when PyYAML is present, and a markdown rendering for humans and llms.txt-style docs. Offered upstream as #499. (#41)

🐛 Fixes

  • Field-reported capability fixes, from a downstream consumer who diffed the dump against their hand-maintained table (13 of 16 models agreed, and the dump caught a regression on their side): parser defaults now normalize to wire types at record-build time (a Path default truncated the streamed JSON mid-value) with the JSON serialized to a string before writing; and mapping defaults stay JSON objects rather than repr strings. (#43, #44)
  • Eight flux-family commands now tell the truth about --negative-prompt and --guidance: the controlnet, depth, fill, redux, kontext and the three in-context CLIs all accepted --negative-prompt and never read it while the dump reported it honoured, and the base and controlnet CLIs honour --guidance on dev but drop it on schnell (no guidance embedder is built). All declared, wired to runtime warnings keyed on the resolved model, and regression-pinned. (#43, #44)

🏠 Project

  • Synced with upstream: the stepwise VAE-routing fix and its 104-line regression test file, by @plz12345 (upstream #444); cv/main..upstream/main is empty again. The 0.18.28 defensive lora-paths read in the stepwise handler is now pinned by a test covering attribute-less models, the same fix offered upstream as #500 where the crash still reproduces. (#42, #45)

0.18.33-CV

Choose a tag to compare

@fxd0h fxd0h released this 01 Aug 22:45

🎨 New Features

  • NVIDIA PiD pixel-diffusion decoder (--pid-decode): replaces the VAE decode with NVIDIA's PiD, a 4x super-resolving re-render of the final latents, so a 512x512 generation decodes straight to 2048x2048. Wired on FLUX.1, FLUX.2 Klein, Qwen Image, Krea 2, ERNIE, Ideogram 4 and Z-Image (which shares Flux's latent space and uses its PiD checkpoint). Opt-in and off by default; the normal decode path is untouched. Weights download at runtime: one model_ema_bf16.pth per VAE family from nvidia/PiD plus google/gemma-2-2b-it (gated, accept the license once). --pid-degrade-sigma trades source fidelity for invented detail, and with --pid-decode the transformer is evicted the moment the denoising loop ends, which upstream measured as a straight win. From upstream #490 by @azrahello at its post-review state, with the degrade-sigma piece co-authored by @plz12345, who also verified it with real runs on five model families. Documented behaviors carried as-is: the 4x output re-draws rather than sharpens, portrait skin can over-texture, and flux2-checkpoint families show a small green drift with an upstream correction promised as follow-up. One deliberate divergence: the sampler threads explicit RNG keys instead of reseeding the global stream, so multi-seed runs stay reproducible with and without --pid-decode. (#40)

0.18.32-CV

Choose a tag to compare

@fxd0h fxd0h released this 01 Aug 21:35

🐛 Fixes

  • FLUX.2 CLIs discarded all image metadata: both FLUX.2 CLIs called ImageUtil.save_image(...) without metadata=, so --metadata wrote a sidecar JSON containing literal null. They now route through GeneratedImage.save(...) like every other entry point. Cherry-pick of upstream #492, fix by @plz12345. (#36)
  • EXIF orientation is applied when loading images: ImageUtil.load_image ignored the EXIF Orientation tag, so most photos straight off a phone reached the model sideways. The model is conditioned on the rotated pixels, so edit variants produced wrong output rather than correctly-oriented output that needs a flip. exif_transpose now runs on both branches of load_image and strips the tag it applies, so a downstream save cannot double-rotate. Reported upstream as #495. (#37)
  • --steps 1 crashed FlowMatchEulerDiscreteScheduler: the linear spacing divides by (num_steps - 1), and guarding just that denominator moves the crash into _stretch_to_terminal. num_steps == 1 now returns the 1-step schedule the class's sibling paths already define, sigmas [1.0, 0.0]; every other step count is byte-identical, pinned by regression tests. Affected FLUX.2 Klein, FIBO, and Z-Image with guidance active. Reported upstream as #494. (#38)

✨ Improvements

  • CLIs warn when an option the model cannot honour is dropped: FLUX.1 reads --negative-prompt and discards it unused, Ideogram 4 accepts the flag without a parameter for it, Z-Image Turbo overrides an explicit --guidance to 0.0 and never encodes the negative, and Boogu accepts both and passes neither. The options stay accepted so existing scripts keep working; the drop is just no longer silent. Warnings key on the effective post-resolution behavior, including the omitted---guidance default (0.0, CFG disabled) on base Z-Image. Abbreviated long options (argparse prefix matching) are now rejected parser-wide. (#39)

0.18.31-CV

Choose a tag to compare

@fxd0h fxd0h released this 31 Jul 08:54

🐛 Fixes

  • Ideogram 4 models saved with a LoRA could not be loaded back: baking a LoRA over the fp8 base folds the adapted layers to MLX q8, so the checkpoint stores a packed weight plus scales/biases for those layers. On reload the fresh Fp8Linear modules cannot hold those tensors and the native checkpoint validation rejected the save (missing weight_scale, unexpected scales/biases). The large fp8 layers also defer allocation until the weight update fills them, and the validator read those empty placeholders as shape mismatches. Folded layers are now rebuilt as QuantizedLinear before validation, and zero-size placeholders are exempt from the shape check; a fill that never happens still fails loudly in the Fp8Linear forward. (#35)
  • A reloaded Ideogram save generated with the wrong CFG negative: baking strips the LoRA wrappers, so nothing marked the checkpoint as a LoRA model and the empty prompt ran through the clean unconditional transformer. Full guidance then amplifies the baked LoRA delta: the subject holds but the prompt scene washes out. mflux-save now records the baked LoRA (file names and scales) in mflux_model_config.json, and the loader keeps the negative routed through the conditional transformer when the marker is present. A save/reload round-trip now reproduces the live-LoRA generation pixel-identically. Saves made before this release carry no marker, so re-save them to pick up the routing. (#35)

0.18.30-CV

Choose a tag to compare

@fxd0h fxd0h released this 30 Jul 06:18

🐛 Fixes

  • Qwen VAE saved models could not be loaded back: any natively saved Qwen-VAE model (Qwen Image, Qwen Image Edit, Qwen-Image-Layered, and Krea 2 Turbo, Raw and Depth) failed to load with a shape_mismatches error on five decoder.mid_block.* tensors. QwenImageRMSNorm initialized its gamma with spatial trailing dimensions while the checkpoints store it one-dimensional, a mismatch dating back to upstream #269. The native checkpoint integrity validation added with Mage Flow (#483) turned that latent difference into a hard load failure. Gamma is now initialized in the checkpoint's own shape; the forward path already reshaped either form, and output is bit-identical on both the 4D image and 5D video paths. (fix by @fortinmike)