Spaces:
Running on Zero
Running on Zero
Add fal/MiniMax-H3-Realism-People-LoRA as a third LoRA set
Browse filesStyle LoRA (trigger word r34l1sm), reference-tree keys under a
diffusion_model. prefix, folded through the same mapping as larry.
Suggested 28 steps; H3_REALISM=off skips loading it.
- README.md +7 -1
- app.py +3 -3
- h3_lora.py +30 -2
README.md
CHANGED
|
@@ -55,6 +55,11 @@ and the low-rank factors stay resident so switching is an in-place unfold/fold t
|
|
| 55 |
`H3_LORA` selects the larry file (`off` skips it), `H3_LIGHTX=off` skips lightx, `H3_LORA_DEFAULT` picks which set
|
| 56 |
starts folded, and `H3_LORA_STRENGTH` scales the larry update (the card's sharpness/artifact dial).
|
| 57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
## AoTI-compiled blocks
|
| 59 |
|
| 60 |
With `H3_AOTI=1` the 50 repeated transformer blocks run from a compiled package,
|
|
@@ -181,7 +186,8 @@ one-time `PIPE.to("cuda")` is inside the first row's 339 s and does not reappear
|
|
| 181 |
| `H3_LORA_REPO` | `larryvrh/MiniMax-H3-Turbo-Lora` | Hub repo the LoRA is fetched from. |
|
| 182 |
| `H3_LORA_STRENGTH` | `1.0` | Scales the larry LoRA delta (sharpness/artifact trade-off). |
|
| 183 |
| `H3_LIGHTX` | `on` | Set to `off` to skip loading the lightx2v LoRA set. |
|
| 184 |
-
| `
|
|
|
|
| 185 |
|
| 186 |
## Whose GPU quota pays
|
| 187 |
|
|
|
|
| 55 |
`H3_LORA` selects the larry file (`off` skips it), `H3_LIGHTX=off` skips lightx, `H3_LORA_DEFAULT` picks which set
|
| 56 |
starts folded, and `H3_LORA_STRENGTH` scales the larry update (the card's sharpness/artifact dial).
|
| 57 |
|
| 58 |
+
A third, non-turbo set is [`fal/MiniMax-H3-Realism-People-LoRA`](https://huggingface.co/fal/MiniMax-H3-Realism-People-LoRA)
|
| 59 |
+
(`realism` in the dropdown, trigger word `r34l1sm`): realistic people at the full 28 steps. It ships in the same
|
| 60 |
+
reference-tree layout as larry under a `diffusion_model.` prefix, so it folds through the same key mapping.
|
| 61 |
+
`H3_REALISM=off` skips loading it.
|
| 62 |
+
|
| 63 |
## AoTI-compiled blocks
|
| 64 |
|
| 65 |
With `H3_AOTI=1` the 50 repeated transformer blocks run from a compiled package,
|
|
|
|
| 186 |
| `H3_LORA_REPO` | `larryvrh/MiniMax-H3-Turbo-Lora` | Hub repo the LoRA is fetched from. |
|
| 187 |
| `H3_LORA_STRENGTH` | `1.0` | Scales the larry LoRA delta (sharpness/artifact trade-off). |
|
| 188 |
| `H3_LIGHTX` | `on` | Set to `off` to skip loading the lightx2v LoRA set. |
|
| 189 |
+
| `H3_REALISM` | `on` | Set to `off` to skip loading the fal realism-people LoRA set. |
|
| 190 |
+
| `H3_LORA_DEFAULT` | `larry` | Which loaded LoRA set starts folded (`larry` / `lightx` / `realism`). |
|
| 191 |
|
| 192 |
## Whose GPU quota pays
|
| 193 |
|
app.py
CHANGED
|
@@ -304,8 +304,8 @@ def _fit_keyframe(image_path, current_canvas):
|
|
| 304 |
|
| 305 |
|
| 306 |
def _resolve_lora(lora, use_lora) -> str:
|
| 307 |
-
"""`lora` (`larry` / `lightx` / `off`) wins; the legacy `use_lora` bool maps onto `larry` / `off`."""
|
| 308 |
-
if isinstance(lora, str) and lora in ("larry", "lightx", "off"):
|
| 309 |
return lora
|
| 310 |
return "larry" if use_lora else "off"
|
| 311 |
|
|
@@ -423,7 +423,7 @@ def studio_config():
|
|
| 423 |
# The LoRA dropdown: value -> {label, suggested steps}.
|
| 424 |
"loras": {
|
| 425 |
**{
|
| 426 |
-
name: {"label": spec["label"], "steps": {"larry": 6, "lightx": 4}.get(name, 6)}
|
| 427 |
for name, spec in sets.items()
|
| 428 |
},
|
| 429 |
"off": {"label": "off (base model)", "steps": 28},
|
|
|
|
| 304 |
|
| 305 |
|
| 306 |
def _resolve_lora(lora, use_lora) -> str:
|
| 307 |
+
"""`lora` (`larry` / `lightx` / `realism` / `off`) wins; the legacy `use_lora` bool maps onto `larry` / `off`."""
|
| 308 |
+
if isinstance(lora, str) and lora in ("larry", "lightx", "realism", "off"):
|
| 309 |
return lora
|
| 310 |
return "larry" if use_lora else "off"
|
| 311 |
|
|
|
|
| 423 |
# The LoRA dropdown: value -> {label, suggested steps}.
|
| 424 |
"loras": {
|
| 425 |
**{
|
| 426 |
+
name: {"label": spec["label"], "steps": {"larry": 6, "lightx": 4, "realism": 28}.get(name, 6)}
|
| 427 |
for name, spec in sets.items()
|
| 428 |
},
|
| 429 |
"off": {"label": "off (base model)", "steps": 28},
|
h3_lora.py
CHANGED
|
@@ -21,8 +21,14 @@ The two supported LoRAs ship in different layouts:
|
|
| 21 |
`transformer_blocks.N.attn.to_q.lora_A.default.weight` and friends — rank 128, `alpha == 8`, so the fold scale is
|
| 22 |
`8 / 128 = 0.0625` (matching `set_adapters(weights=1.0)` in their inference script). Keys map name-for-name.
|
| 23 |
|
| 24 |
-
`
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
"""
|
| 27 |
|
| 28 |
from __future__ import annotations
|
|
@@ -37,6 +43,8 @@ LARRY_FILE = os.environ.get("H3_LORA", "minimax_h3_turbo_4step_ema_ckpt850.safet
|
|
| 37 |
LIGHTX_REPO = os.environ.get("H3_LIGHTX_REPO", "lightx2v/Minimax-h3-Turbo")
|
| 38 |
LIGHTX_FILE = os.environ.get("H3_LIGHTX_FILE", "minimax_h3_fl2v_turbo_4step_v0.1.safetensors")
|
| 39 |
LIGHTX_ALPHA = 8
|
|
|
|
|
|
|
| 40 |
# The card's sharpness/artifact dial for the larry LoRA: >1 against blurry ghosting/smear, <1 against grain.
|
| 41 |
LARRY_STRENGTH = float(os.environ.get("H3_LORA_STRENGTH", "1.0"))
|
| 42 |
DEFAULT_LORA = os.environ.get("H3_LORA_DEFAULT", "larry")
|
|
@@ -105,6 +113,24 @@ def _load_lightx() -> dict:
|
|
| 105 |
}
|
| 106 |
|
| 107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
def _apply(entries, params, sign: float) -> None:
|
| 109 |
for key, a, b in entries:
|
| 110 |
param = params.get(key)
|
|
@@ -135,6 +161,8 @@ def apply_lora(transformer) -> str | None:
|
|
| 135 |
sets["larry"] = _load_larry(inner_dim)
|
| 136 |
if os.environ.get("H3_LIGHTX", "on").lower() not in ("", "off", "none"):
|
| 137 |
sets["lightx"] = _load_lightx()
|
|
|
|
|
|
|
| 138 |
if not sets:
|
| 139 |
return None
|
| 140 |
|
|
|
|
| 21 |
`transformer_blocks.N.attn.to_q.lora_A.default.weight` and friends — rank 128, `alpha == 8`, so the fold scale is
|
| 22 |
`8 / 128 = 0.0625` (matching `set_adapters(weights=1.0)` in their inference script). Keys map name-for-name.
|
| 23 |
|
| 24 |
+
* `realism` (`fal/MiniMax-H3-Realism-People-LoRA`) is a *style* LoRA, not a turbo one — realistic people, trigger
|
| 25 |
+
word `r34l1sm`. Same reference tree as larry under a `diffusion_model.` prefix, attention only (`qkv_proj` /
|
| 26 |
+
`out_proj` on the 52 blocks), rank 16, `alpha == rank` (the card's scale 1.0), so it goes through the same
|
| 27 |
+
`_larry_targets` mapping. It wants the full step count, not 4–6.
|
| 28 |
+
|
| 29 |
+
`H3_LORA` selects the larry file (`off` skips loading it), `H3_LIGHTX=off` skips lightx, `H3_REALISM=off` skips
|
| 30 |
+
realism, `H3_LORA_DEFAULT` picks which set starts folded, and `H3_LORA_STRENGTH` is the larry card's
|
| 31 |
+
sharpness/artifact dial.
|
| 32 |
"""
|
| 33 |
|
| 34 |
from __future__ import annotations
|
|
|
|
| 43 |
LIGHTX_REPO = os.environ.get("H3_LIGHTX_REPO", "lightx2v/Minimax-h3-Turbo")
|
| 44 |
LIGHTX_FILE = os.environ.get("H3_LIGHTX_FILE", "minimax_h3_fl2v_turbo_4step_v0.1.safetensors")
|
| 45 |
LIGHTX_ALPHA = 8
|
| 46 |
+
REALISM_REPO = os.environ.get("H3_REALISM_REPO", "fal/MiniMax-H3-Realism-People-LoRA")
|
| 47 |
+
REALISM_FILE = os.environ.get("H3_REALISM_FILE", "h3-realism-people-t2v.safetensors")
|
| 48 |
# The card's sharpness/artifact dial for the larry LoRA: >1 against blurry ghosting/smear, <1 against grain.
|
| 49 |
LARRY_STRENGTH = float(os.environ.get("H3_LORA_STRENGTH", "1.0"))
|
| 50 |
DEFAULT_LORA = os.environ.get("H3_LORA_DEFAULT", "larry")
|
|
|
|
| 113 |
}
|
| 114 |
|
| 115 |
|
| 116 |
+
def _load_realism(inner_dim: int) -> dict:
|
| 117 |
+
from huggingface_hub import hf_hub_download
|
| 118 |
+
from safetensors.torch import load_file
|
| 119 |
+
|
| 120 |
+
lora = load_file(hf_hub_download(REALISM_REPO, REALISM_FILE))
|
| 121 |
+
bases = sorted({key.rsplit(".lora_", 1)[0].removeprefix("diffusion_model.") for key in lora})
|
| 122 |
+
entries = []
|
| 123 |
+
for name in bases:
|
| 124 |
+
a = lora[f"diffusion_model.{name}.lora_A.weight"]
|
| 125 |
+
b = lora[f"diffusion_model.{name}.lora_B.weight"]
|
| 126 |
+
entries.extend((key, a, b_part) for key, b_part in _larry_targets(name, b, inner_dim))
|
| 127 |
+
return {
|
| 128 |
+
"label": f"{REALISM_REPO}/{REALISM_FILE}",
|
| 129 |
+
"scale": 1.0, # alpha == rank, per the card's scale 1.0
|
| 130 |
+
"entries": entries,
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
|
| 134 |
def _apply(entries, params, sign: float) -> None:
|
| 135 |
for key, a, b in entries:
|
| 136 |
param = params.get(key)
|
|
|
|
| 161 |
sets["larry"] = _load_larry(inner_dim)
|
| 162 |
if os.environ.get("H3_LIGHTX", "on").lower() not in ("", "off", "none"):
|
| 163 |
sets["lightx"] = _load_lightx()
|
| 164 |
+
if os.environ.get("H3_REALISM", "on").lower() not in ("", "off", "none"):
|
| 165 |
+
sets["realism"] = _load_realism(inner_dim)
|
| 166 |
if not sets:
|
| 167 |
return None
|
| 168 |
|