rashisht commited on
Commit
7cee824
Β·
verified Β·
1 Parent(s): c17c27f

About tab: JSON-driven panel cards

Browse files
Files changed (1) hide show
  1. app.py +77 -4
app.py CHANGED
@@ -1,8 +1,10 @@
1
  """Real World VoiceEQ Benchmark β€” Gradio Space (Text-to-Speech / Speech-to-Speech /
2
  Voice Controllability / Speech Understanding / Speech Recognition / SLM Judge).
3
 
4
- One Space, six tabs β€” one per modality (plus the SLM Judge meta-leaderboard of
5
- judge-vs-human agreement). Each tab renders a heatmap-style ranking
 
 
6
  table from a self-describing JSON file that holds a *list* of boards (an Overall
7
  board + one per factor). The boards are pivoted into one wide table: each factor's
8
  `score` becomes a heatmapped column. Rows are ranked by the first factor column by
@@ -314,6 +316,44 @@ def merge_boards(boards: list) -> dict:
314
  }
315
 
316
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  def _logo_data_uri(suffix: str = "") -> str:
318
  mimes = {".avif": "image/avif", ".svg": "image/svg+xml",
319
  ".png": "image/png", ".webp": "image/webp"}
@@ -523,6 +563,20 @@ TABLE_CSS = """
523
  .ttslb .smp-text { flex:1; min-width:220px; text-align:left; font-size:12.5px;
524
  line-height:1.45; color:var(--lb-ink-2); }
