zoo3d / app.py
bulatko's picture
Runtime fallback: install local detectron2 if import fails (no build isolation)
a981840
import os
import sys
import subprocess
import gradio as gr
def _launch():
# Check if we need to install detectron2 and dependencies (first run only)
if not os.environ.get("DETECTRON2_INSTALLED"):
print("πŸ”§ Installing CropFormer dependencies...")
try:
# Install CropFormer/Mask2Former dependencies
subprocess.check_call([
sys.executable, "-m", "pip", "install",
"mmcv>=1.4.0,<2.0.0", "cython", "shapely", "timm", "h5py", "scikit-image"
])
subprocess.check_call([
sys.executable, "-m", "pip", "install", "--no-build-isolation",
"git+https://github.com/facebookresearch/pytorch3d.git"
])
print("βœ… CropFormer dependencies installed!")
print("πŸ”§ Installing detectron2 from vendored source...")
subprocess.check_call([
sys.executable, "-m", "pip", "install",
"--no-build-isolation", "-e", "MaskClustering/third_party/detectron2"
])
print("βœ… detectron2 installed successfully!")
# Compile CropFormer components
repo_root = os.path.dirname(os.path.abspath(__file__))
cropformer_root = os.path.join(repo_root, "MaskClustering/third_party/detectron2/projects/CropFormer")
# 1. Compile entity_api PythonAPI
print("πŸ”§ Compiling entity_api PythonAPI...")
entity_api_dir = os.path.join(cropformer_root, "entity_api/PythonAPI")
if os.path.exists(entity_api_dir):
try:
subprocess.check_call(["make"], cwd=entity_api_dir, shell=True)
print("βœ… entity_api compiled successfully!")
except subprocess.CalledProcessError as e:
print(f"⚠️ entity_api compilation failed (non-critical): {e}")
else:
print(f"⚠️ entity_api directory not found: {entity_api_dir}")
# 2. Compile MSDeformAttn CUDA ops
print("πŸ”§ Compiling MSDeformAttn CUDA operators...")
ops_dir = os.path.join(cropformer_root, "mask2former/modeling/pixel_decoder/ops")
if os.path.exists(ops_dir):
try:
# Try with CUDA first
subprocess.check_call(["sh", "make.sh"], cwd=ops_dir)
print("βœ… MSDeformAttn ops compiled successfully!")
except subprocess.CalledProcessError as e:
print(f"⚠️ CUDA compilation failed, trying CPU-only mode: {e}")
try:
# Fallback to CPU-only build
subprocess.check_call(
["python", "setup.py", "build", "install"],
cwd=ops_dir,
env={**os.environ, "FORCE_CUDA": "0"}
)
print("βœ… MSDeformAttn ops compiled (CPU mode)!")
except subprocess.CalledProcessError as e2:
print(f"⚠️ MSDeformAttn compilation failed (non-critical): {e2}")
else:
print(f"⚠️ MSDeformAttn ops directory not found: {ops_dir}")
print("πŸ”„ Restarting to load detectron2...")
# Set environment variable to avoid reinstalling on restart
os.environ["DETECTRON2_INSTALLED"] = "1"
# Restart the script
os.execv(sys.executable, [sys.executable] + sys.argv)
except subprocess.CalledProcessError as e:
print(f"❌ Failed to install dependencies: {e}")
raise
else:
# Second run: verify imports work
print("πŸ” Verifying detectron2 and mmcv imports...")
try:
import detectron2
import mmcv
print(f"βœ… detectron2 available (version: {getattr(detectron2, '__version__', 'unknown')})")
print(f"βœ… mmcv available (version: {getattr(mmcv, '__version__', 'unknown')})")
except ImportError as e:
print(f"❌ Required module cannot be imported: {e}")
print(f" sys.path: {sys.path}")
raise
# HF Spaces/Gradio sometimes calls /api_info regardless of `show_api=False`.
# Some gradio_client versions crash when JSON schema uses boolean `additionalProperties`.
# Patch defensively to avoid bringing down the whole app.
try:
import gradio_client.utils as _gcu
if hasattr(_gcu, "_json_schema_to_python_type"):
_orig = _gcu._json_schema_to_python_type
def _json_schema_to_python_type_patched(schema, defs=None):
if isinstance(schema, bool):
return "Any"
return _orig(schema, defs)
_gcu._json_schema_to_python_type = _json_schema_to_python_type_patched
except Exception:
pass
# HF Spaces expects the app to listen on 0.0.0.0:7860 (PORT may be provided).
import mvp
port = int(os.getenv("PORT", "7860"))
# `mvp` defines `demo` (gr.Blocks). We launch it here instead of inside `mvp.py`.
mvp.demo.queue(max_size=20).launch(
server_name="0.0.0.0",
server_port=port,
show_error=True,
share=False,
show_api=False,
)
if __name__ == "__main__":
_launch()