Spaces:
Running
Running
| import gradio as gr | |
| import pandas as pd | |
| import numpy as np | |
| import uuid | |
| # Import the custom component and the HTML generator | |
| from gradio_htmlplus import HTMLPlus | |
| from leaderboard import generate_leaderboard_html | |
| # Generate Mock Data | |
| def create_mock_leaderboard_data(num_rows=15): | |
| """ | |
| Creates a pandas DataFrame with random data for the leaderboard demo. | |
| Args: | |
| num_rows (int): The number of rows to generate. | |
| Returns: | |
| pd.DataFrame: A DataFrame containing mock leaderboard data. | |
| """ | |
| data = { | |
| 'run_id': [str(uuid.uuid4()) for _ in range(num_rows)], | |
| 'model': [f'model-v{i}-{np.random.choice(["alpha", "beta", "gamma"])}' for i in range(num_rows)], | |
| 'agent_type': np.random.choice(['tool', 'code', 'both'], num_rows), | |
| 'provider': np.random.choice(['litellm', 'transformers'], num_rows), | |
| 'success_rate': np.random.uniform(40, 99.9, num_rows), | |
| 'total_tests': np.random.randint(50, 100, num_rows), | |
| 'avg_steps': np.random.uniform(3, 8, num_rows), | |
| 'avg_duration_ms': np.random.uniform(1500, 5000, num_rows), | |
| 'total_tokens': np.random.randint(10000, 50000, num_rows), | |
| 'total_cost_usd': np.random.uniform(0.01, 0.2, num_rows), | |
| 'co2_emissions_g': np.random.uniform(0.5, 5, num_rows), | |
| 'gpu_utilization_avg': [np.random.uniform(60, 95) if i % 2 == 0 else None for i in range(num_rows)], | |
| 'timestamp': pd.to_datetime(pd.Timestamp.now() - pd.to_timedelta(np.random.rand(num_rows), unit='D')), | |
| 'submitted_by': [f'user_{np.random.randint(1, 5)}' for _ in range(num_rows)], | |
| } | |
| df = pd.DataFrame(data) | |
| df['successful_tests'] = (df['total_tests'] * (df['success_rate'] / 100)).astype(int) | |
| df['failed_tests'] = df['total_tests'] - df['successful_tests'] | |
| return df | |
| with gr.Blocks(css=".gradio-container { max-width: 95% !important; }") as demo: | |
| gr.Markdown("# π Interactive Leaderboard with Action Buttons") | |
| gr.Markdown("Click on any row in the table to view its complete data, or click a button for a specific action.") | |
| # Create and display the initial table | |
| leaderboard_df = create_mock_leaderboard_data(15) | |
| leaderboard_html = generate_leaderboard_html(leaderboard_df) | |
| html_table = HTMLPlus( | |
| value=leaderboard_html, | |
| # Define both the action button and the table row as selectable elements. | |
| # The more specific selector should come first to ensure it's matched first. | |
| selectable_elements=[".tm-action-button", "tr"] | |
| ) | |
| clicked_data_output = gr.JSON(label="Selected Row Data") | |
| action_log_output = gr.Textbox(label="Action Log", interactive=False) | |
| def on_element_selected(evt: gr.SelectData): | |
| """ | |
| Handles select events from the HTMLPlus component. It differentiates actions | |
| based on which CSS selector was matched (evt.index). | |
| Args: | |
| evt (gr.SelectData): The event data object, containing the matched | |
| selector (`.index`) and the element's data | |
| attributes (`.value`). | |
| Returns: | |
| tuple: A tuple of values to update the output components. | |
| Uses gr.skip() to avoid updating a component. | |
| """ | |
| if evt.index == ".tm-action-button": | |
| # This block handles clicks on the 'Delete' button. | |
| action = evt.value.get('action') | |
| run_id = evt.value.get('run-id') or "Unknown" | |
| log_message = f"ACTION: Button '{action}' clicked for Run ID: {run_id[:8]}..." | |
| # Update the log, but skip updating the JSON output. | |
| return gr.skip(), log_message | |
| elif evt.index == "tr": | |
| # This block handles clicks on the table row itself. | |
| data = evt.value | |
| run_id = data.get('run-id') or "Unknown" | |
| log_message = f"INFO: Row selected for Run ID: {run_id[:8]}..." | |
| # The frontend sends all data attributes as strings. | |
| # Convert numeric strings back to numbers for cleaner display. | |
| numeric_keys = [ | |
| 'success-rate', 'total-tests', 'avg-steps', 'avg-duration-ms', | |
| 'total-tokens', 'total-cost-usd', 'co2-emissions-g', | |
| 'gpu-utilization-avg', 'successful-tests', 'failed-tests' | |
| ] | |
| for key in numeric_keys: | |
| if key in data and data[key] not in ['None', None, '']: | |
| try: | |
| num_val = float(data[key]) | |
| if num_val.is_integer(): | |
| data[key] = int(num_val) | |
| else: | |
| data[key] = round(num_val, 4) | |
| except (ValueError, TypeError): | |
| pass # Leave as a string if conversion fails | |
| # Update both the JSON output and the log. | |
| return data, log_message | |
| # A fallback for any unexpected event. | |
| return gr.skip(), "Unknown action occurred." | |
| # Connect the 'select' event to the callback function, mapping its | |
| # return values to the two output components. | |
| html_table.select( | |
| fn=on_element_selected, | |
| inputs=None, | |
| outputs=[clicked_data_output, action_log_output] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |