Files
CthomasdesignandClaude Opus 4.8 c9f8f0ace1 docs: README overhaul (architecture, editing guide, env vars, tools)
Architecture overview (the MLX island), editing guide (grounding_px
semantics, aspect-ratio rule, two-ref order and caveats, Turbo vs
Raw-removals limitation), example-workflow index, environment-variable
reference, tools/harness section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 17:16:08 -04:00

155 lines
8.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ComfyUI-Krea2-MLX
Run **Krea-2-Turbo** locally on **Apple Silicon** inside ComfyUI, using Apple's **MLX**
framework — text-to-image, img2img, and **identity-preserving image editing** with dual
conditioning (in-context reference frames + Qwen3-VL vision grounding). Quantized to fit a
32 GB Mac; supports **stackable LoRAs** (official Krea / diffusers *and* ai-toolkit / PEFT
formats, including the `krea2_edit` identity LoRA).
> **macOS on Apple Silicon (M-series) only.** The MLX dependencies do not run on Windows/Linux.
> ~24 GB unified memory recommended for 1024²; editing with grounding wants ~32 GB.
## Architecture
The pure-MLX pipeline (`krea2_engine/`) is vendored directly in this repo — no external git
dependency — and runs **in-process**, returning standard ComfyUI `IMAGE` tensors:
```
Krea2 Model Loader ──KREA2_PIPE──┬── Krea2 Generate ──┐
Krea2 LoRA ──KREA2_LORASTACK─────┼── Krea2 Img2Img ───┼──IMAGE──► any ComfyUI node
LoadImage ──IMAGE────────────────┴── Krea2 Edit ──────┘ (save, upscale, …)
```
Inside the pipe, everything is MLX on Metal: the Qwen3-VL-4B text encoder (with its vision
tower for grounded editing), the 12.9B Krea-2 MMDiT transformer, the flow-matching sampler,
and the Qwen-Image VAE. **No PyTorch in the generation path.** It's a self-contained island:
it does not expose a torch `MODEL`, so it does not plug into ComfyUI's native
KSampler/ControlNet — by design.
## Install
**Via ComfyUI-Manager** (recommended): search for *Krea2-MLX* and install; Manager runs
`requirements.txt`, which installs the vendored pipeline's MLX deps into ComfyUI's Python.
**Manual:**
```bash
cd ComfyUI/custom_nodes
git clone https://github.com/cthomasdesign/ComfyUI-Krea2-MLX
<ComfyUI-python> -m pip install -r ComfyUI-Krea2-MLX/requirements.txt
```
Restart ComfyUI.
## Models
Put a transformer build in **`ComfyUI/models/krea2/`** — the **Krea2 Model Loader** lists what's
there and infers precision from the filename (`mixed_4_8` / `8bit` / `bf16`):
| Build | Size | Repo → file |
|---|---|---|
| mixed-4/8 | 9.8 GB | [avlp12/Krea-2-Turbo-Alis-MLX-mixed-4-8](https://huggingface.co/avlp12/Krea-2-Turbo-Alis-MLX-mixed-4-8) → `transformer_mixed_4_8.safetensors` |
| 8-bit | 14 GB | [avlp12/Krea-2-Turbo-Alis-MLX-8bit](https://huggingface.co/avlp12/Krea-2-Turbo-Alis-MLX-8bit) → `transformer_8bit.safetensors` |
On first generation the **VAE + Qwen3-VL-4B text encoder** (~9 GB) download automatically from
`krea/Krea-2-Turbo` (cached in `~/.cache/krea2_alis_mlx`). Put **LoRAs** in `ComfyUI/models/loras/`
— e.g. [conradlocke/krea2-identity-edit](https://huggingface.co/conradlocke/krea2-identity-edit)
for editing.
## Nodes (category **Krea2 MLX**)
| Node | Purpose |
|---|---|
| **Krea2 Model Loader (MLX)** | Pick a build from `models/krea2` → `KREA2_PIPE` (cached; stays resident). |
| **Krea2 LoRA (MLX)** | Pick a LoRA from `models/loras` + strength → `KREA2_LORASTACK`. Chain several to stack. |
| **Krea2 Generate (MLX)** | Text→image. Prompt/size/steps/seed (+ LoRA stack) → `IMAGE`. Progress bar + Cancel supported; NSFW `safety_filter` on by default. |
| **Krea2 Img2Img (MLX)** | Source image + prompt + `denoise` → `IMAGE`. Reinterprets the **whole frame**: `denoise` 0→1 goes from near-copy to full reinterpretation (`1.0` == plain text→image). |
| **Krea2 Edit (MLX)** | Source image + instruction (+ optional 2nd reference, + `grounding_px`) → `IMAGE`. **Identity-preserving edit**: the source rides as a clean reference frame while a fresh target is generated. |
| **Krea2 Unload (MLX)** | Frees the cached model and clears the Metal cache to reclaim memory. |
Ready-made graphs in [`example_workflows/`](example_workflows/): text-to-image
(`Krea2-MLX-example.json`), img2img (`Krea2-MLX-img2img.json`), identity edit with the LoRA
chained in (`Krea2-MLX-edit.json`).
## Editing guide (Krea2 Edit)
The edit node implements the **dual conditioning** the
[krea2_edit identity LoRA](https://huggingface.co/conradlocke/krea2-identity-edit) was trained
with: the source enters (1) as clean VAE reference tokens the transformer attends to while
generating, and (2) through the Qwen3-VL **vision tower**, so the instruction is read *while
looking at the image*. Stack the identity LoRA at **strength 1.0** for best results.
- **Match the output aspect ratio to the source** — training pairs are same-size; mismatches
degrade preservation.
- **`grounding_px`** (default 768): lower = stronger edit adherence and more uniform scene
changes; higher = stronger identity/likeness. `0` = plain-text conditioning (no vision tower).
- **Two references** (`image_b`): training order is **scene first, subject second**. Two-person
inputs tend to drift faces toward each other — for best identity, **chain single-reference
edits** instead.
- **What works on Turbo** (this island): add, recolor, restyle, re-stage — at 8 steps, no CFG.
**Large removals/deletions** were tuned for Krea-2-**Raw** at 20 steps with CFG, which this
Turbo-only island doesn't run; expect them to be weaker.
- Img2Img vs Edit: img2img *reinterprets everything* (style transfers, variations); Edit
*preserves the subject and applies the instruction* (targeted changes).
## Performance
The vendored engine is heavily optimized for Apple Silicon — measured on an M1 Max 32 GB
(mixed-4/8 build, 8 steps):
| | before (v0.3) | after (v0.4+) | faster |
|---|---|---|---|
| 512², short prompt | ~103s | **~67s** | ~35% |
| 512², long prompt | ~104s | **~72s** | ~31% |
| 1024² | ~310s | **~263s** | ~15% |
Repeat generations with the same prompt (seed sweeps) additionally skip the text encoder via a
per-prompt embedding cache. What changed: native grouped-query attention; step-invariant
conditioning hoisted out of the denoising loop; padded text tokens trimmed before the DiT (~30%
of the sequence at 512²); dynamic-length text encoding; prompt-embedding cache. All validated
mathematically faithful to the reference computation (see `tools/`).
**Seed reproducibility:** the sequence-length optimizations alter bf16 kernel rounding order, so
a fixed seed renders an *equal-quality but not pixel-identical* image vs v0.3 — the same class
of change as an MLX or hardware upgrade. Within a version, generation is fully deterministic
(same seed → same image, bit-for-bit).
## Environment variables
| Variable | Effect |
|---|---|
| `KREA2_EXACT_LEGACY=1` | Bit-exact pre-0.4 outputs: restores padded encoding/attention, bypasses the prompt cache (slower). For reproducing old seeds. |
| `KREA2_BASE_DIR` | Local `krea/Krea-2-Turbo` snapshot (skips the first-run download). |
| `KREA2_DISABLE_SAFETY=1` | Globally disables the NSFW filter (the license requires filtering in deployments — see Notes). |
| `KREA2_SAFETY_THRESHOLD` | NSFW flag threshold (default 0.85). |
## Development: bench & parity harness (`tools/`)
`tools/bench.py` attributes generation time to encode / per-step / decode stages;
`tools/parity.py` snapshots reference outputs and asserts later runs stay pixel-identical — the
quality gate every engine change passes through. `tools/test_*.py` validate each feature
(img2img guard, edit forward, vision tower vs the PyTorch reference, grounded encode, two-ref
grounding).
## Notes
- One 12.9B model (~18–20 GB with encoder/VAE; +~2.7 GB with the vision tower and identity LoRA)
stays resident. On 32 GB, avoid loading large torch models simultaneously; use **Krea2 Unload**
to free memory.
- The `safety_filter` runs the pure-MLX `Falconsai/nsfw_image_detection` classifier; the Krea 2
Community License (§4.2) requires reasonable content-filtering in deployments — keep it on there.
- Where required by law, disclose that outputs are AI-generated (License §4.3).
## License & attribution
Independent, unofficial — **not** an official Krea product or endorsed by Krea. The model is a
Derivative of [`krea/Krea-2-Turbo`](https://huggingface.co/krea/Krea-2-Turbo) under the **Krea 2
Community License** (see [`LICENSE`](LICENSE)); the MLX port is by **avlp12**
([Alis MLX](https://github.com/avlp12/krea2_alis_mlx)), with LoRA support added in
[krea2-mlx-studio](https://github.com/Cthomasdesign/krea2-mlx-studio). The engine (`krea2_engine/`)
is vendored here from that lineage; the Qwen3-VL vision tower is vendored from
[mlx-vlm](https://github.com/Blaizzy/mlx-vlm) (MIT) — see [`NOTICE`](NOTICE) for the full
attribution chain and what changed at each step. Model weights are downloaded by the user, not
redistributed here. Node/engine code here: MIT (per upstream). NSFW classifier:
[Falconsai/nsfw_image_detection](https://huggingface.co/Falconsai/nsfw_image_detection)
(Apache-2.0). By using the weights you agree to the Krea 2 Community License (commercial use
requires < $1M annual revenue, or an enterprise license).