Files
feedmill-auto-label/backend/main.py
T

76 lines
2.1 KiB
Python

"""FastAPI server for the dataset enrichment platform.
Run it with: .venv/bin/uvicorn backend.main:app --port 8000
or: docker compose up
Routes live in `backend/api/`, one module per domain; this file only wires them
together and owns startup.
"""
import os
import shutil
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from backend import config, db, jobs
from backend.api import batches, jobs as job_routes, models, projects, review
@asynccontextmanager
async def lifespan(_app: FastAPI):
config.ensure_dirs()
db.migrate()
from backend import projects as project_store
project_store.ensure_seed_project()
interrupted = jobs.recover()
if interrupted:
print(f"[startup] closed {interrupted} job(s) interrupted by the last restart")
yield
app = FastAPI(title="Dataset Enrichment", lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
allow_origins=config.CORS_ORIGINS,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(projects.router)
app.include_router(batches.router)
app.include_router(review.router)
app.include_router(models.router)
app.include_router(job_routes.router)
@app.get("/api/health")
def health() -> dict:
import torch
from backend import hardware
free_vram = hardware.free_vram_gb()
needed = hardware.SAM3_RESIDENT_GB + hardware.SAM3_HEADROOM_GB
return {
"device": "cuda" if torch.cuda.is_available() else "cpu",
"gpu": torch.cuda.get_device_name(0) if torch.cuda.is_available() else None,
"vram_free_gb": free_vram,
"sam3_ready": free_vram >= needed or _engine_loaded(),
"ffmpeg": shutil.which("ffmpeg") is not None,
"ffprobe": shutil.which("ffprobe") is not None,
"hf_token": bool(os.environ.get("HUGGING_FACE_HUB_TOKEN")),
"db": db.healthy(),
"data_dir": config.DATA_DIR,
"video_root": config.VIDEO_ROOT,
"model_loaded": _engine_loaded(),
}
def _engine_loaded() -> bool:
from backend.sam3_engine import engine_is_loaded
return engine_is_loaded()