AdnanElAssadi commited on
Commit
5242f3c
·
verified ·
1 Parent(s): 06960f4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -157
app.py CHANGED
@@ -301,61 +301,7 @@ def create_reranking_interface(task_data):
301
  margin: 0 auto;
302
  font-size: 12px !important;
303
  }
304
-
305
- /* Add styling for validation button */
306
- .validate-btn {
307
- margin-top: 10px !important;
308
- width: 100% !important;
309
- }
310
-
311
- /* Add loading animation for dropdowns */
312
- .rank-dropdown.loading select {
313
- background-color: #f0f0f0 !important;
314
- cursor: wait !important;
315
- }
316
-
317
- /* Quick tools improvements */
318
- .tools-container button {
319
- transition: all 0.3s ease !important;
320
- }
321
-
322
- .tools-container button:active {
323
- transform: scale(0.98) !important;
324
- }
325
-
326
- /* Add this to make dropdown updates more responsive */
327
- .rank-dropdown select {
328
- transition: background-color 0.2s ease !important;
329
- }
330
  </style>
331
-
332
- <script>
333
- // Add simple loading state indication for quick rank buttons
334
- function addLoadingBehavior() {
335
- const quickButtons = document.querySelectorAll('.tools-container button');
336
- if (quickButtons) {
337
- quickButtons.forEach(btn => {
338
- btn.addEventListener('click', function() {
339
- // Show loading state in the button
340
- const originalText = this.textContent;
341
- this.textContent = "Applying...";
342
-
343
- // Reset after a short delay
344
- setTimeout(() => {
345
- this.textContent = originalText;
346
- }, 1000);
347
- });
348
- });
349
- }
350
- }
351
-
352
- // Run when DOM is loaded
353
- if (document.readyState === 'loading') {
354
- document.addEventListener('DOMContentLoaded', addLoadingBehavior);
355
- } else {
356
- addLoadingBehavior();
357
- }
358
- </script>
359
  """)
360
 
361
  def validate_rankings(*rankings):
@@ -440,6 +386,46 @@ def create_reranking_interface(task_data):
440
 
441
  return status, progress
442
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
  def auto_save_and_navigate(direction, current_id, auto_save, *rankings):
444
  """Save rankings if auto-save is enabled, then navigate."""
445
  # Extract rankings (remove validation indicators)
@@ -499,143 +485,74 @@ def create_reranking_interface(task_data):
499
  except Exception as e:
500
  return f"Error saving results: {str(e)}"
501
 
502
- # Optimize the navigation functions to reduce unnecessary updates
503
- def handle_next(current_id, auto_save, *rankings):
504
- """Optimized handler for next query navigation."""
505
- # First, handle auto-save (only if needed)
506
- new_id, status, progress = auto_save_and_navigate("next", current_id, auto_save, *rankings)
507
-
508
- # Return the new sample ID for a more efficient update
509
- # The load_sample function will handle all UI updates in one batch
510
- return new_id
511
-
512
- def handle_prev(current_id, auto_save, *rankings):
513
- """Optimized handler for previous query navigation."""
514
- # First, handle auto-save (only if needed)
515
- new_id, status, progress = auto_save_and_navigate("prev", current_id, auto_save, *rankings)
516
-
517
- # Return the new sample ID for a more efficient update
518
- # The load_sample function will handle all UI updates in one batch
519
- return new_id
520
-
521
- # Optimize the load_sample function to handle all UI updates efficiently
522
- def load_sample(sample_id):
523
- """Load a specific sample into the interface."""
524
- # Clear all validation indicators first for a cleaner transition
525
- blank_validations = [""] * len(validation_indicators)
526
-
527
- # Find the sample data
528
- sample = next((s for s in samples if s["id"] == sample_id), None)
529
- if not sample:
530
- return [query_text.value] + [d.value for d in doc_containers] + [""] * len(ranking_inputs) + blank_validations + [sample_id, progress_text.value, status_box.value]
531
-
532
- # Update query
533
- new_query = sample["query"]
534
-
535
- # Update documents
536
- new_docs = []
537
- for i, doc in enumerate(sample["candidates"]):
538
- if i < len(doc_containers):
539
- new_docs.append(doc)
540
-
541
- # Initialize rankings
542
- new_rankings = [""] * len(ranking_inputs)
543
-
544
- # Check if this sample has already been annotated
545
- existing_annotation = next((a for a in results["annotations"] if a["sample_id"] == sample_id), None)
546
- if existing_annotation:
547
- # Restore previous rankings
548
- for i, rank in enumerate(existing_annotation["rankings"]):
549
- if i < len(new_rankings) and rank is not None:
550
- new_rankings[i] = str(rank)
551
-
552
- # Update progress
553
- current_idx = samples.index(sample)
554
- new_progress = f"Progress: {sum(completed_samples.values())}/{len(samples)}"
555
-
556
- new_status = f"Viewing query {current_idx + 1} of {len(samples)}"
557
- if completed_samples[sample_id]:
558
- new_status += " (already completed)"
559
-
560
- # Initialize validation indicators (but don't run validation until needed)
561
- # This improves load time
562
-
563
- return [new_query] + new_docs + new_rankings + blank_validations + [sample_id, new_progress, new_status]
564
-
565
- # Optimize the quick ranking functions for better performance
566
  def assign_sequential_ranks():
567
- """Assign sequential rankings (1,2,3...) to all documents."""
568
- sequential_ranks = [str(i+1) for i in range(len(samples[0]["candidates"]))]
569
- # Return ranks only - validation will be done separately for better performance
570
- return sequential_ranks
571
 
572
  def assign_reverse_ranks():
573
- """Assign reverse rankings (n,n-1...) to all documents."""
574
  n = len(samples[0]["candidates"])
575
- reverse_ranks = [str(n-i) for i in range(n)]
576
- # Return ranks only - validation will be done separately for better performance
577
- return reverse_ranks
578
 
579
  def clear_rankings():
580
- """Clear all rankings."""
581
- empty_ranks = [""] * len(samples[0]["candidates"])
582
- # Return empty ranks only - validation will be done separately for better performance
583
- return empty_ranks
584
 
585
- # Add a function to update status after quick ranking operations
586
- def update_status_after_ranking(operation_name):
587
- """Update status box after a ranking operation."""
588
- return f"✅ {operation_name} applied successfully"
589
-
590
- # Connect quick ranking buttons with more efficient handling
591
  sequential_btn.click(
592
  fn=assign_sequential_ranks,
593
  inputs=None,
594
  outputs=ranking_inputs
595
- ).then(
596
- fn=lambda: update_status_after_ranking("Sequential ranking"),
597
- inputs=None,
598
- outputs=[status_box]
599
  )
600
 
601
  reverse_btn.click(
602
  fn=assign_reverse_ranks,
603
  inputs=None,
604
  outputs=ranking_inputs
605
- ).then(
606
- fn=lambda: update_status_after_ranking("Reverse ranking"),
607
- inputs=None,
608
- outputs=[status_box]
609
  )
610
 
611
  clear_btn.click(
612
  fn=clear_rankings,
613
  inputs=None,
614
  outputs=ranking_inputs
615
- ).then(
616
- fn=lambda: update_status_after_ranking("Rankings cleared"),
617
- inputs=None,
618
- outputs=[status_box]
619
  )
620
 
621
- # Connect navigation with more efficient data handling
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
622
  next_btn.click(
623
  fn=handle_next,
624
  inputs=[current_sample_id, auto_save_toggle] + ranking_inputs,
625
- outputs=[current_sample_id] # Only update the sample ID
626
- ).then(
627
- fn=load_sample, # Then load the sample with all UI updates in one batch
628
- inputs=[current_sample_id],
629
  outputs=[query_text] + doc_containers + ranking_inputs + validation_indicators + [current_sample_id, progress_text, status_box]
630
  )
631
 
632
  prev_btn.click(
633
  fn=handle_prev,
634
  inputs=[current_sample_id, auto_save_toggle] + ranking_inputs,
635
- outputs=[current_sample_id] # Only update the sample ID
636
- ).then(
637
- fn=load_sample, # Then load the sample with all UI updates in one batch
638
- inputs=[current_sample_id],
639
  outputs=[query_text] + doc_containers + ranking_inputs + validation_indicators + [current_sample_id, progress_text, status_box]
640
  )
641
 
@@ -656,6 +573,14 @@ def create_reranking_interface(task_data):
656
  outputs=[auto_save_enabled]
657
  )
658
 
 
 
 
 
 
 
 
 
659
  # Add a real-time validation for the entire set to check for duplicates
660
  def validate_all_inputs(*rankings):
661
  """Check all inputs for duplicate ranks and provide feedback."""
 
301
  margin: 0 auto;
302
  font-size: 12px !important;
303
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
  </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  """)
306
 
307
  def validate_rankings(*rankings):
 
386
 
387
  return status, progress
388
 
389
+ def load_sample(sample_id):
390
+ """Load a specific sample into the interface."""
391
+ sample = next((s for s in samples if s["id"] == sample_id), None)
392
+ if not sample:
393
+ return [query_text.value] + [d.value for d in doc_containers] + [""] * len(ranking_inputs) + [""] * len(validation_indicators) + [sample_id, progress_text.value, status_box.value]
394
+
395
+ # Update query
396
+ new_query = sample["query"]
397
+
398
+ # Update documents
399
+ new_docs = []
400
+ for i, doc in enumerate(sample["candidates"]):
401
+ if i < len(doc_containers):
402
+ new_docs.append(doc)
403
+
404
+ # Initialize rankings
405
+ new_rankings = [""] * len(ranking_inputs)
406
+
407
+ # Check if this sample has already been annotated
408
+ existing_annotation = next((a for a in results["annotations"] if a["sample_id"] == sample_id), None)
409
+ if existing_annotation:
410
+ # Restore previous rankings
411
+ for i, rank in enumerate(existing_annotation["rankings"]):
412
+ if i < len(new_rankings) and rank is not None:
413
+ new_rankings[i] = str(rank)
414
+
415
+ # Update progress
416
+ current_idx = samples.index(sample)
417
+ new_progress = f"Progress: {sum(completed_samples.values())}/{len(samples)}"
418
+
419
+ new_status = f"Viewing query {current_idx + 1} of {len(samples)}"
420
+ if completed_samples[sample_id]:
421
+ new_status += " (already completed)"
422
+
423
+ # Initialize validation indicators
424
+ validation_results = validate_rankings(*new_rankings)
425
+ validation_indicators_values = validation_results[:-1] # Remove validity flag
426
+
427
+ return [new_query] + new_docs + new_rankings + validation_indicators_values + [sample_id, new_progress, new_status]
428
+
429
  def auto_save_and_navigate(direction, current_id, auto_save, *rankings):
