Justin331 commited on
Commit
d918120
·
verified ·
1 Parent(s): 031fd93

Upload handler.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. handler.py +88 -4
handler.py CHANGED
@@ -50,10 +50,19 @@ class EndpointHandler:
50
  # Build SAM3 video predictor
51
  # This automatically downloads model from facebook/sam3 on HuggingFace
52
  try:
53
- self.predictor = build_sam3_video_predictor(gpus_to_use=[0])
 
 
 
 
 
 
 
54
  print("[INIT] SAM3 video predictor loaded successfully")
55
  except Exception as e:
56
  print(f"[INIT] Error loading SAM3 predictor: {e}")
 
 
57
  raise
58
 
59
  # Initialize HuggingFace API for uploads (if available)
@@ -152,9 +161,20 @@ class EndpointHandler:
152
  for frame_idx, frame_output in outputs_per_frame.items():
153
  self._save_frame_masks(frame_output, masks_dir, frame_idx)
154
 
155
- # Collect object IDs
156
  if "object_ids" in frame_output and frame_output["object_ids"] is not None:
157
- all_object_ids.update(frame_output["object_ids"])
 
 
 
 
 
 
 
 
 
 
 
158
 
159
  print(f"[STEP 5] Saved masks for {len(outputs_per_frame)} frames")
160
 
@@ -212,6 +232,57 @@ class EndpointHandler:
212
  "error_type": type(e).__name__
213
  }
214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  def _prepare_video(self, video_data: str, tmpdir: Path) -> Path:
216
  """Decode base64 video and save to file."""
217
  try:
@@ -235,10 +306,23 @@ class EndpointHandler:
235
  masks = frame_output["masks"]
236
  object_ids = frame_output.get("object_ids", [])
237
 
238
- # Convert to numpy if tensor
 
 
 
 
 
 
 
 
239
  if torch.is_tensor(masks):
240
  masks = masks.cpu().numpy()
241
 
 
 
 
 
 
242
  # Save each object's mask
243
  for i, obj_id in enumerate(object_ids):
244
  if i < len(masks):
 
50
  # Build SAM3 video predictor
51
  # This automatically downloads model from facebook/sam3 on HuggingFace
52
  try:
53
+ # Ensure BPE tokenizer file exists
54
+ bpe_path = self._ensure_bpe_file()
55
+
56
+ # Build predictor with explicit bpe_path
57
+ self.predictor = build_sam3_video_predictor(
58
+ gpus_to_use=[0],
59
+ bpe_path=bpe_path
60
+ )
61
  print("[INIT] SAM3 video predictor loaded successfully")
62
  except Exception as e:
63
  print(f"[INIT] Error loading SAM3 predictor: {e}")
64
+ import traceback
65
+ traceback.print_exc()
66
  raise
67
 
68
  # Initialize HuggingFace API for uploads (if available)
 
161
  for frame_idx, frame_output in outputs_per_frame.items():
162
  self._save_frame_masks(frame_output, masks_dir, frame_idx)
163
 
164
+ # Collect object IDs - handle tensors properly
165
  if "object_ids" in frame_output and frame_output["object_ids"] is not None:
166
+ obj_ids = frame_output["object_ids"]
167
+ # Convert to list if tensor or numpy array
168
+ if torch.is_tensor(obj_ids):
169
+ obj_ids = obj_ids.cpu().tolist()
170
+ elif isinstance(obj_ids, np.ndarray):
171
+ obj_ids = obj_ids.tolist()
172
+
173
+ # Add to set (handles single int or list)
174
+ if isinstance(obj_ids, list):
175
+ all_object_ids.update(obj_ids)
176
+ else:
177
+ all_object_ids.add(obj_ids)
178
 
179
  print(f"[STEP 5] Saved masks for {len(outputs_per_frame)} frames")
180
 
 
232
  "error_type": type(e).__name__
233
  }
234
 
235
+ def _ensure_bpe_file(self) -> str:
236
+ """
237
+ Ensure BPE tokenizer file exists. Download from HuggingFace if missing.
238
+ Returns path to the BPE file.
239
+ """
240
+ # Default expected path
241
+ assets_dir = Path("/repository/assets")
242
+ bpe_file = assets_dir / "bpe_simple_vocab_16e6.txt.gz"
243
+
244
+ if bpe_file.exists():
245
+ print(f"[INIT] BPE file found at: {bpe_file}")
246
+ return str(bpe_file)
247
+
248
+ print(f"[INIT] BPE file not found, downloading from HuggingFace...")
249
+
250
+ # Create assets directory
251
+ assets_dir.mkdir(parents=True, exist_ok=True)
252
+
253
+ # Download BPE file from facebook/sam3 repo
254
+ try:
255
+ from huggingface_hub import hf_hub_download
256
+
257
+ downloaded_path = hf_hub_download(
258
+ repo_id="facebook/sam3",
259
+ filename="assets/bpe_simple_vocab_16e6.txt.gz",
260
+ local_dir="/repository",
261
+ local_dir_use_symlinks=False
262
+ )
263
+
264
+ print(f"[INIT] BPE file downloaded to: {downloaded_path}")
265
+ return downloaded_path
266
+
267
+ except Exception as e:
268
+ print(f"[INIT] Error downloading BPE file: {e}")
269
+ print(f"[INIT] Trying alternative download method...")
270
+
271
+ # Fallback: download directly from raw URL
272
+ import urllib.request
273
+ url = "https://huggingface.co/facebook/sam3/resolve/main/assets/bpe_simple_vocab_16e6.txt.gz"
274
+
275
+ try:
276
+ urllib.request.urlretrieve(url, str(bpe_file))
277
+ print(f"[INIT] BPE file downloaded to: {bpe_file}")
278
+ return str(bpe_file)
279
+ except Exception as e2:
280
+ print(f"[INIT] Fallback download also failed: {e2}")
281
+ raise ValueError(
282
+ f"Could not download BPE tokenizer file. Please add assets/bpe_simple_vocab_16e6.txt.gz "
283
+ f"to your repository. Download from: {url}"
284
+ )
285
+
286
  def _prepare_video(self, video_data: str, tmpdir: Path) -> Path:
287
  """Decode base64 video and save to file."""
288
  try:
 
306
  masks = frame_output["masks"]
307
  object_ids = frame_output.get("object_ids", [])
308
 
309
+ # Handle different types of object_ids
310
+ if torch.is_tensor(object_ids):
311
+ object_ids = object_ids.cpu().tolist()
312
+ elif isinstance(object_ids, np.ndarray):
313
+ object_ids = object_ids.tolist()
314
+ elif not isinstance(object_ids, list):
315
+ object_ids = list(object_ids) if object_ids is not None else []
316
+
317
+ # Convert masks to numpy if tensor
318
  if torch.is_tensor(masks):
319
  masks = masks.cpu().numpy()
320
 
321
+ # Ensure masks is 3D array [num_objects, height, width]
322
+ if len(masks.shape) == 4:
323
+ # Remove batch dimension if present
324
+ masks = masks[0]
325
+
326
  # Save each object's mask
327
  for i, obj_id in enumerate(object_ids):
328
  if i < len(masks):