| |
| |
| """ |
| 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() |
|
|