525
  .ttslb .smp-pending { color:var(--lb-ink-3); font-size:12px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
  /* Header logo swap: each img bakes its default visibility inline as
527
  display:var(--lb-logo-*, ...) β€” gradio strips class-based styling from
528
  gr.HTML imgs, but inline styles and inherited custom properties survive.
@@ -580,6 +634,15 @@ APP_JS = """
580
  }
581
  document.addEventListener('click', function (e) {
582
  if (!e.target.closest) return;
 
 
 
 
 
 
 
 
 
583
  var btn = e.target.closest('.ttslb .csv-btn');
584
  if (btn) {
585
  var card = btn.closest('.ttslb');
@@ -619,6 +682,13 @@ APP_JS = """
619
  if (numeric) { var f = parseFloat(v); return isNaN(f) ? { empty: true } : { n: f }; }
620
  return { s: v };
621
  }
 
 
 
 
 
 
 
622
  document.addEventListener('click', function (e) {
623
  if (!e.target.closest) return;
624
  if (e.target.closest('.info')) return; // β“˜ tooltip icon: not a sort click
@@ -973,10 +1043,13 @@ def build_demo() -> gr.Blocks:
973
  gr.Markdown(f"# {title}")
974
 
975
  samples = load_samples()
 
976
  with gr.Tabs():
 
 
 
977
  for label, key, data_name in MODALITIES:
978
- boards = load_boards(data_name)
979
- board = merge_boards(boards)
980
  factor_labels = {c["field"]: c["label"] for c in board["metricColumns"]}
981
  # CSV filenames follow the visible tab label, e.g.
982
  # rw-voice-eq-speech-understanding.csv
 
1
  """Real World VoiceEQ Benchmark β€” Gradio Space (Text-to-Speech / Speech-to-Speech /
2
  Voice Controllability / Speech Understanding / Speech Recognition / SLM Judge).
3
 
4
+ One Space: an About tab (about.json prose + one clickable card per panel that
5
+ jumps to its tab), then one tab per modality (plus the SLM Judge
6
+ meta-leaderboard of judge-vs-human agreement). Each leaderboard tab renders a
7
+ heatmap-style ranking
8
  table from a self-describing JSON file that holds a *list* of boards (an Overall
9
  board + one per factor). The boards are pivoted into one wide table: each factor's
10
  `score` becomes a heatmapped column. Rows are ranked by the first factor column by
 
316
  }
317
 
318
 
319
+ # ── About tab ───────────────────────────────────────────────────────────────
320
+ # Content lives in about.json next to the board JSONs ({intro: [...],
321
+ # panels: [{tab, title, paragraphs}], outro: [...]}). Each panel renders as
322
+ # one clickable card that jumps to that leaderboard tab (wired in APP_JS);
323
+ # "tab" must match the MODALITIES label exactly.
324
+ ABOUT_NAME = "about.json"
325
+
326
+
327
+ def load_about() -> dict:
328
+ """about.json from the dataset (or ./data), {} when absent β€” the About
329
+ tab is simply skipped without it."""
330
+ try:
331
+ return json.loads(_data_path(ABOUT_NAME).read_text())
332
+ except Exception:
333
+ return {}
334
+
335
+
336
+ def render_about(about: dict) -> str:
337
+ """The About tab: intro paragraphs, one clickable card per leaderboard
338
+ panel (title + description, click = jump to that tab), outro."""
339
+ parts = ["<div class='ttslb abt'>"]
340
+ for p in about.get("intro", []):
341
+ parts.append(f"<p class='abt-p'>{html.escape(p)}</p>")
342
+ cards = []
343
+ for panel in about.get("panels", []):
344
+ body = "".join(f"<p>{html.escape(q)}</p>" for q in panel.get("paragraphs", []))
345
+ cards.append(
346
+ f"<div class='abt-card' role='button' tabindex='0' "
347
+ f"data-tab='{html.escape(panel['tab'], quote=True)}'>"
348
+ f"<div class='abt-card-t'>{html.escape(panel.get('title') or panel['tab'])}"
349
+ f"<span class='abt-go'>β†’</span></div>{body}</div>")
350
+ parts.append("<div class='abt-cards'>" + "".join(cards) + "</div>")
351
+ for p in about.get("outro", []):
352
+ parts.append(f"<p class='abt-p'>{html.escape(p)}</p>")
353
+ parts.append("</div>")
354
+ return "".join(parts)
355
+
356
+
357
  def _logo_data_uri(suffix: str = "") -> str:
358
  mimes = {".avif": "image/avif", ".svg": "image/svg+xml",
359
  ".png": "image/png", ".webp": "image/webp"}
 
563
  .ttslb .smp-text { flex:1; min-width:220px; text-align:left; font-size:12.5px;
564
  line-height:1.45; color:var(--lb-ink-2); }
565
  .ttslb .smp-pending { color:var(--lb-ink-3); font-size:12px; }
566
+ /* About tab: intro/outro prose + one clickable card per leaderboard panel
567
+ (title + description; the whole card jumps to that tab via APP_JS). */
568
+ .ttslb.abt { max-width:920px; }
569
+ .ttslb .abt-p { margin:8px 2px; font-size:13px; line-height:1.55; color:var(--lb-ink-2); text-align:left; }
570
+ .ttslb .abt-cards { display:grid; grid-template-columns:repeat(auto-fill, minmax(360px, 1fr));
571
+ gap:12px; margin:14px 0 12px; }
572
+ .ttslb .abt-card { border:1px solid var(--lb-border); border-radius:10px; padding:13px 16px;
573
+ cursor:pointer; text-align:left; }
574
+ .ttslb .abt-card:hover { border-color:var(--lb-accent); box-shadow:inset 0 0 0 1px var(--lb-accent); }
575
+ .ttslb .abt-card-t { display:flex; align-items:baseline; justify-content:space-between; gap:10px;
576
+ font-size:13.5px; font-weight:700; }
577
+ .ttslb .abt-go { color:var(--lb-ink-4); font-weight:400; }
578
+ .ttslb .abt-card:hover .abt-go { color:var(--lb-accent); }
579
+ .ttslb .abt-card p { margin:7px 0 0; font-size:12.5px; line-height:1.5; color:var(--lb-ink-2); }
580
  /* Header logo swap: each img bakes its default visibility inline as
581
  display:var(--lb-logo-*, ...) β€” gradio strips class-based styling from
582
  gr.HTML imgs, but inline styles and inherited custom properties survive.
 
634
  }
635
  document.addEventListener('click', function (e) {
636
  if (!e.target.closest) return;
637
+ var chip = e.target.closest('.ttslb .abt-card');
638
+ if (chip) { // About-tab panel card: jump to that panel's tab
639
+ var want = chip.getAttribute('data-tab');
640
+ var tabs = document.querySelectorAll("button[role='tab']");
641
+ for (var i = 0; i < tabs.length; i++) {
642
+ if (tabs[i].textContent.trim() === want) { tabs[i].click(); window.scrollTo(0, 0); break; }
643
+ }
644
+ return;
645
+ }
646
  var btn = e.target.closest('.ttslb .csv-btn');
647
  if (btn) {
648
  var card = btn.closest('.ttslb');
 
682
  if (numeric) { var f = parseFloat(v); return isNaN(f) ? { empty: true } : { n: f }; }
683
  return { s: v };
684
  }
685
+ document.addEventListener('keydown', function (e) {
686
+ // About-tab panel cards are div[role=button]: Enter/Space activates
687
+ if ((e.key === 'Enter' || e.key === ' ') && e.target.closest) {
688
+ var card = e.target.closest('.ttslb .abt-card');
689
+ if (card) { e.preventDefault(); card.click(); }
690
+ }
691
+ });
692
  document.addEventListener('click', function (e) {
693
  if (!e.target.closest) return;
694
  if (e.target.closest('.info')) return; // β“˜ tooltip icon: not a sort click
 
1043
  gr.Markdown(f"# {title}")
1044
 
1045
  samples = load_samples()
1046
+ about = load_about()
1047
  with gr.Tabs():
1048
+ if about:
1049
+ with gr.Tab("About"):
1050
+ gr.HTML(render_about(about))
1051
  for label, key, data_name in MODALITIES:
1052
+ board = merge_boards(load_boards(data_name))
 
1053
  factor_labels = {c["field"]: c["label"] for c in board["metricColumns"]}
1054
  # CSV filenames follow the visible tab label, e.g.
1055
  # rw-voice-eq-speech-understanding.csv