Lior-0618 commited on
Commit
d0d44f6
·
1 Parent(s): 468f785

fix: detect Git LFS pointer in FER model, auto-download real binary

Browse files

If Docker COPY models/ copies a Git LFS pointer instead of the actual
ONNX binary, _init_fer() now:
1. Logs file size + first bytes for diagnosis
2. Detects LFS pointer (file <10KB starting with "version https://git-lfs")
3. Downloads the real binary from HF Space resolve URL
4. Loads the downloaded binary instead

Also adds onnxruntime version logging and full traceback on load failure.

Files changed (1) hide show
  1. api/main.py +51 -1
api/main.py CHANGED
@@ -115,6 +115,39 @@ _FER_CLASSES = ["Anger", "Contempt", "Disgust", "Fear", "Happy", "Neutral", "S
115
  _VIDEO_EXTS = {".mp4", ".mkv", ".avi", ".mov", ".m4v"}
116
 
117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  def _init_fer() -> None:
119
  global _fer_session, _fer_input_name, _face_cascade
120
 
@@ -129,13 +162,30 @@ def _init_fer() -> None:
129
  print("[voxtral] FER model not found — facial emotion disabled")
130
  return
131
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  try:
133
  import onnxruntime as rt
 
134
  _fer_session = rt.InferenceSession(fer_path, providers=["CPUExecutionProvider"])
135
  _fer_input_name = _fer_session.get_inputs()[0].name
136
- print(f"[voxtral] FER model loaded: {fer_path} (input={_fer_input_name})")
137
  except Exception as e:
 
138
  print(f"[voxtral] FER model load failed: {e}")
 
139
  return
140
 
141
  try:
 
115
  _VIDEO_EXTS = {".mp4", ".mkv", ".avi", ".mov", ".m4v"}
116
 
117
 
118
+ def _is_lfs_pointer(path: str) -> bool:
119
+ """Return True if the file looks like a Git LFS pointer (small text file)."""
120
+ try:
121
+ size = os.path.getsize(path)
122
+ if size > 10_000:
123
+ return False
124
+ with open(path, "rb") as f:
125
+ header = f.read(64)
126
+ return header.startswith(b"version https://git-lfs")
127
+ except Exception:
128
+ return False
129
+
130
+
131
+ def _resolve_lfs_model(fer_path: str) -> str:
132
+ """
133
+ If fer_path is a Git LFS pointer, download the real binary.
134
+ Returns the path to the actual model file.
135
+ """
136
+ import urllib.request
137
+ real_path = fer_path + ".resolved"
138
+ # Use HF Space's own file resolution URL to download the actual binary
139
+ url = "https://huggingface.co/spaces/mistral-hackaton-2026/ethos/resolve/main/models/emotion_model_web.onnx"
140
+ print(f"[voxtral] FER: file is LFS pointer — downloading from {url}")
141
+ try:
142
+ urllib.request.urlretrieve(url, real_path)
143
+ size = os.path.getsize(real_path)
144
+ print(f"[voxtral] FER: downloaded {size} bytes to {real_path}")
145
+ return real_path
146
+ except Exception as e:
147
+ print(f"[voxtral] FER: download failed: {e}")
148
+ return fer_path
149
+
150
+
151
  def _init_fer() -> None:
152
  global _fer_session, _fer_input_name, _face_cascade
153
 
 
162
  print("[voxtral] FER model not found — facial emotion disabled")
163
  return
164
 
165
+ # Debug: log file size and first bytes to diagnose LFS pointer vs real binary
166
+ try:
167
+ file_size = os.path.getsize(fer_path)
168
+ with open(fer_path, "rb") as f:
169
+ first_bytes = f.read(32).hex()
170
+ print(f"[voxtral] FER file: {fer_path} size={file_size} first_bytes={first_bytes}")
171
+ except Exception as e:
172
+ print(f"[voxtral] FER file stat error: {e}")
173
+
174
+ # If it's a Git LFS pointer, download the actual binary
175
+ if _is_lfs_pointer(fer_path):
176
+ print("[voxtral] FER: detected Git LFS pointer — resolving...")
177
+ fer_path = _resolve_lfs_model(fer_path)
178
+
179
  try:
180
  import onnxruntime as rt
181
+ print(f"[voxtral] FER: onnxruntime version = {rt.__version__}")
182
  _fer_session = rt.InferenceSession(fer_path, providers=["CPUExecutionProvider"])
183
  _fer_input_name = _fer_session.get_inputs()[0].name
184
+ print(f"[voxtral] FER model loaded: {fer_path} (input={_fer_input_name}, shape={_fer_session.get_inputs()[0].shape})")
185
  except Exception as e:
186
+ import traceback
187
  print(f"[voxtral] FER model load failed: {e}")
188
+ print(f"[voxtral] FER traceback: {traceback.format_exc()}")
189
  return
190
 
191
  try: