|
|
|
|
|
|
|
|
""" |
|
|
Quiet Startup Self-Check for Hugging Face Space |
|
|
- Verifies SAM2 + MatAnyone can load and run a tiny inference |
|
|
- Defaults to ASYNC so UI launches immediately; logs results |
|
|
- Switch to SYNC by setting env SELF_CHECK_MODE=sync |
|
|
""" |
|
|
|
|
|
import logging |
|
|
import os |
|
|
import threading |
|
|
import numpy as np |
|
|
import torch |
|
|
|
|
|
|
|
|
def _safe_imports(): |
|
|
from models.loaders.sam2_loader import SAM2Loader |
|
|
from models.loaders.matanyone_loader import MatAnyoneLoader |
|
|
return SAM2Loader, MatAnyoneLoader |
|
|
|
|
|
log = logging.getLogger("selfcheck") |
|
|
if not log.handlers: |
|
|
logging.basicConfig(level=logging.INFO) |
|
|
|
|
|
def run_selfcheck() -> None: |
|
|
"""Do the actual check; log results. Non-throwing.""" |
|
|
try: |
|
|
SAM2Loader, MatAnyoneLoader = _safe_imports() |
|
|
except Exception as e: |
|
|
log.error(f"β Self-check import failure: {e}", exc_info=True) |
|
|
return |
|
|
|
|
|
try: |
|
|
|
|
|
img = np.zeros((64, 64, 3), dtype=np.uint8) |
|
|
mask = np.ones((64, 64), dtype=np.float32) |
|
|
|
|
|
|
|
|
try: |
|
|
sam_loader = SAM2Loader(device="cuda" if torch.cuda.is_available() else "cpu") |
|
|
sam = sam_loader.load("tiny") |
|
|
if sam: |
|
|
sam.set_image(img) |
|
|
out = sam.predict(point_coords=None, point_labels=None) |
|
|
m = out["masks"] |
|
|
log.info(f"β
SAM2 OK β masks {m.shape} {m.dtype} [{m.min():.3f},{m.max():.3f}]") |
|
|
else: |
|
|
log.error("β SAM2 failed to load (adapter is None)") |
|
|
except Exception as e: |
|
|
log.error(f"β SAM2 self-check error: {e}", exc_info=True) |
|
|
|
|
|
|
|
|
try: |
|
|
mat_loader = MatAnyoneLoader(device="cuda" if torch.cuda.is_available() else "cpu") |
|
|
session = mat_loader.load() |
|
|
if session: |
|
|
alpha = session(img, mask) |
|
|
log.info(f"β
MatAnyone OK β alpha {alpha.shape} {alpha.dtype} [{alpha.min():.3f},{alpha.max():.3f}]") |
|
|
else: |
|
|
log.error("β MatAnyone failed to load (session is None)") |
|
|
except Exception as e: |
|
|
log.error(f"β MatAnyone self-check error: {e}", exc_info=True) |
|
|
|
|
|
except Exception as e: |
|
|
log.error(f"β Self-check unexpected error: {e}", exc_info=True) |
|
|
|
|
|
def schedule_startup_selfcheck(mode: str = "async") -> None: |
|
|
""" |
|
|
mode: "async" (default) β run in a daemon thread; UI doesn't wait |
|
|
"sync" β block until check completes (slower startup) |
|
|
""" |
|
|
mode = (mode or "async").lower() |
|
|
if mode == "sync": |
|
|
log.info("π Running model self-check (sync)β¦") |
|
|
run_selfcheck() |
|
|
return |
|
|
|
|
|
def _worker(): |
|
|
try: |
|
|
log.info("π Running model self-check (async)β¦") |
|
|
run_selfcheck() |
|
|
except Exception: |
|
|
|
|
|
log.exception("Self-check thread crashed") |
|
|
|
|
|
t = threading.Thread(target=_worker, name="startup-selfcheck", daemon=True) |
|
|
t.start() |
|
|
|