AdarshDRC commited on
Commit
cbbe6c5
·
1 Parent(s): c5da3f3

fix: build issues

Browse files
Files changed (1) hide show
  1. src/models.py +45 -83
src/models.py CHANGED
@@ -44,18 +44,9 @@ except ImportError:
44
  print(" pip install insightface onnxruntime (linux/win)")
45
 
46
  # ── AdaFace ──────────────────────────────────────────────────────
47
- # AdaFace IR-50 MS1MV2 (CVPR 2022) quality-adaptive margin loss
48
- # Repo : minchul/cvlface_adaface_ir50_ms1mv2 (HuggingFace)
49
- # Loaded : AutoModel + trust_remote_code=True (custom_code repo)
50
- # Needs : HF_TOKEN env var set in HF Space secrets
51
- try:
52
- import shutil as _shutil
53
- from huggingface_hub import hf_hub_download
54
- from transformers import AutoModel as _HF_AutoModel
55
- ADAFACE_WEIGHTS_AVAILABLE = True
56
- except ImportError:
57
- ADAFACE_WEIGHTS_AVAILABLE = False
58
- print("⚠️ huggingface_hub / transformers not installed — AdaFace fusion disabled")
59
 
60
  # ── Constants ─────────────────────────────────────────────────────
61
  YOLO_PERSON_CLASS_ID = 0
@@ -230,97 +221,58 @@ class AIModelManager:
230
 
231
  def _load_adaface(self):
232
  """
233
- Load AdaFace IR-50 MS1MV2 from HuggingFace.
234
- Repo : minchul/cvlface_adaface_ir50_ms1mv2
235
- Method : AutoModel + trust_remote_code (repo has custom_code)
236
- Token : HF_TOKEN env var (required for custom_code repos)
237
- Output : 512-D L2-normalised embedding per face crop
238
  """
239
- if not ADAFACE_WEIGHTS_AVAILABLE:
240
- print("⚠️ AdaFace skipped — huggingface_hub / transformers not installed")
 
 
241
  return
242
 
243
- import os, sys
244
-
245
- REPO_ID = "minchul/cvlface_adaface_ir50_ms1mv2"
246
  HF_TOKEN = os.getenv("HF_TOKEN", None)
 
247
  CACHE_PATH = os.path.expanduser("~/.cvlface_cache/minchul/cvlface_adaface_ir50_ms1mv2")
248
-
249
  try:
250
- print("📦 Loading AdaFace IR-50 MS1MV2 from HuggingFace...")
251
- if HF_TOKEN:
252
- print(" HF_TOKEN found ✅")
253
- else:
254
- print(" ⚠️ HF_TOKEN not set — may fail on gated/custom_code repos")
255
-
256
- # ── Step 1: Download all repo files ──────────────────
257
  os.makedirs(CACHE_PATH, exist_ok=True)
258
-
259
- # Download files.txt manifest first
260
- files_txt = os.path.join(CACHE_PATH, "files.txt")
261
- if not os.path.exists(files_txt):
262
- hf_hub_download(
263
- repo_id=REPO_ID, filename="files.txt",
264
- token=HF_TOKEN, local_dir=CACHE_PATH,
265
- local_dir_use_symlinks=False,
266
- )
267
-
268
- # Read manifest and download each listed file
269
- with open(files_txt, "r") as f:
270
- extra_files = [x.strip() for x in f.read().split("\n") if x.strip()]
271
-
272
- for fname in extra_files + ["config.json", "wrapper.py", "model.safetensors"]:
273
  fpath = os.path.join(CACHE_PATH, fname)
274
  if not os.path.exists(fpath):
275
- print(f" Downloading {fname}...")
276
- hf_hub_download(
277
- repo_id=REPO_ID, filename=fname,
278
- token=HF_TOKEN, local_dir=CACHE_PATH,
279
- local_dir_use_symlinks=False,
280
- )
281
-
282
- # ── Step 2: Load model from local cache ──────────────
283
- # Must chdir + add to sys.path because the repo uses
284
- # trust_remote_code with relative imports in wrapper.py
285
  cwd = os.getcwd()
