AdarshDRC commited on
Commit
7c8c165
·
1 Parent(s): 1feca1e

fix : search engine

Browse files
Files changed (1) hide show
  1. Dockerfile +82 -87
Dockerfile CHANGED
@@ -3,21 +3,15 @@
3
  # Changes vs V3:
4
  # • Removed deepface / GhostFaceNet / RetinaFace entirely
5
  # • Added insightface + onnxruntime (SCRFD + ArcFace-R100)
6
- # • Added huggingface_hub for AdaFace weight download
7
- # • Pre-downloads AdaFace IR-50 WebFace4M weights at build time
8
- # • Pre-downloads InsightFace buffalo_l pack at build time
9
- # • Single worker (InsightFace ONNX is NOT thread-safe)
10
- # • index dimensions: enterprise-faces=1024, enterprise-objects=1536
11
 
12
  FROM python:3.10-slim
13
 
14
  WORKDIR /app
15
 
16
  # ── System deps ───────────────────────────────────────────────────
17
- # libGL + libGLib : OpenCV headless
18
- # libgomp1 : OpenMP (used by ONNX runtime + numpy)
19
- # git : needed by some HF hub downloads
20
- # curl : useful for health checks / debug
21
  RUN apt-get update && apt-get install -y --no-install-recommends \
22
  libgl1 \
23
  libglib2.0-0 \
@@ -26,118 +20,119 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
26
  curl \
