Spaces:
Sleeping
Sleeping
k22056537 commited on
Commit ·
f6f50c4
1
Parent(s): 5bbefab
fix: resolve LFS pointers at runtime instead of build time
Browse filesBuild-time downloads fail (circular dep — files not served while
building). Moved LFS resolution to a startup script that runs
before uvicorn launches.
- Dockerfile +2 -47
- resolve_lfs.py +46 -0
- start.sh +8 -0
Dockerfile
CHANGED
|
@@ -21,58 +21,13 @@ RUN pip install --no-cache-dir -r requirements.txt
|
|
| 21 |
|
| 22 |
COPY . .
|
| 23 |
|
| 24 |
-
# HF Docker builds copy LFS pointers, not real files.
|
| 25 |
-
# Resolve them by downloading from the HF API.
|
| 26 |
-
ARG HF_SPACE=FocusGuard/final
|
| 27 |
-
RUN python -c "\
|
| 28 |
-
import os, urllib.request, sys;\
|
| 29 |
-
SPACE='${HF_SPACE}';\
|
| 30 |
-
BASE=f'https://huggingface.co/spaces/{SPACE}/resolve/main';\
|
| 31 |
-
files=[\
|
| 32 |
-
'checkpoints/mlp_best.pt',\
|
| 33 |
-
'checkpoints/scaler_mlp.joblib',\
|
| 34 |
-
'checkpoints/hybrid_combiner.joblib',\
|
| 35 |
-
'checkpoints/hybrid_focus_config.json',\
|
| 36 |
-
'checkpoints/xgboost_face_orientation_best.json',\
|
| 37 |
-
'checkpoints/meta_best.npz',\
|
| 38 |
-
'checkpoints/meta_mlp.npz',\
|
| 39 |
-
'checkpoints/L2CSNet_gaze360.pkl',\
|
| 40 |
-
'models/L2CS-Net/models/L2CSNet_gaze360.pkl',\
|
| 41 |
-
];\
|
| 42 |
-
for f in files:\
|
| 43 |
-
path=f;\
|
| 44 |
-
is_ptr=False;\
|
| 45 |
-
if os.path.isfile(path):\
|
| 46 |
-
with open(path,'rb') as fh:\
|
| 47 |
-
is_ptr=fh.read(50).startswith(b'version https://git-lfs');\
|
| 48 |
-
if not os.path.isfile(path) or is_ptr:\
|
| 49 |
-
url=f'{BASE}/{f}';\
|
| 50 |
-
print(f'Downloading {f} ...');\
|
| 51 |
-
try:\
|
| 52 |
-
os.makedirs(os.path.dirname(path),exist_ok=True);\
|
| 53 |
-
urllib.request.urlretrieve(url,path);\
|
| 54 |
-
sz=os.path.getsize(path);\
|
| 55 |
-
print(f' OK ({sz} bytes)');\
|
| 56 |
-
except Exception as e:\
|
| 57 |
-
print(f' WARN: {e}');\
|
| 58 |
-
else:\
|
| 59 |
-
print(f'[OK] {f} ({os.path.getsize(path)} bytes)');\
|
| 60 |
-
print('Checkpoint resolution done')\
|
| 61 |
-
"
|
| 62 |
-
|
| 63 |
RUN npm install && npm run build && mkdir -p /app/static && cp -R dist/* /app/static/
|
| 64 |
|
| 65 |
ENV FOCUSGUARD_CACHE_DIR=/app/.cache/focusguard
|
| 66 |
-
RUN python -c "\
|
| 67 |
-
try:\
|
| 68 |
-
from models.face_mesh import _ensure_model; _ensure_model(); print('face_mesh model cached')\
|
| 69 |
-
except Exception as e:\
|
| 70 |
-
print(f'face_mesh pre-download skipped: {e} — will retry at runtime')\
|
| 71 |
-
"
|
| 72 |
|
| 73 |
-
RUN mkdir -p /app/data && chown -R user:user /app
|
| 74 |
|
| 75 |
USER user
|
| 76 |
EXPOSE 7860
|
| 77 |
|
| 78 |
-
CMD ["
|
|
|
|
| 21 |
|
| 22 |
COPY . .
|
| 23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
RUN npm install && npm run build && mkdir -p /app/static && cp -R dist/* /app/static/
|
| 25 |
|
| 26 |
ENV FOCUSGUARD_CACHE_DIR=/app/.cache/focusguard
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
+
RUN mkdir -p /app/data /app/.cache && chown -R user:user /app
|
| 29 |
|
| 30 |
USER user
|
| 31 |
EXPOSE 7860
|
| 32 |
|
| 33 |
+
CMD ["bash", "start.sh"]
|
resolve_lfs.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Resolve Git LFS pointers left by HF Docker builds."""
|
| 2 |
+
import os
|
| 3 |
+
import urllib.request
|
| 4 |
+
|
| 5 |
+
SPACE = os.environ.get("SPACE_ID", "FocusGuard/final")
|
| 6 |
+
BASE = f"https://huggingface.co/spaces/{SPACE}/resolve/main"
|
| 7 |
+
|
| 8 |
+
FILES = [
|
| 9 |
+
"checkpoints/mlp_best.pt",
|
| 10 |
+
"checkpoints/scaler_mlp.joblib",
|
| 11 |
+
"checkpoints/hybrid_combiner.joblib",
|
| 12 |
+
"checkpoints/hybrid_focus_config.json",
|
| 13 |
+
"checkpoints/xgboost_face_orientation_best.json",
|
| 14 |
+
"checkpoints/meta_best.npz",
|
| 15 |
+
"checkpoints/meta_mlp.npz",
|
| 16 |
+
"checkpoints/L2CSNet_gaze360.pkl",
|
| 17 |
+
"models/L2CS-Net/models/L2CSNet_gaze360.pkl",
|
| 18 |
+
]
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def _is_lfs_pointer(path):
|
| 22 |
+
if not os.path.isfile(path):
|
| 23 |
+
return True
|
| 24 |
+
with open(path, "rb") as f:
|
| 25 |
+
return f.read(50).startswith(b"version https://git-lfs")
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def resolve():
|
| 29 |
+
for rel in FILES:
|
| 30 |
+
if not _is_lfs_pointer(rel):
|
| 31 |
+
sz = os.path.getsize(rel)
|
| 32 |
+
print(f"[OK] {rel} ({sz} bytes)")
|
| 33 |
+
continue
|
| 34 |
+
url = f"{BASE}/{rel}"
|
| 35 |
+
print(f"[LFS] Downloading {rel} ...")
|
| 36 |
+
try:
|
| 37 |
+
os.makedirs(os.path.dirname(rel), exist_ok=True)
|
| 38 |
+
urllib.request.urlretrieve(url, rel)
|
| 39 |
+
print(f" -> {os.path.getsize(rel)} bytes")
|
| 40 |
+
except Exception as e:
|
| 41 |
+
print(f" WARN: {e}")
|
| 42 |
+
print("LFS resolution done.")
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
if __name__ == "__main__":
|
| 46 |
+
resolve()
|
start.sh
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
set -e
|
| 3 |
+
|
| 4 |
+
echo "=== Resolving LFS pointers ==="
|
| 5 |
+
python resolve_lfs.py
|
| 6 |
+
|
| 7 |
+
echo "=== Starting FocusGuard ==="
|
| 8 |
+
exec uvicorn main:app --host 0.0.0.0 --port 7860 --log-level info
|