Releases: HowDidTheCatGetSoFat/mflux-cv
Releases · HowDidTheCatGetSoFat/mflux-cv
Release list
0.18.39-CV
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
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 4now keeps the 60img_mod_linearlayers 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
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-modelsurvives 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_matmulpast 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_PUBLISHINGrepository variable until the PyPI side is configured. The manual publish path keeps working unchanged. (#59)
0.18.36-CV
🎨 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-promptare declared conditional so the runtime warnings andmflux-capabilitiesreport 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:
atoldefaults to 2 (upstream #467/#491): the hardcodedatol=0collapsed tolerance to exact-match on near-black pixels, flagging visually identical dark references. Overridable viaMFLUX_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 shippedImageUtilhelpers, snippet executed and verified. (#54)
0.18.35-CV
🐛 Fixes
--base-model <alias>with no--modelcrashed with an error blaming the vae:from_namereturned a differently shaped config depending on which keyword named the model, handing backmodel_name=Nonethrough thebase_modelkeyword; every FLUX initializer read that None as the weights path and the failure surfaced asNo root_path and no download_url for component: vaeon 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 inAVAILABLE_MODELS. Offered upstream as #501. (#46)- ComfyUI-format LoRAs (tensors named
lora_A/lora_Bwith 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.weightpattern 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.diffdeltas) 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-capabilitieshardening 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
🎨 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--helpoverstates: 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 andparser_defaults from each CLI's livebuild_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
Pathdefault 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-promptand--guidance: the controlnet, depth, fill, redux, kontext and the three in-context CLIs all accepted--negative-promptand never read it while the dump reported it honoured, and the base and controlnet CLIs honour--guidanceon 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/mainis 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
🎨 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: onemodel_ema_bf16.pthper VAE family fromnvidia/PiDplusgoogle/gemma-2-2b-it(gated, accept the license once).--pid-degrade-sigmatrades source fidelity for invented detail, and with--pid-decodethe 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
🐛 Fixes
- FLUX.2 CLIs discarded all image metadata: both FLUX.2 CLIs called
ImageUtil.save_image(...)withoutmetadata=, so--metadatawrote a sidecar JSON containing literalnull. They now route throughGeneratedImage.save(...)like every other entry point. Cherry-pick of upstream #492, fix by @plz12345. (#36) - EXIF orientation is applied when loading images:
ImageUtil.load_imageignored 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_transposenow runs on both branches ofload_imageand strips the tag it applies, so a downstream save cannot double-rotate. Reported upstream as #495. (#37) --steps 1crashed FlowMatchEulerDiscreteScheduler: the linear spacing divides by(num_steps - 1), and guarding just that denominator moves the crash into_stretch_to_terminal.num_steps == 1now 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-promptand discards it unused, Ideogram 4 accepts the flag without a parameter for it, Z-Image Turbo overrides an explicit--guidanceto 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---guidancedefault (0.0, CFG disabled) on base Z-Image. Abbreviated long options (argparse prefix matching) are now rejected parser-wide. (#39)
0.18.31-CV
🐛 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
weightplusscales/biasesfor those layers. On reload the freshFp8Linearmodules cannot hold those tensors and the native checkpoint validation rejected the save (missingweight_scale, unexpectedscales/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 asQuantizedLinearbefore validation, and zero-size placeholders are exempt from the shape check; a fill that never happens still fails loudly in theFp8Linearforward. (#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-savenow records the baked LoRA (file names and scales) inmflux_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
🐛 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_mismatcheserror on fivedecoder.mid_block.*tensors.QwenImageRMSNorminitialized 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)