Spaces:
Running on Zero
Running on Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -75,6 +75,7 @@ import sys
|
|
| 75 |
import time
|
| 76 |
import threading
|
| 77 |
import traceback
|
|
|
|
| 78 |
|
| 79 |
import torch
|
| 80 |
|
|
@@ -132,6 +133,8 @@ try:
|
|
| 132 |
except Exception:
|
| 133 |
pass
|
| 134 |
|
|
|
|
|
|
|
| 135 |
import gradio as gr
|
| 136 |
|
| 137 |
# ---------------------------------------------------------------------------
|
|
@@ -191,6 +194,7 @@ def _runtime_report():
|
|
| 191 |
"cuda_available": bool(torch.cuda.is_available()),
|
| 192 |
"cuda_device_count": int(torch.cuda.device_count()) if torch.cuda.is_available() else 0,
|
| 193 |
"has_spaces": HAS_SPACES,
|
|
|
|
| 194 |
"torch_compile_bypassed": torch.compile is _asf_zerogpu_compile_bypass,
|
| 195 |
"hf_home": os.environ.get("HF_HOME", ""),
|
| 196 |
"hf_modules_cache": os.environ.get("HF_MODULES_CACHE", ""),
|
|
@@ -204,6 +208,7 @@ def _lora_report():
|
|
| 204 |
"active_strength": _active_lora_strength,
|
| 205 |
"loaded_loras": sorted(list(_loaded_loras)),
|
| 206 |
"available_loras": list(KNOWN_LORAS.keys()),
|
|
|
|
| 207 |
}
|
| 208 |
|
| 209 |
|
|
@@ -356,6 +361,12 @@ def _load_lora_if_needed(pipe, lora_label):
|
|
| 356 |
if not cfg:
|
| 357 |
return None
|
| 358 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 359 |
adapter_name = cfg["adapter_name"]
|
| 360 |
|
| 361 |
if adapter_name in _loaded_loras:
|
|
@@ -380,6 +391,30 @@ def _load_lora_if_needed(pipe, lora_label):
|
|
| 380 |
return adapter_name
|
| 381 |
|
| 382 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 383 |
def _set_lora(pipe, lora_label, lora_strength, allow_load=True):
|
| 384 |
"""
|
| 385 |
Activate the selected LoRA, or disable LoRA for base model.
|
|
@@ -396,13 +431,7 @@ def _set_lora(pipe, lora_label, lora_strength, allow_load=True):
|
|
| 396 |
cfg = KNOWN_LORAS.get(lora_label)
|
| 397 |
|
| 398 |
if not cfg:
|
| 399 |
-
|
| 400 |
-
transformer.disable_lora()
|
| 401 |
-
elif hasattr(transformer, "set_adapters"):
|
| 402 |
-
try:
|
| 403 |
-
transformer.set_adapters([], adapter_weights=[])
|
| 404 |
-
except Exception:
|
| 405 |
-
pass
|
| 406 |
|
| 407 |
_active_lora = None
|
| 408 |
_active_lora_label = "Base model"
|
|
@@ -449,8 +478,8 @@ def load_selected_lora(lora_style, lora_strength):
|
|
| 449 |
if pipe is None:
|
| 450 |
return {
|
| 451 |
"status": "error",
|
|
|
|
| 452 |
"error": _pipeline_error or "Pipeline failed to load",
|
| 453 |
-
"runtime": _runtime_report(),
|
| 454 |
"lora": _lora_report(),
|
| 455 |
}
|
| 456 |
|
|
@@ -460,8 +489,7 @@ def load_selected_lora(lora_style, lora_strength):
|
|
| 460 |
|
| 461 |
return {
|
| 462 |
"status": "ready",
|
| 463 |
-
"message": "Base model active. No LoRA
|
| 464 |
-
"runtime": _runtime_report(),
|
| 465 |
"lora": _lora_report(),
|
| 466 |
}
|
| 467 |
|
|
@@ -478,7 +506,6 @@ def load_selected_lora(lora_style, lora_strength):
|
|
| 478 |
"status": "ready",
|
| 479 |
"message": f"LoRA loaded and activated: {lora_style}",
|
| 480 |
"trigger": trigger,
|
| 481 |
-
"runtime": _runtime_report(),
|
| 482 |
"lora": _lora_report(),
|
| 483 |
}
|
| 484 |
|
|
@@ -486,8 +513,8 @@ def load_selected_lora(lora_style, lora_strength):
|
|
| 486 |
traceback.print_exc()
|
| 487 |
return {
|
| 488 |
"status": "error",
|
|
|
|
| 489 |
"error": f"{type(e).__name__}: {e}",
|
| 490 |
-
"runtime": _runtime_report(),
|
| 491 |
"lora": _lora_report(),
|
| 492 |
}
|
| 493 |
|
|
@@ -503,8 +530,8 @@ def disable_lora():
|
|
| 503 |
if pipe is None:
|
| 504 |
return {
|
| 505 |
"status": "error",
|
|
|
|
| 506 |
"error": _pipeline_error or "Pipeline failed to load",
|
| 507 |
-
"runtime": _runtime_report(),
|
| 508 |
"lora": _lora_report(),
|
| 509 |
}
|
| 510 |
|
|
@@ -515,7 +542,6 @@ def disable_lora():
|
|
| 515 |
return {
|
| 516 |
"status": "ready",
|
| 517 |
"message": "LoRA disabled. Base model active.",
|
| 518 |
-
"runtime": _runtime_report(),
|
| 519 |
"lora": _lora_report(),
|
| 520 |
}
|
| 521 |
|
|
@@ -523,8 +549,8 @@ def disable_lora():
|
|
| 523 |
traceback.print_exc()
|
| 524 |
return {
|
| 525 |
"status": "error",
|
|
|
|
| 526 |
"error": f"{type(e).__name__}: {e}",
|
| 527 |
-
"runtime": _runtime_report(),
|
| 528 |
"lora": _lora_report(),
|
| 529 |
}
|
| 530 |
|
|
@@ -547,11 +573,8 @@ def health():
|
|
| 547 |
"model_ready": _pipeline is not None,
|
| 548 |
"pipeline_ready": _pipeline is not None,
|
| 549 |
"model_id": MODEL_ID,
|
| 550 |
-
"model_family": "diffusers_modular_pipeline",
|
| 551 |
-
"loader_strategy": "ModularPipeline_from_pretrained_trust_remote_code",
|
| 552 |
"runtime_mode": "zerogpu_compatibility_compile_bypass",
|
| 553 |
"last_error": _pipeline_error or "",
|
| 554 |
-
"expected_output_type": "video",
|
| 555 |
"runtime": _runtime_report(),
|
| 556 |
"lora": _lora_report(),
|
| 557 |
}
|
|
@@ -568,6 +591,7 @@ def warmup_model():
|
|
| 568 |
if pipe is None:
|
| 569 |
return {
|
| 570 |
"status": "error",
|
|
|
|
| 571 |
"error": _pipeline_error or "Pipeline failed to load",
|
| 572 |
"runtime": _runtime_report(),
|
| 573 |
"lora": _lora_report(),
|
|
@@ -575,9 +599,8 @@ def warmup_model():
|
|
| 575 |
|
| 576 |
return {
|
| 577 |
"status": "ready",
|
| 578 |
-
"model_id": MODEL_ID,
|
| 579 |
-
"runtime_mode": "zerogpu_compatibility_compile_bypass",
|
| 580 |
"message": "Model loaded and cached in this Space process.",
|
|
|
|
| 581 |
"runtime": _runtime_report(),
|
| 582 |
"lora": _lora_report(),
|
| 583 |
}
|
|
@@ -645,14 +668,11 @@ def generate(
|
|
| 645 |
|
| 646 |
device = "cuda"
|
| 647 |
|
| 648 |
-
# Make sure the pipeline is on CUDA inside the ZeroGPU-decorated function.
|
| 649 |
try:
|
| 650 |
pipe = pipe.to(device)
|
| 651 |
except Exception as e:
|
| 652 |
_log(f"Pipeline .to('cuda') warning: {type(e).__name__}: {e}")
|
| 653 |
|
| 654 |
-
# Activate selected LoRA without hidden loading during generation.
|
| 655 |
-
# If user selected a LoRA but did not load it, fail with a clear message.
|
| 656 |
with _lora_lock:
|
| 657 |
trigger = _set_lora(
|
| 658 |
pipe,
|
|
@@ -731,79 +751,82 @@ def generate(
|
|
| 731 |
with gr.Blocks(title="Krea Realtime Video 14B") as demo:
|
| 732 |
gr.Markdown(
|
| 733 |
"# Krea Realtime Video 14B\n\n"
|
| 734 |
-
"
|
| 735 |
-
"
|
| 736 |
-
"
|
| 737 |
-
"ZeroGPU does not support it.\n\n"
|
| 738 |
-
"**Video length** is controlled by the number of blocks. "
|
| 739 |
-
"Roughly: 1 block ≈ ~1 second, 9 blocks ≈ ~9 seconds. "
|
| 740 |
-
"Values above 9 are experimental.\n\n"
|
| 741 |
-
"**LoRA support**: select a style, click **Load selected LoRA**, then generate. "
|
| 742 |
-
"The Origami preset automatically prefixes the prompt with `[origami]`."
|
| 743 |
)
|
| 744 |
|
| 745 |
with gr.Row():
|
| 746 |
-
with gr.Column():
|
| 747 |
-
|
| 748 |
-
|
| 749 |
-
|
| 750 |
-
|
| 751 |
-
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
prompt = gr.Textbox(
|
| 755 |
-
label="Prompt",
|
| 756 |
-
placeholder="e.g., a cat sitting on a boat",
|
| 757 |
-
lines=3,
|
| 758 |
-
)
|
| 759 |
|
| 760 |
-
gr.
|
|
|
|
| 761 |
|
| 762 |
-
|
| 763 |
-
|
| 764 |
-
|
| 765 |
-
|
| 766 |
-
|
|
|
|
|
|
|
| 767 |
|
| 768 |
-
|
| 769 |
-
|
| 770 |
-
|
| 771 |
-
|
| 772 |
-
|
| 773 |
-
|
| 774 |
-
|
|
|
|
| 775 |
|
| 776 |
-
|
| 777 |
-
|
| 778 |
-
|
| 779 |
|
| 780 |
-
|
|
|
|
|
|
|
|
|
|
| 781 |
|
| 782 |
-
gr.
|
|
|
|
| 783 |
|
| 784 |
-
|
| 785 |
-
|
| 786 |
-
|
| 787 |
-
|
| 788 |
-
|
| 789 |
-
|
| 790 |
-
|
|
|
|
| 791 |
|
| 792 |
-
|
| 793 |
-
|
| 794 |
-
|
| 795 |
-
|
| 796 |
-
|
| 797 |
-
|
| 798 |
-
|
| 799 |
|
| 800 |
-
|
| 801 |
|
| 802 |
-
|
| 803 |
|
| 804 |
-
with gr.Column():
|
| 805 |
output_video = gr.Video(label="Generated Video")
|
| 806 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 807 |
gr.Examples(
|
| 808 |
examples=[
|
| 809 |
[
|
|
|
|
| 75 |
import time
|
| 76 |
import threading
|
| 77 |
import traceback
|
| 78 |
+
import importlib.util
|
| 79 |
|
| 80 |
import torch
|
| 81 |
|
|
|
|
| 133 |
except Exception:
|
| 134 |
pass
|
| 135 |
|
| 136 |
+
PEFT_AVAILABLE = importlib.util.find_spec("peft") is not None
|
| 137 |
+
|
| 138 |
import gradio as gr
|
| 139 |
|
| 140 |
# ---------------------------------------------------------------------------
|
|
|
|
| 194 |
"cuda_available": bool(torch.cuda.is_available()),
|
| 195 |
"cuda_device_count": int(torch.cuda.device_count()) if torch.cuda.is_available() else 0,
|
| 196 |
"has_spaces": HAS_SPACES,
|
| 197 |
+
"peft_available": PEFT_AVAILABLE,
|
| 198 |
"torch_compile_bypassed": torch.compile is _asf_zerogpu_compile_bypass,
|
| 199 |
"hf_home": os.environ.get("HF_HOME", ""),
|
| 200 |
"hf_modules_cache": os.environ.get("HF_MODULES_CACHE", ""),
|
|
|
|
| 208 |
"active_strength": _active_lora_strength,
|
| 209 |
"loaded_loras": sorted(list(_loaded_loras)),
|
| 210 |
"available_loras": list(KNOWN_LORAS.keys()),
|
| 211 |
+
"peft_available": PEFT_AVAILABLE,
|
| 212 |
}
|
| 213 |
|
| 214 |
|
|
|
|
| 361 |
if not cfg:
|
| 362 |
return None
|
| 363 |
|
| 364 |
+
if not PEFT_AVAILABLE:
|
| 365 |
+
raise RuntimeError(
|
| 366 |
+
"PEFT is required for LoRA support. Add `peft` to requirements.txt "
|
| 367 |
+
"and rebuild the Space."
|
| 368 |
+
)
|
| 369 |
+
|
| 370 |
adapter_name = cfg["adapter_name"]
|
| 371 |
|
| 372 |
if adapter_name in _loaded_loras:
|
|
|
|
| 391 |
return adapter_name
|
| 392 |
|
| 393 |
|
| 394 |
+
def _safe_disable_lora(transformer):
|
| 395 |
+
"""
|
| 396 |
+
Disable PEFT LoRA if available.
|
| 397 |
+
|
| 398 |
+
Some diffusers methods raise if PEFT is not installed, so this is defensive.
|
| 399 |
+
"""
|
| 400 |
+
if transformer is None:
|
| 401 |
+
return
|
| 402 |
+
|
| 403 |
+
if hasattr(transformer, "disable_lora"):
|
| 404 |
+
try:
|
| 405 |
+
transformer.disable_lora()
|
| 406 |
+
return
|
| 407 |
+
except Exception as e:
|
| 408 |
+
_log(f"disable_lora warning: {type(e).__name__}: {e}")
|
| 409 |
+
|
| 410 |
+
if hasattr(transformer, "set_adapters"):
|
| 411 |
+
try:
|
| 412 |
+
transformer.set_adapters([], adapter_weights=[])
|
| 413 |
+
return
|
| 414 |
+
except Exception as e:
|
| 415 |
+
_log(f"set_adapters([]) warning: {type(e).__name__}: {e}")
|
| 416 |
+
|
| 417 |
+
|
| 418 |
def _set_lora(pipe, lora_label, lora_strength, allow_load=True):
|
| 419 |
"""
|
| 420 |
Activate the selected LoRA, or disable LoRA for base model.
|
|
|
|
| 431 |
cfg = KNOWN_LORAS.get(lora_label)
|
| 432 |
|
| 433 |
if not cfg:
|
| 434 |
+
_safe_disable_lora(transformer)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 435 |
|
| 436 |
_active_lora = None
|
| 437 |
_active_lora_label = "Base model"
|
|
|
|
| 478 |
if pipe is None:
|
| 479 |
return {
|
| 480 |
"status": "error",
|
| 481 |
+
"message": "Pipeline failed to load.",
|
| 482 |
"error": _pipeline_error or "Pipeline failed to load",
|
|
|
|
| 483 |
"lora": _lora_report(),
|
| 484 |
}
|
| 485 |
|
|
|
|
| 489 |
|
| 490 |
return {
|
| 491 |
"status": "ready",
|
| 492 |
+
"message": "Base model active. No LoRA selected.",
|
|
|
|
| 493 |
"lora": _lora_report(),
|
| 494 |
}
|
| 495 |
|
|
|
|
| 506 |
"status": "ready",
|
| 507 |
"message": f"LoRA loaded and activated: {lora_style}",
|
| 508 |
"trigger": trigger,
|
|
|
|
| 509 |
"lora": _lora_report(),
|
| 510 |
}
|
| 511 |
|
|
|
|
| 513 |
traceback.print_exc()
|
| 514 |
return {
|
| 515 |
"status": "error",
|
| 516 |
+
"message": "LoRA load failed.",
|
| 517 |
"error": f"{type(e).__name__}: {e}",
|
|
|
|
| 518 |
"lora": _lora_report(),
|
| 519 |
}
|
| 520 |
|
|
|
|
| 530 |
if pipe is None:
|
| 531 |
return {
|
| 532 |
"status": "error",
|
| 533 |
+
"message": "Pipeline failed to load.",
|
| 534 |
"error": _pipeline_error or "Pipeline failed to load",
|
|
|
|
| 535 |
"lora": _lora_report(),
|
| 536 |
}
|
| 537 |
|
|
|
|
| 542 |
return {
|
| 543 |
"status": "ready",
|
| 544 |
"message": "LoRA disabled. Base model active.",
|
|
|
|
| 545 |
"lora": _lora_report(),
|
| 546 |
}
|
| 547 |
|
|
|
|
| 549 |
traceback.print_exc()
|
| 550 |
return {
|
| 551 |
"status": "error",
|
| 552 |
+
"message": "Could not disable LoRA cleanly.",
|
| 553 |
"error": f"{type(e).__name__}: {e}",
|
|
|
|
| 554 |
"lora": _lora_report(),
|
| 555 |
}
|
| 556 |
|
|
|
|
| 573 |
"model_ready": _pipeline is not None,
|
| 574 |
"pipeline_ready": _pipeline is not None,
|
| 575 |
"model_id": MODEL_ID,
|
|
|
|
|
|
|
| 576 |
"runtime_mode": "zerogpu_compatibility_compile_bypass",
|
| 577 |
"last_error": _pipeline_error or "",
|
|
|
|
| 578 |
"runtime": _runtime_report(),
|
| 579 |
"lora": _lora_report(),
|
| 580 |
}
|
|
|
|
| 591 |
if pipe is None:
|
| 592 |
return {
|
| 593 |
"status": "error",
|
| 594 |
+
"message": "Pipeline failed to load.",
|
| 595 |
"error": _pipeline_error or "Pipeline failed to load",
|
| 596 |
"runtime": _runtime_report(),
|
| 597 |
"lora": _lora_report(),
|
|
|
|
| 599 |
|
| 600 |
return {
|
| 601 |
"status": "ready",
|
|
|
|
|
|
|
| 602 |
"message": "Model loaded and cached in this Space process.",
|
| 603 |
+
"model_id": MODEL_ID,
|
| 604 |
"runtime": _runtime_report(),
|
| 605 |
"lora": _lora_report(),
|
| 606 |
}
|
|
|
|
| 668 |
|
| 669 |
device = "cuda"
|
| 670 |
|
|
|
|
| 671 |
try:
|
| 672 |
pipe = pipe.to(device)
|
| 673 |
except Exception as e:
|
| 674 |
_log(f"Pipeline .to('cuda') warning: {type(e).__name__}: {e}")
|
| 675 |
|
|
|
|
|
|
|
| 676 |
with _lora_lock:
|
| 677 |
trigger = _set_lora(
|
| 678 |
pipe,
|
|
|
|
| 751 |
with gr.Blocks(title="Krea Realtime Video 14B") as demo:
|
| 752 |
gr.Markdown(
|
| 753 |
"# Krea Realtime Video 14B\n\n"
|
| 754 |
+
"Real local inference with Diffusers `ModularPipeline` on ZeroGPU.\n\n"
|
| 755 |
+
"The model loads at app startup. Generation uses ZeroGPU. "
|
| 756 |
+
"LoRAs can be loaded manually before generation."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 757 |
)
|
| 758 |
|
| 759 |
with gr.Row():
|
| 760 |
+
with gr.Column(scale=4):
|
| 761 |
+
with gr.Group():
|
| 762 |
+
gr.Markdown("## 1. Prompt")
|
| 763 |
+
prompt = gr.Textbox(
|
| 764 |
+
label="Prompt",
|
| 765 |
+
placeholder="Describe the video you want to generate...",
|
| 766 |
+
lines=4,
|
| 767 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 768 |
|
| 769 |
+
with gr.Group():
|
| 770 |
+
gr.Markdown("## 2. Optional Style / LoRA")
|
| 771 |
|
| 772 |
+
with gr.Row():
|
| 773 |
+
lora_style = gr.Dropdown(
|
| 774 |
+
choices=list(KNOWN_LORAS.keys()),
|
| 775 |
+
value="Base model",
|
| 776 |
+
label="Style / LoRA",
|
| 777 |
+
scale=2,
|
| 778 |
+
)
|
| 779 |
|
| 780 |
+
lora_strength = gr.Slider(
|
| 781 |
+
minimum=0.0,
|
| 782 |
+
maximum=1.5,
|
| 783 |
+
value=1.0,
|
| 784 |
+
step=0.05,
|
| 785 |
+
label="Strength",
|
| 786 |
+
scale=3,
|
| 787 |
+
)
|
| 788 |
|
| 789 |
+
with gr.Row():
|
| 790 |
+
load_lora_btn = gr.Button("Load selected LoRA", variant="secondary")
|
| 791 |
+
disable_lora_btn = gr.Button("Use Base Model", variant="secondary")
|
| 792 |
|
| 793 |
+
gr.Markdown(
|
| 794 |
+
"For **Origami**, the app automatically adds the `[origami]` trigger "
|
| 795 |
+
"when generating."
|
| 796 |
+
)
|
| 797 |
|
| 798 |
+
with gr.Group():
|
| 799 |
+
gr.Markdown("## 3. Generation Settings")
|
| 800 |
|
| 801 |
+
with gr.Row():
|
| 802 |
+
num_blocks = gr.Slider(
|
| 803 |
+
minimum=1,
|
| 804 |
+
maximum=12,
|
| 805 |
+
value=9,
|
| 806 |
+
step=1,
|
| 807 |
+
label="Video Length / Blocks",
|
| 808 |
+
)
|
| 809 |
|
| 810 |
+
num_inference_steps = gr.Slider(
|
| 811 |
+
minimum=1,
|
| 812 |
+
maximum=8,
|
| 813 |
+
value=6,
|
| 814 |
+
step=1,
|
| 815 |
+
label="Steps per Block",
|
| 816 |
+
)
|
| 817 |
|
| 818 |
+
seed = gr.Number(value=42, precision=0, label="Seed")
|
| 819 |
|
| 820 |
+
generate_btn = gr.Button("Generate Video", variant="primary")
|
| 821 |
|
| 822 |
+
with gr.Column(scale=5):
|
| 823 |
output_video = gr.Video(label="Generated Video")
|
| 824 |
|
| 825 |
+
with gr.Accordion("Runtime status", open=False):
|
| 826 |
+
model_status = gr.JSON(label="Model Status")
|
| 827 |
+
lora_status = gr.JSON(label="LoRA Status")
|
| 828 |
+
warmup_btn = gr.Button("Refresh model status", variant="secondary")
|
| 829 |
+
|
| 830 |
gr.Examples(
|
| 831 |
examples=[
|
| 832 |
[
|