286
  os.chdir(CACHE_PATH)
287
  sys.path.insert(0, CACHE_PATH)
288
  try:
 
289
  model = _HF_AutoModel.from_pretrained(
290
- CACHE_PATH,
291
- trust_remote_code=True,
292
- token=HF_TOKEN,
293
- )
294
  finally:
295
  os.chdir(cwd)
296
- if CACHE_PATH in sys.path:
297
- sys.path.remove(CACHE_PATH)
298
-
299
  model = model.to(self.device).eval()
300
- if self.device == "cuda":
301
- model = model.half()
302
-
303
- # ── Step 3: Verify output shape ───────────────────────
304
  with torch.no_grad():
305
- dummy = torch.zeros(1, 3, 112, 112).to(self.device)
306
- out = model(dummy)
307
- # Model may return tensor directly or an object with .embedding
308
- out_vec = out if isinstance(out, torch.Tensor) else out.embedding
309
- out_dim = out_vec.shape[-1]
310
- if out_dim != ADAFACE_DIM:
311
- raise ValueError(
312
- f"AdaFace output dim={out_dim}, expected {ADAFACE_DIM}")
313
-
314
  self.adaface_model = model
315
- print(f"✅ AdaFace IR-50 MS1MV2 loaded — output dim={out_dim} — 1024-D fusion ACTIVE")
316
-
317
  except Exception as e:
318
- print(f"⚠️ AdaFace load failed: {e}")
319
- print(f" Detail: {traceback.format_exc()[-500:]}")
320
- print(" Falling back to ArcFace-only (zero-padded to 1024-D)")
321
  self.adaface_model = None
322
 
323
- # ── Object Lane: batched SigLIP + DINOv2 embedding ───────────
324
  def _embed_crops_batch(self, crops: list) -> list:
325
  """Embed a list of PIL images → list of 1536-D numpy arrays."""
326
  if not crops:
@@ -333,8 +285,18 @@ class AIModelManager:
333
  sig_in = {k: v.half() if v.dtype == torch.float32 else v
334
  for k, v in sig_in.items()}
335
  sig_out = self.siglip_model.get_image_features(**sig_in)
336
- if hasattr(sig_out, "image_embeds"): sig_out = sig_out.image_embeds
337
- elif isinstance(sig_out, tuple): sig_out = sig_out[0]
 
 
 
 
 
 
 
 
 
 
338
  sig_vecs = F.normalize(sig_out.float(), p=2, dim=1).cpu()
339
 
340
  # DINOv2
 
44
  print(" pip install insightface onnxruntime (linux/win)")
45
 
46
  # ── AdaFace ──────────────────────────────────────────────────────
47
+ # Disabled by default enable by setting ENABLE_ADAFACE=1 env var.
48
+ # When disabled: ArcFace(512) + zeros(512) = 1024-D (fully functional).
49
+ ADAFACE_WEIGHTS_AVAILABLE = False # controlled by ENABLE_ADAFACE env var
 
 
 
 
 
 
 
 
 
50
 
51
  # ── Constants ─────────────────────────────────────────────────────
52
  YOLO_PERSON_CLASS_ID = 0
 
221
 
222
  def _load_adaface(self):
223
  """
224
+ AdaFace IR-50 MS1MV2 disabled for now.
225
+ Face vectors use ArcFace(512) + zeros(512) = 1024-D.
226
+ This is fully functional cosine similarity works correctly.
227
+ Re-enable by setting ENABLE_ADAFACE=1 env var when HF token
228
+ injection into Docker build is confirmed working.
229
  """
230
+ enable = os.getenv("ENABLE_ADAFACE", "0").strip() == "1"
231
+ if not enable:
232
+ print("⚠️ AdaFace disabled (ENABLE_ADAFACE != 1) — using ArcFace zero-padded 1024-D")
233
+ self.adaface_model = None
234
  return
