AppleSwing commited on
Commit
a67de47
·
verified ·
1 Parent(s): 2a5ac42

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -391
app.py CHANGED
@@ -7,6 +7,8 @@ os.environ["GRADIO_LANGUAGE"] = "en"
7
 
8
  RESULT_DIR = os.environ.get("MOECAP_RESULT_DIR")
9
  if not RESULT_DIR:
 
 
10
  raise RuntimeError(
11
  "MOECAP_RESULT_DIR is not set. Please set MOECAP_RESULT_DIR (HF Repo ID) before running app.py"
12
  )
@@ -48,12 +50,16 @@ def normalize_cost(val, max_tick, baseline=20):
48
  def generate_radar_plot(selected_rows_data: List[dict]) -> go.Figure:
49
  """Generate a CAP radar plot from selected rows."""
50
 
51
- # --- COMMON LAYOUT SETTINGS ---
52
- # We use balanced margins here so the chart is centered.
53
- # l=80, r=80 gives space for labels. b=100 gives space for the legend.
54
- common_margin = dict(t=80, b=100, l=80, r=80)
55
-
56
- # Validation: max 3 rows, all same dataset
 
 
 
 
57
  if not selected_rows_data or len(selected_rows_data) == 0:
58
  fig = go.Figure()
59
  fig.add_annotation(
@@ -65,12 +71,9 @@ def generate_radar_plot(selected_rows_data: List[dict]) -> go.Figure:
65
  yanchor='middle'
66
  )
67
  fig.update_layout(
68
- height=600, # Reduced slightly to fit screens better
69
  xaxis=dict(visible=False),
70
  yaxis=dict(visible=False),
71
- paper_bgcolor='white',
72
- plot_bgcolor='white',
73
- margin=common_margin # Use balanced margins
74
  )
75
  return fig
76
 
@@ -85,12 +88,9 @@ def generate_radar_plot(selected_rows_data: List[dict]) -> go.Figure:
85
  yanchor='middle'
86
  )
87
  fig.update_layout(
88
- height=600,
89
  xaxis=dict(visible=False),
90
  yaxis=dict(visible=False),
91
- paper_bgcolor='white',
92
- plot_bgcolor='white',
93
- margin=common_margin # Use balanced margins
94
  )
95
  return fig
96
 
@@ -107,12 +107,9 @@ def generate_radar_plot(selected_rows_data: List[dict]) -> go.Figure:
107
  yanchor='middle'
108
  )
109
  fig.update_layout(
110
- height=600,
111
  xaxis=dict(visible=False),
112
  yaxis=dict(visible=False),
113
- paper_bgcolor='white',
114
- plot_bgcolor='white',
115
- margin=common_margin # Use balanced margins
116
  )
117
  return fig
118
 
@@ -203,7 +200,7 @@ def generate_radar_plot(selected_rows_data: List[dict]) -> go.Figure:
203
  title=dict(
204
  text=f"CAP Radar Plot: {dataset_name}",
205
  x=0.5,
206
- xanchor='center', # Center the title
207
  font=dict(size=20)
208
  ),
209
  polar=dict(
@@ -214,25 +211,19 @@ def generate_radar_plot(selected_rows_data: List[dict]) -> go.Figure:
214
  ),
215
  angularaxis=dict(
216
  tickfont=dict(size=14),
217
- rotation=90, # Rotated to put Throughput at top
218
  direction='clockwise'
219
  ),
220
  ),
221
  legend=dict(
222
  orientation='h',
223
  yanchor='bottom',
224
- y=-0.15, # Lowered slightly to fit bottom margin
225
  xanchor='center',
226
  x=0.5,
227
  font=dict(size=13)
228
  ),
229
- # UPDATED MARGINS HERE
230
- margin=common_margin,
231
- height=700,
232
- # Removed fixed 'width' to allow Gradio to resize it responsively
233
- autosize=True,
234
- paper_bgcolor='white',
235
- plot_bgcolor='white'
236
  )
237
 
238
  return fig
@@ -289,83 +280,11 @@ def json_to_row(path: str, metrics: dict) -> dict:
289
  "Decoding<br>S-MFU(%)": pct(metrics.get("decoding_smfu")),
290
  "TTFT(s)": f2(metrics.get("ttft")),
291
  "TPOT(s)": f2(metrics.get("tpot")),
292
- "Batch size": batch_size, # moved to tail
293
  }
294
  return row
295
 
296
 
297
- def build_leaderboard_from_files(files: List[gr.File], prev_rows: list | None = None):
298
- if prev_rows is None:
299
- prev_rows = []
300
-
301
- if not files and prev_rows:
302
- df = pd.DataFrame(prev_rows)
303
- raw_models = set()
304
- for cell in df["Model"].tolist():
305
- if isinstance(cell, str) and "href" in cell:
306
- try:
307
- name = cell.split(">", 1)[1].split("<", 1)[0]
308
- except Exception:
309
- name = cell
310
- else:
311
- name = cell
312
- raw_models.add(name)
313
- links = []
314
- for name in sorted(raw_models):
315
- if isinstance(name, str) and "/" in name:
316
- hf_url = f"https://huggingface.co/{name}"
317
- links.append(f"[{name}]({hf_url})")
318
- else:
319
- links.append(str(name))
320
- models_str = ", ".join(links)
321
- summary_md = f"**Loaded {len(prev_rows)} result files.** \n**Models:** {models_str}"
322
- table_html = f'<div class="table-container">{df.to_html(escape=False, index=False, classes="metrics-table")}</div>'
323
- return summary_md, table_html, prev_rows
324
-
325
- new_rows = []
326
- if files:
327
- for f in files:
328
- path = f.name
329
- try:
330
- with open(path, "r", encoding="utf-8") as fp:
331
- metrics = json.load(fp)
332
- new_rows.append(json_to_row(path, metrics))
333
- except Exception:
334
- continue
335
-
336
- all_rows = prev_rows + new_rows
337
-
338
- if not all_rows:
339
- empty_html = "<p>No files loaded.</p>"
340
- return "No files uploaded.", empty_html, []
341
-
342
- df = pd.DataFrame(all_rows)
343
-
344
- raw_models = set()
345
- for cell in df["Model"].tolist():
346
- if isinstance(cell, str) and "href" in cell:
347
- try:
348
- name = cell.split(">", 1)[1].split("<", 1)[0]
349
- except Exception:
350
- name = cell
351
- else:
352
- name = cell
353
- raw_models.add(name)
354
- links = []
355
- for name in sorted(raw_models):
356
- if isinstance(name, str) and "/" in name:
357
- hf_url = f"https://huggingface.co/{name}"
358
- links.append(f"[{name}]({hf_url})")
359
- else:
360
- links.append(str(name))
361
- models_str = ", ".join(links)
362
- summary_md = f"**Loaded {len(all_rows)} result files.** \n**Models:** {models_str}"
363
-
364
- table_html = f'<div class="table-container">{df.to_html(escape=False, index=False, classes="metrics-table")}</div>'
365
-
366
- return summary_md, table_html, all_rows
367
-
368
-
369
  def load_from_dir(
370
  dir_path: str,
371
  selected_tasks: List[str] | None = None,
@@ -388,7 +307,7 @@ def load_from_dir(
388
  )
389
  except Exception as e:
390
  empty_html = "<p>No files loaded or Dataset not found.</p>"
391
- return empty_html
392
 
393
  rows = []
394
  for i, example in enumerate(ds):
@@ -400,35 +319,29 @@ def load_from_dir(
400
 
401
  if not rows:
402
  empty_html = "<p>No records found.</p>"
403
- return empty_html
404
 
405
  df = pd.DataFrame(rows)
406
 
407
- # Dataset filter
408
  if selected_tasks is not None:
409
  lower_selected = [x.lower() for x in selected_tasks]
410
  df = df[df["Dataset"].astype(str).str.lower().isin(lower_selected)]
411
 
412
-
413
- # Inference framework filter (Method)
414
  if selected_frameworks is not None:
415
  lower_selected = [str(x).lower() for x in selected_frameworks]
416
  df = df[df["Method"].astype(str).str.lower().isin(lower_selected)]
417
 
418
- # Model type filter
419
  if selected_model_types is not None:
420
  lower_selected = [str(x).lower() for x in selected_model_types]
421
  df = df[df["Model type"].astype(str).str.lower().isin(lower_selected)]
422
 
423
- # Precision filter
424
  if selected_precisions is not None:
425
  lower_selected = [str(x).lower() for x in selected_precisions]
426
  df = df[df["Precision"].astype(str).str.lower().isin(lower_selected)]
427
 
428
- # Search keyword filter - search across all columns
429
  if search_keyword and search_keyword.strip():
430
  keyword_lower = search_keyword.strip().lower()
431
- # Create a mask that checks if the keyword appears in any column
432
  mask = df.astype(str).apply(lambda row: row.str.lower().str.contains(keyword_lower).any(), axis=1)
433
  df = df[mask]
434
 
@@ -437,29 +350,8 @@ def load_from_dir(
437
  return empty_html, []
438
 
439
  df = df.fillna("-")
440
- raw_models = set()
441
-
442
-
443
- for cell in df["Model"].tolist():
444
- if isinstance(cell, str) and "href" in cell:
445
- try:
446
- name = cell.split(">", 1)[1].split("<", 1)[0]
447
- except Exception:
448
- name = cell
449
- else:
450
- name = cell
451
- raw_models.add(name)
452
-
453
- links = []
454
- for name in sorted(raw_models):
455
- if isinstance(name, str) and "/" in name:
456
- hf_url = f"https://huggingface.co/{name}"
457
- links.append(f"[{name}]({hf_url})")
458
- else:
459
- links.append(str(name))
460
- models_str = ", ".join(links)
461
-
462
- # Insert row number column at the beginning for easy reference
463
  df.insert(0, 'Row #', range(len(df)))
464
 
465
  # Create HTML table
@@ -488,16 +380,6 @@ def auto_refresh_from_dir(
488
  )
489
 
490
 
491
- def update_radar_plot(df_data: list, selected_indices: list):
492
- """Update radar plot based on selected row indices."""
493
- if not selected_indices or not df_data:
494
- return generate_radar_plot([])
495
-
496
- # Get selected rows (limit to 3)
497
- selected_rows = [df_data[i] for i in selected_indices[:3] if i < len(df_data)]
498
- return generate_radar_plot(selected_rows)
499
-
500
-
501
  def parse_and_generate_plot(df_data: list, indices_str: str):
502
  """Parse comma-separated indices and generate radar plot."""
503
  if not indices_str or not indices_str.strip():
@@ -515,273 +397,79 @@ def parse_and_generate_plot(df_data: list, indices_str: str):
515
  return generate_radar_plot([])
516
 
517
 
518
- def on_table_select(df, evt: gr.SelectData):
519
- """Handle table row selection."""
520
- return evt.index
521
-
522
-
523
  # Gradio UI
524
 
525
  def build_app() -> gr.Blocks:
526
  row_css = """
527
- /* Force light theme everywhere */
528
- body {
529
- background-color: #f5f7fa !important;
530
- }
531
 
532
  /* Row number column styling */
533
- .metrics-table th:first-child,
534
- .metrics-table td:first-child {
535
- width: 60px !important;
536
- text-align: center !important;
537
- padding: 8px !important;
538
- font-weight: 600 !important;
539
  background-color: #f0f0f0 !important;
540
  }
541
- /* The outer Group container */
542
  .search-box {
543
- background: white !important;
544
- padding: 16px !important;
545
- border-radius: 6px;
546
- border: 2px solid #e1e4e8 !important;
547
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
548
- margin-bottom: 16px;
549
  }
550
- /* Reset the internal Gradio Block styles so they fit in the white box */
551
- .search-box .block {
552
- background: transparent !important;
553
- border: none !important;
554
- padding: 0 !important;
555
- }
556
- /* Style the Label Text (🔍 Search) */
557
- .search-box label span {
558
- color: #24292e !important;
559
- font-weight: 600;
560
- font-size: 14px;
561
- margin-bottom: 8px;
562
- background: transparent !important;
563
- }
564
- /* Style the actual Input Field */
565
  .search-box input.scroll-hide {
566
- background-color: white !important;
567
- color: #24292e !important;
568
- border: 1.5px solid #e1e4e8 !important;
569
- border-radius: 4px !important;
570
- padding: 10px !important;
571
- box-shadow: none !important;
572
- }
573
- /* Fix focus state */
574
- .search-box input.scroll-hide:focus {
575
- border-color: #0366d6 !important;
576
- ring: 0 !important;
577
- outline: none !important;
578
- }
579
-
580
- .gradio-container {
581
- max-width: 100% !important;
582
- padding: 20px !important;
583
- background-color: #f5f7fa !important;
584
- }
585
-
586
- /* Override all dark backgrounds */
587
- .gradio-container .block,
588
- .gradio-container .form,
589
- .gradio-container fieldset,
590
- .gradio-container .input-block,
591
- .gradio-container .wrap,
592
- .gradio-container .gr-box,
593
- .gradio-container .gr-form,
594
- .gradio-container .gr-input {
595
- background-color: white !important;
596
- border-color: #e1e4e8 !important;
597
- }
598
-
599
- .gradio-container label {
600
- background-color: transparent !important;
601
- color: #24292e !important;
602
- }
603
-
604
- /* Remove any potential dark wrappers */
605
- .gradio-container > div,
606
- .gradio-container .container {
607
- background-color: transparent !important;
608
  }
 
609
 
610
- /* Force all text to be dark */
611
- .gradio-container,
612
- .gradio-container label,
613
- .gradio-container p,
614
- .gradio-container span,
615
- .gradio-container div {
616
- color: #24292e !important;
617
  }
 
618
 
619
  /* Table styling */
620
- .gradio-container table.metrics-table th,
621
- .gradio-container table.metrics-table td {
622
- padding: 10px 14px;
623
- border: 1.5px solid #e1e4e8;
624
- white-space: nowrap;
625
- font-size: 13px;
626
- text-align: left;
627
- color: #24292e !important;
628
  }
629
-
630
  .gradio-container table.metrics-table th {
631
  background: linear-gradient(to bottom, #fafbfc, #f6f8fa);
632
- font-weight: 600;
633
- color: #24292e !important;
634
- position: sticky;
635
- top: 0;
636
- z-index: 10;
637
  border-bottom: 2px solid #d1d5da;
638
  }
 
 
 
 
 
639
 
640
- .gradio-container table.metrics-table tbody tr:nth-child(even) {
641
- background-color: #f6f8fa;
642
- }
643
-
644
- .gradio-container table.metrics-table tbody tr:hover {
645
- background-color: #e1e4e8;
646
- }
647
-
648
- .gradio-container table.metrics-table {
649
- border-collapse: collapse;
650
- width: 100%;
651
- background: white;
652
- }
653
-
654
- .gradio-container table.metrics-table a {
655
- color: #0366d6 !important;
656
- text-decoration: none;
657
- }
658
-
659
- .gradio-container table.metrics-table a:hover {
660
- color: #0366d6 !important;
661
- text-decoration: underline;
662
- }
663
-
664
- .gradio-container .plot-container {
665
- width: 100% !important;
666
- max-width: 1200px !important;
667
- }
668
 
669
- /* Scrollable table container */
670
  .table-container {
671
- overflow-x: auto;
672
- overflow-y: auto;
673
- max-height: 75vh;
674
- border: 2px solid #e1e4e8;
675
- border-radius: 6px;
676
- background: white;
677
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
678
  }
679
-
680
- /* Filter section styling */
681
  .filter-section {
682
- background: white !important;
683
- padding: 0 !important;
684
- border-radius: 6px;
685
- border: 2px solid #e1e4e8 !important;
686
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
687
- }
688
-
689
- .filter-section * {
690
- color: #24292e !important;
691
- }
692
-
693
- .filter-section .wrap,
694
- .filter-section .block,
695
- .filter-section .container,
696
- .filter-section .group,
697
- .filter-section > div,
698
- .filter-section > div > div {
699
- background: transparent !important;
700
- }
701
-
702
- .filter-section .wrap {
703
- padding: 20px !important;
704
- }
705
-
706
- .filter-section label {
707
- background: transparent !important;
708
- color: #24292e !important;
709
  }
710
-
711
- .filter-section fieldset {
712
- background: transparent !important;
713
- border-color: #e1e4e8 !important;
714
- }
715
-
716
- /* Accordion styling */
717
  .gradio-container .accordion {
718
- background: white !important;
719
- border: 2px solid #e1e4e8 !important;
720
- border-radius: 6px !important;
721
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
722
- }
723
-
724
- .gradio-container .accordion * {
725
- color: #24292e !important;
726
- }
727
-
728
- .gradio-container .accordion label {
729
- background: transparent !important;
730
- color: #24292e !important;
731
- }
732
-
733
- .gradio-container .accordion button {
734
- background: transparent !important;
735
- color: #24292e !important;
736
- }
737
-
738
- /* Info section */
739
- .info-section {
740
- padding: 16px;
741
- background: white !important;
742
- }
743
-
744
- /* Make text in info section dark */
745
- .info-section p,
746
- .info-section li,
747
- .info-section ul,
748
- .info-section h3,
749
- .info-section strong,
750
- .info-section * {
751
- color: #24292e !important;
752
- }
753
-
754
- .info-section a {
755
- color: #0366d6 !important;
756
- }
757
-
758
- /* Override any dark backgrounds in groups and accordions */
759
- .gradio-container .group,
760
- .gradio-container .accordion,
761
- .gradio-container .panel {
762
- background-color: white !important;
763
- }
764
-
765
- /* Heading styling */
766
- .gradio-container h1 {
767
- color: #24292e !important;
768
- font-weight: 700;
769
- margin-bottom: 24px;
770
- }
771
-
772
- .gradio-container h3 {
773
- color: #24292e !important;
774
- font-weight: 600;
775
- margin-bottom: 16px;
776
- }
777
-
778
- /* Checkbox styling */
779
- .gradio-container input[type="checkbox"] {
780
- accent-color: #0366d6 !important;
781
- }
782
  """
783
 
784
- # Use Gradio's default (light) theme explicitly
785
  with gr.Blocks(title="MoE-CAP Dashboard", css=row_css, theme=gr.themes.Default()) as demo:
786
  gr.Markdown("# MoE-CAP Dashboard")
787
 
@@ -800,7 +488,6 @@ def build_app() -> gr.Blocks:
800
 
801
  dir_path = gr.State(RESULT_DIR)
802
 
803
- # 1) Tasks filter
804
  task_filter = gr.CheckboxGroup(
805
  label="📊 Tasks",
806
  choices=[
@@ -813,21 +500,18 @@ def build_app() -> gr.Blocks:
813
  value=["gsm8k", "longbench", "mmlu", "numinamath", "ruler"]
814
  )
815
 
816
- # 2) Inference frameworks filter
817
  framework_filter = gr.CheckboxGroup(
818
  label="⚙️ Inference Frameworks",
819
  choices=["sglang", "vllm"],
820
  value=["sglang", "vllm"],
821
  )
822
 
823
- # 3) Model types filter
824
  model_type_filter = gr.CheckboxGroup(
825
  label="🤖 Model Types",
826
  choices=["instruct", "thinking"],
827
  value=["instruct", "thinking"],
828
  )
829
 
830
- # 4) Precision filter
831
  precision_filter = gr.CheckboxGroup(
832
  label="🎯 Precision",
833
  choices=["bfloat16", "fp8"],
@@ -874,13 +558,12 @@ def build_app() -> gr.Blocks:
874
  )
875
  generate_btn = gr.Button("🎯 Generate", variant="primary", scale=1, size="lg")
876
 
877
- with gr.Row():
878
- with gr.Column(scale=1):
879
- pass
880
- with gr.Column(scale=3):
881
- radar_plot = gr.Plot(label="", value=generate_radar_plot([]))
882
- with gr.Column(scale=1):
883
- pass
884
 
885
  df_data_state = gr.State([])
886
 
 
7
 
8
  RESULT_DIR = os.environ.get("MOECAP_RESULT_DIR")
9
  if not RESULT_DIR:
10
+ # For testing purposes, you can uncomment the line below to set a dummy dir or keep the raise
11
+ # RESULT_DIR = "generic_result_dir"
12
  raise RuntimeError(
13
  "MOECAP_RESULT_DIR is not set. Please set MOECAP_RESULT_DIR (HF Repo ID) before running app.py"
14
  )
 
50
  def generate_radar_plot(selected_rows_data: List[dict]) -> go.Figure:
51
  """Generate a CAP radar plot from selected rows."""
52
 
53
+ # Standard layout settings for consistent sizing
54
+ layout_settings = dict(
55
+ height=750, # Taller height
56
+ autosize=True, # Auto width
57
+ margin=dict(t=80, b=100, l=80, r=80), # Balanced margins
58
+ paper_bgcolor='white',
59
+ plot_bgcolor='white',
60
+ )
61
+
62
+ # Validation: max 3 rows
63
  if not selected_rows_data or len(selected_rows_data) == 0:
64
  fig = go.Figure()
65
  fig.add_annotation(
 
71
  yanchor='middle'
72
  )
73
  fig.update_layout(
 
74
  xaxis=dict(visible=False),
75
  yaxis=dict(visible=False),
76
+ **layout_settings
 
 
77
  )
78
  return fig
79
 
 
88
  yanchor='middle'
89
  )
90
  fig.update_layout(
 
91
  xaxis=dict(visible=False),
92
  yaxis=dict(visible=False),
93
+ **layout_settings
 
 
94
  )
95
  return fig
96
 
 
107
  yanchor='middle'
108
  )
109
  fig.update_layout(
 
110
  xaxis=dict(visible=False),
111
  yaxis=dict(visible=False),
112
+ **layout_settings
 
 
113
  )
114
  return fig
115
 
 
200
  title=dict(
201
  text=f"CAP Radar Plot: {dataset_name}",
202
  x=0.5,
203
+ xanchor='center',
204
  font=dict(size=20)
205
  ),
206
  polar=dict(
 
211
  ),
212
  angularaxis=dict(
213
  tickfont=dict(size=14),
214
+ rotation=90, # Rotate so top is 12 o'clock
215
  direction='clockwise'
216
  ),
217
  ),
218
  legend=dict(
219
  orientation='h',
220
  yanchor='bottom',
221
+ y=-0.15,
222
  xanchor='center',
223
  x=0.5,
224
  font=dict(size=13)
225
  ),
226
+ **layout_settings
 
 
 
 
 
 
227
  )
228
 
229
  return fig
 
280
  "Decoding<br>S-MFU(%)": pct(metrics.get("decoding_smfu")),
281
  "TTFT(s)": f2(metrics.get("ttft")),
282
  "TPOT(s)": f2(metrics.get("tpot")),
283
+ "Batch size": batch_size,
284
  }
285
  return row
286
 
287
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  def load_from_dir(
289
  dir_path: str,
290
  selected_tasks: List[str] | None = None,
 
307
  )
308
  except Exception as e:
309
  empty_html = "<p>No files loaded or Dataset not found.</p>"
310
+ return empty_html, []
311
 
312
  rows = []
313
  for i, example in enumerate(ds):
 
319
 
320
  if not rows:
321
  empty_html = "<p>No records found.</p>"
322
+ return empty_html, []
323
 
324
  df = pd.DataFrame(rows)
325
 
326
+ # Filters
327
  if selected_tasks is not None:
328
  lower_selected = [x.lower() for x in selected_tasks]
329
  df = df[df["Dataset"].astype(str).str.lower().isin(lower_selected)]
330
 
 
 
331
  if selected_frameworks is not None:
332
  lower_selected = [str(x).lower() for x in selected_frameworks]
333
  df = df[df["Method"].astype(str).str.lower().isin(lower_selected)]
