|
|
|
|
|
""" |
|
|
MIMO - Fast Startup Version for HuggingFace Spaces |
|
|
Minimal imports to prevent timeout, full features loaded on demand |
|
|
""" |
|
|
|
|
|
import os |
|
|
import gradio as gr |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
import spaces |
|
|
|
|
|
@spaces.GPU |
|
|
def warmup_gpu(): |
|
|
try: |
|
|
|
|
|
import importlib |
|
|
torch_spec = importlib.util.find_spec("torch") |
|
|
if torch_spec is None: |
|
|
return {"cuda": False, "detail": "torch not installed yet"} |
|
|
import torch |
|
|
return {"cuda": torch.cuda.is_available()} |
|
|
except Exception as _e: |
|
|
return {"cuda": False, "detail": str(_e)} |
|
|
except Exception: |
|
|
|
|
|
pass |
|
|
|
|
|
def create_simple_interface(): |
|
|
"""Create a simple interface that loads quickly""" |
|
|
|
|
|
def setup_and_load(): |
|
|
"""Force-clean and install modern stack, stub missing functorch symbol early, then validate. |
|
|
|
|
|
Steps: |
|
|
1. Uninstall conflicting packages (torch, torchvision, diffusers, transformers, peft, accelerate, safetensors). |
|
|
2. Install torch/torchvision first (CPU build to reduce risk) then other libs pinned. |
|
|
3. Pre-create functorch eager_transforms.grad_and_value stub if absent BEFORE importing transformers/diffusers. |
|
|
4. Validate imports. |
|
|
""" |
|
|
try: |
|
|
import subprocess, sys, importlib, traceback, types |
|
|
|
|
|
def run(cmd): |
|
|
try: |
|
|
subprocess.check_call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) |
|
|
return True |
|
|
except Exception: |
|
|
return False |
|
|
|
|
|
def pip_install(spec): |
|
|
ok = run([sys.executable, '-m', 'pip', 'install', '--no-cache-dir', spec]) |
|
|
return ok, (f"Installed {spec}" if ok else f"Failed {spec}") |
|
|
|
|
|
messages = [] |
|
|
|
|
|
uninstall_list = [ |
|
|
'diffusers', 'transformers', 'torchvision', 'torch', 'peft', 'accelerate', 'safetensors' |
|
|
] |
|
|
for pkg in uninstall_list: |
|
|
run([sys.executable, '-m', 'pip', 'uninstall', '-y', pkg]) |
|
|
messages.append("Forced uninstall of prior core packages (best-effort)") |
|
|
|
|
|
|
|
|
core_specs = [ 'torch==2.0.1', 'torchvision==0.15.2' ] |
|
|
for spec in core_specs: |
|
|
ok, msg = pip_install(spec) |
|
|
messages.append(msg) |
|
|
|
|
|
|
|
|
try: |
|
|
import importlib |
|
|
fx_mod = importlib.import_module('torch._functorch.eager_transforms') |
|
|
if not hasattr(fx_mod, 'grad_and_value'): |
|
|
|
|
|
def grad_and_value(f): |
|
|
def wrapper(*a, **kw): |
|
|
import torch |
|
|
x = f(*a, **kw) |
|
|
try: |
|
|
if isinstance(x, torch.Tensor) and x.requires_grad: |
|
|
g = torch.autograd.grad(x, [t for t in a if isinstance(t, torch.Tensor) and t.requires_grad], allow_unused=True) |
|
|
else: |
|
|
g = None |
|
|
except Exception: |
|
|
g = None |
|
|
return g, x |
|
|
return wrapper |
|
|
setattr(fx_mod, 'grad_and_value', grad_and_value) |
|
|
messages.append('Stubbed functorch.grad_and_value') |
|
|
else: |
|
|
messages.append('functorch.grad_and_value present') |
|
|
except Exception as e: |
|
|
messages.append(f'Could not prepare functorch stub: {e}') |
|
|
|
|
|
|
|
|
|
|
|
stack_specs_phase1 = [ |
|
|
"huggingface_hub==0.23.0", |
|
|
"safetensors==0.4.5", |
|
|
"diffusers==0.21.4", |
|
|
"transformers==4.35.2", |
|
|
"peft==0.7.1", |
|
|
"accelerate==0.25.0", |
|
|
] |
|
|
for spec in stack_specs_phase1: |
|
|
ok, msg = pip_install(spec) |
|
|
messages.append(msg) |
|
|
|
|
|
|
|
|
stack_specs_phase2 = [ |
|
|
"einops==0.7.0", |
|
|
"opencv-python-headless==4.8.1.78", |
|
|
"imageio==2.31.6", |
|
|
"imageio-ffmpeg==0.4.8", |
|
|
"tqdm==4.66.1", |
|
|
] |
|
|
for spec in stack_specs_phase2: |
|
|
ok, msg = pip_install(spec) |
|
|
messages.append(msg) |
|
|
|
|
|
|
|
|
try: |
|
|
import sys |
|
|
if 'diffusers' not in sys.modules: |
|
|
import diffusers.utils.import_utils as diff_imports |
|
|
diff_imports.is_onnx_available = lambda: False |
|
|
messages.append('Patched diffusers.is_onnx_available = False') |
|
|
except Exception as e: |
|
|
messages.append(f'ONNX patch failed (non-critical): {e}') |
|
|
|
|
|
|
|
|
deferred_tensorflow = 'tensorflow-cpu==2.13.0' |
|
|
|
|
|
def try_import(autoencoder_strict=False): |
|
|
import importlib |
|
|
import torch |
|
|
import diffusers |
|
|
import transformers |
|
|
if autoencoder_strict: |
|
|
|
|
|
from diffusers import AutoencoderKL |
|
|
return True |
|
|
|
|
|
|
|
|
diffusers_versions = ["0.21.4", "0.20.2"] |
|
|
last_error = None |
|
|
for idx, ver in enumerate(diffusers_versions): |
|
|
try: |
|
|
|
|
|
run([sys.executable, '-m', 'pip', 'uninstall', '-y', 'diffusers']) |
|
|
ok, msg = pip_install(f'diffusers=={ver}') |
|
|
messages.append(msg) |
|
|
if not ok: |
|
|
last_error = msg |
|
|
continue |
|
|
|
|
|
strict = (ver == diffusers_versions[-1]) |
|
|
try_import(autoencoder_strict=strict) |
|
|
messages.append(f'diffusers import OK at {ver} (strict={strict})') |
|
|
last_error = None |
|
|
break |
|
|
except Exception as e: |
|
|
last_error = str(e) |
|
|
messages.append(f'diffusers version {ver} failed: {e}') |
|
|
|
|
|
if last_error: |
|
|
messages.append(f'Final diffusers import failure after fallbacks: {last_error}') |
|
|
return '❌ Setup failed during import validation\n' + '\n'.join(messages) |
|
|
|
|
|
|
|
|
ok_tf, msg_tf = pip_install(deferred_tensorflow) |
|
|
messages.append(msg_tf) |
|
|
|
|
|
|
|
|
try: |
|
|
from diffusers import AutoencoderKL |
|
|
except Exception as e: |
|
|
messages.append(f'Warning: AutoencoderKL direct import not required but failed: {e}') |
|
|
|
|
|
|
|
|
try: |
|
|
from app_hf_spaces import CompleteMIMO, gradio_interface |
|
|
except Exception as e: |
|
|
tb = traceback.format_exc(limit=2) |
|
|
messages.append(f'App import partial failure: {e}\n{tb}') |
|
|
return '⚠️ Core libs installed but app import failed\n' + '\n'.join(messages) |
|
|
|
|
|
return '✅ Clean stack installed! Please refresh to load full MIMO.\n' + '\n'.join(messages) |
|
|
|
|
|
except Exception as e: |
|
|
return f'❌ Setup failed: {e}' |
|
|
|
|
|
with gr.Blocks(title="MIMO - Loading...", theme=gr.themes.Soft()) as demo: |
|
|
gr.HTML(""" |
|
|
<div style="text-align: center; padding: 2rem;"> |
|
|
<h1>🎭 MIMO - Character Video Synthesis</h1> |
|
|
<p>Loading complete implementation...</p> |
|
|
<p>Click the button below to install remaining dependencies and activate full features.</p> |
|
|
</div> |
|
|
""") |
|
|
|
|
|
setup_btn = gr.Button("� Install Dependencies & Activate MIMO", variant="primary", size="lg") |
|
|
status = gr.Textbox(label="Status", interactive=False, lines=3) |
|
|
|
|
|
setup_btn.click(fn=setup_and_load, outputs=[status]) |
|
|
|
|
|
gr.HTML(""" |
|
|
<div style="margin-top: 2rem; padding: 1rem; background: #f0f0f0; border-radius: 8px;"> |
|
|
<h4>Why this approach?</h4> |
|
|
<p>To prevent HuggingFace Spaces build timeout, we use minimal dependencies at startup.</p> |
|
|
<p>Full MIMO features (Character Animation + Video Editing) will be available after setup.</p> |
|
|
</div> |
|
|
""") |
|
|
|
|
|
return demo |
|
|
|
|
|
""" |
|
|
We do NOT attempt to import the full heavy implementation during build/startup. |
|
|
The previous version tried a best-effort import inside a try/except. Even though it |
|
|
failed fast, it still triggered Python to resolve heavy modules (torch/diffusers) |
|
|
which aren't installed in the minimal build image. That adds noise and (in some |
|
|
cases) delays. We now always start with the light interface; the user explicitly |
|
|
chooses to install heavy dependencies. |
|
|
|
|
|
Keeping changes minimal per user request: no extra files or new features, just a |
|
|
safer lazy-loading path. |
|
|
""" |
|
|
|
|
|
|
|
|
app = create_simple_interface() |
|
|
|
|
|
if __name__ == "__main__": |
|
|
app.launch( |
|
|
server_name="0.0.0.0", |
|
|
server_port=7860, |
|
|
share=False, |
|
|
show_error=True |
|
|
) |