kbarnard Claude Sonnet 5 commited on
Commit
5b9891d
·
1 Parent(s): bef2e5b

Fix launch-timeout crash and remove dead Dockerfile

Browse files

Root cause: the yolov5 package's torch.hub download of the yolov5 repo
code, combined with unpinned CUDA torch wheels on cpu-basic hardware,
pushed the build well past the 30-minute health-check window. Redirect
Torch caches to /tmp, pin CPU-only torch/torchvision, patch torch.load
for PyTorch 2.6+'s weights_only default so the legacy yolov5 checkpoint
still loads, and drop the unused Dockerfile/tator_inference.py/tator
dependency left over from an old pipeline the gradio-SDK space never
actually used. Bump gradio to 6.9.0.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Files changed (5) hide show
  1. Dockerfile +0 -10
  2. README.md +1 -1
  3. inference.py +19 -0
  4. requirements.txt +4 -1
  5. tator_inference.py +0 -100
Dockerfile DELETED
@@ -1,10 +0,0 @@
1
- FROM python:3.7
2
-
3
- RUN apt-get update \
4
- && apt-get install ffmpeg libsm6 libxext6 -y
5
-
6
- RUN pip install yolov5 tator gradio
7
-
8
- COPY . ./
9
-
10
- CMD [ "python", "-u", "./tator_inference.py" ]
 
 
 
 
 
 
 
 
 
 
 
README.md CHANGED
@@ -4,7 +4,7 @@ emoji: 🐠
4
  colorFrom: indigo
5
  colorTo: gray
6
  sdk: gradio
7
- sdk_version: 4.36.1
8
  app_file: app.py
9
  pinned: false
10
  ---
 
4
  colorFrom: indigo
5
  colorTo: gray
6
  sdk: gradio
7
+ sdk_version: 6.9.0
8
  app_file: app.py
9
  pinned: false
10
  ---
inference.py CHANGED
@@ -1,6 +1,25 @@
 
 
 
 
 
 
 
 
 
1
  import glob
2
  import numpy as np
3
  import torch
 
 
 
 
 
 
 
 
 
 
4
  import yolov5
5
  from typing import Union, List, Optional
6
 
 
1
+ import os
2
+
3
+ # Keep Torch/YOLO hub caches off the Space's persistent disk so repeated
4
+ # loads don't exceed the storage quota:
5
+ # https://discuss.huggingface.co/t/how-to-fix-workload-evicted-storage-limit-exceeded-50g-error-in-huggingface-spaces/169258
6
+ os.environ.setdefault("TORCH_HOME", "/tmp/torch_cache")
7
+ os.environ.setdefault("HUB_DIR", "/tmp/torch_hub")
8
+ os.environ.setdefault("TMPDIR", "/tmp")
9
+
10
  import glob
11
  import numpy as np
12
  import torch
13
+
14
+ # PyTorch >=2.6 defaults torch.load(weights_only=True), which can't unpickle
15
+ # this legacy yolov5 checkpoint format. We trust this checkpoint (it's our
16
+ # own model), so restore the old default for it.
17
+ _torch_load = torch.load
18
+ def _torch_load_compat(*args, **kwargs):
19
+ kwargs.setdefault("weights_only", False)
20
+ return _torch_load(*args, **kwargs)
21
+ torch.load = _torch_load_compat
22
+
23
  import yolov5
24
  from typing import Union, List, Optional
25
 
requirements.txt CHANGED
@@ -1,3 +1,6 @@
 
 
 
1
  numpy<2.0
2
  yolov5==6.2.3
3
- tator
 
1
+ --extra-index-url https://download.pytorch.org/whl/cpu
2
+ torch==2.14.0
3
+ torchvision==0.29.0
4
  numpy<2.0
5
  yolov5==6.2.3
6
+ setuptools<81
tator_inference.py DELETED
@@ -1,100 +0,0 @@
1
- import os
2
- import logging
3
- from tempfile import TemporaryFile
4
-
5
- import cv2
6
- import numpy as np
7
- from PIL import Image
8
-
9
- import tator
10
- import inference
11
-
12
-
13
- logger = logging.getLogger(__name__)
14
- logger.setLevel(logging.INFO)
15
-
16
- # Read environment variables that are provided from TATOR
17
- host = os.getenv('HOST')
18
- token = os.getenv('TOKEN')
19
- project_id = int(os.getenv('PROJECT_ID'))
20
- media_ids = [int(id_) for id_ in os.getenv('MEDIA_IDS').split(',')]
21
- frames_per_inference = int(os.getenv('FRAMES_PER_INFERENCE', 30))
22
-
23
- # Set up the TATOR API.
24
- api = tator.get_api(host, token)
25
-
26
- # Iterate through each video.
27
- for media_id in media_ids:
28
-
29
- # Download video.
30
- media = api.get_media(media_id)
31
- logger.info(f"Downloading {media.name}...")
32
- out_path = f"/tmp/{media.name}"
33
- for progress in tator.util.download_media(api, media, out_path):
34
- logger.info(f"Download progress: {progress}%")
35
-
36
- # Do inference on each video.
37
- logger.info(f"Doing inference on {media.name}...")
38
- localizations = []
39
- vid = cv2.VideoCapture(out_path)
40
- frame_number = 0
41
-
42
- # Read *every* frame from the video, break when at the end.
43
- while True:
44
- ret, frame = vid.read()
45
- if not ret:
46
- break
47
-
48
- # Create a temporary file, access the image data, save data to file.
49
- framefile = TemporaryFile(suffix='.jpg')
50
- im = Image.fromarray(frame)
51
- im.save(framefile)
52
-
53
- # For every N frames, make a prediction; append prediction results
54
- # to a list, increase the frame count.
55
- if frame_number % frames_per_inference == 0:
56
-
57
- spec = {}
58
-
59
- # Predictions contains all information inside pandas dataframe
60
- predictions = inference.run_inference(framefile)
61
-
62
- for i, r in predictions.pandas().xyxy[0].iterrows:
63
-
64
- spec['media_id'] = media_id
65
- spec['type'] = None # Unsure, docs not specific
66
- spec['frame'] = frame_number
67
-
68
- x, y, x2, y2 = r['xmin'], r['ymin'], r['xmax'], r['ymax']
69
- w, h = x2 - x, y2 - y
70
-
71
- spec['x'] = x
72
- spec['y'] = y
73
- spec['width'] = w
74
- spec['height'] = h
75
- spec['class_category'] = r['name']
76
- spec['confidence'] = r['confidence']
77
-
78
- localizations.append(spec)
79
-
80
- frame_number += 1
81
-
82
- # End interaction with video properly.
83
- vid.release()
84
-
85
- logger.info(f"Uploading object detections on {media.name}...")
86
-
87
- # Create the localizations in the video.
88
- num_created = 0
89
- for response in tator.util.chunked_create(api.create_localization_list,
90
- project_id,
91
- localization_spec=localizations):
92
- num_created += len(response.id)
93
-
94
- # Output pretty logging information.
95
- logger.info(f"Successfully created {num_created} localizations on "
96
- f"{media.name}!")
97
-
98
- logger.info("-------------------------------------------------")
99
-
100
- logger.info(f"Completed inference on {len(media_ids)} files.")