334
 
 
335
  if selected_model_types is not None:
336
  lower_selected = [str(x).lower() for x in selected_model_types]
337
  df = df[df["Model type"].astype(str).str.lower().isin(lower_selected)]
338
 
 
339
  if selected_precisions is not None:
340
  lower_selected = [str(x).lower() for x in selected_precisions]
341
  df = df[df["Precision"].astype(str).str.lower().isin(lower_selected)]
342
 
 
343
  if search_keyword and search_keyword.strip():
344
  keyword_lower = search_keyword.strip().lower()
 
345
  mask = df.astype(str).apply(lambda row: row.str.lower().str.contains(keyword_lower).any(), axis=1)
346
  df = df[mask]
347
 
 
350
  return empty_html, []
351
 
352
  df = df.fillna("-")
353
+
354
+ # Insert row number column at the beginning
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
355
  df.insert(0, 'Row #', range(len(df)))
356
 
357
  # Create HTML table
 
380
  )
381
 
382
 
 
 
 
 
 
 
 
 
 
 
383
  def parse_and_generate_plot(df_data: list, indices_str: str):
384
  """Parse comma-separated indices and generate radar plot."""
385
  if not indices_str or not indices_str.strip():
 
397
  return generate_radar_plot([])
398
 
399
 
 
 
 
 
 
400
  # Gradio UI
401
 
402
  def build_app() -> gr.Blocks:
403
  row_css = """
404
+ body { background-color: #f5f7fa !important; }
 
 
 
405
 
406
  /* Row number column styling */
407
+ .metrics-table th:first-child, .metrics-table td:first-child {
408
+ width: 60px !important; text-align: center !important;
409
+ padding: 8px !important; font-weight: 600 !important;
 
 
 
410
  background-color: #f0f0f0 !important;
411
  }
 
412
  .search-box {
413
+ background: white !important; padding: 16px !important;
414
+ border-radius: 6px; border: 2px solid #e1e4e8 !important;
415
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06); margin-bottom: 16px;
 
 
 
416
  }
417
+ .search-box .block { background: transparent !important; border: none !important; padding: 0 !important; }
418
+ .search-box label span { color: #24292e !important; font-weight: 600; font-size: 14px; margin-bottom: 8px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
419
  .search-box input.scroll-hide {
420
+ background-color: white !important; color: #24292e !important;
421
+ border: 1.5px solid #e1e4e8 !important; border-radius: 4px !important;
422
+ padding: 10px !important; box-shadow: none !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
  }
424
+ .search-box input.scroll-hide:focus { border-color: #0366d6 !important; outline: none !important; }
425
 
426
+ .gradio-container { max-width: 100% !important; padding: 20px !important; background-color: #f5f7fa !important; }
427
+ .gradio-container .block, .gradio-container .form, .gradio-container .gr-box, .gradio-container .gr-input {
428
+ background-color: white !important; border-color: #e1e4e8 !important;
 
 
 
 
429
  }
430
+ .gradio-container label, .gradio-container p, .gradio-container span, .gradio-container div { color: #24292e !important; }
431
 
432
  /* Table styling */
433
+ .gradio-container table.metrics-table th, .gradio-container table.metrics-table td {
434
+ padding: 10px 14px; border: 1.5px solid #e1e4e8; white-space: nowrap;
435
+ font-size: 13px; text-align: left; color: #24292e !important;
 
 
 
 
 
436
  }
 
437
  .gradio-container table.metrics-table th {
438
  background: linear-gradient(to bottom, #fafbfc, #f6f8fa);
439
+ font-weight: 600; position: sticky; top: 0; z-index: 10;
 
 
 
 
440
  border-bottom: 2px solid #d1d5da;
441
  }
442
+ .gradio-container table.metrics-table tbody tr:nth-child(even) { background-color: #f6f8fa; }
443
+ .gradio-container table.metrics-table tbody tr:hover { background-color: #e1e4e8; }
444
+ .gradio-container table.metrics-table { border-collapse: collapse; width: 100%; background: white; }
445
+ .gradio-container table.metrics-table a { color: #0366d6 !important; text-decoration: none; }
446
+ .gradio-container table.metrics-table a:hover { text-decoration: underline; }
447
 
448
+ /* Allow plot container to expand */
449
+ .gradio-container .plot-container { width: 100% !important; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
 
 
451
  .table-container {
452
+ overflow-x: auto; overflow-y: auto; max-height: 75vh;
453
+ border: 2px solid #e1e4e8; border-radius: 6px;
454
+ background: white; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
 
 
 
 
455
  }
 
 
456
  .filter-section {
457
+ background: white !important; padding: 0 !important; border-radius: 6px;
458
+ border: 2px solid #e1e4e8 !important; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
459
  }
460
+ .filter-section .wrap, .filter-section .block, .filter-section .container, .filter-section .group { background: transparent !important; }
461
+ .filter-section .wrap { padding: 20px !important; }
 
 
 
 
 
462
  .gradio-container .accordion {
463
+ background: white !important; border: 2px solid #e1e4e8 !important;
464
+ border-radius: 6px !important; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
465
+ }
466
+ .info-section { padding: 16px; background: white !important; }
467
+ .info-section a { color: #0366d6 !important; }
468
+ .gradio-container h1 { color: #24292e !important; font-weight: 700; margin-bottom: 24px; }
469
+ .gradio-container h3 { color: #24292e !important; font-weight: 600; margin-bottom: 16px; }
470
+ .gradio-container input[type="checkbox"] { accent-color: #0366d6 !important; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
471
  """
