rashisht commited on
Commit
4bd5ced
·
verified ·
1 Parent(s): 896a43b

Samples: Better/Worse verdict chips + shared pair transcripts

Browse files
Files changed (1) hide show
  1. app.py +59 -9
app.py CHANGED
@@ -68,8 +68,8 @@ MODALITIES = [
68
  HIDDEN_BOARDS: frozenset = frozenset()
69
 
70
  # Curated audio samples (optional): a samples.json manifest next to the board
71
- # JSONs, each record {modality, factor, label?, group?, model?, text?,
72
- # transcript?, audio} where "audio" is a repo-relative path (e.g.
73
  # "samples/foo.mp3") resolved against the dataset (or ./data locally). A
74
  # record's modality routes it to that tab, which appends a samples section
75
  # (per-factor category tabs) below the board table. "text" (generation prompt)
@@ -79,6 +79,11 @@ HIDDEN_BOARDS: frozenset = frozenset()
79
  # render under one shared subheading instead of per-row labels; a group whose
80
  # records carry a "scenario" renders a bold "Scenario:" blurb as its lead-in
81
  # instead of the heading.
 
 
 
 
 
82
  # A record with "turns" is a conversation (STS samples) rendered as a card:
83
  # header = model (or "label" for stimulus cards) + optional "score"
84
  # ({value, max, label}) badge + "verdict"/"verdict_label" chip + "caption";
@@ -412,6 +417,7 @@ TABLE_CSS = """
412
  --lb-row-line:#f1f2f4; --lb-row-alt:#fafafa; --lb-tip-bg:#1f2328; --lb-tip-ink:#f5f6f7;
413
  --lb-tip-border:#1f2328; --lb-shadow:rgba(0,0,0,.18); --lb-ramp:@RAMP_LIGHT@;
414
  --lb-dim-bg:#eef0f2; --lb-dim-ink:#9aa1ab;
 
415
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
416
  color:var(--lb-ink); max-width:100%; margin:0; color-scheme:light;
417
  background:var(--lb-surface); border:1px solid var(--lb-border); border-radius:12px; padding:16px 18px; }
@@ -420,6 +426,7 @@ TABLE_CSS = """
420
  --lb-row-line:#26292e; --lb-row-alt:#202327; --lb-tip-bg:#262e3a; --lb-tip-ink:#e7eaef;
421
  --lb-tip-border:#39424f; --lb-shadow:rgba(0,0,0,.55); --lb-ramp:@RAMP_DARK@;
422
  --lb-dim-bg:#22262d; --lb-dim-ink:#79818d;
 
423
  color-scheme:dark; }
424
  .ttslb .tbl-wrap { overflow-x:auto; }
425
  /* Natural table width + pinned widths keep the rank/provider/License columns the
@@ -551,6 +558,19 @@ TABLE_CSS = """
551
  .ttslb .smp-gnote { margin:2px 0 8px; max-width:760px; text-align:left;
552
  font-size:12px; line-height:1.5; color:var(--lb-ink-2); }
553
  .ttslb .smp-gnote strong { color:var(--lb-ink); }
 
 
 
 
 
 
 
 
 
 
 
 
 
554
  /* a Scenario blurb starting the next group gets breathing room after the
555
  previous group's cards */
556
  .ttslb .smp-convo + .smp-gnote { margin-top:20px; }