235
 
236
+ # Full loading code kept here for when AdaFace is re-enabled
237
+ import sys
 
238
  HF_TOKEN = os.getenv("HF_TOKEN", None)
239
+ REPO_ID = "minchul/cvlface_adaface_ir50_ms1mv2"
240
  CACHE_PATH = os.path.expanduser("~/.cvlface_cache/minchul/cvlface_adaface_ir50_ms1mv2")
 
241
  try:
242
+ from huggingface_hub import hf_hub_download
243
+ print("📦 Loading AdaFace IR-50 MS1MV2...")
 
 
 
 
 
244
  os.makedirs(CACHE_PATH, exist_ok=True)
245
+ hf_hub_download(repo_id=REPO_ID, filename="files.txt",
246
+ token=HF_TOKEN, local_dir=CACHE_PATH, local_dir_use_symlinks=False)
247
+ with open(os.path.join(CACHE_PATH, "files.txt")) as f:
248
+ extra = [x.strip() for x in f.read().split("\n") if x.strip()]
249
+ for fname in extra + ["config.json", "wrapper.py", "model.safetensors"]:
 
 
 
 
 
 
 
 
 
 
250
  fpath = os.path.join(CACHE_PATH, fname)
251
  if not os.path.exists(fpath):
252
+ hf_hub_download(repo_id=REPO_ID, filename=fname,
253
+ token=HF_TOKEN, local_dir=CACHE_PATH, local_dir_use_symlinks=False)
 
 
 
 
 
 
 
 
254
  cwd = os.getcwd()
255
  os.chdir(CACHE_PATH)
256
  sys.path.insert(0, CACHE_PATH)
257
  try:
258
+ from transformers import AutoModel as _HF_AutoModel
259
  model = _HF_AutoModel.from_pretrained(
260
+ CACHE_PATH, trust_remote_code=True, token=HF_TOKEN)
 
 
 
261
  finally:
262
  os.chdir(cwd)
263
+ if CACHE_PATH in sys.path: sys.path.remove(CACHE_PATH)
 
 
264
  model = model.to(self.device).eval()
 
 
 
 
265
  with torch.no_grad():
266
+ out = model(torch.zeros(1, 3, 112, 112).to(self.device))
267
+ emb = out if isinstance(out, torch.Tensor) else out.embedding
268
+ assert emb.shape[-1] == ADAFACE_DIM
 
 
 
 
 
 
269
  self.adaface_model = model
270
+ print(f"✅ AdaFace IR-50 loaded — 1024-D FULL FUSION active")
 
271
  except Exception as e:
272
+ print(f"⚠️ AdaFace load failed: {e} — falling back to zero-padded 1024-D")
 
 
273
  self.adaface_model = None
274
 
275
+ # ── Object Lane: batched SigLIP + DINOv2 embedding ───────────
276
  def _embed_crops_batch(self, crops: list) -> list:
277
  """Embed a list of PIL images → list of 1536-D numpy arrays."""
278
  if not crops:
 
285
  sig_in = {k: v.half() if v.dtype == torch.float32 else v
286
  for k, v in sig_in.items()}
287
  sig_out = self.siglip_model.get_image_features(**sig_in)
288
+ # Handle all output types across transformers versions
289
+ if hasattr(sig_out, "image_embeds"):
290
+ sig_out = sig_out.image_embeds
291
+ elif hasattr(sig_out, "pooler_output"):
292
+ sig_out = sig_out.pooler_output
293
+ elif hasattr(sig_out, "last_hidden_state"):
294
+ sig_out = sig_out.last_hidden_state[:, 0, :]
295
+ elif isinstance(sig_out, tuple):
296
+ sig_out = sig_out[0]
297
+ # sig_out is now a tensor
298
+ if not isinstance(sig_out, torch.Tensor):
299
+ sig_out = sig_out[0]
300
  sig_vecs = F.normalize(sig_out.float(), p=2, dim=1).cpu()
301
 
302
  # DINOv2