472
 
 
473
  with gr.Blocks(title="MoE-CAP Dashboard", css=row_css, theme=gr.themes.Default()) as demo:
474
  gr.Markdown("# MoE-CAP Dashboard")
475
 
 
488
 
489
  dir_path = gr.State(RESULT_DIR)
490
 
 
491
  task_filter = gr.CheckboxGroup(
492
  label="📊 Tasks",
493
  choices=[
 
500
  value=["gsm8k", "longbench", "mmlu", "numinamath", "ruler"]
501
  )
502
 
 
503
  framework_filter = gr.CheckboxGroup(
504
  label="⚙️ Inference Frameworks",
505
  choices=["sglang", "vllm"],
506
  value=["sglang", "vllm"],
507
  )
508
 
 
509
  model_type_filter = gr.CheckboxGroup(
510
  label="🤖 Model Types",
511
  choices=["instruct", "thinking"],
512
  value=["instruct", "thinking"],
513
  )
514
 
 
515
  precision_filter = gr.CheckboxGroup(
516
  label="🎯 Precision",
517
  choices=["bfloat16", "fp8"],
 
558
  )
559
  generate_btn = gr.Button("🎯 Generate", variant="primary", scale=1, size="lg")
560
 
561
+ # Modified Layout: Removed surrounding columns to allow plot to fill full width
562
+ radar_plot = gr.Plot(
563
+ label="",
564
+ value=generate_radar_plot([]),
565
+ elem_classes="plot-container"
566
+ )
 
567
 
568
  df_data_state = gr.State([])
569