vargha commited on
Commit
8ebff9f
Β·
1 Parent(s): 78de9fc

debugging intial loading issue

Browse files
Files changed (1) hide show
  1. components/review_dashboard_page.py +168 -53
components/review_dashboard_page.py CHANGED
@@ -151,13 +151,37 @@ class ReviewDashboardPage:
151
  # gr.Error(f"❌ Failed to load audio: {filename_to_load}. Error: {e}")
152
  # return None, None, gr.update(value=None, autoplay=False)
153
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  def load_review_items_fn(session):
155
  user_id = session.get("user_id")
156
  username = session.get("username")
157
 
158
  if not user_id or not username:
159
  log.warning("load_review_items_fn: user not found in session")
160
- # items, idx, review_info, tts_id, filename, sentence, ann_sentence, annotator_name_placeholder, annotated_at, validation_status, audio_update, rejection_reason_update, rejection_mode, btn_reject_update
161
  return [], 0, "", "", "", "", "", "", "", "", gr.update(value=None, autoplay=False), gr.update(visible=False, value=""), False, gr.update(value="❌ Reject")
162
 
163
  # Check if user is in Phase 2 (should be a reviewer)
@@ -176,9 +200,8 @@ class ReviewDashboardPage:
176
  log.warning(f"No target annotator found for reviewer {username}")
177
  return [], 0, "", "", "", "", "", "", "", "", gr.update(value=None, autoplay=False), gr.update(visible=False, value=""), False, gr.update(value="❌ Reject")
178
 
179
- # Load annotations from target annotator
180
  with get_db() as db:
181
- # try:
182
  # Get target annotator's ID
183
  target_annotator_obj = db.query(Annotator).filter_by(name=target_annotator).first()
184
  if not target_annotator_obj:
@@ -187,59 +210,47 @@ class ReviewDashboardPage:
187
 
188
  log.info(f"Found target annotator with ID: {target_annotator_obj.id}")
189
 
190
- # Get all annotations by target annotator (including deleted ones)
191
- annotations = db.query(Annotation).join(TTSData).filter(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  Annotation.annotator_id == target_annotator_obj.id
193
- ).options(
194
- orm.joinedload(Annotation.tts_data),
195
- orm.joinedload(Annotation.annotator)
196
- ).order_by(Annotation.id).all() # Added order_by for consistency
197
 
198
- log.info(f"Fetched {len(annotations)} annotations for target annotator ID {target_annotator_obj.id}")
199
 
 
200
  items = []
201
- for annotation in annotations:
202
- # Check if annotation is deleted (no annotated_sentence or empty)
203
  is_deleted = not annotation.annotated_sentence or annotation.annotated_sentence.strip() == ""
204
-
205
- # Check if this annotation has been reviewed by current user
206
- existing_validation = db.query(Validation).filter_by(
207
- annotation_id=annotation.id,
208
- validator_id=user_id
209
- ).first()
210
-
211
- validation_status = "Not Reviewed"
212
- rejection_reason_val = "" # For the input box
213
- rejection_visible_val = False # For the input box
214
-
215
- if existing_validation:
216
- if existing_validation.validated:
217
- validation_status = "Approved"
218
- else:
219
- validation_status = f"Rejected"
220
- if existing_validation.description:
221
- validation_status += f" ({existing_validation.description})"
222
- rejection_reason_val = existing_validation.description
223
- rejection_visible_val = True
224
-
225
- # For deleted annotations, show special status
226
- if is_deleted:
227
- annotated_sentence_display = "[DELETED ANNOTATION]"
228
- if validation_status == "Not Reviewed":
229
- validation_status = "Not Reviewed (Deleted)"
230
- else:
231
- annotated_sentence_display = annotation.annotated_sentence
232
 
233
  items.append({
234
  "annotation_id": annotation.id,
235
- "tts_id": annotation.tts_data.id,
236
- "filename": annotation.tts_data.filename,
237
- "sentence": annotation.tts_data.sentence,
238
  "annotated_sentence": annotated_sentence_display,
239
  "is_deleted": is_deleted,
240
- # "annotator_name": annotation.annotator.name, # Anonymized
241
  "annotated_at": annotation.annotated_at.isoformat() if annotation.annotated_at else "",
242
- "validation_status": validation_status
 
243
  })
244
 
245
  # Find the first item that is not reviewed (prioritize non-deleted annotations)
@@ -269,7 +280,7 @@ class ReviewDashboardPage:
269
  # Set initial display
270
  if items:
271
  initial_item = items[initial_idx]
272
- review_info_text = f"πŸ” **Phase 2 Review Mode** - Reviewing assigned annotations."
273
  # Ensure correct order of return values for 12 outputs
274
  # items, idx, review_info, tts_id, filename, sentence, ann_sentence, annotated_at, validation_status, annotator_placeholder, audio_update, rejection_reason_update
275
  rejection_reason_val = ""
@@ -314,6 +325,30 @@ class ReviewDashboardPage:
314
  return "", "", "", "", "", "", "", gr.update(value=None, autoplay=False), gr.update(visible=False, value=""), False, gr.update(value="❌ Reject")
315
 
316
  current_item = items[idx]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  rejection_reason = ""
318
  rejection_visible = False
319
 
@@ -346,7 +381,11 @@ class ReviewDashboardPage:
346
  if not items:
347
  return 0
348
  if direction == "next":
349
- return min(current_idx + 1, len(items) - 1)
 
 
 
 
350
  else: # prev
351
  return max(current_idx - 1, 0)
352
 
@@ -459,6 +498,86 @@ class ReviewDashboardPage:
459
  # gr.Warning(f"Invalid Data ID format: {target_data_id}")
460
  return current_idx
461
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  # Output definitions
463
  review_display_outputs = [
464
  self.tts_id, self.filename, self.sentence, self.ann_sentence,
@@ -487,12 +606,8 @@ class ReviewDashboardPage:
487
  outputs=self.interactive_ui_elements
488
  )
489
 
490
- # Load audio when filename changes
491
- self.filename.change(
492
- fn=download_voice_fn,
493
- inputs=[self.filename],
494
- outputs=[self.audio, self.original_audio_state, self.audio]
495
- )
496
 
497
  # Navigation buttons
498
  for btn, direction in [(self.btn_prev, "prev"), (self.btn_next, "next")]:
 
151
  # gr.Error(f"❌ Failed to load audio: {filename_to_load}. Error: {e}")
152
  # return None, None, gr.update(value=None, autoplay=False)
153
 
154
+ def get_validation_status_for_item(db, annotation_id, user_id, annotation_obj):
155
+ """Get validation status for a specific item - called on-demand"""
156
+ validation = db.query(Validation).filter_by(
157
+ annotation_id=annotation_id,
158
+ validator_id=user_id
159
+ ).first()
160
+
161
+ # Check if annotation is deleted
162
+ is_deleted = not annotation_obj.annotated_sentence or annotation_obj.annotated_sentence.strip() == ""
163
+
164
+ validation_status = "Not Reviewed"
165
+ if validation:
166
+ if validation.validated:
167
+ validation_status = "Approved"
168
+ else:
169
+ validation_status = "Rejected"
170
+ if validation.description:
171
+ validation_status += f" ({validation.description})"
172
+
173
+ # For deleted annotations, show special status
174
+ if is_deleted and validation_status == "Not Reviewed":
175
+ validation_status = "Not Reviewed (Deleted)"
176
+
177
+ return validation_status, is_deleted
178
+
179
  def load_review_items_fn(session):
180
  user_id = session.get("user_id")
181
  username = session.get("username")
182
 
183
  if not user_id or not username:
184
  log.warning("load_review_items_fn: user not found in session")
 
185
  return [], 0, "", "", "", "", "", "", "", "", gr.update(value=None, autoplay=False), gr.update(visible=False, value=""), False, gr.update(value="❌ Reject")
186
 
187
  # Check if user is in Phase 2 (should be a reviewer)
 
200
  log.warning(f"No target annotator found for reviewer {username}")
201
  return [], 0, "", "", "", "", "", "", "", "", gr.update(value=None, autoplay=False), gr.update(visible=False, value=""), False, gr.update(value="❌ Reject")
202
 
203
+ # Load annotations from target annotator with FAST INITIAL LOADING
204
  with get_db() as db:
 
205
  # Get target annotator's ID
206
  target_annotator_obj = db.query(Annotator).filter_by(name=target_annotator).first()
207
  if not target_annotator_obj:
 
210
 
211
  log.info(f"Found target annotator with ID: {target_annotator_obj.id}")
212
 
213
+ # FAST INITIAL QUERY: Load only essential data without complex validation processing
214
+ # Reduced batch size for instant loading in HuggingFace spaces
215
+ INITIAL_BATCH_SIZE = 5 # Load only 5 items initially for instant response
216
+
217
+ # Simple query to get basic annotation data quickly
218
+ initial_query = db.query(
219
+ Annotation,
220
+ TTSData.filename,
221
+ TTSData.sentence
222
+ ).join(
223
+ TTSData, Annotation.tts_data_id == TTSData.id
224
+ ).filter(
225
+ Annotation.annotator_id == target_annotator_obj.id
226
+ ).order_by(Annotation.id).limit(INITIAL_BATCH_SIZE)
227
+
228
+ initial_results = initial_query.all()
229
+
230
+ # Get total count for progress info (this is fast)
231
+ total_count = db.query(Annotation).filter(
232
  Annotation.annotator_id == target_annotator_obj.id
233
+ ).count()
 
 
 
234
 
235
+ log.info(f"Fast initial load: {len(initial_results)} annotations out of {total_count} total for target annotator ID {target_annotator_obj.id}")
236
 
237
+ # Process items with minimal data - validation status will be loaded on-demand
238
  items = []
239
+ for annotation, filename, sentence in initial_results:
240
+ # Check if annotation is deleted (minimal processing)
241
  is_deleted = not annotation.annotated_sentence or annotation.annotated_sentence.strip() == ""
242
+ annotated_sentence_display = "[DELETED ANNOTATION]" if is_deleted else annotation.annotated_sentence
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
 
244
  items.append({
245
  "annotation_id": annotation.id,
246
+ "tts_id": annotation.tts_data_id,
247
+ "filename": filename,
248
+ "sentence": sentence,
249
  "annotated_sentence": annotated_sentence_display,
250
  "is_deleted": is_deleted,
 
251
  "annotated_at": annotation.annotated_at.isoformat() if annotation.annotated_at else "",
252
+ "validation_status": "Loading...", # Will be loaded on-demand
253
+ "validation_loaded": False # Track if validation status has been loaded
254
  })
255
 
256
  # Find the first item that is not reviewed (prioritize non-deleted annotations)
 
280
  # Set initial display
281
  if items:
282
  initial_item = items[initial_idx]
283
+ review_info_text = f"πŸ” **Phase 2 Review Mode** - Reviewing assigned annotations. Loaded {len(items)} of {total_count} total items."
284
  # Ensure correct order of return values for 12 outputs
285
  # items, idx, review_info, tts_id, filename, sentence, ann_sentence, annotated_at, validation_status, annotator_placeholder, audio_update, rejection_reason_update
286
  rejection_reason_val = ""
 
325
  return "", "", "", "", "", "", "", gr.update(value=None, autoplay=False), gr.update(visible=False, value=""), False, gr.update(value="❌ Reject")
326
 
327
  current_item = items[idx]
328
+
329
+ # Load validation status on-demand if not already loaded
330
+ if not current_item.get("validation_loaded", False):
331
+ user_id = session.get("user_id")
332
+ if user_id:
333
+ with get_db() as db:
334
+ try:
335
+ # Get the full annotation object for validation processing
336
+ annotation_obj = db.query(Annotation).filter_by(id=current_item["annotation_id"]).first()
337
+ if annotation_obj:
338
+ validation_status, is_deleted = get_validation_status_for_item(db, current_item["annotation_id"], user_id, annotation_obj)
339
+ current_item["validation_status"] = validation_status
340
+ current_item["is_deleted"] = is_deleted
341
+ current_item["validation_loaded"] = True
342
+
343
+ # Update displayed annotation if deleted
344
+ if is_deleted:
345
+ current_item["annotated_sentence"] = "[DELETED ANNOTATION]"
346
+
347
+ log.info(f"Loaded validation status for item {idx}: {validation_status}")
348
+ except Exception as e:
349
+ log.error(f"Error loading validation status for item {idx}: {e}")
350
+ current_item["validation_status"] = "Error loading status"
351
+
352
  rejection_reason = ""