430
  """Save rankings if auto-save is enabled, then navigate."""
431
  # Extract rankings (remove validation indicators)
 
485
  except Exception as e:
486
  return f"Error saving results: {str(e)}"
487
 
488
+ # Define functions for the quick ranking buttons
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
489
  def assign_sequential_ranks():
490
+ return [str(i+1) for i in range(len(samples[0]["candidates"]))]
 
 
 
491
 
492
  def assign_reverse_ranks():
 
493
  n = len(samples[0]["candidates"])
494
+ return [str(n-i) for i in range(n)]
 
 
495
 
496
  def clear_rankings():
497
+ return [""] * len(samples[0]["candidates"])
 
 
 
498
 
499
+ # Connect quick ranking buttons
 
 
 
 
 
500
  sequential_btn.click(
501
  fn=assign_sequential_ranks,
502
  inputs=None,
503
  outputs=ranking_inputs
 
 
 
 
504
  )
505
 
506
  reverse_btn.click(
507
  fn=assign_reverse_ranks,
508
  inputs=None,
509
  outputs=ranking_inputs
 
 
 
 
510
  )
511
 
512
  clear_btn.click(
513
  fn=clear_rankings,
514
  inputs=None,
515
  outputs=ranking_inputs
 
 
 
 
516
  )
517
 
518
+ # Wire up events (Gradio 3.x syntax)
519
+ submit_btn.click(
520
+ fn=submit_rankings,
521
+ inputs=ranking_inputs + [current_sample_id],
522
+ outputs=[status_box, progress_text]
523
+ )
524
+
525
+ # Auto-save and navigate events
526
+ def handle_next(current_id, auto_save, *rankings):
527
+ # First, handle auto-save
528
+ new_id, status, progress = auto_save_and_navigate("next", current_id, auto_save, *rankings)
529
+ # Then, load the new sample
530
+ outputs = load_sample(new_id)
531
+ # Add the status and progress
532
+ outputs[-2] = progress if status else outputs[-2]
533
+ outputs[-1] = status if status else outputs[-1]
534
+ return outputs
535
+
536
+ def handle_prev(current_id, auto_save, *rankings):
537
+ # First, handle auto-save
538
+ new_id, status, progress = auto_save_and_navigate("prev", current_id, auto_save, *rankings)
539
+ # Then, load the new sample
540
+ outputs = load_sample(new_id)
541
+ # Add the status and progress
542
+ outputs[-2] = progress if status else outputs[-2]
543
+ outputs[-1] = status if status else outputs[-1]
544
+ return outputs
545
+
546
+ # Connect navigation with Gradio 3.x syntax
547
  next_btn.click(
548
  fn=handle_next,
549
  inputs=[current_sample_id, auto_save_toggle] + ranking_inputs,
 
 
 
 
550
  outputs=[query_text] + doc_containers + ranking_inputs + validation_indicators + [current_sample_id, progress_text, status_box]
551
  )
552
 
553
  prev_btn.click(
554
  fn=handle_prev,
555
  inputs=[current_sample_id, auto_save_toggle] + ranking_inputs,
 
 
 
 
556
  outputs=[query_text] + doc_containers + ranking_inputs + validation_indicators + [current_sample_id, progress_text, status_box]
557
  )
558
 
 
573
  outputs=[auto_save_enabled]
574
  )
575
 
576
+ # Connect validation to ranking inputs for real-time feedback
577
+ for ranking in ranking_inputs:
578
+ ranking.change(
579
+ fn=on_ranking_change,
580
+ inputs=ranking_inputs,
581
+ outputs=validation_indicators
582
+ )
583
+
584
  # Add a real-time validation for the entire set to check for duplicates
585
  def validate_all_inputs(*rankings):
586
  """Check all inputs for duplicate ranks and provide feedback."""