Luis J Camargo commited on
Commit
84dac14
Β·
1 Parent(s): 40f26b2

Add persistent UI logging for crash debugging

Browse files
Files changed (1) hide show
  1. app.py +87 -81
app.py CHANGED
@@ -91,85 +91,87 @@ def get_mem_usage():
91
  # === INFERENCE FUNCTION ===
92
  def predict_language(audio):
93
  if audio is None:
94
- return "⚠️ No audio provided", "", ""
95
-
96
- gc.collect() # Start clean
97
- start_mem = get_mem_usage()
98
-
99
- sample_rate, audio_array = audio
100
- audio_len_sec = len(audio_array) / sample_rate
101
-
102
- # Normalization
103
- print("[LOG] Step 1: Normalizing audio...")
104
- if audio_array.dtype == np.int16:
105
- print("was npint16")
106
- audio_array = audio_array.astype(np.float32) / 32768.0
107
- elif audio_array.dtype == np.int32:
108
- print("was npint32")
109
- audio_array = audio_array.astype(np.float32) / 2147483648.0
110
- print(f"[LOG] Memory after normalization: {get_mem_usage():.2f} MB")
111
-
112
- # Resampling
113
- if sample_rate != 16000:
114
- print(f"[LOG] Step 2: Resampling {sample_rate}Hz -> 16000Hz...")
115
- import librosa
116
- # Use res_type="kaiser_fast" to save memory/cpu if needed, but default is usually fine
117
- audio_array = librosa.resample(audio_array, orig_sr=sample_rate, target_sr=16_000)
118
- print(f"[LOG] Memory after resampling: {get_mem_usage():.2f} MB")
119
-
120
-
121
- print(f"\n--- [LOG] New Request ---")
122
- print(f"[LOG] Start Memory: {start_mem:.2f} MB")
123
- print(f"[LOG] Audio duration: {audio_len_sec:.2f}s, SR: {sample_rate}")
124
-
125
- # Preprocessing
126
- print("[LOG] Step 3: Extracting features...")
127
- inputs = processor(
128
- audio_array,
129
- sampling_rate=16_000,
130
- do_normalize=True,
131
- device="cpu",
132
- return_tensors="pt",
133
- )
134
- # Delete raw audio array immediately as it's now in 'inputs'
135
- del audio_array
136
- gc.collect()
137
- print(f"[LOG] Memory after preprocessing: {get_mem_usage():.2f} MB")
138
-
139
- # Inference
140
- print("[LOG] Step 4: Running model inference...")
141
- with torch.no_grad():
142
- outputs = model(input_features=inputs.input_features)
143
-
144
- # Cleanup inputs
145
- del inputs
146
- gc.collect()
147
- print(f"[LOG] Memory after inference: {get_mem_usage():.2f} MB")
148
-
149
- # Post-processing
150
- print("[LOG] Step 5: Post-processing results...")
151
- fam_probs = torch.softmax(outputs["fam_logits"], dim=-1)
152
- super_probs = torch.softmax(outputs["super_logits"], dim=-1)
153
- code_probs = torch.softmax(outputs["code_logits"], dim=-1)
154
-
155
- fam_idx = outputs["fam_logits"].argmax(-1).item()
156
- super_idx = outputs["super_logits"].argmax(-1).item()
157
- code_idx = outputs["code_logits"].argmax(-1).item()
158
-
159
- fam_conf = fam_probs[0, fam_idx].item()
160
- super_conf = super_probs[0, super_idx].item()
161
- code_conf = code_probs[0, code_idx].item()
162
-
163
- print(f"[LOG] Final Memory: {get_mem_usage():.2f} MB")
164
- print(f"--- [LOG] Request Finished ---\n")
165
-
166
- # Formatting results
167
- return (
168
- {f"{fam_idx}": fam_conf},
169
- {f"{super_idx}": super_conf},
170
- {f"{code_idx}": code_conf}
171
- )
172
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
  # === UI COMPONENTS ===
175
  with gr.Blocks() as demo:
@@ -194,6 +196,9 @@ with gr.Blocks() as demo:
194
  clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary")
195
  submit_btn = gr.Button("πŸš€ Classify", variant="primary")
196
 
 
 
 
197
  with gr.Column(scale=1):
198
  gr.Markdown("### πŸ“Š 2. Classification Results")
199
  fam_output = gr.Label(num_top_classes=1, label="🌍 Language Family")
@@ -203,15 +208,16 @@ with gr.Blocks() as demo:
203
  submit_btn.click(
204
  fn=predict_language,
205
  inputs=audio_input,
206
- outputs=[fam_output, super_output, code_output]
207
  )
208
 
209
  clear_btn.click(
210
- fn=lambda: (None, None, None, None),
211
  inputs=None,
212
- outputs=[audio_input, fam_output, super_output, code_output]
213
  )
