mflux-lora
One-command LoRA training, sampling, and evaluation for mflux on Apple Silicon.
mflux-lora is a thin, opinionated wrapper around mflux. It prepares a dataset, writes a safe training config, calls mflux-train, extracts the adapter, and gives you a repeatable evaluation grid. It does not reimplement the diffusion models: all inference and training math comes from mflux/MLX.
Unofficial community tool. Not affiliated with the mflux maintainers.
Why
mflux exposes powerful primitives, but a first LoRA run still means hand-writing a training JSON, wiring captions, choosing LoRA targets, and finding the checkpoint afterwards. mflux-lora turns that into:
uvx mflux-lora train ./photos --trigger ohwx --preset balanced
uvx mflux-lora sample --lora lora-run/adapter.safetensors --prompt "ohwx, a portrait photo"
uvx mflux-lora eval --lora lora-run/adapter.safetensors --trigger ohwx
Install
No install needed with uvx:
uvx mflux-lora --help
Or install as a tool:
uv tool install mflux-lora
mflux-lora --help
Requirements:
- macOS on Apple Silicon
- Python 3.10+
- 32 GB unified memory minimum (48 GB recommended)
- Free disk: ~10 GB for q8 FLUX.2 4B weights, plus checkpoints
The first run downloads model weights from Hugging Face. Set HF_ENDPOINT=https://hf-mirror.com if direct access is slow, or pass --model-path to reuse a local model directory.
Quick start
# 1. Check the machine
uvx mflux-lora doctor
# 2. Train (images + optional .txt captions in ./photos)
uvx mflux-lora train ./photos \
--trigger ohwx \
--preset balanced \
--output ./lora-run
# 3. Sample
uvx mflux-lora sample \
--lora ./lora-run/adapter.safetensors \
--prompt "ohwx, a close-up portrait photo, natural light" \
--size 512x768 \
--seed 42 \
--output ./sample.png
# 4. Evaluate angles / seeds / scales
uvx mflux-lora eval \
--lora ./lora-run/adapter.safetensors \
--trigger ohwx \
--output-dir ./eval
eval writes one image per prompt × seed × scale plus eval/contact.jpg.
Use --dry-run on train or demo to inspect the plan and generated config without loading a model.
Dataset
Point train at a folder:
photos/
01.jpg
01.txt
02.png
02.txt
- Images:
.jpg,.jpeg,.png,.webp - Caption: a sibling
.txtwith the same stem - Missing captions are generated from
--caption-templateand prefixed with--trigger - The trigger is prepended to existing captions if it is not already the first word
- By default images are copied to
<output>/dataset; use--in-placeto write captions next to the source images
Recommended for identity LoRA:
| Item | Recommendation |
|---|---|
| Count | 20–60 images (80–150 for very high fidelity) |
| Angles | 25% front, 40% three-quarter, 20% profile, 15% other |
| Resolution | 768–1024 px longest side |
| Consistency | Same person, similar age/makeup; avoid heavy retouching |
| Captions | Describe angle, expression, outfit, light; keep the trigger token first |
For angle control, write captions such as:
ohwx, front view portrait, neutral expression, soft studio light, white shirt
ohwx, three-quarter view portrait, looking left, outdoor daylight, black coat
ohwx, side profile view portrait, window light, no accessories
This lets the model bind identity to ohwx instead of memorizing one pose.
Inspect a dataset without training:
uvx mflux-lora dataset validate ./photos
uvx mflux-lora dataset sheet ./photos --output ./sheet.jpg
uvx mflux-lora dataset caption ./photos --trigger ohwx
Supported models
| Key | Train on | Sample on | Weights |
|---|---|---|---|
flux2-klein-base-4b |
FLUX.2 klein base 4B | same | bf16, q8, q5, q4 |
flux2-klein-base-9b |
FLUX.2 klein base 9B | same | bf16, q8 |
z-image-turbo |
Z-Image Turbo | same | bf16, q8 |
z-image |
Z-Image base | same | bf16 |
ernie-image-turbo |
ERNIE-Image Turbo | same | bf16, q8 |
ernie-image |
ERNIE-Image base | same | bf16 |
krea-2-raw |
Krea 2 Raw | Krea 2 Turbo | bf16, q8 |
Default: flux2-klein-base-4b with q8 (≈8.6 GB download). Use --weights bf16 to download the full checkpoint and quantize at load.
uvx mflux-lora models
Presets
| Preset | Resolution | Rank | Targets | Epochs |
|---|---|---|---|---|
fast |
512 | 8 | attention | 10 |
balanced |
512 | 8 | attention | 20 |
quality |
768 | 16 | attention + MLP/FF | 20 |
max |
1024 | 32 | attention + MLP/FF | 30 |
Override any of them:
uvx mflux-lora train ./photos --preset balanced --resolution 768 --rank 16 --epochs 30
Models that do not define FF/MLP targets (Z-Image) automatically fall back to attention targets.
Memory guide
Rough peak memory with q8 weights and gradient checkpointing:
| Mac memory | Suggested |
|---|---|
| 32 GB | flux2-klein-base-4b, fast/balanced, 512 px |
| 48 GB | 4B at 768 px, 9B at 512 px |
| 64 GB+ | 9B at 768 px, Krea 2 Raw at 512 px |
Flags for tight machines:
uvx mflux-lora train ./photos \
--low-ram \
--cache-limit-gb 12 \
--resolution 512
--low-ram trades speed for memory. --cache-limit-gb bounds MLX's buffer cache and is usually enough without the full low-RAM overhead.
Commands
train
uvx mflux-lora train IMAGES [options]
Key options: --model, --preset, --trigger, --weights, --output, --resolution, --rank, --epochs, --targets, --lr, --batch-size, --grad-accum, --seed, --model-path, --low-ram, --cache-limit-gb, --save-frequency, --no-preview, --dry-run, --in-place.
The generated config is <output>/train.json. Checkpoints are <output>/train*/checkpoints/*.zip. The best/latest adapter is copied to <output>/adapter.safetensors.
sample
uvx mflux-lora sample \
--lora ./lora-run/adapter.safetensors \
--prompt "ohwx, a portrait photo" \
--scale 1.0 \
--size 512x768 \
--seed 42 \
--output ./out.png
--loraaccepts either an adapter.safetensorsor a mflux checkpoint.zip--no-bake-lorais the default; q8 baking can drop part of the update--compare-basewrites a base/LoRA side-by-side image- Use
--model-pathto reuse a local model directory
eval
uvx mflux-lora eval \
--lora ./lora-run/adapter.safetensors \
--trigger ohwx \
--seeds 42,123 \
--scales 0.8,1.0 \
--size 512x768 \
--output-dir ./eval
Without --prompts-file, it generates front / three-quarter / profile / full-body prompts. With --include-base, the contact sheet includes a base-model row for comparison.
Other commands
uvx mflux-lora dataset validate ./photos
uvx mflux-lora dataset sheet ./photos
uvx mflux-lora doctor
uvx mflux-lora models
uvx mflux-lora demo --dry-run
demo uses two bundled images and a 2-epoch run to verify the whole pipeline. It still downloads the model weights on the first real run.
How the config is built
mflux-lora writes a normal mflux training config. You can edit it or pass it directly:
mflux-train --config ./lora-run/train.json
The wrapper chooses:
- model-specific scheduler steps / guidance / timestep range
- LoRA targets for the selected model
cache_limit_gb, gradient checkpointing, preview cadence- a checkpoint every
--save-frequencysteps
If you already have a config, use mflux directly; this tool is for the common path.
Evaluation and choosing a checkpoint
Do not pick a checkpoint by training loss. Generate the same prompts and seeds for several checkpoints/scales and compare:
uvx mflux-lora eval --lora ./lora-run/train/checkpoints/0000300_checkpoint.zip --trigger ohwx --scales 0.7,1.0 --output-dir ./eval-300
uvx mflux-lora eval --lora ./lora-run/train/checkpoints/0000500_checkpoint.zip --trigger ohwx --scales 0.7,1.0 --output-dir ./eval-500
For quantitative identity checks, run an ArcFace/InsightFace embedding comparison against held-out reference photos. The package intentionally does not bundle a face-recognition model.
If a late checkpoint starts ignoring the prompt (wrong pose, collages), lower the LoRA scale or pick an earlier checkpoint. This is a known overfitting/strength failure mode, not a bug in the wrapper.
Troubleshooting
Pillow import error on Python 3.13
Pillow 13 requires Python 3.14. mflux-lora pins pillow<13; if you install mflux separately, also pin it:
uv tool install mflux --with "pillow<13"
Hugging Face downloads are slow
export HF_ENDPOINT=https://hf-mirror.com
If the mirror is unavailable, direct Hugging Face plus multiple connections is usually faster.
OOM or the machine starts swapping
- Lower
--resolution(512 → 448) - Add
--low-ram - Lower
--cache-limit-gb(18 → 12 → 8) - Close other MLX/GPU jobs
- Keep
--gradient-checkpointingon (default)
Training is much slower than expected
Check vm.swapusage. If swap is nearly full, another process or session is competing for unified memory. Stop other jobs before restarting training.
LoRA has little effect
- Include the trigger token in the prompt
- Use
--no-bake-lora(default) - Raise
--scalefrom 0.7 to 0.9/1.0 - Make sure the trigger appears first in captions
Development
git clone <this repo>
cd mflux-lora
uv sync
uv run pytest
uv run mflux-lora --help
uv build
uv publish
License
MIT. mflux is MIT-licensed; the bundled demo images come from mflux's training example assets. Model weights and generated images are subject to their own licenses and, for real people, to likeness and publicity rights.
Metadata
Release files for mflux-lora 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| mflux_lora-0.1.0.tar.gz | 2.1 MB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mflux_lora-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 4.2 MB
Release files / mflux_lora-0.1.0.tar.gz
| Download URL | mflux_lora-0.1.0.tar.gz |
|---|---|
| Size | 2.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5946f5a56c782d133384ad4767f0b4e97f3c60e23c46c784ce82b1fc66d3e18f
|
|
BLAKE2b-256 checksum How to use checksums |
2174d0b606c85d977ed565fdd57dad35a8d1c6c52b2ead3eab869cb639da89f0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / mflux_lora-0.1.0-py3-none-any.whl
| Download URL | mflux_lora-0.1.0-py3-none-any.whl |
|---|---|
| Size | 2.1 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
515835ae9775ec10493798d44e4ca010631e791715dd1b54ff76a30534da647d
|
|
BLAKE2b-256 checksum How to use checksums |
6c44a389a720f7b756e6beeb32d98f621c32e009b91c380a1b4a2ee1bea7a576
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for mflux-lora 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.