xocialize/qwen-image-edit-swift

Swift/MLX port of Qwen-Image-Edit-2511 (imageEdit) + MLXEngine MLXQwenImageEdit package — instruction-driven image editing (contract 1.2.0).

1

stars

54

commits

Swift

primary language

Jul 25, 2026

updated

README

qwen-image-edit-swift

A Swift/MLX port of Qwen/Qwen-Image-Edit-2511 plus its MLXEngine imageEdit packages — instruction-driven image editing (contract 1.3.0's first imageEdit backer): identity-preserving edits, multi-image fusion, and content+style style transfer (TeleStyleV2).

  • QwenImageEdit — the standalone inference port: Qwen2.5-VL-7B prompt+image conditioning (via qwen25vl-mlx-swift) → 20B 60-layer zero_cond_t double-stream DiT (Lens block family) → Wan 3D causal VAE. Reference = diffusers QwenImageEditPlusPipeline (the VL encoder runs plain sequential 1D RoPE, not the mRoPE grid — diffusers omits mm_token_type_ids so HF falls back; proven by true-SDPA-input capture). generate(images:) does N-image conditioning (per-image VAE cond latents + grids); image 0 is the content, later images are extra references ("Picture 1/2/…").

  • MLXQwenImageEdit — the thin MLXEngine wrapper (QwenImageEditPackage, PackageID qwen-image-edit): the canonical IEditRequest/IEditResponse surface, multi-image, license declaration, requirements manifest, and PNG artifact encoding.

  • MLXQwenImageFlashnvidia/Qwen-Image-Flash text-to-image (QwenImageFlashPackage, PackageID qwen-image-flash): NVIDIA's DMD2 4-step distill of Qwen-Image on the same core's T2I path (QwenImageT2IGenerator). The distilled checkpoint is a pure weight delta — the transformer key set is identical to 2511's (1933 tensors) and the text encoder / tokenizer / VAE files are byte-identical (sha256-verified) — so the port is the T2I pipeline delta only: text-only prompt encoding (template drop_idx 34, not 64), no conditioning latents, and the packaged static shift-3 schedule (use_dynamic_shifting: false) giving sigmas [1.0, 0.9, 0.75, 0.5, 0.0]. Guidance was internalized by the distillation, so it runs true CFG 1.0 — one DiT forward per step. Two tiers, both pre-quantized so consumers never materialize bf16: -bf16 (quality reference, 41.4 GB resident / 57.4 GB peak, 83.3 s) and -8bit (near-lossless — DiT cos 0.9973, encoder 0.99992 — 22.3 GB resident / 30.0 GB peak, 19.8 s). The package is BudgetAware: when the governor cannot seat bf16 it selects int8 before materializing, so a constrained machine downloads 28 GB rather than 41 GB it could never load. No 4-bit tier — int4 measured DiT cos 0.9623 (0.9659 at group 32) and rendered visibly soft/washed out; the sweep is preserved in FlashQuantSweepTests. Weights: NVIDIA Open Model License (commercially permissive; redistributing them requires shipping the Agreement + the "Licensed by NVIDIA Corporation under the NVIDIA Open Model License" notice) with Apache-2.0 as additional information.

  • MLXTeleStyleTeleStyleV2 content-preserving style transfer (TeleStylePackage, PackageID telestyle-v2): the imageEdit surface with a styleTransfer mode (image 0 = content, image 1 = style). Same QwenImageEdit core over a pre-fused snapshot (style + Lightning-4step DMD LoRAs merged at scale 1.0); 4-step DMD defaults. Weights: mlx-community/TeleStyleV2-Qwen-Image-Edit-2511-bf16.

Parity

Validated against PyTorch fp32 goldens: DiT step-0 pos 0.99986 / neg 0.99944 bf16 (neg 0.999989 fp32-CPU) · VAE decode 73.7 dB · VAE encode 0.9999999 · VL encoder 0.974 bf16 / 0.9977 fp32-CPU. In-app eye-verified: a lighthouse photo edited "dusk + stormy → day + clear", identity-preserving.

Use

import MLXQwenImageEdit
import MLXToolKit

let package = QwenImageEditPackage(configuration: .init(
    snapshotPath: "<root>/Qwen-Image-Edit-2511"))   // transformer/ vae/ text_encoder/ processor/
try await package.load()
let response = try await package.run(IEditRequest(
    images: [inputImage],                            // schema is multi-image-first; core takes 1 for now
    prompt: "make it night with neon reflections",
    seed: 42)) as! IEditResponse                     // steps/true-CFG default to 20 / 4.0
// response.image: canonical Image (.png)

Behavior notes: the schema is multi-image-first (images[], in prompt order — "Picture 1", "Picture 2", …), but the core pipeline currently consumes a single conditioning image; multi-image fusion (per-image VAE sizes + grids) is the tracked follow-up. guidanceScale is the true-CFG scale.

Status / consuming this package

The MLX-converted weights are not yet on the Hub (the PyTorch source Qwen/Qwen-Image-Edit-2511 is; this wrapper needs MLX weights and reads a local snapshot — it does not download) — load from a local Qwen-Image-Edit-2511 snapshot. The package depends on qwen25vl-mlx-swift (VL conditioning) and mlx-engine-swift (the MLXToolKit contract) via tagged-URL net dependencies (.package(url: "https://github.com/xocialize/qwen25vl-mlx-swift", from: "0.1.0") and .package(url: "https://github.com/xocialize/mlx-engine-swift", from: "0.32.0") — the floor is 0.32.0 for contract 1.24 WeightSourcing + the allowlisted SPDXLicense.nvidiaOpenModel, both used by MLXQwenImageFlash), so it builds standalone. ~60 GB resident bf16 (20B DiT + VL-7B + fp32 VAE); 4-bit DiT+VL (~16 GB) is a tracked follow-up.

MLXQwenImageFlash is the exception to the "no Hub weights" note above: it materializes from the Qwen-Image-Flash (MLX) collection with no local snapshot required. Measured split footprints (1024², 4 steps): bf16 41.4 GB resident / 19.3 GB activation; int8 22.3 / 9.3 GB.

MIT (port code) · weights per model: Apache-2.0 (Qwen-Image-Edit-2511, TeleStyleV2), NVIDIA Open Model License (Qwen-Image-Flash).

Contributors

xocialize

54 commits

xocialize/qwen-image-edit-swift

Swift/MLX port of Qwen-Image-Edit-2511 (imageEdit) + MLXEngine MLXQwenImageEdit package — instruction-driven image editing (contract 1.2.0).

1

stars

54

commits

Swift

primary language

Jul 25, 2026

updated

README

qwen-image-edit-swift

A Swift/MLX port of Qwen/Qwen-Image-Edit-2511 plus its MLXEngine imageEdit packages — instruction-driven image editing (contract 1.3.0's first imageEdit backer): identity-preserving edits, multi-image fusion, and content+style style transfer (TeleStyleV2).

  • QwenImageEdit — the standalone inference port: Qwen2.5-VL-7B prompt+image conditioning (via qwen25vl-mlx-swift) → 20B 60-layer zero_cond_t double-stream DiT (Lens block family) → Wan 3D causal VAE. Reference = diffusers QwenImageEditPlusPipeline (the VL encoder runs plain sequential 1D RoPE, not the mRoPE grid — diffusers omits mm_token_type_ids so HF falls back; proven by true-SDPA-input capture). generate(images:) does N-image conditioning (per-image VAE cond latents + grids); image 0 is the content, later images are extra references ("Picture 1/2/…").

  • MLXQwenImageEdit — the thin MLXEngine wrapper (QwenImageEditPackage, PackageID qwen-image-edit): the canonical IEditRequest/IEditResponse surface, multi-image, license declaration, requirements manifest, and PNG artifact encoding.

  • MLXQwenImageFlashnvidia/Qwen-Image-Flash text-to-image (QwenImageFlashPackage, PackageID qwen-image-flash): NVIDIA's DMD2 4-step distill of Qwen-Image on the same core's T2I path (QwenImageT2IGenerator). The distilled checkpoint is a pure weight delta — the transformer key set is identical to 2511's (1933 tensors) and the text encoder / tokenizer / VAE files are byte-identical (sha256-verified) — so the port is the T2I pipeline delta only: text-only prompt encoding (template drop_idx 34, not 64), no conditioning latents, and the packaged static shift-3 schedule (use_dynamic_shifting: false) giving sigmas [1.0, 0.9, 0.75, 0.5, 0.0]. Guidance was internalized by the distillation, so it runs true CFG 1.0 — one DiT forward per step. Two tiers, both pre-quantized so consumers never materialize bf16: -bf16 (quality reference, 41.4 GB resident / 57.4 GB peak, 83.3 s) and -8bit (near-lossless — DiT cos 0.9973, encoder 0.99992 — 22.3 GB resident / 30.0 GB peak, 19.8 s). The package is BudgetAware: when the governor cannot seat bf16 it selects int8 before materializing, so a constrained machine downloads 28 GB rather than 41 GB it could never load. No 4-bit tier — int4 measured DiT cos 0.9623 (0.9659 at group 32) and rendered visibly soft/washed out; the sweep is preserved in FlashQuantSweepTests. Weights: NVIDIA Open Model License (commercially permissive; redistributing them requires shipping the Agreement + the "Licensed by NVIDIA Corporation under the NVIDIA Open Model License" notice) with Apache-2.0 as additional information.

  • MLXTeleStyleTeleStyleV2 content-preserving style transfer (TeleStylePackage, PackageID telestyle-v2): the imageEdit surface with a styleTransfer mode (image 0 = content, image 1 = style). Same QwenImageEdit core over a pre-fused snapshot (style + Lightning-4step DMD LoRAs merged at scale 1.0); 4-step DMD defaults. Weights: mlx-community/TeleStyleV2-Qwen-Image-Edit-2511-bf16.

Parity

Validated against PyTorch fp32 goldens: DiT step-0 pos 0.99986 / neg 0.99944 bf16 (neg 0.999989 fp32-CPU) · VAE decode 73.7 dB · VAE encode 0.9999999 · VL encoder 0.974 bf16 / 0.9977 fp32-CPU. In-app eye-verified: a lighthouse photo edited "dusk + stormy → day + clear", identity-preserving.

Use

import MLXQwenImageEdit
import MLXToolKit

let package = QwenImageEditPackage(configuration: .init(
    snapshotPath: "<root>/Qwen-Image-Edit-2511"))   // transformer/ vae/ text_encoder/ processor/
try await package.load()
let response = try await package.run(IEditRequest(
    images: [inputImage],                            // schema is multi-image-first; core takes 1 for now
    prompt: "make it night with neon reflections",
    seed: 42)) as! IEditResponse                     // steps/true-CFG default to 20 / 4.0
// response.image: canonical Image (.png)

Behavior notes: the schema is multi-image-first (images[], in prompt order — "Picture 1", "Picture 2", …), but the core pipeline currently consumes a single conditioning image; multi-image fusion (per-image VAE sizes + grids) is the tracked follow-up. guidanceScale is the true-CFG scale.

Status / consuming this package

The MLX-converted weights are not yet on the Hub (the PyTorch source Qwen/Qwen-Image-Edit-2511 is; this wrapper needs MLX weights and reads a local snapshot — it does not download) — load from a local Qwen-Image-Edit-2511 snapshot. The package depends on qwen25vl-mlx-swift (VL conditioning) and mlx-engine-swift (the MLXToolKit contract) via tagged-URL net dependencies (.package(url: "https://github.com/xocialize/qwen25vl-mlx-swift", from: "0.1.0") and .package(url: "https://github.com/xocialize/mlx-engine-swift", from: "0.32.0") — the floor is 0.32.0 for contract 1.24 WeightSourcing + the allowlisted SPDXLicense.nvidiaOpenModel, both used by MLXQwenImageFlash), so it builds standalone. ~60 GB resident bf16 (20B DiT + VL-7B + fp32 VAE); 4-bit DiT+VL (~16 GB) is a tracked follow-up.

MLXQwenImageFlash is the exception to the "no Hub weights" note above: it materializes from the Qwen-Image-Flash (MLX) collection with no local snapshot required. Measured split footprints (1024², 4 steps): bf16 41.4 GB resident / 19.3 GB activation; int8 22.3 / 9.3 GB.

MIT (port code) · weights per model: Apache-2.0 (Qwen-Image-Edit-2511, TeleStyleV2), NVIDIA Open Model License (Qwen-Image-Flash).

Contributors

xocialize

54 commits

Languages

Swift

100.0%