@@ -1065,7 +1085,11 @@ def render_samples_section(samples: list, factor_labels: dict,
1065
  but not displayed; a "transcript" (the human reference for ASR golden
1066
  samples) is rendered next to the player. Rows carrying a "group" cluster
1067
  under one shared subheading (with a sample count) instead of repeating a
1068
- per-row label — the manifest is expected to keep a group's rows adjacent."""
 
 
 
 
1069
  if not samples:
1070
  return ""
1071
  factors = []
@@ -1081,23 +1105,39 @@ def render_samples_section(samples: list, factor_labels: dict,
1081
  f"{html.escape(f_label)} <span class='smp-n'>({len(rows)})</span></button>")
1082
  rows_html = []
1083
  cur_group = None
 
1084
  for s in rows:
1085
  group = (s.get("group") or "").strip()
1086
  # each run of same-group records opens with a lead-in: a bold
1087
  # "Scenario:" blurb when the record carries one (STS conversation
1088
- # groups), else the group name + count subheading (ASR tag
1089
- # buckets, whose grouped flat rows drop the head column and
1090
- # indent under it)
 
 
 
1091
  if group and group != cur_group:
 
 
1092
  if s.get("scenario"):
1093
  rows_html.append(f"<div class='smp-gnote'><strong>Scenario:"
1094
  f"</strong> {html.escape(s['scenario'])}</div>")
1095
  elif group != f_label:
1096
  # a bucket named exactly like its tab would just repeat the
1097
  # tab label — skip the subheading, keep the grouped rows
1098
- n = sum(1 for r in rows if (r.get("group") or "").strip() == group)
1099
- rows_html.append(f"<div class='smp-group'>{html.escape(group)} "
1100
- f"<span class='smp-n'>({n})</span></div>")
 
 
 
 
 
 
 
 
 
 
1101
  cur_group = group or None
1102
  if s.get("turns"):
1103
  rows_html.append(_convo_html(s))
@@ -1106,6 +1146,16 @@ def render_samples_section(samples: list, factor_labels: dict,
1106
  player = (f"<audio controls preload='none' src='{src}'></audio>"
1107
  if src else "<span class='smp-pending'>audio pending</span>")
1108
  transcript = (s.get("transcript") or "").strip()
 
 
 
 
 
 
 
 
 
 
1109
  if group:
1110
  body = (f"{player}<div class='smp-text'>{html.escape(transcript)}</div>"
1111
  if transcript else player)
 
68
  HIDDEN_BOARDS: frozenset = frozenset()
69
 
70
  # Curated audio samples (optional): a samples.json manifest next to the board
71
+ # JSONs, each record {modality, factor, label?, group?, verdict?, model?,
72
+ # text?, transcript?, audio} where "audio" is a repo-relative path (e.g.
73
  # "samples/foo.mp3") resolved against the dataset (or ./data locally). A
74
  # record's modality routes it to that tab, which appends a samples section
75
  # (per-factor category tabs) below the board table. "text" (generation prompt)
 
79
  # render under one shared subheading instead of per-row labels; a group whose
80
  # records carry a "scenario" renders a bold "Scenario:" blurb as its lead-in
81
  # instead of the heading.
82
+ # A flat record with "verdict" (better|worse) is one half of a curated TTS
83
+ # contrast pair: it renders as a colored chip + player row under its group
84
+ # (the eval's display name), whose shared prompt "transcript" prints once at
85
+ # the lead-in. "model"/"score"/"instructions"/"tag"/"eval" ride along in the
86
+ # manifest as provenance, deliberately never displayed.
87
  # A record with "turns" is a conversation (STS samples) rendered as a card:
88
  # header = model (or "label" for stimulus cards) + optional "score"
89
  # ({value, max, label}) badge + "verdict"/"verdict_label" chip + "caption";
 
417
  --lb-row-line:#f1f2f4; --lb-row-alt:#fafafa; --lb-tip-bg:#1f2328; --lb-tip-ink:#f5f6f7;
418
  --lb-tip-border:#1f2328; --lb-shadow:rgba(0,0,0,.18); --lb-ramp:@RAMP_LIGHT@;
419
  --lb-dim-bg:#eef0f2; --lb-dim-ink:#9aa1ab;
420
+ --lb-good-bg:#eaf3df; --lb-good-ink:#567d2e; --lb-bad-bg:#f9e9e6; --lb-bad-ink:#b04a3e;
421
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
422
  color:var(--lb-ink); max-width:100%; margin:0; color-scheme:light;
423
  background:var(--lb-surface); border:1px solid var(--lb-border); border-radius:12px; padding:16px 18px; }
 
426
  --lb-row-line:#26292e; --lb-row-alt:#202327; --lb-tip-bg:#262e3a; --lb-tip-ink:#e7eaef;
427
  --lb-tip-border:#39424f; --lb-shadow:rgba(0,0,0,.55); --lb-ramp:@RAMP_DARK@;
428
  --lb-dim-bg:#22262d; --lb-dim-ink:#79818d;
429
+ --lb-good-bg:#2c3f1e; --lb-good-ink:#a3c585; --lb-bad-bg:#48261f; --lb-bad-ink:#d98a80;
430
  color-scheme:dark; }
431
  .ttslb .tbl-wrap { overflow-x:auto; }
432
  /* Natural table width + pinned widths keep the rank/provider/License columns the
 
558
  .ttslb .smp-gnote { margin:2px 0 8px; max-width:760px; text-align:left;
559
  font-size:12px; line-height:1.5; color:var(--lb-ink-2); }
560
  .ttslb .smp-gnote strong { color:var(--lb-ink); }
561
+ /* Better/Worse contrast pairs (curated TTS samples): fixed-width verdict
562
+ chips keep the pair's two players aligned; inks match the STS verdict
563
+ dots below. The pair's shared prompt text (.smp-gtx) sits under its group
564
+ heading — .long (the multi-minute long-form evals) caps it into a scroll
565
+ box instead of a wall of prose. */
566
+ .ttslb .smp-chip { flex:none; width:60px; text-align:center; font-size:11px; font-weight:700;
567
+ letter-spacing:.2px; padding:3px 0; border-radius:999px; }
568
+ .ttslb .smp-chip.better { background:var(--lb-good-bg); color:var(--lb-good-ink); }
569
+ .ttslb .smp-chip.worse { background:var(--lb-bad-bg); color:var(--lb-bad-ink); }
570
+ .ttslb .smp-gtx { margin:2px 0 4px; padding-left:14px; max-width:760px; text-align:left;
571
+ font-size:12.5px; line-height:1.5; color:var(--lb-ink-2); }
572
+ .ttslb .smp-gtx.long { max-height:76px; overflow-y:auto; margin-left:14px; padding:8px 10px;
573
+ border:1px solid var(--lb-row-line); border-radius:8px; }
574
  /* a Scenario blurb starting the next group gets breathing room after the
575
  previous group's cards */
