mimo-1.0 / app_installer.py.bak
minhho's picture
Clean deployment: All fixes without binary files
6f2c7f0
#!/usr/bin/env python3
"""
MIMO - Fast Startup Version for HuggingFace Spaces
Minimal imports to prevent timeout, full features loaded on demand
"""
import os
import gradio as gr
# Optional: small warmup function so Spaces runtime detects a GPU task and removes
# the startup warning "No @spaces.GPU function detected". This does NOT import
# heavy ML libs; it only checks environment lazily at call. If spaces package
# isn't available the decorator import will fail silently.
try: # keep ultra-safe
import spaces
@spaces.GPU
def warmup_gpu(): # lightweight, returns availability flag
try:
# defer torch import until after user installs heavy deps
import importlib
torch_spec = importlib.util.find_spec("torch")
if torch_spec is None:
return {"cuda": False, "detail": "torch not installed yet"}
import torch # type: ignore
return {"cuda": torch.cuda.is_available()}
except Exception as _e: # noqa: N806
return {"cuda": False, "detail": str(_e)}
except Exception:
# spaces not present; ignore – minimal build still works
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 = []
# 1. Force uninstall
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)")
# 2. Install core (CPU torch to avoid GPU wheel delays; pipeline mainly uses GPU later if available)
core_specs = [ 'torch==2.0.1', 'torchvision==0.15.2' ]
for spec in core_specs:
ok, msg = pip_install(spec)
messages.append(msg)
# 3. Pre-stub functorch symbol before any heavy imports
try:
import importlib
fx_mod = importlib.import_module('torch._functorch.eager_transforms')
if not hasattr(fx_mod, 'grad_and_value'):
# Create lightweight placeholder using autograd backward pass simulation
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}')
# 4. Install remainder
# Phase 1: Core ML libs (force clean versions)
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)
# Phase 2: Utility libs needed by app_hf_spaces.py
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)
# Patch diffusers to disable ONNX (avoid _CAFFE2_ATEN_FALLBACK errors)
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}')
# Defer tensorflow until after core validation to reduce failure surface
deferred_tensorflow = 'tensorflow-cpu==2.13.0'
# 5. Validate imports with diffusers fallback chain
def try_import(autoencoder_strict=False):
import importlib
import torch # noqa: F401
import diffusers # noqa: F401
import transformers # noqa: F401
if autoencoder_strict:
# direct AutoencoderKL import path changed in some versions
from diffusers import AutoencoderKL # noqa: F401
return True
# Try import with fallback: 0.21.4 → 0.20.2
diffusers_versions = ["0.21.4", "0.20.2"]
last_error = None
for idx, ver in enumerate(diffusers_versions):
try:
# Reinstall target diffusers version fresh each attempt
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
# Relax autoencoder import for first attempts (some versions restructure)
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)
# Install deferred tensorflow optionally
ok_tf, msg_tf = pip_install(deferred_tensorflow)
messages.append(msg_tf)
# Secondary optional: attempt AutoencoderKL explicit import to ensure availability (soft)
try:
from diffusers import AutoencoderKL # noqa: F401
except Exception as e:
messages.append(f'Warning: AutoencoderKL direct import not required but failed: {e}')
# 6. Try app import
try:
from app_hf_spaces import CompleteMIMO, gradio_interface # noqa: F401
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.
"""
# Always start with minimal interface (no premature heavy imports)
app = create_simple_interface()
if __name__ == "__main__":
app.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
show_error=True
)