File size: 3,253 Bytes
ab8cebe
 
ff31e2d
 
ab8cebe
 
 
 
7189f3f
ab8cebe
a01d457
 
 
ff31e2d
ab8cebe
ff31e2d
 
67ac72b
ff31e2d
 
 
 
bb776bc
ff31e2d
ab8cebe
 
ff31e2d
 
 
 
 
 
 
 
 
ab8cebe
ff31e2d
 
 
 
 
 
 
 
 
7189f3f
 
 
 
 
 
 
 
 
ff31e2d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
"""
Called during Docker build to pre-download DeepFace AI models.
Tries Hugging Face Hub first (fast & reliable within HF infrastructure),
then falls back to DeepFace's built-in downloader (GitHub releases).
Models are baked into the image so no runtime download is needed.
"""
import os
import sys
from concurrent.futures import ThreadPoolExecutor, TimeoutError as FuturesTimeout

# Use DEEPFACE_HOME from env (set in Dockerfile) or fallback to user home
DEEPFACE_HOME = os.environ.get("DEEPFACE_HOME", os.path.expanduser("~"))
WEIGHTS_DIR = os.path.join(DEEPFACE_HOME, ".deepface", "weights")
os.makedirs(WEIGHTS_DIR, exist_ok=True)

HF_REPO = "Hodfa71/deepface-weights"
MODEL_FILES = [
    "vgg_face_weights.h5",
    "age_model_weights.h5",
    "gender_model_weights.h5",
    "facial_expression_model_weights.h5",
    "race_model_single_batch.h5",
    "retinaface.h5",
]


def try_hf_hub():
    """Download weights from Hodfa71/deepface-weights on Hugging Face Hub."""
    try:
        from huggingface_hub import hf_hub_download, list_repo_files
        # Check the repo exists and has files
        files = list(list_repo_files(HF_REPO))
        if not files:
            print(f"  HF repo {HF_REPO} is empty or not found.", flush=True)
            return False

        for filename in MODEL_FILES:
            dest = os.path.join(WEIGHTS_DIR, filename)
            if os.path.exists(dest):
                print(f"  {filename} already present, skipping.", flush=True)
                continue
            if filename not in files:
                print(f"  {filename} not in HF repo, skipping.", flush=True)
                continue
            print(f"  Downloading {filename} from HF Hub...", flush=True)
            with ThreadPoolExecutor(max_workers=1) as executor:
                future = executor.submit(
                    hf_hub_download,
                    repo_id=HF_REPO,
                    filename=filename,
                    local_dir=WEIGHTS_DIR,
                    local_dir_use_symlinks=False,
                )
                future.result(timeout=300)  # 5 minute cap per file
            print(f"  {filename} ready.", flush=True)
        return True
    except Exception as exc:
        print(f"  HF Hub download failed: {exc}", flush=True)
        return False


def try_deepface_build():
    """Download weights via DeepFace (from GitHub releases)."""
    try:
        from deepface import DeepFace
        for model_name in ["Age", "Gender", "Emotion", "Race"]:
            print(f"  Building {model_name} via DeepFace (GitHub)...", flush=True)
            DeepFace.build_model(model_name)
            print(f"  {model_name} ready.", flush=True)
        return True
    except Exception as exc:
        print(f"  DeepFace build failed: {exc}", flush=True)
        return False


print("=== Downloading AI model weights ===", flush=True)
print(f"Trying HF Hub ({HF_REPO})...", flush=True)
if try_hf_hub():
    print("=== HF Hub download successful ===", flush=True)
elif try_deepface_build():
    print("=== GitHub download successful ===", flush=True)
else:
    print("WARNING: All download attempts failed.", flush=True)
    print("Models will attempt to download on first request.", flush=True)
    sys.exit(0)