from __future__ import annotations
import base64
import json
from functools import cmp_to_key
from html import escape
from pathlib import Path
from typing import Any
import gradio as gr
HOME_VIEW = "HOME"
TASK_ORDER = [
"K-disentQA",
"SQA",
"Instruct",
"ASR",
"Translation",
"LSQA",
]
ROOT = Path(__file__).parent
DATA_PATH = ROOT / "data" / "leaderboard-data.json"
IMAGES_DIR = ROOT / "images"
def to_num(value: Any) -> float | None:
try:
num = float(value)
except (TypeError, ValueError):
return None
return num
def average(values: list[float | None]) -> float | None:
valid = [value for value in values if value is not None]
if not valid:
return None
return sum(valid) / len(valid)
def compare_scores(left: float | None, right: float | None, lower_better: bool) -> int:
if left is None and right is None:
return 0
if left is None:
return 1
if right is None:
return -1
if left == right:
return 0
if lower_better:
return -1 if left < right else 1
return -1 if left > right else 1
def ordered_tasks(tasks: list[dict[str, Any]]) -> list[dict[str, Any]]:
def sort_key(task: dict[str, Any]) -> tuple[int, str]:
try:
task_index = TASK_ORDER.index(task["id"])
except ValueError:
task_index = 10**6
return task_index, task["label"]
return sorted(tasks, key=sort_key)
def dataset_ids(task: dict[str, Any]) -> list[str]:
return [dataset["id"] for dataset in task.get("datasets", [])]
def metric_value(entry: dict[str, Any], task_id: str, dataset_id: str) -> float | None:
dataset = entry.get("tasks", {}).get(task_id, {}).get(dataset_id)
if not dataset:
return None
return to_num(dataset.get("value"))
def metric_display(entry: dict[str, Any], task_id: str, dataset_id: str) -> str:
dataset = entry.get("tasks", {}).get(task_id, {}).get(dataset_id)
if not dataset:
return "-"
if dataset.get("display") is not None:
return str(dataset["display"])
if dataset.get("value") is None:
return "-"
return str(dataset["value"])
def compute_task_overall(entry: dict[str, Any], task: dict[str, Any]) -> float | None:
return average([metric_value(entry, task["id"], dataset_id) for dataset_id in dataset_ids(task)])
def normalize_task_scores(entries: list[dict[str, Any]], tasks: list[dict[str, Any]]) -> dict[str, dict[str, float] | None]:
ranges: dict[str, dict[str, float] | None] = {}
for task in tasks:
values = [entry["task_overall"][task["id"]] for entry in entries if entry["task_overall"][task["id"]] is not None]
if not values:
ranges[task["id"]] = None
continue
ranges[task["id"]] = {"min": min(values), "max": max(values)}
return ranges
def normalized_score(value: float | None, score_range: dict[str, float] | None, lower_better: bool) -> float | None:
if value is None or score_range is None:
return None
if score_range["min"] == score_range["max"]:
return 100.0
if lower_better:
return ((score_range["max"] - value) / (score_range["max"] - score_range["min"])) * 100
return ((value - score_range["min"]) / (score_range["max"] - score_range["min"])) * 100
def enrich_entries(entries: list[dict[str, Any]], tasks: list[dict[str, Any]]) -> list[dict[str, Any]]:
entries_with_task_overall = []
for entry in entries:
task_overall = {}
for task in tasks:
task_overall[task["id"]] = compute_task_overall(entry, task)
entries_with_task_overall.append({**entry, "task_overall": task_overall})
task_ranges = normalize_task_scores(entries_with_task_overall, tasks)
enriched_entries = []
for entry in entries_with_task_overall:
normalized_task_scores = {}
for task in tasks:
normalized_task_scores[task["id"]] = normalized_score(
entry["task_overall"][task["id"]],
task_ranges[task["id"]],
task["lowerBetter"],
)
enriched_entries.append(
{
**entry,
"normalized_task_scores": normalized_task_scores,
"overall": average([normalized_task_scores[task["id"]] for task in tasks]),
}
)
return enriched_entries
def sort_overall(entries: list[dict[str, Any]]) -> list[dict[str, Any]]:
sorted_entries = sorted(
entries,
key=cmp_to_key(lambda left, right: compare_scores(left["overall"], right["overall"], False)),
)
return [{**entry, "rank": index} for index, entry in enumerate(sorted_entries, start=1)]
def sort_task(entries: list[dict[str, Any]], task: dict[str, Any], dataset_id: str) -> list[dict[str, Any]]:
def compare(left: dict[str, Any], right: dict[str, Any]) -> int:
left_value = left["task_overall"][task["id"]] if dataset_id == "Overall" else metric_value(left, task["id"], dataset_id)
right_value = right["task_overall"][task["id"]] if dataset_id == "Overall" else metric_value(right, task["id"], dataset_id)
return compare_scores(left_value, right_value, task["lowerBetter"])
sorted_entries = sorted(entries, key=cmp_to_key(compare))
return [{**entry, "rank": index} for index, entry in enumerate(sorted_entries, start=1)]
def metric_class(lower_better: bool, value: float | None) -> str:
if value is None:
return "muted"
return "metric-bad" if lower_better else "metric-good"
def fmt_score(value: float | None) -> str:
return "-" if value is None else f"{value:.2f}"
def image_data_uri(path: Path) -> str:
encoded = base64.b64encode(path.read_bytes()).decode("ascii")
suffix = path.suffix.lower().lstrip(".") or "png"
mime = "image/png" if suffix == "png" else f"image/{suffix}"
return f"data:{mime};base64,{encoded}"
def load_payload() -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
payload = json.loads(DATA_PATH.read_text(encoding="utf-8"))
tasks = ordered_tasks(payload.get("tasks", []))
entries = enrich_entries(payload.get("entries", []), tasks)
return tasks, entries
TASKS, ENTRIES = load_payload()
TASK_MAP = {task["id"]: task for task in TASKS}
RANKED_OVERALL = sort_overall(ENTRIES)
BADGE_IMAGES = {
1: image_data_uri(IMAGES_DIR / "1st.png"),
2: image_data_uri(IMAGES_DIR / "2nd.png"),
3: image_data_uri(IMAGES_DIR / "3rd.png"),
}
EXTERNAL_LINK_IMAGE = image_data_uri(IMAGES_DIR / "external-link.png")
def menu_choices() -> list[tuple[str, str]]:
choices = [("Home\nOverall ranking", HOME_VIEW)]
for task in TASKS:
choices.append((f"{task['label']}\n{len(task['datasets'])} datasets", task["id"]))
return choices
def dataset_choices(task_id: str) -> list[str]:
task = TASK_MAP[task_id]
return ["Overall", *[dataset["id"] for dataset in task.get("datasets", [])]]
def render_rank_strip(entries: list[dict[str, Any]]) -> str:
cards = []
for entry in entries[:12]:
if entry["rank"] in BADGE_IMAGES:
badge = f'
'
else:
badge = f'#{entry["rank"]}'
cards.append(
f"""
{badge}
{escape(entry["rank_name"])}
"""
)
return f"""
Top Ranking
{"".join(cards)}
"""
def render_home_table(entries: list[dict[str, Any]]) -> str:
header_top = [
'Rank | ',
'RankName | ',
'Model | ',
'URL | ',
'Overall | ',
*[f'{escape(task["label"])} | ' for task in TASKS],
]
header_bottom = [f'{escape(task["shortMetric"])} | ' for task in TASKS]
rows = []
for entry in entries:
url = entry.get("url") or ""
if url:
url_cell = (
f'
'
)
else:
url_cell = "-"
task_cells = []
for task in TASKS:
value = entry["task_overall"][task["id"]]
task_cells.append(f'{fmt_score(value)} | ')
rows.append(
""
f'| {entry["rank"]} | '
f'{escape(entry["rank_name"])} | '
f'{escape(entry.get("model") or entry["rank_name"])} | '
f"{url_cell} | "
f"{fmt_score(entry['overall'])} | "
f"{''.join(task_cells)}"
"
"
)
return f"""
"""
def render_home() -> str:
return f"{render_rank_strip(RANKED_OVERALL)}{render_home_table(RANKED_OVERALL)}"
def render_task_title(task: dict[str, Any]) -> str:
return f"""
Task : {escape(task["label"])}
"""
def render_task_table(task: dict[str, Any], dataset_id: str) -> str:
ranked_entries = sort_task(ENTRIES, task, dataset_id)
active_label = "Overall"
if dataset_id != "Overall":
active_label = next(
(dataset["label"] for dataset in task["datasets"] if dataset["id"] == dataset_id),
dataset_id,
)
rows = []
for entry in ranked_entries:
numeric_value = entry["task_overall"][task["id"]] if dataset_id == "Overall" else metric_value(entry, task["id"], dataset_id)
display_value = fmt_score(numeric_value) if dataset_id == "Overall" else metric_display(entry, task["id"], dataset_id)
rows.append(
""
f'| {entry["rank"]} | '
f'{escape(entry["rank_name"])} | '
f'{escape(entry.get("model") or entry["rank_name"])} | '
f'{escape(display_value)} | '
"
"
)
return f"""
"""
def update_view(active_view: str, current_dataset: str | None) -> tuple[Any, Any, str, str, str]:
if active_view == HOME_VIEW:
first_task = TASKS[0]
return (
gr.update(visible=True),
gr.update(visible="hidden"),
gr.update(choices=dataset_choices(first_task["id"]), value="Overall"),
render_task_title(first_task),
first_task["metricLabel"],
render_task_table(first_task, "Overall"),
)
task = TASK_MAP[active_view]
choices = dataset_choices(active_view)
dataset_id = current_dataset if current_dataset in choices else "Overall"
return (
gr.update(visible="hidden"),
gr.update(visible=True),
gr.update(choices=choices, value=dataset_id),
render_task_title(task),
task["metricLabel"],
render_task_table(task, dataset_id),
)
CUSTOM_CSS = """
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Noto+Sans+KR:wght@400;500;700&display=swap');
:root {
--bg: #f2f4f8;
--bg-strong: #dde5f2;
--panel: rgba(255, 255, 255, 0.84);
--panel-strong: #ffffff;
--text: #0c1730;
--muted: #66748b;
--line: rgba(12, 23, 48, 0.14);
--primary: #0e3a8a;
--accent: #c56b12;
--pending: #74674a;
--pending-bg: #f4ecd8;
--success: #0c8f61;
--danger: #b8612f;
--shadow: 0 14px 38px rgba(12, 23, 48, 0.08);
}
html, body, .gradio-container {
margin: 0 !important;
min-height: 100vh;
font-family: "Noto Sans KR", "Space Grotesk", sans-serif !important;
color: var(--text);
background:
radial-gradient(circle at 15% 0%, #dce8ff 0%, transparent 32%),
radial-gradient(circle at 95% 5%, #ffe4cf 0%, transparent 24%),
linear-gradient(180deg, #f8fbff 0%, #eef2f7 100%) !important;
}
.gradio-container {
max-width: 100% !important;
}
.app-root {
position: relative;
max-width: 1440px;
margin: 0 auto;
padding: 24px 20px 56px;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.bg-orb {
position: fixed;
border-radius: 999px;
filter: blur(70px);
opacity: 0.45;
pointer-events: none;
z-index: 0;
}
.orb-1 {
width: 280px;
height: 280px;
background: #a7c5ff;
top: -110px;
left: -80px;
}
.orb-2 {
width: 240px;
height: 240px;
background: #ffd2a4;
top: -70px;
right: -60px;
}
.layout-row {
position: relative;
z-index: 1;
flex-wrap: nowrap !important;
gap: 24px;
align-items: flex-start;
min-width: 1180px;
}
.sidebar-panel {
flex: 0 0 260px !important;
width: 260px !important;
min-width: 260px !important;
max-width: 260px !important;
position: sticky;
top: 20px;
align-self: start;
border: 1px solid var(--line);
border-radius: 26px;
background: rgba(7, 17, 40, 0.95);
color: #ffffff;
padding: 22px 18px;
box-shadow: var(--shadow);
}
.sidebar-head,
.sidebar-head * {
color: #ffffff !important;
}
.sidebar-head {
margin-bottom: 26px;
}
.sidebar-kicker, .kicker {
margin: 0;
letter-spacing: 0.12em;
text-transform: uppercase;
font-size: 12px;
}
.sidebar-kicker {
color: rgba(255, 255, 255, 0.82) !important;
}
.sidebar-head h1 {
color: #ffffff !important;
}
.sidebar-head h1 {
margin: 8px 0 0;
font-size: 34px;
line-height: 0.95;
color: #ffffff;
}
.content-panel {
flex: 1 1 auto !important;
min-width: 0;
}
.hero {
margin-bottom: 20px;
}
.hero .kicker {
font-size: 14px !important;
letter-spacing: 0.18em;
color: var(--muted) !important;
}
.hero-topline {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 20px;
text-align: center;
}
.hero-topline > div {
flex: 1;
}
.hero h2 {
margin: 8px 0 6px;
font-family: "Space Grotesk", sans-serif;
font-size: clamp(56px, 7vw, 80px) !important;
line-height: 1.02;
color: var(--text);
font-weight: 700;
}
.desc {
margin: 0 auto;
max-width: 760px;
color: var(--muted);
font-size: 17px;
}
.card {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 24px;
box-shadow: var(--shadow);
backdrop-filter: blur(8px);
}
.section-card {
padding: 18px;
}
.section-head {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
margin-bottom: 12px;
}
.section-head h3,
.task-title {
margin: 0;
font-size: 28px;
font-family: "Space Grotesk", sans-serif;
}
.rank-strip-list {
display: grid;
grid-template-columns: repeat(6, minmax(120px, 1fr));
gap: 10px;
}
.rank-pill {
border: 1px solid var(--line);
border-radius: 16px;
padding: 12px;
background: linear-gradient(135deg, #ffffff 0%, var(--bg-strong) 100%);
}
.rank-badge-wrap {
min-height: 28px;
}
.rank-badge {
display: inline-flex !important;
align-items: center;
justify-content: center;
min-width: 34px;
height: 34px;
padding: 0 10px;
border-radius: 999px;
background: var(--primary);
color: #ffffff !important;
font-size: 13px;
font-weight: 700;
line-height: 1;
}
.rank-badge-image {
display: block;
width: auto;
height: 28px;
}
.rank-name {
display: block;
margin-top: 8px;
font-weight: 700;
color: var(--text) !important;
}
.table-scroll {
overflow-x: auto;
overflow-y: visible;
border-radius: 0;
border: 1px solid #ffffff !important;
background: var(--panel-strong);
}
table {
width: 100%;
min-width: 1080px;
border-collapse: collapse;
border: 1px solid #ffffff !important;
}
.task-performance-table {
table-layout: fixed;
}
thead th {
background: #e8edf6;
border-bottom: 1px solid #ffffff !important;
white-space: nowrap;
}
thead tr:first-child th.grouped {
text-align: center;
}
th, td {
padding: 12px 14px;
text-align: left;
border-bottom: 1px solid #ffffff !important;
border-right: 1px solid #ffffff !important;
font-size: 14px;
}
th:first-child,
td:first-child {
border-left: 1px solid #ffffff !important;
}
th:last-child,
td:last-child {
border-right: 0;
}
.table-scroll table,
.table-scroll thead,
.table-scroll tbody,
.table-scroll tr,
.table-scroll th,
.table-scroll td {
border-color: #ffffff !important;
}
tbody tr:hover {
background: #f8fbff;
}
.rank-col {
font-family: "Space Grotesk", sans-serif;
font-weight: 700;
width: 72px;
}
.col-rank {
width: 96px;
}
.col-rankname {
width: 240px;
}
.col-model {
width: 320px;
}
.url-link {
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
}
.url-link img {
display: block;
width: 18px;
height: 18px;
}
.metric-good {
color: var(--success);
font-weight: 700;
}
.metric-bad {
color: var(--danger);
font-weight: 700;
}
.muted {
color: var(--muted);
}
.task-filters {
display: flex;
flex-wrap: nowrap;
align-items: flex-start;
gap: 12px;
margin-top: 12px;
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
padding-bottom: 6px;
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
}
.task-filters .dataset-wrap { flex: 0 0 620px; min-width: 620px; }
.task-filters .metric-wrap { flex: 0 0 340px; min-width: 340px; }
.task-filters .dataset-wrap,
.task-filters .metric-wrap,
.task-filters .dataset-wrap > div,
.task-filters .metric-wrap > div {
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
}
/* Keep Dataset / Metric columns pinned to the same top baseline. */
.task-filters .dataset-wrap,
.task-filters .metric-wrap {
align-self: flex-start !important;
justify-self: flex-start !important;
margin-top: 0 !important;
padding-top: 0 !important;
}
.task-view-shell .filter-title {
margin: 0 0 6px 0 !important;
font-size: 13px !important;
color: var(--muted) !important;
line-height: 1.2 !important;
}
#taskTableMount {
margin-top: 18px;
}
.task-menu-radio {
gap: 8px;
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
padding: 0 !important;
}
.task-menu-radio > div,
.task-menu-radio .block,
.task-menu-radio .gradio-radio,
.task-menu-radio .form {
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
padding: 0 !important;
}
.task-menu-radio label > span,
.task-menu-radio label > div,
.task-menu-radio label .wrap {
white-space: pre-line !important;
}
.task-menu-radio label:has(input[type="radio"]) {
width: 100%;
margin: 0 !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
background: rgba(255, 255, 255, 0.05) !important;
color: #f5f7fb !important;
border-radius: 14px !important;
padding: 12px 14px !important;
cursor: pointer !important;
min-height: 72px;
align-content: center;
box-shadow: none !important;
transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
.task-menu-radio label:has(input[type="radio"]):hover {
background: rgba(255, 255, 255, 0.1) !important;
}
.task-menu-radio label:has(input[type="radio"]:checked) {
background: linear-gradient(135deg, #fcf7eb 0%, #dfeaff 100%) !important;
color: var(--text) !important;
border-color: transparent !important;
}
.task-menu-radio input[type="radio"] {
display: none !important;
}
.task-menu-radio label span,
.task-menu-radio label div,
.task-menu-radio label p {
color: inherit !important;
}
.task-menu-radio label:has(input[type="radio"]) span,
.task-menu-radio label:has(input[type="radio"]) div {
color: #f5f7fb !important;
}
.task-menu-radio label:has(input[type="radio"]:checked) span,
.task-menu-radio label:has(input[type="radio"]:checked) div {
color: var(--text) !important;
}
.task-menu-radio .wrap,
.task-menu-radio label span:last-child {
opacity: 0.72;
font-size: 12px;
}
.task-view-shell .gradio-radio,
.task-view-shell .gradio-textbox {
margin: 0 !important;
min-width: 0 !important;
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
}
.task-view-shell .gradio-radio label,
.task-view-shell .gradio-textbox label {
font-size: 13px !important;
color: var(--muted) !important;
}
.task-view-shell .dataset-radio {
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
padding: 0 !important;
margin-left: 0 !important;
margin-bottom: 12px !important;
max-width: 100% !important;
width: 100% !important;
}
.task-view-shell .dataset-radio > div,
.task-view-shell .dataset-radio .block,
.task-view-shell .dataset-radio .form {
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
padding: 0 !important;
display: grid !important;
grid-template-columns: repeat(2, minmax(180px, 1fr)) !important;
gap: 8px 10px !important;
align-items: start !important;
justify-content: start !important;
min-height: 86px !important;
align-content: start !important;
max-width: 100% !important;
width: 100% !important;
}
.task-view-shell .dataset-radio label:has(input[type="radio"]) {
margin: 0 !important;
border: 1px solid var(--line) !important;
background: rgba(255, 255, 255, 0.88) !important;
color: var(--text) !important;
border-radius: 10px !important;
padding: 0 12px !important;
height: 40px !important;
min-height: 40px !important;
width: auto !important;
display: flex !important;
align-items: center !important;
box-shadow: none !important;
justify-content: flex-start !important;
font-size: 14px !important;
line-height: 1.2 !important;
}
.task-view-shell .dataset-radio label:has(input[type="radio"]:checked) {
background: linear-gradient(135deg, #fcf7eb 0%, #dfeaff 100%) !important;
border-color: rgba(14, 58, 138, 0.22) !important;
font-weight: 700 !important;
}
.task-view-shell .dataset-radio input[type="radio"] {
display: none !important;
}
.task-view-shell .metric-field,
.task-view-shell .dataset-field {
align-self: flex-start !important;
background: transparent !important;
}
/* Remove any residual top spacing on metric box so it aligns with Dataset. */
.task-view-shell .metric-wrap .metric-field,
.task-view-shell .metric-wrap .gradio-textbox,
.task-view-shell .metric-wrap .gradio-textbox > div,
.task-view-shell .metric-wrap .gradio-textbox .block,
.task-view-shell .metric-wrap .gradio-textbox .form,
.task-view-shell .metric-wrap .gradio-textbox .wrap {
margin-top: 0 !important;
padding-top: 0 !important;
}
.task-view-shell .metric-field > div,
.task-view-shell .dataset-field > div {
background: transparent !important;
}
.task-view-shell .metric-field .gradio-textbox,
.task-view-shell .metric-field .gradio-textbox > div,
.task-view-shell .metric-field .gradio-textbox .block,
.task-view-shell .metric-field .gradio-textbox .form {
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
}
.task-view-shell .metric-field,
.task-view-shell .metric-field .gradio-textbox,
.task-view-shell .metric-field .gradio-textbox .wrap {
width: 100% !important;
max-width: none !important;
}
.task-view-shell .metric-field .gradio-textbox .wrap,
.task-view-shell .metric-field .gradio-textbox textarea,
.task-view-shell .metric-field .gradio-textbox input {
height: 40px !important;
min-height: 40px !important;
width: 100% !important;
}
.task-view-shell input,
.task-view-shell textarea,
.task-view-shell .wrap-inner,
.task-view-shell button.secondary-down-arrow,
.task-view-shell .gradio-textbox .wrap {
border-radius: 12px !important;
}
.task-view-shell .gradio-textbox .wrap,
.task-view-shell .gradio-textbox textarea,
.task-view-shell .gradio-textbox input {
border: 1px solid var(--line) !important;
background: rgba(255, 255, 255, 0.88) !important;
color: var(--text) !important;
}
@media (max-width: 1280px) {
.layout-row {
min-width: 1120px;
}
.task-filters .dataset-wrap { flex-basis: 560px; min-width: 560px; }
.task-filters .metric-wrap { flex-basis: 320px; min-width: 320px; }
.task-view-shell .dataset-radio > div,
.task-view-shell .dataset-radio .block,
.task-view-shell .dataset-radio .form {
grid-template-columns: repeat(2, minmax(150px, 1fr)) !important;
}
}
@media (max-width: 980px) {
.layout-row {
min-width: 1040px;
}
.rank-strip-list {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.task-view-shell .dataset-radio > div,
.task-view-shell .dataset-radio .block,
.task-view-shell .dataset-radio .form {
grid-template-columns: repeat(2, minmax(140px, 1fr)) !important;
}
}
@media (max-width: 720px) {
.app-root {
padding: 16px 14px 40px;
}
.hero-topline {
flex-direction: column;
align-items: center;
}
.hero h2 {
font-size: 40px;
}
.rank-strip-list {
grid-template-columns: 1fr;
}
.task-view-shell .dataset-radio > div,
.task-view-shell .dataset-radio .block,
.task-view-shell .dataset-radio .form {
grid-template-columns: 1fr !important;
}
}
"""
def build_app() -> gr.Blocks:
with gr.Blocks(title="Ko-Speech-Eval Leaderboard", fill_width=True) as demo:
with gr.Column(elem_classes=["app-root"]):
gr.HTML('')
with gr.Row(elem_classes=["layout-row"]):
with gr.Column(scale=0, min_width=260, elem_classes=["sidebar-panel"]):
gr.HTML(
"""
"""
)
menu = gr.Radio(
choices=menu_choices(),
value=HOME_VIEW,
show_label=False,
container=False,
elem_classes=["task-menu", "task-menu-radio"],
)
with gr.Column(scale=1, elem_classes=["content-panel"]):
gr.HTML(
"""
Korean Audio Language benchmark
Leaderboard for KoALa
"""
)
home_view = gr.HTML(render_home(), visible=True)
with gr.Column(visible="hidden", elem_classes=["task-view-shell", "section-card", "card"]) as task_view:
task_title = gr.HTML()
with gr.Row(elem_classes=["task-filters"]):
with gr.Column(scale=3, min_width=420, elem_classes=["dataset-wrap"]):
gr.HTML('Dataset
')
dataset_dropdown = gr.Radio(
choices=dataset_choices(TASKS[0]["id"]),
value="Overall",
show_label=False,
elem_classes=["dataset-field", "dataset-radio"],
)
with gr.Column(scale=2, min_width=280, elem_classes=["metric-wrap"]):
gr.HTML('Metric
')
metric_text = gr.Textbox(
show_label=False,
interactive=False,
elem_classes=["metric-field"],
)
task_table = gr.HTML()
menu.change(
fn=update_view,
inputs=[menu, dataset_dropdown],
outputs=[home_view, task_view, dataset_dropdown, task_title, metric_text, task_table],
)
dataset_dropdown.change(
fn=update_view,
inputs=[menu, dataset_dropdown],
outputs=[home_view, task_view, dataset_dropdown, task_title, metric_text, task_table],
)
demo.load(
fn=update_view,
inputs=[menu, dataset_dropdown],
outputs=[home_view, task_view, dataset_dropdown, task_title, metric_text, task_table],
)
return demo
if __name__ == "__main__":
app = build_app()
app.launch(css=CUSTOM_CSS)