214
 
 
215
  gr.Markdown(
216
  """
217
  ---
 
91
  # === INFERENCE FUNCTION ===
92
  def predict_language(audio):
93
  if audio is None:
94
+ yield "⚠️ No audio provided", {}, {}, {}
95
+ return
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
+ log_buffer = "--- [LOG] New Request ---\n"
98
+ yield log_buffer, {}, {}, {}
99
+
100
+ try:
101
+ gc.collect()
102
+ start_mem = get_mem_usage()
103
+ sample_rate, audio_array = audio
104
+ audio_len_sec = len(audio_array) / sample_rate
105
+
106
+ log_buffer += f"RAM: {start_mem:.2f} MB | Len: {audio_len_sec:.2f}s | SR: {sample_rate}\n"
107
+ yield log_buffer, {}, {}, {}
108
+
109
+ # Normalization
110
+ log_buffer += "Step 1: Normalizing...\n"
111
+ yield log_buffer, {}, {}, {}
112
+ if audio_array.dtype == np.int16:
113
+ audio_array = audio_array.astype(np.float32) / 32768.0
114
+ elif audio_array.dtype == np.int32:
115
+ audio_array = audio_array.astype(np.float32) / 2147483648.0
116
+
117
+ # Resampling
118
+ if sample_rate != 16000:
119
+ log_buffer += f"Step 2: Resampling {sample_rate}Hz -> 16kHz...\n"
120
+ yield log_buffer, {}, {}, {}
121
+ import librosa
122
+ audio_array = librosa.resample(audio_array, orig_sr=sample_rate, target_sr=16000)
123
+ log_buffer += f"Mem post-resample: {get_mem_usage():.2f} MB\n"
124
+ yield log_buffer, {}, {}, {}
125
+
126
+ # Preprocessing
127
+ log_buffer += "Step 3: Extracting features...\n"
128
+ yield log_buffer, {}, {}, {}
129
+ inputs = processor(
130
+ audio_array,
131
+ sampling_rate=16000,
132
+ return_tensors="pt"
133
+ )
134
+ del audio_array
135
+ gc.collect()
136
+ log_buffer += f"Mem post-features: {get_mem_usage():.2f} MB\n"
137
+ yield log_buffer, {}, {}, {}
138
+
139
+ # Inference
140
+ log_buffer += "Step 4: Running Model (CPU)... \n"
141
+ yield log_buffer, {}, {}, {}
142
+ with torch.no_grad():
143
+ outputs = model(input_features=inputs.input_features)
144
+
145
+ del inputs
146
+ gc.collect()
147
+ log_buffer += f"Mem post-inference: {get_mem_usage():.2f} MB\n"
148
+ yield log_buffer, {}, {}, {}
149
+
150
+ # Post-processing
151
+ log_buffer += "Step 5: Formatting results...\n"
152
+ yield log_buffer, {}, {}, {}
153
+ fam_probs = torch.softmax(outputs["fam_logits"], dim=-1)
154
+ super_probs = torch.softmax(outputs["super_logits"], dim=-1)
155
+ code_probs = torch.softmax(outputs["code_logits"], dim=-1)
156
+
157
+ fam_idx = outputs["fam_logits"].argmax(-1).item()
158
+ super_idx = outputs["super_logits"].argmax(-1).item()
159
+ code_idx = outputs["code_logits"].argmax(-1).item()
160
+
161
+ fam_conf = fam_probs[0, fam_idx].item()
162
+ super_conf = super_probs[0, super_idx].item()
163
+ code_conf = code_probs[0, code_idx].item()
164
+
165
+ log_buffer += "--- [LOG] Finished Successfully ---"
166
+ yield (
167
+ log_buffer,
168
+ {f"{fam_idx}": fam_conf},
169
+ {f"{super_idx}": super_conf},
170
+ {f"{code_idx}": code_conf}
171
+ )
172
+ except Exception as e:
173
+ log_buffer += f"\n❌ CRASH: {str(e)}"
174
+ yield log_buffer, {}, {}, {}
175
 
176
  # === UI COMPONENTS ===
177
  with gr.Blocks() as demo:
 
196
  clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary")
197
  submit_btn = gr.Button("πŸš€ Classify", variant="primary")
198
 
199
+ # Persistent Log Output
200
+ status_logs = gr.Textbox(label="πŸ” Persistent Status Log (Visible after crash)", interactive=False, lines=10)
201
+
202
  with gr.Column(scale=1):
203
  gr.Markdown("### πŸ“Š 2. Classification Results")
204
  fam_output = gr.Label(num_top_classes=1, label="🌍 Language Family")
 
208
  submit_btn.click(
209
  fn=predict_language,
210
  inputs=audio_input,
211
+ outputs=[status_logs, fam_output, super_output, code_output]
212
  )
213
 
214
  clear_btn.click(
215
+ fn=lambda: ("", None, None, None, None),
216
  inputs=None,
217
+ outputs=[status_logs, audio_input, fam_output, super_output, code_output]
218
  )
219
 
220
+
221
  gr.Markdown(
222
  """
223
  ---