openhands commited on
Commit
974f31f
·
1 Parent(s): 361b5c2

Add timer-based auto-refresh for leaderboard data

Browse files

When background data refresh occurs, the UI now automatically updates
within 60 seconds without requiring a page reload. This fixes the issue
where new results pushed to the GitHub repo weren't reflected on the
live site until the HF Space container was restarted.

Changes:
- Add data version tracking to detect when cache is cleared
- Add gr.Timer() that checks for data updates every 60 seconds
- Automatically refresh DataFrame and Plot components when new data is available

Files changed (1) hide show
  1. ui_components.py +85 -2
ui_components.py CHANGED
@@ -365,6 +365,13 @@ plot_legend_html = f"""
365
  CACHED_VIEWERS = {}
366
  CACHED_TAG_MAPS = {}
367
  _cache_lock = __import__('threading').Lock()
 
 
 
 
 
 
 
368
 
369
 
370
  def clear_viewer_cache():
@@ -372,11 +379,12 @@ def clear_viewer_cache():
372
  Clear all cached viewers and tag maps.
373
  Called when data is refreshed from the background scheduler.
374
  """
375
- global CACHED_VIEWERS, CACHED_TAG_MAPS
376
  with _cache_lock:
377
  CACHED_VIEWERS.clear()
378
  CACHED_TAG_MAPS.clear()
379
- print("[CACHE] Viewer cache cleared after data refresh")
 
380
 
381
 
382
  # Register the cache clear callback with the data refresh system
@@ -457,7 +465,13 @@ def create_leaderboard_display(
457
  """
458
  This UI factory takes pre-loaded data and renders the main DataFrame and Plot
459
  for a given category (e.g., "Overall" or "Literature Understanding").
 
 
 
460
  """
 
 
 
461
  # 1. Instantiate the transformer and get the specific view for this category.
462
  # The function no longer loads data itself; it filters the data it receives.
463
  transformer = DataTransformer(full_df, tag_map)
@@ -664,6 +678,75 @@ def create_leaderboard_display(
664
 
665
  legend_markdown = create_legend_markdown(category_name)
666
  gr.HTML(value=legend_markdown, elem_id="legend-markdown")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
667
 
668
  # Return the components so they can be referenced elsewhere.
669
  return plot_component, dataframe_component
 
365
  CACHED_VIEWERS = {}
366
  CACHED_TAG_MAPS = {}
367
  _cache_lock = __import__('threading').Lock()
368
+ _data_version = 0 # Incremented when data is refreshed
369
+
370
+
371
+ def get_data_version():
372
+ """Get the current data version number."""
373
+ global _data_version
374
+ return _data_version
375
 
376
 
377
  def clear_viewer_cache():
 
379
  Clear all cached viewers and tag maps.
380
  Called when data is refreshed from the background scheduler.
381
  """
382
+ global CACHED_VIEWERS, CACHED_TAG_MAPS, _data_version
383
  with _cache_lock:
384
  CACHED_VIEWERS.clear()
385
  CACHED_TAG_MAPS.clear()
386
+ _data_version += 1
387
+ print(f"[CACHE] Viewer cache cleared after data refresh (version: {_data_version})")
388
 
389
 
390
  # Register the cache clear callback with the data refresh system
 
465
  """
466
  This UI factory takes pre-loaded data and renders the main DataFrame and Plot
467
  for a given category (e.g., "Overall" or "Literature Understanding").
468
+
469
+ The display includes a timer that periodically checks for data updates and
470
+ refreshes the UI when new data is available.
471
  """
472
+ # Track the data version when this display was created
473
+ initial_data_version = get_data_version()
474
+
475
  # 1. Instantiate the transformer and get the specific view for this category.
476
  # The function no longer loads data itself; it filters the data it receives.
477
  transformer = DataTransformer(full_df, tag_map)
 
678
 
679
  legend_markdown = create_legend_markdown(category_name)
680
  gr.HTML(value=legend_markdown, elem_id="legend-markdown")
681
+
682
+ # Add a timer to periodically check for data updates and refresh the UI
683
+ # This runs every 60 seconds to check if new data is available
684
+ def check_and_refresh_data(current_checkbox_state):
685
+ """Check if data has been refreshed and return updated data if so."""
686
+ current_version = get_data_version()
687
+ if current_version > initial_data_version:
688
+ # Data has been refreshed, reload it
689
+ print(f"[REFRESH] Data version changed from {initial_data_version} to {current_version}, reloading...")
690
+ new_df, new_tag_map = get_full_leaderboard_data(split_name)
691
+ if not new_df.empty:
692
+ new_transformer = DataTransformer(new_df, new_tag_map)
693
+ new_df_view_full, _ = new_transformer.view(tag=category_name, use_plotly=True)
694
+
695
+ # Prepare both complete and all entries versions
696
+ if 'Categories Attempted' in new_df_view_full.columns:
697
+ new_df_view_complete = new_df_view_full[new_df_view_full['Categories Attempted'] == '5/5'].copy()
698
+ else:
699
+ new_df_view_complete = new_df_view_full.copy()
700
+
701
+ new_df_display_complete = prepare_df_for_display(new_df_view_complete)
702
+ new_df_display_all = prepare_df_for_display(new_df_view_full)
703
+
704
+ # Create new scatter plots
705
+ new_scatter_complete = create_scatter_plot(new_df_view_complete) if len(new_df_display_complete) > 0 else go.Figure()
706
+ new_scatter_all = create_scatter_plot(new_df_view_full)
707
+
708
+ # Return the appropriate data based on checkbox state
709
+ if current_checkbox_state:
710
+ return new_df_display_all, new_scatter_all
711
+ else:
712
+ return new_df_display_complete, new_scatter_complete
713
+
714
+ # No change, return current values
715
+ if current_checkbox_state:
716
+ return df_display_all, scatter_plot_all
717
+ else:
718
+ return df_display_complete, scatter_plot_complete
719
+
720
+ # Create a timer that checks for updates every 60 seconds
721
+ refresh_timer = gr.Timer(value=60)
722
+
723
+ # Connect the timer to the refresh function
724
+ if show_incomplete_checkbox is not None:
725
+ refresh_timer.tick(
726
+ fn=check_and_refresh_data,
727
+ inputs=[show_incomplete_checkbox],
728
+ outputs=[dataframe_component, plot_component]
729
+ )
730
+ else:
731
+ # If no checkbox, always show all data
732
+ def check_and_refresh_all():
733
+ current_version = get_data_version()
734
+ if current_version > initial_data_version:
735
+ print(f"[REFRESH] Data version changed, reloading...")
736
+ new_df, new_tag_map = get_full_leaderboard_data(split_name)
737
+ if not new_df.empty:
738
+ new_transformer = DataTransformer(new_df, new_tag_map)
739
+ new_df_view_full, _ = new_transformer.view(tag=category_name, use_plotly=True)
740
+ new_df_display_all = prepare_df_for_display(new_df_view_full)
741
+ new_scatter_all = create_scatter_plot(new_df_view_full)
742
+ return new_df_display_all, new_scatter_all
743
+ return df_display_all, scatter_plot_all
744
+
745
+ refresh_timer.tick(
746
+ fn=check_and_refresh_all,
747
+ inputs=[],
748
+ outputs=[dataframe_component, plot_component]
749
+ )
750
 
751
  # Return the components so they can be referenced elsewhere.
752
  return plot_component, dataframe_component