Spaces:
Running on Zero
Running on Zero
Build on CPU, move to cuda once (ZeroGPU)
Browse files
zoom.py
CHANGED
|
@@ -5,6 +5,7 @@ of them to the model: no disk round-trip between recursions, the zoom window can
|
|
| 5 |
anywhere instead of only the centre, and the loop is a generator so the UI can show each
|
| 6 |
level the moment it lands. Everything on one device, which is what ZeroGPU gives us.
|
| 7 |
"""
|
|
|
|
| 8 |
import os
|
| 9 |
import sys
|
| 10 |
|
|
@@ -60,7 +61,10 @@ def _build_vlm(lora_path):
|
|
| 60 |
model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
|
| 61 |
VLM, torch_dtype=torch.bfloat16, attn_implementation="sdpa"
|
| 62 |
)
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
| 64 |
return model.eval().to("cuda"), AutoProcessor.from_pretrained(VLM), process_vision_info
|
| 65 |
|
| 66 |
|
|
@@ -68,13 +72,10 @@ def _build_sr(coz_ckpt, merged_transformer):
|
|
| 68 |
from safetensors.torch import load_file
|
| 69 |
from osediff_sd3 import OSEDiff_SD3_TEST, SD3Euler
|
| 70 |
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
sr
|
| 75 |
-
sr.vae.to("cuda", dtype=torch.float32)
|
| 76 |
-
for m in (sr.text_enc_1, sr.text_enc_2, sr.text_enc_3, sr.transformer, sr.vae):
|
| 77 |
-
m.requires_grad_(False)
|
| 78 |
# Construct first, load second. OSEDiff_SD3_TEST swaps every targeted Linear for a
|
| 79 |
# LoraInjectedLinear, which renames the keys. Our merged checkpoint was saved after that
|
| 80 |
# swap, so loading it earlier matches nothing and silently leaves the base transformer.
|
|
@@ -86,6 +87,16 @@ def _build_sr(coz_ckpt, merged_transformer):
|
|
| 86 |
raise RuntimeError(f"merged transformer did not match: {len(unexpected)} of {len(sd)} "
|
| 87 |
f"keys unexpected. LoRA injection order or checkpoint is wrong.")
|
| 88 |
print(f"#### merged transformer loaded (missing {len(missing)} unexpected {len(unexpected)})")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
return test
|
| 90 |
|
| 91 |
|
|
|
|
| 5 |
anywhere instead of only the centre, and the loop is a generator so the UI can show each
|
| 6 |
level the moment it lands. Everything on one device, which is what ZeroGPU gives us.
|
| 7 |
"""
|
| 8 |
+
import gc
|
| 9 |
import os
|
| 10 |
import sys
|
| 11 |
|
|
|
|
| 61 |
model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
|
| 62 |
VLM, torch_dtype=torch.bfloat16, attn_implementation="sdpa"
|
| 63 |
)
|
| 64 |
+
# torch_device="cpu" is load-bearing. Left to itself peft calls infer_device(), which reads
|
| 65 |
+
# the cuda flag ZeroGPU patches to True, then hands "cuda" to safetensors. That builds
|
| 66 |
+
# tensors straight on a device that is not attached yet: RuntimeError, no CUDA GPUs.
|
| 67 |
+
model = PeftModel.from_pretrained(model, lora_path, torch_device="cpu").merge_and_unload()
|
| 68 |
return model.eval().to("cuda"), AutoProcessor.from_pretrained(VLM), process_vision_info
|
| 69 |
|
| 70 |
|
|
|
|
| 72 |
from safetensors.torch import load_file
|
| 73 |
from osediff_sd3 import OSEDiff_SD3_TEST, SD3Euler
|
| 74 |
|
| 75 |
+
# Assemble entirely on CPU, then move once. Two places here materialise weights straight
|
| 76 |
+
# onto the model's own device (inject_lora's torch.load map_location, and safetensors), and
|
| 77 |
+
# on ZeroGPU that device reads as cuda while no GPU is attached yet.
|
| 78 |
+
sr = SD3Euler(device="cpu")
|
|
|
|
|
|
|
|
|
|
| 79 |
# Construct first, load second. OSEDiff_SD3_TEST swaps every targeted Linear for a
|
| 80 |
# LoraInjectedLinear, which renames the keys. Our merged checkpoint was saved after that
|
| 81 |
# swap, so loading it earlier matches nothing and silently leaves the base transformer.
|
|
|
|
| 87 |
raise RuntimeError(f"merged transformer did not match: {len(unexpected)} of {len(sd)} "
|
| 88 |
f"keys unexpected. LoRA injection order or checkpoint is wrong.")
|
| 89 |
print(f"#### merged transformer loaded (missing {len(missing)} unexpected {len(unexpected)})")
|
| 90 |
+
del sd
|
| 91 |
+
gc.collect()
|
| 92 |
+
|
| 93 |
+
for m in (sr.text_enc_1, sr.text_enc_2, sr.text_enc_3):
|
| 94 |
+
m.to("cuda")
|
| 95 |
+
sr.transformer.to("cuda", dtype=torch.float32)
|
| 96 |
+
sr.vae.to("cuda", dtype=torch.float32)
|
| 97 |
+
for m in (sr.text_enc_1, sr.text_enc_2, sr.text_enc_3, sr.transformer, sr.vae):
|
| 98 |
+
m.requires_grad_(False)
|
| 99 |
+
sr.device = "cuda" # encode_prompt and set_timesteps read this, not the module devices
|
| 100 |
return test
|
| 101 |
|
| 102 |
|