MOSS-Image-SFT Turbo for Apple Silicon (MLX)

A fast sampler for OpenMOSS-Team/MOSS-Image-SFT on Macs. It uses 15 network passes instead of 100: about 2 minutes per ~1 MP image on an M4 Pro instead of about 12½ (6.2×). It stays close to the image the full 50-step model draws for the same seed, including its textures and lettering.

Code: moss-image-mlx (--turbo) · Write-up: how I designed and measured it · Base tiers: 8bit, compact

Wet river pebbles at actual size: the full model at 50 steps above, --turbo below, same prompt and seed

Both crops show the same image region at actual size, from the same prompt and seed. The prompt was not in the training set.

This repository holds only the trained LoRA: rank 64 on the SFT transformer (252 projections, fp32, 595 MB). The package downloads it for you.

Quickstart

pip install -U moss-image-mlx     # 0.2.0 or newer
moss-mlx "A highway LED sign at sunset that reads \"HELLO MLX\"" --turbo -o sign.png
  • First run: the package downloads the 8-bit MOSS-Image tier, this LoRA (pinned to a fixed revision) and the stripe-removal LoRA, then caches them.
  • Sizes: I trained it at ~1 MP in 9 aspect ratios, from 768×1360 through 1024×1024 to 1360×768. Set the size with --width and --height.
  • More images: --seeds 1,2,3 renders several seeds with one model load; --batch jobs.jsonl renders many prompts.
  • Ignored in turbo mode: --steps and --shift. --turbo-weights FILE uses a local copy of the LoRA.
  • Hardware: an Apple Silicon Mac. I measured everything on the 8bit tier, the default on Macs with ≥ 24 GB.

Speed

Time per image on an M4 Pro: 12 min 23 s for the full model, 1 min 59 s for --turbo

Each network pass takes as long as before; --turbo simply needs 15 instead of 100. Peak memory is 9.4 GB (9.3 GB for the full model).

Results

I compared --turbo with the full model's own image (50 steps, CFG 3, with the stripe-removal LoRA) on 32 prompts that were not in the training set, each at its own aspect ratio, seed 101:

--turbo Full model, 50 steps
Network passes 15 100
Time per ~1 MP image (M4 Pro, 8bit) ~119 s ~743 s
Average pixel difference from the full model's image (0–1 scale) 0.090 0
Repeated-texture score, relative to the full model (materials and nature prompts, n = 8) −0.006 (no extra repetition) 0
Fine detail (high-frequency energy), relative to the full model −0.004 0
Brightness, relative to the full model +0.011 0
English text read back correctly by OCR (n = 4) 94.7% 93.4%

The package's sampler reproduces the research images bit for bit. how-the-numbers-work.md defines each measure.

Four pairs, full model left and --turbo right, same seed: a beekeeper, a novel cover, a Chinese tea wrapper and a croissant

How it works

The official sampler's 100 passes vs the 15 of --turbo

  1. A small LoRA sets the composition in 5 steps without CFG. I trained it on the full model's own sampling paths for about 2,000 prompts (English and Chinese text, layouts, people, products, places, materials). When the LoRA drifted off a saved path during training, I reran the full model from where the LoRA was and trained on that result. Pulling it straight back to the saved path instead produced double exposures.
  2. The full model takes one step with CFG among those early steps (the third), where the shapes of large letters form. I tried that step at each of the 6 positions; only the third repaired both a garbled shop sign and an infographic title.
  3. The full model draws the fine detail in 4 DPM-Solver++(2M) steps, with no distilled steps.
  4. Every pass applies nynxz's stripe-removal LoRA at 1.5. I applied it to the training data too.

Training cost about $37 on rented A100s.

Why not distill every step? I took the full model's saved intermediate states and finished them with a DMD-distilled LoRA, a common way to build few-step models. The more DMD steps it took in the middle of sampling, the more it turned natural textures into repeating patterns:

Lichen on a stone wall: the full model, then the full model's saved states after 42, 35 and 14 steps finished with 2, 3 and 6 DMD steps

So this LoRA learns to follow the full model's own path for each seed, and the full model finishes the image. The technical write-up has the evidence for each decision and what failed; the research repo has the full lab notebook.

Limitations

  • Small, dense text has a few more errors than with the full model (OCR 95.7% vs 97.0% on 8 prompts).
  • Regular patterns, like a chain-link fence shadow or rows of machines, can come out irregular.
  • Compositions usually match the full model for the same seed, but not always.
  • Untested: sizes outside ~1 MP and the 9 trained aspect ratios; the compact and bf16 tiers with --turbo; the Base checkpoint (the CLI refuses --transformer in turbo mode).
  • Evidence size: each comparison uses 1–2 seeds and 7–32 prompts, and I checked the images by eye. I did not compute FID or KID at scale.

License and credits

Apache-2.0.

  • Base model: MOSS-Image SFT, © OpenMOSS, Apache-2.0.
  • Stripe-removal LoRA: by nynxz, Apache-2.0.
  • This work is independent and not affiliated with OpenMOSS.
Downloads last month

-

Downloads are not tracked for this model. How to track
MLX
Hardware compatibility
Log In to add your hardware

Quantized

Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for VisualInference/MOSS-Image-SFT-Turbo-MLX

Adapter
(32)
this model