Sean Carnahan commited on
Commit
e2839df
·
1 Parent(s): fef15d6

Fix internal server error: Add memory management and improve error handling

Browse files
Files changed (2) hide show
  1. Dockerfile +5 -1
  2. app.py +46 -7
Dockerfile CHANGED
@@ -6,6 +6,7 @@ WORKDIR /code
6
  RUN apt-get update && apt-get install -y \
7
  libgl1-mesa-glx \
8
  libglib2.0-0 \
 
9
  && rm -rf /var/lib/apt/lists/*
10
 
11
  # Copy requirements first to leverage Docker cache
@@ -16,9 +17,11 @@ RUN pip install --no-cache-dir -r requirements.txt
16
  RUN mkdir -p /code/static/uploads \
17
  && mkdir -p /code/logs \
18
  && mkdir -p /code/external/BodybuildingPoseClassifier \
 
19
  && chmod -R 777 /code/static/uploads \
20
  && chmod -R 777 /code/logs \
21
- && chmod -R 777 /code/external
 
22
 
23
  # Copy the model file first
24
  COPY external/BodybuildingPoseClassifier/bodybuilding_pose_classifier.h5 /code/external/BodybuildingPoseClassifier/
@@ -29,6 +32,7 @@ COPY . .
29
  # Set environment variables
30
  ENV PYTHONUNBUFFERED=1
31
  ENV FLASK_APP=app.py
 
32
 
33
  # Expose the port
34
  EXPOSE 7860
 
6
  RUN apt-get update && apt-get install -y \
7
  libgl1-mesa-glx \
8
  libglib2.0-0 \
9
+ ffmpeg \
10
  && rm -rf /var/lib/apt/lists/*
11
 
12
  # Copy requirements first to leverage Docker cache
 
17
  RUN mkdir -p /code/static/uploads \
18
  && mkdir -p /code/logs \
19
  && mkdir -p /code/external/BodybuildingPoseClassifier \
20
+ && mkdir -p /code/templates \
21
  && chmod -R 777 /code/static/uploads \
22
  && chmod -R 777 /code/logs \
23
+ && chmod -R 777 /code/external \
24
+ && chmod -R 777 /code/templates
25
 
26
  # Copy the model file first
27
  COPY external/BodybuildingPoseClassifier/bodybuilding_pose_classifier.h5 /code/external/BodybuildingPoseClassifier/
 
32
  # Set environment variables
33
  ENV PYTHONUNBUFFERED=1
34
  ENV FLASK_APP=app.py
35
+ ENV TF_CPP_MIN_LOG_LEVEL=2
36
 
37
  # Expose the port
38
  EXPOSE 7860
app.py CHANGED
@@ -42,6 +42,23 @@ logging.basicConfig(
42
  )
43
  logger = logging.getLogger(__name__)
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  # Add file handler for persistent logging
46
  log_dir = 'logs'
47
  os.makedirs(log_dir, exist_ok=True)
@@ -83,6 +100,19 @@ except Exception as e:
83
  logger.error(traceback.format_exc())
84
  raise
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  cnn_class_labels = ['side_chest', 'front_double_biceps', 'back_double_biceps', 'front_lat_spread', 'back_lat_spread']
87
 
88
  def predict_pose_cnn(img_path):
@@ -371,6 +401,21 @@ def process_video_mediapipe(video_path):
371
  def index():
372
  return render_template('index.html')
373
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  @app.route('/upload', methods=['POST'])
375
  def upload_file():
376
  try:
@@ -416,13 +461,7 @@ def upload_file():
416
  model_choice = request.form.get('model_choice', 'Gladiator SupaDot')
417
  logger.info(f"[UPLOAD] Processing with model: {model_choice}")
418
 
419
- if model_choice == 'movenet':
420
- movenet_variant = request.form.get('movenet_variant', 'lightning')
421
- logger.info(f"[UPLOAD] Using MoveNet variant: {movenet_variant}")
422
- output_path_url = process_video_movenet(filepath)
423
- else:
424
- output_path_url = process_video_mediapipe(filepath)
425
-
426
  logger.info(f"[UPLOAD] Processing complete. Output URL: {output_path_url}")
427
 
428
  output_path = os.path.join(app.config['UPLOAD_FOLDER'], os.path.basename(output_path_url))
 
42
  )
43
  logger = logging.getLogger(__name__)
44
 
45
+ def log_memory_usage():
46
+ """Log current memory usage."""
47
+ try:
48
+ process = psutil.Process()
49
+ memory_info = process.memory_info()
50
+ logger.info(f"Memory usage: {memory_info.rss / 1024 / 1024:.2f} MB")
51
+ except Exception as e:
52
+ logger.error(f"Error logging memory usage: {e}")
53
+
54
+ def cleanup_memory():
55
+ """Force garbage collection and log memory usage."""
56
+ try:
57
+ gc.collect()
58
+ log_memory_usage()
59
+ except Exception as e:
60
+ logger.error(f"Error in cleanup_memory: {e}")
61
+
62
  # Add file handler for persistent logging
63
  log_dir = 'logs'
64
  os.makedirs(log_dir, exist_ok=True)
 
100
  logger.error(traceback.format_exc())
101
  raise
102
 
103
+ # Initialize TensorFlow session with memory growth
104
+ try:
105
+ gpus = tf.config.list_physical_devices('GPU')
106
+ if gpus:
107
+ for gpu in gpus:
108
+ tf.config.experimental.set_memory_growth(gpu, True)
109
+ logger.info("GPU memory growth enabled")
110
+ else:
111
+ logger.info("No GPU found, using CPU")
112
+ except Exception as e:
113
+ logger.error(f"Error configuring GPU: {e}")
114
+ logger.error(traceback.format_exc())
115
+
116
  cnn_class_labels = ['side_chest', 'front_double_biceps', 'back_double_biceps', 'front_lat_spread', 'back_lat_spread']
117
 
118
  def predict_pose_cnn(img_path):
 
401
  def index():
402
  return render_template('index.html')
403
 
404
+ # Add error handling for video processing
405
+ def safe_video_processing(video_path, model_choice):
406
+ """Wrapper function to handle video processing with proper cleanup."""
407
+ try:
408
+ if model_choice == 'movenet':
409
+ return process_video_movenet(video_path)
410
+ else:
411
+ return process_video_mediapipe(video_path)
412
+ except Exception as e:
413
+ logger.error(f"Error in video processing: {e}")
414
+ logger.error(traceback.format_exc())
415
+ raise
416
+ finally:
417
+ cleanup_memory()
418
+
419
  @app.route('/upload', methods=['POST'])
420
  def upload_file():
421
  try:
 
461
  model_choice = request.form.get('model_choice', 'Gladiator SupaDot')
462
  logger.info(f"[UPLOAD] Processing with model: {model_choice}")
463
 
464
+ output_path_url = safe_video_processing(filepath, model_choice)
 
 
 
 
 
 
465
  logger.info(f"[UPLOAD] Processing complete. Output URL: {output_path_url}")
466
 
467
  output_path = os.path.join(app.config['UPLOAD_FOLDER'], os.path.basename(output_path_url))