dima0987654321 commited on
Commit
1acf164
Β·
verified Β·
1 Parent(s): 09580d9

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +13 -89
app.py CHANGED
@@ -65,18 +65,21 @@ REALISM_LORA_FILE = os.environ.get(
65
  REALISM_LORA_SCALE = float(os.environ.get("H3_REALISM_LORA_SCALE", "0.8"))
66
  REALISM_LORA_TRIGGER = "r34l1sm"
67
 
68
- # Polyhedron: Perfect Eyes / Perfect Skin / Perfect Hands. The Civitai model
69
- # has multiple versions, so the loader resolves the current version/file at
70
- # startup instead of hard-coding a version ID that may become stale.
71
- DETAIL_LORA_REPO = os.environ.get("H3_DETAIL_LORA_REPO", "civitai-model://2899220")
 
 
 
72
  DETAIL_LORA_FILE = os.environ.get(
73
  "H3_DETAIL_LORA_FILE",
74
- "polyhedron_minimax_h3_image_lora_v2__perfe8ct.safetensors",
75
  )
76
  DETAIL_LORA_SCALE = float(os.environ.get("H3_DETAIL_LORA_SCALE", "0.7"))
77
 
78
  # Spatial & Physics: object collisions, gravity, stacking, falling, occlusion, and
79
- # more consistent spatial relationships. The pruned H3 adapter does not require a trigger word.
80
  SPATIAL_LORA_REPO = os.environ.get(
81
  "H3_SPATIAL_LORA_REPO",
82
  "Jojocodex/minimax-h3-spatial-physics-lora",
@@ -87,16 +90,6 @@ SPATIAL_LORA_FILE = os.environ.get(
87
  )
88
  SPATIAL_LORA_SCALE = float(os.environ.get("H3_SPATIAL_LORA_SCALE", "0.4"))
89
 
90
- BLOWJOB_LORA_REPO = os.environ.get(
91
- "H3_BLOWJOB_LORA_REPO",
92
- "iamgroot1212/minimax-h3-loras",
93
- )
94
- BLOWJOB_LORA_FILE = os.environ.get(
95
- "H3_BLOWJOB_LORA_FILE",
96
- "MMH3-Hybrid-BlowJob-lora.safetensors",
97
- )
98
- BLOWJOB_LORA_SCALE = float(os.environ.get("H3_BLOWJOB_LORA_SCALE", "1.0"))
99
-
100
  CONDITIONER_SPACE = os.environ.get("H3_CONDITIONER", "multimodalart/qwen3vl-conditioner")
101
  # ``pack`` places the transformer at startup (66 GB on disk via the spaces pack); VAEs move on first GPU call.
102
  PLACEMENT = os.environ.get("H3_PLACEMENT", "pack").lower()
@@ -365,72 +358,10 @@ def _apply_extra_lora(
365
  from huggingface_hub import hf_hub_download
366
  from safetensors.torch import load_file
367
 
368
- if repo_id.startswith("civitai-model://"):
369
- # Resolve a Civitai model page to its newest model version, then use
370
- # the same streaming downloader as the explicit civitai://version-id
371
- # path. This keeps the Space independent of a hard-coded version ID.
372
- import requests
373
- model_id = repo_id.removeprefix("civitai-model://")
374
- api_url = f"https://civitai.com/api/v1/models/{model_id}"
375
- metadata = requests.get(api_url, timeout=30).json()
376
- versions = metadata.get("modelVersions") or []
377
- if not versions:
378
- raise ValueError(f"{label}: Civitai model {model_id} has no model versions")
379
- version = versions[0]
380
- model_version_id = str(version["id"])
381
- files = [f for f in (version.get("files") or []) if str(f.get("name", "")).lower().endswith(".safetensors")]
382
- if not files:
383
- raise ValueError(f"{label}: Civitai version {model_version_id} has no .safetensors file")
384
- # Prefer the requested filename when it exists; otherwise use the first
385
- # safetensors file exposed by the current version.
386
- selected = next((f for f in files if f.get("name") == filename), files[0])
387
- filename = os.path.basename(selected["name"])
388
- download_url = selected.get("downloadUrl") or f"https://civitai.com/api/download/models/{model_version_id}"
389
- cache_dir = os.path.join(tempfile.gettempdir(), "h3-lora-cache")
390
- os.makedirs(cache_dir, exist_ok=True)
391
- path = os.path.join(cache_dir, filename)
392
- if not os.path.isfile(path) or os.path.getsize(path) == 0:
393
- tmp_path = f"{path}.part"
394
- with requests.get(download_url, stream=True, timeout=120, allow_redirects=True) as response:
395
- response.raise_for_status()
396
- with open(tmp_path, "wb") as handle:
397
- for chunk in response.iter_content(chunk_size=8 * 1024 * 1024):
398
- if chunk:
399
- handle.write(chunk)
400
- os.replace(tmp_path, path)
401
- elif repo_id.startswith("civitai://"):
402
- import requests
403
- model_version_id = repo_id.removeprefix("civitai://")
404
- download_url = f"https://civitai.com/api/download/models/{model_version_id}"
405
- cache_dir = os.path.join(tempfile.gettempdir(), "h3-lora-cache")
406
- os.makedirs(cache_dir, exist_ok=True)
407
- path = os.path.join(cache_dir, filename)
408
- if not os.path.isfile(path) or os.path.getsize(path) == 0:
409
- tmp_path = f"{path}.part"
410
- with requests.get(download_url, stream=True, timeout=120, allow_redirects=True) as response:
411
- response.raise_for_status()
412
- with open(tmp_path, "wb") as handle:
413
- for chunk in response.iter_content(chunk_size=8 * 1024 * 1024):
414
- if chunk:
415
- handle.write(chunk)
416
- os.replace(tmp_path, path)
417
- elif repo_id == "aronzhan/H3-Loras-bucket":
418
- import requests
419
- bucket_url = f"https://huggingface.co/buckets/{repo_id}/resolve/{filename}"
420
- cache_dir = os.path.join(tempfile.gettempdir(), "h3-lora-cache")
421
- os.makedirs(cache_dir, exist_ok=True)
422
- path = os.path.join(cache_dir, filename)
423
- if not os.path.isfile(path) or os.path.getsize(path) == 0:
424
- tmp_path = f"{path}.part"
425
- with requests.get(bucket_url, stream=True, timeout=60, allow_redirects=True) as response:
426
- response.raise_for_status()
427
- with open(tmp_path, "wb") as handle:
428
- for chunk in response.iter_content(chunk_size=8 * 1024 * 1024):
429
- if chunk:
430
- handle.write(chunk)
431
- os.replace(tmp_path, path)
432
- else:
433
- path = hf_hub_download(repo_id, filename)
434
 
435
  lora = load_file(path, device="cpu")
436
 
@@ -598,13 +529,6 @@ def load_and_apply_extra_loras(transformer) -> list[str]:
598
  "Spatial & Physics LoRA",
599
  SPATIAL_LORA_SCALE,
600
  ),
601
- _apply_extra_lora(
602
- transformer,
603
- BLOWJOB_LORA_REPO,
604
- BLOWJOB_LORA_FILE,
605
- "MiniMax H3 BlowJob LoRA",
606
- BLOWJOB_LORA_SCALE,
607
- ),
608
  ]
609
 
610
  # ── Model loading ───────────────────────────────────────────────────────────
 
65
  REALISM_LORA_SCALE = float(os.environ.get("H3_REALISM_LORA_SCALE", "0.8"))
66
  REALISM_LORA_TRIGGER = "r34l1sm"
67
 
68
+ # Perfect Eyes / Skin / Hands. The original release is on Civitai, but the
69
+ # weights are mirrored in a Hugging Face repository so this Space never needs
70
+ # to contact Civitai at startup. The filename is pinned; no model-page/API lookup.
71
+ DETAIL_LORA_REPO = os.environ.get(
72
+ "H3_DETAIL_LORA_REPO",
73
+ "Alex995647/loras-minimax-h3",
74
+ )
75
  DETAIL_LORA_FILE = os.environ.get(
76
  "H3_DETAIL_LORA_FILE",
77
+ "minimax-h3-t2va-t2v-polyhedron-perfect-eyes-perfect-skin/polyhedron_minimax_h3_image_lora_v2__perfe8ct.safetensors",
78
  )
79
  DETAIL_LORA_SCALE = float(os.environ.get("H3_DETAIL_LORA_SCALE", "0.7"))
80
 
81
  # Spatial & Physics: object collisions, gravity, stacking, falling, occlusion, and
82
+ # more consistent spatial relationships. The clean pruned H3 adapter has no trigger word.
83
  SPATIAL_LORA_REPO = os.environ.get(
84
  "H3_SPATIAL_LORA_REPO",
85
  "Jojocodex/minimax-h3-spatial-physics-lora",
 
90
  )
91
  SPATIAL_LORA_SCALE = float(os.environ.get("H3_SPATIAL_LORA_SCALE", "0.4"))
92
 
 
 
 
 
 
 
 
 
 
 
93
  CONDITIONER_SPACE = os.environ.get("H3_CONDITIONER", "multimodalart/qwen3vl-conditioner")
94
  # ``pack`` places the transformer at startup (66 GB on disk via the spaces pack); VAEs move on first GPU call.
95
  PLACEMENT = os.environ.get("H3_PLACEMENT", "pack").lower()
 
358
  from huggingface_hub import hf_hub_download
359
  from safetensors.torch import load_file
360
 
361
+ # All adapters used by this Space are pinned to repository/file paths.
362
+ # There is deliberately no Civitai/API fallback here: startup must only
363
+ # resolve repository files through the Hugging Face Hub.
364
+ path = hf_hub_download(repo_id, filename)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
 
366
  lora = load_file(path, device="cpu")
367
 
 
529
  "Spatial & Physics LoRA",
530
  SPATIAL_LORA_SCALE,
531
  ),
 
 
 
 
 
 
 
532
  ]
533
 
534
  # ── Model loading ───────────────────────────────────────────────────────────