576
  .ttslb .smp-convo + .smp-gnote { margin-top:20px; }
 
1085
  but not displayed; a "transcript" (the human reference for ASR golden
1086
  samples) is rendered next to the player. Rows carrying a "group" cluster
1087
  under one shared subheading (with a sample count) instead of repeating a
1088
+ per-row label — the manifest is expected to keep a group's rows adjacent.
1089
+ Flat rows carrying a "verdict" (better|worse) are curated contrast pairs:
1090
+ each renders as a colored chip + player, and the pair's shared prompt
1091
+ transcript prints once under the group heading (whose count is dropped —
1092
+ "(2)" on every pair says nothing)."""
1093
  if not samples:
1094
  return ""
1095
  factors = []
 
1105
  f"{html.escape(f_label)} <span class='smp-n'>({len(rows)})</span></button>")
1106
  rows_html = []
1107
  cur_group = None
1108
+ shared_tx = False # the group lead-in already printed the pair's prompt
1109
  for s in rows:
1110
  group = (s.get("group") or "").strip()
1111
  # each run of same-group records opens with a lead-in: a bold
1112
  # "Scenario:" blurb when the record carries one (STS conversation
1113
+ # groups), else the group name subheading with a row count for
1114
+ # ASR's tag buckets, but without one for Better/Worse pairs, where
1115
+ # "(2)" says nothing. A verdict pair is a same-text contrast, so
1116
+ # its shared "transcript" prints once here; the multi-minute
1117
+ # long-form evals' text gets a capped scroll box (.long) instead
1118
+ # of a wall of prose.
1119
  if group and group != cur_group:
1120
+ grp_rows = [r for r in rows if (r.get("group") or "").strip() == group]
1121
+ pair = all(r.get("verdict") and not r.get("turns") for r in grp_rows)
1122
  if s.get("scenario"):
1123
  rows_html.append(f"<div class='smp-gnote'><strong>Scenario:"
1124
  f"</strong> {html.escape(s['scenario'])}</div>")
1125
  elif group != f_label:
1126
  # a bucket named exactly like its tab would just repeat the
1127
  # tab label — skip the subheading, keep the grouped rows
1128
+ count = ("" if pair else
1129
+ f" <span class='smp-n'>({len(grp_rows)})</span>")
1130
+ rows_html.append(f"<div class='smp-group'>{html.escape(group)}{count}</div>")
1131
+ shared_tx = False
1132
+ if pair:
1133
+ txs = {(r.get("transcript") or "").strip() for r in grp_rows}
1134
+ tx = txs.pop() if len(txs) == 1 else ""
1135
+ if tx:
1136
+ shared_tx = True
1137
+ rows_html.append(f"<div class='smp-gtx{' long' if len(tx) > 400 else ''}'>"
1138
+ f"{html.escape(tx)}</div>")
1139
+ elif not group:
1140
+ shared_tx = False
1141
  cur_group = group or None
1142
  if s.get("turns"):
1143
  rows_html.append(_convo_html(s))
 
1146
  player = (f"<audio controls preload='none' src='{src}'></audio>"
1147
  if src else "<span class='smp-pending'>audio pending</span>")
1148
  transcript = (s.get("transcript") or "").strip()
1149
+ if s.get("verdict"):
1150
+ # a contrast-pair half: Better/Worse chip + player; the
1151
+ # transcript rides in the row only when the lead-in didn't
1152
+ # already print it for the whole pair
1153
+ v = "better" if s["verdict"] == "better" else "worse"
1154
+ tx = "" if shared_tx else transcript
1155
+ body = (f"<span class='smp-chip {v}'>{v.capitalize()}</span>{player}"
1156
+ + (f"<div class='smp-text'>{html.escape(tx)}</div>" if tx else ""))
1157
+ rows_html.append(f"<div class='smp-row grp{' txt' if tx else ''}'>{body}</div>")
1158
+ continue
1159
  if group:
1160
  body = (f"{player}<div class='smp-text'>{html.escape(transcript)}</div>"
1161
  if transcript else player)