353
  rejection_visible = False
354
 
 
381
  if not items:
382
  return 0
383
  if direction == "next":
384
+ new_idx = min(current_idx + 1, len(items) - 1)
385
+ # Check if we're getting close to the end - load more items if needed
386
+ if new_idx >= len(items) - 2 and len(items) % 5 == 0: # Near end and items is a multiple of initial batch size
387
+ log.info(f"User is near end of loaded items ({new_idx}/{len(items)}), may need to load more items")
388
+ return new_idx
389
  else: # prev
390
  return max(current_idx - 1, 0)
391
 
 
498
  # gr.Warning(f"Invalid Data ID format: {target_data_id}")
499
  return current_idx
500
 
501
+ def load_more_items_fn(items, session, current_batch_size=100):
502
+ """Load more items when user needs them (pagination support)"""
503
+ user_id = session.get("user_id")
504
+ username = session.get("username")
505
+
506
+ if not user_id or not username:
507
+ return items # Return existing items if no user session
508
+
509
+ # Find target annotator
510
+ target_annotator = None
511
+ for annotator_name, reviewer_name in conf.REVIEW_MAPPING.items():
512
+ if reviewer_name == username:
513
+ target_annotator = annotator_name
514
+ break
515
+
516
+ if not target_annotator:
517
+ return items
518
+
519
+ with get_db() as db:
520
+ target_annotator_obj = db.query(Annotator).filter_by(name=target_annotator).first()
521
+ if not target_annotator_obj:
522
+ return items
523
+
524
+ # Load next batch starting from where we left off
525
+ offset = len(items)
526
+ query = db.query(
527
+ Annotation,
528
+ TTSData.filename,
529
+ TTSData.sentence,
530
+ Validation.validated,
531
+ Validation.description
532
+ ).join(
533
+ TTSData, Annotation.tts_data_id == TTSData.id
534
+ ).outerjoin(
535
+ Validation,
536
+ (Validation.annotation_id == Annotation.id) &
537
+ (Validation.validator_id == user_id)
538
+ ).filter(
539
+ Annotation.annotator_id == target_annotator_obj.id
540
+ ).order_by(Annotation.id).offset(offset).limit(current_batch_size)
541
+
542
+ results = query.all()
543
+
544
+ # Process new items same as before
545
+ new_items = []
546
+ for annotation, filename, sentence, validated, validation_description in results:
547
+ is_deleted = not annotation.annotated_sentence or annotation.annotated_sentence.strip() == ""
548
+
549
+ validation_status = "Not Reviewed"
550
+ if validated is not None:
551
+ if validated:
552
+ validation_status = "Approved"
553
+ else:
554
+ validation_status = "Rejected"
555
+ if validation_description:
556
+ validation_status += f" ({validation_description})"
557
+
558
+ if is_deleted:
559
+ annotated_sentence_display = "[DELETED ANNOTATION]"
560
+ if validation_status == "Not Reviewed":
561
+ validation_status = "Not Reviewed (Deleted)"
562
+ else:
563
+ annotated_sentence_display = annotation.annotated_sentence
564
+
565
+ new_items.append({
566
+ "annotation_id": annotation.id,
567
+ "tts_id": annotation.tts_data_id,
568
+ "filename": filename,
569
+ "sentence": sentence,
570
+ "annotated_sentence": annotated_sentence_display,
571
+ "is_deleted": is_deleted,
572
+ "annotated_at": annotation.annotated_at.isoformat() if annotation.annotated_at else "",
573
+ "validation_status": validation_status
574
+ })
575
+
576
+ # Combine with existing items
577
+ all_items = items + new_items
578
+ log.info(f"Loaded {len(new_items)} more items, total now: {len(all_items)}")
579
+ return all_items
580
+
581
  # Output definitions
582
  review_display_outputs = [
583
  self.tts_id, self.filename, self.sentence, self.ann_sentence,
 
606
  outputs=self.interactive_ui_elements
607
  )
608
 
609
+ # Audio loading is now manual only via the Load Audio button
610
+ # Removed automatic filename.change callback to prevent slow loading during initialization
 
 
 
 
611
 
612
  # Navigation buttons
613
  for btn, direction in [(self.btn_prev, "prev"), (self.btn_next, "next")]: