akhaliq HF Staff commited on
Commit
2b67062
·
1 Parent(s): 456aa27

Add fal/MiniMax-H3-Realism-People-LoRA as a third LoRA set

Browse files

Style 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.

Files changed (3) hide show
  1. README.md +7 -1
  2. app.py +3 -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
- | `H3_LORA_DEFAULT` | `larry` | Which loaded LoRA set starts folded (`larry` / `lightx`). |
 
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
- `H3_LORA` selects the larry file (`off` skips loading it), `H3_LIGHTX=off` skips lightx, `H3_LORA_DEFAULT` picks
25
- which set starts folded, and `H3_LORA_STRENGTH` is the larry card's sharpness/artifact dial.
 
 
 
 
 
 
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