27
  && rm -rf /var/lib/apt/lists/*
28
 
 
 
 
 
 
 
 
29
  # ── Python deps ───────────────────────────────────────────────────
30
  COPY requirements.txt .
31
  RUN pip install --no-cache-dir --compile -r requirements.txt
32
 
33
- # ── Copy application code ────────────────────────────────────────
34
  COPY . .
35
 
36
  RUN mkdir -p temp_uploads saved_images && chmod -R 777 temp_uploads saved_images
37
 
38
- # ── Pre-download ALL AI models at BUILD time ─────────────────────
39
- # Bakes weights into image layer cold start ~10s instead of ~5min
40
- #
41
- # Model sizes (approximate):
42
- # SigLIP base ~380 MB
43
- # DINOv2 base ~330 MB
44
- # YOLO11n-seg ~6 MB
45
- # InsightFace buffalo_l (SCRFD-10GF + ArcFace-R100) ~280 MB
46
- # AdaFace IR-50 WebFace4M ~170 MB
47
- # Total image delta: ~1.2 GB
48
  RUN python - <<'EOF'
49
  import os, sys
50
 
51
- # ── SigLIP ────────────────────────────────────────────────────────
52
- print("📦 Pre-downloading SigLIP...")
53
- from transformers import AutoProcessor, AutoModel
54
  AutoProcessor.from_pretrained("google/siglip-base-patch16-224", use_fast=True)
55
  AutoModel.from_pretrained("google/siglip-base-patch16-224")
56
- print("SigLIP done")
57
 
58
- # ── DINOv2 ───────────────────────────────────────────────────────
59
- print("📦 Pre-downloading DINOv2...")
60
- from transformers import AutoImageProcessor
61
  AutoImageProcessor.from_pretrained("facebook/dinov2-base")
62
  AutoModel.from_pretrained("facebook/dinov2-base")
63
- print("DINOv2 done")
64
 
65
- # ── YOLO11n-seg ───────────────────────────────────────────────────
66
- print("📦 Pre-downloading YOLO11n-seg...")
67
  from ultralytics import YOLO
68
  YOLO("yolo11n-seg.pt")
69
- print("YOLO done")
70
 
71
- # ── InsightFace buffalo_l ─────────────────────────────────────────
72
- # buffalo_l = SCRFD-10GF (detector) + ArcFace-R100 (encoder)
73
- # Handles small faces in group photos (det_size up to 1280x1280)
74
- print("📦 Pre-downloading InsightFace buffalo_l...")
75
  import numpy as np
76
  from insightface.app import FaceAnalysis
77
- face_app = FaceAnalysis(
78
- name="buffalo_l",
79
- providers=["CPUExecutionProvider"],
80
- )
81
  face_app.prepare(ctx_id=-1, det_size=(640, 640))
82
- # Warmup inference to confirm weights loaded
83
- test = np.zeros((112, 112, 3), dtype=np.uint8)
84
- face_app.get(test)
85
- print(" ✅ InsightFace buffalo_l done")
86
-
87
- # ── AdaFace IR-50 MS1MV2 ─────────────────────────────────────────
88
- # Repo: minchul/cvlface_adaface_ir50_ms1mv2
89
- # Loaded via AutoModel + trust_remote_code=True
90
- # Requires HF_TOKEN build arg (set in HF Space secrets)
91
- print("📦 Pre-downloading AdaFace IR-50 MS1MV2...")
92
- import os, sys
93
- from huggingface_hub import hf_hub_download
94
- from transformers import AutoModel
95
 
96
- HF_TOKEN = os.getenv("HF_TOKEN", None)
97
- REPO_ID = "minchul/cvlface_adaface_ir50_ms1mv2"
98
- CACHE_PATH = os.path.expanduser("~/.cvlface_cache/minchul/cvlface_adaface_ir50_ms1mv2")
99
- os.makedirs(CACHE_PATH, exist_ok=True)
100
 
101
- # Download files.txt manifest
102
- hf_hub_download(repo_id=REPO_ID, filename="files.txt",
103
- token=HF_TOKEN, local_dir=CACHE_PATH, local_dir_use_symlinks=False)
 
 
 
104
 
105
- with open(os.path.join(CACHE_PATH, "files.txt")) as f:
106
- extra = [x.strip() for x in f.read().split("\n") if x.strip()]
 
107
 
108
- for fname in extra + ["config.json", "wrapper.py", "model.safetensors"]:
109
- fpath = os.path.join(CACHE_PATH, fname)
110
- if not os.path.exists(fpath):
111
- hf_hub_download(repo_id=REPO_ID, filename=fname,
112
- token=HF_TOKEN, local_dir=CACHE_PATH, local_dir_use_symlinks=False)
113
 
114
- # Load and verify
115
- cwd = os.getcwd(); os.chdir(CACHE_PATH); sys.path.insert(0, CACHE_PATH)
116
  try:
117
- model = AutoModel.from_pretrained(CACHE_PATH, trust_remote_code=True, token=HF_TOKEN)
118
- finally:
119
- os.chdir(cwd)
120
- if CACHE_PATH in sys.path: sys.path.remove(CACHE_PATH)
121
-
122
- import torch
123
- with torch.no_grad():
124
- out = model(torch.zeros(1, 3, 112, 112))
125
- emb = out if isinstance(out, torch.Tensor) else out.embedding
126
- print(f" ✅ AdaFace loaded — output dim={emb.shape[-1]}")
127
-
128
- print("")
129
- print("✅ All V4 models pre-downloaded and verified!")
130
- print(" enterprise-faces index dim : 1024 (ArcFace-512 + AdaFace-512)")
131
- print(" enterprise-objects index dim: 1536 (SigLIP-768 + DINOv2-768)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  EOF
133
 
134
  EXPOSE 7860
135
 
136
  # ── Single worker — InsightFace ONNX is NOT thread-safe ──────────
137
- # Each request acquires _face_lock before ONNX inference.
138
- # Multiple workers would each load their own model copy into RAM
139
- # (~1.5 GB each) which OOMs free HF Spaces (16 GB limit).
140
- # If you have a paid GPU Space with >32 GB RAM, set WEB_CONCURRENCY=2.
141
  ENV WEB_CONCURRENCY=1
142
 
143
  CMD uvicorn main:app \
 
3
  # Changes vs V3:
4
  # • Removed deepface / GhostFaceNet / RetinaFace entirely
5
  # • Added insightface + onnxruntime (SCRFD + ArcFace-R100)
6
+ # • AdaFace IR-50 MS1MV2 pre-downloaded at build time (needs HF_TOKEN)
7
+ # • Single worker InsightFace ONNX is NOT thread-safe
8
+ # • Index dims: enterprise-faces=1024, enterprise-objects=1536
 
 
9
 
10
  FROM python:3.10-slim
11
 
12
  WORKDIR /app
13
 
14
  # ── System deps ───────────────────────────────────────────────────
 
 
 
 
15
  RUN apt-get update && apt-get install -y --no-install-recommends \
16
  libgl1 \
17
  libglib2.0-0 \
 
20
  curl \
21
  && rm -rf /var/lib/apt/lists/*
22
 
23
+ # ── HF_TOKEN build arg ────────────────────────────────────────────
24
+ # Set in HF Space -> Settings -> Repository Secrets as HF_TOKEN.
25
+ # HF Spaces passes Repository Secrets as both runtime env vars
26
+ # AND Docker build ARGs with the same name automatically.
27
+ ARG HF_TOKEN=""
28
+ ENV HF_TOKEN=${HF_TOKEN}
29
+
30
  # ── Python deps ───────────────────────────────────────────────────
31
  COPY requirements.txt .
32
  RUN pip install --no-cache-dir --compile -r requirements.txt
33
 
34
+ # ── Copy application code ────────────────────────────────────────
35
  COPY . .
36
 
37
  RUN mkdir -p temp_uploads saved_images && chmod -R 777 temp_uploads saved_images
38
 
39
+ # ── Pre-download public models at BUILD time ─────────────────────
40
+ # SigLIP, DINOv2, YOLO, InsightFace buffalo_l no token needed
 
 
 
 
 
 
 
 
41
  RUN python - <<'EOF'
42
  import os, sys
43
 
44
+ print("Pre-downloading SigLIP...")
45
+ from transformers import AutoProcessor, AutoModel, AutoImageProcessor
 
46
  AutoProcessor.from_pretrained("google/siglip-base-patch16-224", use_fast=True)
47
  AutoModel.from_pretrained("google/siglip-base-patch16-224")
48
+ print("SigLIP done")
49
 
50
+ print("Pre-downloading DINOv2...")
 
 
51
  AutoImageProcessor.from_pretrained("facebook/dinov2-base")
52
  AutoModel.from_pretrained("facebook/dinov2-base")
53
+ print("DINOv2 done")
54
 
55
+ print("Pre-downloading YOLO11n-seg...")
 
56
  from ultralytics import YOLO
57
  YOLO("yolo11n-seg.pt")
58
+ print("YOLO done")
59
 
60
+ print("Pre-downloading InsightFace buffalo_l...")
 
 
 
61
  import numpy as np
62
  from insightface.app import FaceAnalysis
63
+ face_app = FaceAnalysis(name="buffalo_l", providers=["CPUExecutionProvider"])
 
 
 
64
  face_app.prepare(ctx_id=-1, det_size=(640, 640))
65
+ face_app.get(np.zeros((112, 112, 3), dtype=np.uint8))
66
+ print("InsightFace buffalo_l done")
 
 
 
 
 
 
 
 
 
 
 
67
 
68
+ print("All public models pre-downloaded successfully")
69
+ EOF
 
 
70
 
71
+ # ── Pre-download AdaFace (separate step — graceful failure) ───────
72
+ # Split from above so a failure here does NOT fail the whole build.
73
+ # If HF_TOKEN is missing or wrong, build still succeeds and the app
74
+ # runs in ArcFace-only fallback mode (zero-padded to 1024-D).
75
+ RUN python - <<'EOF'
76
+ import os, sys, traceback
77
 
78
+ HF_TOKEN = os.getenv("HF_TOKEN", "").strip()
79
+ REPO_ID = "minchul/cvlface_adaface_ir50_ms1mv2"
80
+ CACHE_PATH = os.path.expanduser("~/.cvlface_cache/minchul/cvlface_adaface_ir50_ms1mv2")
81
 
82
+ if not HF_TOKEN:
83
+ print("HF_TOKEN not set - skipping AdaFace pre-download")
84
+ print("AdaFace will retry at runtime if HF_TOKEN is set then")
85
+ print("Fallback: ArcFace-only zero-padded to 1024-D (build succeeds)")
86
+ sys.exit(0)
87
 
 
 
88
  try:
89
+ from huggingface_hub import hf_hub_download
90
+ from transformers import AutoModel
91
+ import torch
92
+
93
+ print("Pre-downloading AdaFace IR-50 MS1MV2...")
94
+ os.makedirs(CACHE_PATH, exist_ok=True)
95
+
96
+ hf_hub_download(repo_id=REPO_ID, filename="files.txt",
97
+ token=HF_TOKEN, local_dir=CACHE_PATH, local_dir_use_symlinks=False)
98
+
99
+ with open(os.path.join(CACHE_PATH, "files.txt")) as f:
100
+ extra = [x.strip() for x in f.read().split("\n") if x.strip()]
101
+
102
+ for fname in extra + ["config.json", "wrapper.py", "model.safetensors"]:
103
+ fpath = os.path.join(CACHE_PATH, fname)
104
+ if not os.path.exists(fpath):
105
+ print("Downloading " + fname)
106
+ hf_hub_download(repo_id=REPO_ID, filename=fname,
107
+ token=HF_TOKEN, local_dir=CACHE_PATH, local_dir_use_symlinks=False)
108
+
109
+ cwd = os.getcwd()
110
+ os.chdir(CACHE_PATH)
111
+ sys.path.insert(0, CACHE_PATH)
112
+ try:
113
+ model = AutoModel.from_pretrained(
114
+ CACHE_PATH, trust_remote_code=True, token=HF_TOKEN)
115
+ finally:
116
+ os.chdir(cwd)
117
+ if CACHE_PATH in sys.path:
118
+ sys.path.remove(CACHE_PATH)
119
+
120
+ with torch.no_grad():
121
+ out = model(torch.zeros(1, 3, 112, 112))
122
+ emb = out if isinstance(out, torch.Tensor) else out.embedding
123
+ print("AdaFace pre-download complete - output dim=" + str(emb.shape[-1]))
124
+ print("1024-D FULL FUSION will be active at runtime")
125
+
126
+ except Exception as e:
127
+ print("AdaFace pre-download failed: " + str(e))
128
+ print(traceback.format_exc()[-400:])
129
+ print("Build continues - fallback to ArcFace-only zero-padded 1024-D")
130
+ sys.exit(0)
131
  EOF
132
 
133
  EXPOSE 7860
134
 
135
  # ── Single worker — InsightFace ONNX is NOT thread-safe ──────────
 
 
 
 
136
  ENV WEB_CONCURRENCY=1
137
 
138
  CMD uvicorn main:app \