Spaces:
Running
Benchmark pages as tabs under a compact hero
Browse filesEach benchmark page shows one view at a time, picked from tabs at the top
of its controls: Summary (the default), Leaderboard, Quality vs time, Head
to head and Per dataset. Every view is on the page from the start, so a
switch needs no round trip, and `?view=<key>` links to one.
- The tabs, the one-row Customize bar and the shown view's first card form
one block at full width. The controls sit on a surface a shade apart
from the view, with a firmer line where it starts.
- The tab captions moved to each tab's hover text, with what the selection
covers.
- The hero drops the "Meet our benchmark" eyebrow and the stats band; the
numbers are in the Learn more pills' hover texts.
- The floating bottom selection bar and its Jump to menu are gone.
- The Summary table shows every row instead of scrolling inside a 680px
box, and its heading takes the table's own surface.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- AGENTS.md +32 -24
- main.py +259 -472
- pages.py +128 -186
- views.py +127 -214
- website_texts.py +53 -120
|
@@ -57,15 +57,15 @@ Do not edit files under `data/` by hand — they are generated artifacts.
|
|
| 57 |
reorders the figure grid, in the browser; it computes nothing and costs no render.
|
| 58 |
- Every selector lives in one card at the top of the page (`views.selector_card`, built by
|
| 59 |
`pages._render_control_band` and `pages._render_beyond_control_band`). It is one `gr.HTML` of plain
|
| 60 |
-
buttons, not Gradio controls
|
| 61 |
-
|
| 62 |
-
browser's (`.ta-pdbar`) but without its wash of colour, beside that column (it spans the bar and the
|
| 63 |
-
lines, so opening only grows it): the title, which is the toggle, and
|
| 64 |
shortcuts (`website_texts.SELECTOR_EXAMPLES`, `BEYOND_SELECTOR_EXAMPLES`; `views._selector_examples` drops
|
| 65 |
-
locked chips) that pick a chip of the card, or several toggles at once, and open it there
|
|
|
|
|
|
|
|
|
|
| 66 |
the bar once it is open, pressed while the selection matches, so a second click undoes them. Opening is client-side only, so the
|
| 67 |
-
open state survives every re-render
|
| 68 |
-
it too. A click updates the card in the browser
|
| 69 |
(`main.taSelector`: chip state, dataset counts, that number, system warnings) and sends the whole
|
| 70 |
selection as one custom `pick` event (`trigger('pick', …)` in `js_on_load`), whose listener validates
|
| 71 |
every value (`views.picked`) and returns the page's `gr.State`s. A State re-renders its readers only when its value changed, and
|
|
@@ -73,10 +73,23 @@ Do not edit files under `data/` by hand — they are generated artifacts.
|
|
| 73 |
comes from the `n_datasets_*` marker of the leaderboard that chip would select; a chip whose leaderboard
|
| 74 |
is not published cannot be picked. Hover text is written into the card (`title`), from the notes dicts
|
| 75 |
and `data_loading.AXIS_NOTES` (per row caption).
|
| 76 |
-
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
the page element (`.ta-page[data-care][data-metric]`, the `gr.TabItem`'s class), and the stylesheet
|
| 81 |
orders the tiles from it: the figure that answers the choice first, its partner beside it, then the
|
| 82 |
overview. The figure that leads takes the metric the reader picked and the others the other one, so both
|
|
@@ -112,18 +125,17 @@ Do not edit files under `data/` by hand — they are generated artifacts.
|
|
| 112 |
system from its name.
|
| 113 |
- Each top-level page has a `slug` (`pages.PAGES`) that is its tab id and its `?tab=<slug>` link, e.g. `huggingface.co/spaces/TabArena/leaderboard?tab=beyondarena`. `main._open_linked_page` selects it on load, and a click on a page link in the top bar writes it back to the address bar and, inside the Space, to the Hugging Face page URL over `postMessage`. Not `?page=`: Gradio reserves that name (and `deep_link`) for its own routing.
|
| 114 |
- The top bar (`views.make_page_chrome`) is plain HTML above `gr.Tabs(elem_id="top-tabs")`, whose own tab bar is hidden. A page link clicks the matching Gradio tab button, found by the tab's label (`main.taGoToPage`); with the bar hidden Gradio keeps every button in its overflow menu, where the selected one carries `.selected` rather than `aria-selected`. The bar keeps one row while brand, links and actions fit and gives the links a row of their own otherwise (`main.taFitTopBar` measures, since where that happens depends on the reader's font). Its version chip and the version-history dialog are parsed from `website_texts.VERSION_HISTORY_BUTTON_TEXT` (`views.parse_version_history`), so release entries must keep the `* YYYY/MM/DD-vX.Y.Z:` form. The COI statement and the version history are dialogs: a hidden checkbox (`main.taOpenDialog`) shows an overlay on the visible band, and the dialog scrolls inside itself so a click on the overlay always closes it.
|
| 115 |
-
- TabArena and BeyondArena share one hero (`views._page_hero`), coloured like the page's link in the top bar: one panel washed faintly in that colour
|
| 116 |
- A dialog has a link of its own: while it is open, `?doc=<name>` is in the address bar (and in the Hugging Face page URL), a Learn more topic key or `cite`, `team`, `history`, `coi`; `main.taOpenLinkedDialog` opens it on load once the page `?tab=` names shows, e.g. `?tab=beyondarena&doc=subsets`.
|
| 117 |
- Inside the Space the visible band comes from iframe-resizer's `getPageInfo`, which the parent answers once and afterwards only on its own scroll and resize. The first answer arrives while the frame is still short, so `main.taReaskPageInfo` asks again whenever the frame's height changes; without that the band stayed unset until the reader first scrolled.
|
| 118 |
- Gradio rescopes every rule of the launch stylesheet under `.gradio-container.gradio-container-<version> .contain`. A top-level rule also keeps its written form, a rule inside `@media` does not, so a media query cannot style `.contain` or its ancestors (`.main`, `.gradio-container`); use a top-level rule with `clamp()` there instead.
|
| 119 |
- `LBContainer` (`data_loading.py`) loads one subset's `website_leaderboard.csv`, lazily unzips its PNGs, and inlines its interactive HTML plots.
|
| 120 |
-
- The cross-subset overview,
|
| 121 |
- Logos: the `Organization` column of `website_leaderboard.csv` comes from `MethodMetadata.organization` upstream; `views.ORGANIZATION_LOGOS` maps it to a file in `assets/logos/` (64 px PNGs through LFS, SVGs as text), served with `gr.set_static_paths` (`main.main`). A logo fills its tile at its own shape, with no backdrop; one whose artwork is dark on transparency (Amazon, NVIDIA, Perpetual ML) has a white tile baked into the file, since it would vanish on the dark table. An organization without a logo shows its initial, a method without one an empty tile; artifacts generated before the column existed show no logos. A new organization needs its name spelled as upstream spells it, plus a logo file and an entry here.
|
| 122 |
- The reactive render is driven by one `gr.State` per axis: selecting a tab or toggle updates that state, and the `@gr.render` block in `pages.py` rebuilds the subset's figures and table.
|
| 123 |
-
- The full leaderboard table is `views.make_leaderboard`, a card like the figure tiles that
|
| 124 |
-
- The per-dataset browser (`views.make_per_dataset_block`, embedding `per_dataset_explorer.html`)
|
| 125 |
-
|
| 126 |
-
benchmark, unlike "Your leaderboard" below. From 1100px wide it shows its dataset list beside the
|
| 127 |
chosen dataset (upstream). It is read from the `tasks_all/datasets_all` sibling of the selected cell, not from the cell itself: a dataset's own
|
| 128 |
rank and gap do not depend on which *other* datasets share its leaderboard, so upstream publishes one per
|
| 129 |
(entrants, imputation, splits) rather than for all 60 task/dataset cells. The current task and
|
|
@@ -134,14 +146,10 @@ Do not edit files under `data/` by hand — they are generated artifacts.
|
|
| 134 |
splits, α = 0.05, no verdict below five splits), all computed upstream in
|
| 135 |
`plot/interactive/per_dataset_explorer.py`; nothing here recomputes them. Its "Target" filter
|
| 136 |
(balanced / imbalanced) reads the `target_imbalanced` verdict from the dataset metadata upstream.
|
| 137 |
-
- The dataset browser and the full table are collapsed by default; the browser's frame is only built once
|
| 138 |
-
it has been opened (its artifact is the largest the site ships). The selection bar at the bottom hides
|
| 139 |
-
while an open browser fills the view (`main.taOverDataBrowser`).
|
| 140 |
- Section headings come from `views.section_head`: a plain title, a muted line beside it saying what the
|
| 141 |
-
section holds, actions at the right, and the longer text as the title's hover.
|
| 142 |
-
|
| 143 |
-
the
|
| 144 |
-
summary terms. Each figure tile is one flat card with one header row: the figure's name, its caption from
|
| 145 |
`website_texts.FIGURE_CAPTIONS` (shown only where it fits whole, `main.taFitCaptions`; the title's hover
|
| 146 |
carries it either way), and ghost buttons "Customize" (the explorer's controls; paper view is the default), a
|
| 147 |
"Download" menu (SVG, PDF, PNG; shown in paper view) and ⤢.
|
|
|
|
| 57 |
reorders the figure grid, in the browser; it computes nothing and costs no render.
|
| 58 |
- Every selector lives in one card at the top of the page (`views.selector_card`, built by
|
| 59 |
`pages._render_control_band` and `pages._render_beyond_control_band`). It is one `gr.HTML` of plain
|
| 60 |
+
buttons, not Gradio controls. It starts closed, as one row (`.ta-pdbar` without its wash of colour): the
|
| 61 |
+
title "Customize", which is the toggle, small
|
|
|
|
|
|
|
| 62 |
shortcuts (`website_texts.SELECTOR_EXAMPLES`, `BEYOND_SELECTOR_EXAMPLES`; `views._selector_examples` drops
|
| 63 |
+
locked chips) that pick a chip of the card, or several toggles at once, and open it there, and at its end
|
| 64 |
+
how many datasets the selection covers. The shortcuts scroll sideways where the row cannot hold them, on
|
| 65 |
+
a line of their own on a phone. Open, the lines grow under the bar, headed by what the choices change
|
| 66 |
+
(`website_texts.SELECTOR_SUB`). The shortcuts stay in
|
| 67 |
the bar once it is open, pressed while the selection matches, so a second click undoes them. Opening is client-side only, so the
|
| 68 |
+
open state survives every re-render. A click updates the card in the browser
|
|
|
|
| 69 |
(`main.taSelector`: chip state, dataset counts, that number, system warnings) and sends the whole
|
| 70 |
selection as one custom `pick` event (`trigger('pick', …)` in `js_on_load`), whose listener validates
|
| 71 |
every value (`views.picked`) and returns the page's `gr.State`s. A State re-renders its readers only when its value changed, and
|
|
|
|
| 73 |
comes from the `n_datasets_*` marker of the leaderboard that chip would select; a chip whose leaderboard
|
| 74 |
is not published cannot be picked. Hover text is written into the card (`title`), from the notes dicts
|
| 75 |
and `data_loading.AXIS_NOTES` (per row caption).
|
| 76 |
+
- A benchmark page shows one view at a time, picked from tabs at the top of its controls
|
| 77 |
+
(`views.view_bar`, `website_texts.VIEW_TABS`): Summary, the default (the summary table across subsets;
|
| 78 |
+
BeyondArena's overview images), Leaderboard (the Elo overview chart and the full table, open), Quality
|
| 79 |
+
vs time (the Pareto fronts and tuning trajectories), Head to head (the win-rate matrix) and Per dataset
|
| 80 |
+
(the per-dataset browser). Each tab says on hover what its view shows and what the selection covers
|
| 81 |
+
(from `views.lb_spec`); the bar carries the Follow picker. The selector card hangs under it, and the
|
| 82 |
+
shown view under the card as its body on the card's surface (`.block.ta-sel-block` and `.ta-view` pulled
|
| 83 |
+
up over the block gap), so the tabs, the choices and the view read as one panel. The bar renders with the selection (for the Follow list) and marks the page's shown view
|
| 84 |
+
each time it is drawn (`main.taSyncViewTabs`). Every view is a `gr.Column(elem_classes=["ta-view",
|
| 85 |
+
"ta-view-<key>"])` with its own `@gr.render` blocks, all on the page from the start; the browser shows
|
| 86 |
+
the one the page element's `data-view` names (`main.taShowView`, the generated `__TA_VIEW_RULES__`), so
|
| 87 |
+
a switch costs no round trip, loads the view's explorers (`taLoadFrames`) and goes into the address as
|
| 88 |
+
`?view=<key>` (`taOpenLinkedView` reads it back, after `?tab=`).
|
| 89 |
+
- Each figure view is one grid in one `gr.HTML` (`views.make_figure_grid(lb, keys)`, the keys from
|
| 90 |
+
`views.VIEW_TILES`): the overview and the win-rate matrix span the width, the three Pareto fronts
|
| 91 |
+
(inference, end-to-end, train time) and the tuning trajectories sit two to a row (one per row below
|
| 92 |
+
1100px; an odd one out spans the row). "I care about" and "Measured by" are not render inputs. `main.taSelector` writes the choice onto
|
| 93 |
the page element (`.ta-page[data-care][data-metric]`, the `gr.TabItem`'s class), and the stylesheet
|
| 94 |
orders the tiles from it: the figure that answers the choice first, its partner beside it, then the
|
| 95 |
overview. The figure that leads takes the metric the reader picked and the others the other one, so both
|
|
|
|
| 125 |
system from its name.
|
| 126 |
- Each top-level page has a `slug` (`pages.PAGES`) that is its tab id and its `?tab=<slug>` link, e.g. `huggingface.co/spaces/TabArena/leaderboard?tab=beyondarena`. `main._open_linked_page` selects it on load, and a click on a page link in the top bar writes it back to the address bar and, inside the Space, to the Hugging Face page URL over `postMessage`. Not `?page=`: Gradio reserves that name (and `deep_link`) for its own routing.
|
| 127 |
- The top bar (`views.make_page_chrome`) is plain HTML above `gr.Tabs(elem_id="top-tabs")`, whose own tab bar is hidden. A page link clicks the matching Gradio tab button, found by the tab's label (`main.taGoToPage`); with the bar hidden Gradio keeps every button in its overflow menu, where the selected one carries `.selected` rather than `aria-selected`. The bar keeps one row while brand, links and actions fit and gives the links a row of their own otherwise (`main.taFitTopBar` measures, since where that happens depends on the reader's font). Its version chip and the version-history dialog are parsed from `website_texts.VERSION_HISTORY_BUTTON_TEXT` (`views.parse_version_history`), so release entries must keep the `* YYYY/MM/DD-vX.Y.Z:` form. The COI statement and the version history are dialogs: a hidden checkbox (`main.taOpenDialog`) shows an overlay on the visible band, and the dialog scrolls inside itself so a click on the overlay always closes it.
|
| 128 |
+
- TabArena and BeyondArena share one hero (`views._page_hero`), coloured like the page's link in the top bar: one panel washed faintly in that colour, so the background on the benchmark reads apart from the results below it: the lead sentence with its links, then the Learn more row. The Learn more pills carry the benchmark's numbers in their hover texts (`website_texts.HERO_HINTS`, `BEYOND_HERO_HINTS`), read from the data (`views.hero_facts`, `views.beyond_hero_facts`). Its citation, its team and the Learn more topics open as dialogs, with toggle ids per page (`views._hero_toggle`) since both pages are in the document at once. `views.learn_more` puts every topic into the page once, so a pill opens without a round trip to the server; the row ends with the page's call to submit a model (`website_texts.HERO_CTA`, `BEYOND_HERO_CTA`), a link out washed in the page's colour. Reference text lives there and not at the bottom of the page: the MCP & API topic (`website_texts.AGENTS_*`, CSV paths and the MCP tools) replaced the Appendix, and BeyondArena's subsets explainer is its Subsets topic, opened from the overview figures too (`views.open_doc`).
|
| 129 |
- A dialog has a link of its own: while it is open, `?doc=<name>` is in the address bar (and in the Hugging Face page URL), a Learn more topic key or `cite`, `team`, `history`, `coi`; `main.taOpenLinkedDialog` opens it on load once the page `?tab=` names shows, e.g. `?tab=beyondarena&doc=subsets`.
|
| 130 |
- Inside the Space the visible band comes from iframe-resizer's `getPageInfo`, which the parent answers once and afterwards only on its own scroll and resize. The first answer arrives while the frame is still short, so `main.taReaskPageInfo` asks again whenever the frame's height changes; without that the band stayed unset until the reader first scrolled.
|
| 131 |
- Gradio rescopes every rule of the launch stylesheet under `.gradio-container.gradio-container-<version> .contain`. A top-level rule also keeps its written form, a rule inside `@media` does not, so a media query cannot style `.contain` or its ancestors (`.main`, `.gradio-container`); use a top-level rule with `clamp()` there instead.
|
| 132 |
- `LBContainer` (`data_loading.py`) loads one subset's `website_leaderboard.csv`, lazily unzips its PNGs, and inlines its interactive HTML plots.
|
| 133 |
+
- The cross-subset overview, the Summary view (`views.make_cross_subset_overview`), is one table at its full length (it scrolls sideways only). The columns: the rank in the sorted column; the Method column, sticky, with the search in its header's corner (an icon opening a box that finds a method by name), on the table's own opaque surface (`--ta-xo-bg`), the organization's logo and the name in its family colour with its variant, a system's tag (🔒 for a closed-source API, 🤖 with LLMs; `constants.tag_emoji`), ✔️, `$` and ↗; then Overall Elo and Overall improvability, the two metrics the figures show, and the train and inference costs, as in-cell bars (as long as the value is high in its column, on the log scale for the costs, so lower is shorter; coloured amber for the best through violet for the worst, `views.BAR_STOPS` as `--bar-dark` / `--bar-light`); a divider (`ta-xo-sep`) after each of those two groups; then the breakdowns by task, size and target as heat cells. There is no type column and no metric menu. Under the Method header two keys (`views._th_key`): the colours of the names by short family names (`views._method_legend`, full names on hover), and the marks ✔️, `$`, ↗ and the system tags; `*` (imputed) is keyed under the headline Elo and `†` under the train time, each only when a row on screen has it; the medals need no key. The breakdowns start folded into stub columns after the others (`views._FOLDING_GROUPS`; their cells carry `data-g`, the stubs `data-stub`, and the table's `data-open` names the open ones); a stub opens its group, the ✕ in its heading folds it, a group a selector comes to point at opens by itself (the table's `data-auto`), and each open group has an Elo | Improv. switch: every breakdown column is rendered in both metrics (`data-m`), the table's `data-m-<group>` shows one. In the browser (`main.taOverviewTable`): a click on a number heading sorts by it (best first, again reverses; the sort is kept by the heading's `data-label`, the column id, and falls back to the headline Elo when its column folds or switches away); the search hides rows; the sort, the open groups, their metrics and the search survive re-renders (`window.taOverviewState`). Each number's hover gives its rank in the column (and the Elo 95% CI). A "new" badge marks the methods the last three entrant-adding releases of the version history named (`views._recent_additions`), taken from a release whose first bullet reads `Add new verified model: <name>, …`.
|
| 134 |
- Logos: the `Organization` column of `website_leaderboard.csv` comes from `MethodMetadata.organization` upstream; `views.ORGANIZATION_LOGOS` maps it to a file in `assets/logos/` (64 px PNGs through LFS, SVGs as text), served with `gr.set_static_paths` (`main.main`). A logo fills its tile at its own shape, with no backdrop; one whose artwork is dark on transparency (Amazon, NVIDIA, Perpetual ML) has a white tile baked into the file, since it would vanish on the dark table. An organization without a logo shows its initial, a method without one an empty tile; artifacts generated before the column existed show no logos. A new organization needs its name spelled as upstream spells it, plus a logo file and an entry here.
|
| 135 |
- The reactive render is driven by one `gr.State` per axis: selecting a tab or toggle updates that state, and the `@gr.render` block in `pages.py` rebuilds the subset's figures and table.
|
| 136 |
+
- The full leaderboard table is `views.make_leaderboard`, a card like the figure tiles, open in the Leaderboard view, that hides and shows in the browser (`main.taToggleTable`) and embeds the generated `leaderboard_table.html`, so it reuses the explorers' family colours, variant chips, tag chips and imputation markers rather than reimplementing them. Its toolbar (search, family toggles, variants, a Methods and a Columns menu), the 1-based positions and the default columns (Elo, Improvability, runtimes) are upstream's; the "new" badges come from here, the methods `views._recent_additions` names, as `data-new` sent by `main.taSendNew`. `views.make_leaderboard_gradio` is the fallback for subsets whose artifacts predate that file; its filtering lives in `views.filter_leaderboard`, kept pure so it can be tested without a Gradio context. Neither path may reintroduce the `gradio_leaderboard` custom component, which pinned Gradio < 6.
|
| 137 |
+
- The per-dataset browser (`views.make_per_dataset_block`, embedding `per_dataset_explorer.html`) is the
|
| 138 |
+
Per dataset view; its frame loads when the view is first shown. From 1100px wide it shows its dataset list beside the
|
|
|
|
| 139 |
chosen dataset (upstream). It is read from the `tasks_all/datasets_all` sibling of the selected cell, not from the cell itself: a dataset's own
|
| 140 |
rank and gap do not depend on which *other* datasets share its leaderboard, so upstream publishes one per
|
| 141 |
(entrants, imputation, splits) rather than for all 60 task/dataset cells. The current task and
|
|
|
|
| 146 |
splits, α = 0.05, no verdict below five splits), all computed upstream in
|
| 147 |
`plot/interactive/per_dataset_explorer.py`; nothing here recomputes them. Its "Target" filter
|
| 148 |
(balanced / imbalanced) reads the `target_imbalanced` verdict from the dataset metadata upstream.
|
|
|
|
|
|
|
|
|
|
| 149 |
- Section headings come from `views.section_head`: a plain title, a muted line beside it saying what the
|
| 150 |
+
section holds, actions at the right, and the longer text as the title's hover. The selection's line
|
| 151 |
+
(`views.lb_spec`, under the view tabs): the number of datasets, split by task where the selection spans
|
| 152 |
+
both kinds, then the selection's terms. Each figure tile is one flat card with one header row: the figure's name, its caption from
|
|
|
|
| 153 |
`website_texts.FIGURE_CAPTIONS` (shown only where it fits whole, `main.taFitCaptions`; the title's hover
|
| 154 |
carries it either way), and ghost buttons "Customize" (the explorer's controls; paper view is the default), a
|
| 155 |
"Download" menu (SVG, PDF, PNG; shown in paper view) and ⤢.
|
|
@@ -4,6 +4,7 @@ import gradio as gr
|
|
| 4 |
|
| 5 |
import json
|
| 6 |
|
|
|
|
| 7 |
from api import register_api
|
| 8 |
from data_loading import BEYOND_DATA_DIR, DATA_DIR
|
| 9 |
from pages import PAGES, render_page
|
|
@@ -13,10 +14,6 @@ from views import LOGO_DIR, VERSION_HISTORY_TOGGLE, make_page_chrome
|
|
| 13 |
CSS = """
|
| 14 |
/* Use the full page width instead of gradio's narrow centered column. */
|
| 15 |
.gradio-container { max-width: 100% !important; }
|
| 16 |
-
/* Leave room for the fixed selection bar (.ta-selbar sits 18px off the bottom and is ~42px
|
| 17 |
-
tall). Without this the page still scrolls to its end, but the end sits underneath the bar,
|
| 18 |
-
which reads as not being able to get to the bottom. */
|
| 19 |
-
.gradio-container { padding-bottom: 78px !important; }
|
| 20 |
.gradio-container { padding-top: 6px !important; }
|
| 21 |
|
| 22 |
/* --- Colour emoji ----------------------------------------------------------
|
|
@@ -118,17 +115,16 @@ CSS = """
|
|
| 118 |
then one line per choice with the captions in one column down the left, and beside the lines a
|
| 119 |
column that says what the selection covers, its number set like the hero's. A chip in a row that
|
| 120 |
filters the datasets carries the number of datasets the leaderboard would cover with it picked.
|
| 121 |
-
The card starts closed, as its bar alone,
|
| 122 |
-
the
|
| 123 |
-
|
| 124 |
.ta-sel-block .html-container { padding: 0; }
|
| 125 |
.ta-sel {
|
| 126 |
--ta-page-color: var(--ta-accent);
|
| 127 |
--ta-pd-color: var(--ta-page-color);
|
| 128 |
display: grid;
|
| 129 |
-
grid-template-columns: minmax(0, 1fr)
|
| 130 |
-
grid-template-
|
| 131 |
-
grid-template-areas: "bar result" "main result" "warns warns";
|
| 132 |
overflow: hidden;
|
| 133 |
border: 1px solid var(--ta-line-soft);
|
| 134 |
border-radius: 14px;
|
|
@@ -140,20 +136,21 @@ CSS = """
|
|
| 140 |
selling points, a second orange band read as more of the same. The icon, the chevron and the
|
| 141 |
shortcuts carry the colour instead. */
|
| 142 |
.ta-sel-bar { grid-area: bar; }
|
| 143 |
-
.ta-sel .ta-sel-bar { background: transparent; }
|
| 144 |
.ta-sel .ta-sel-bar:hover { background: color-mix(in srgb, var(--ta-ink) 4%, transparent); }
|
| 145 |
-
.ta-sel:not([data-open="true"]) > :is(.ta-sel-main, .ta-sel-warns)
|
| 146 |
-
.ta-sel:not([data-open="true"]) .ta-sel-lead { display: none; }
|
| 147 |
.ta-sel-main { grid-area: main; min-width: 0; padding: 0 18px 2px; }
|
| 148 |
-
.ta-sel-
|
| 149 |
-
.ta-sel-
|
| 150 |
-
.ta-sel-
|
|
|
|
|
|
|
| 151 |
/* The title opens the card, its chevron filled in the page's colour while there is more to see,
|
| 152 |
quiet and turned once the card is open. */
|
| 153 |
.ta-sel-toggle {
|
| 154 |
display: inline-flex;
|
| 155 |
align-items: center;
|
| 156 |
-
gap:
|
| 157 |
margin: 0;
|
| 158 |
padding: 0;
|
| 159 |
border: 0;
|
|
@@ -167,8 +164,8 @@ CSS = """
|
|
| 167 |
display: grid;
|
| 168 |
place-items: center;
|
| 169 |
flex: none;
|
| 170 |
-
width:
|
| 171 |
-
height:
|
| 172 |
border: 1px solid transparent;
|
| 173 |
border-radius: 50%;
|
| 174 |
background: var(--ta-page-color);
|
|
@@ -177,8 +174,8 @@ CSS = """
|
|
| 177 |
}
|
| 178 |
.ta-sel-chev::before {
|
| 179 |
content: "";
|
| 180 |
-
width:
|
| 181 |
-
height:
|
| 182 |
border-style: solid;
|
| 183 |
border-color: var(--ta-on-accent);
|
| 184 |
border-width: 0 2px 2px 0;
|
|
@@ -192,24 +189,35 @@ CSS = """
|
|
| 192 |
transform: rotate(180deg);
|
| 193 |
}
|
| 194 |
.ta-sel[data-open="true"] .ta-sel-chev::before { border-color: var(--ta-ink); }
|
| 195 |
-
/* The shortcuts: dashed, as suggestions rather than settings, each a "+" until it is
|
| 196 |
-
.
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
.ta-sel-ex {
|
|
|
|
| 199 |
margin: 0;
|
| 200 |
-
padding:
|
| 201 |
border: 1px dashed color-mix(in srgb, var(--ta-page-color) 60%, transparent);
|
| 202 |
border-radius: 999px;
|
| 203 |
background: transparent;
|
| 204 |
color: var(--ta-ink);
|
| 205 |
font: inherit;
|
| 206 |
-
font-size: 0.
|
| 207 |
font-weight: 600;
|
| 208 |
white-space: nowrap;
|
| 209 |
cursor: pointer;
|
| 210 |
transition: background .14s ease, border-color .14s ease;
|
| 211 |
}
|
| 212 |
-
.ta-sel-ex::before { content: "+"; margin-right:
|
| 213 |
.ta-sel-ex:hover,
|
| 214 |
.ta-sel-ex[aria-pressed="true"] {
|
| 215 |
border-style: solid;
|
|
@@ -218,18 +226,12 @@ CSS = """
|
|
| 218 |
.ta-sel-ex[aria-pressed="true"]::before { content: "\\2713"; }
|
| 219 |
.ta-sel-ex:focus-visible { outline: 2px solid var(--ta-page-color); outline-offset: 2px; }
|
| 220 |
.ta-sel-ex:disabled { opacity: 0.4; cursor: not-allowed; }
|
| 221 |
-
|
| 222 |
-
|
|
|
|
|
|
|
| 223 |
@media (max-width: 640px) {
|
| 224 |
-
.ta-sel-
|
| 225 |
-
.ta-sel-try {
|
| 226 |
-
flex-wrap: nowrap;
|
| 227 |
-
overflow-x: auto;
|
| 228 |
-
scrollbar-width: none;
|
| 229 |
-
mask-image: linear-gradient(90deg, #000 85%, transparent);
|
| 230 |
-
}
|
| 231 |
-
.ta-sel-try::-webkit-scrollbar { display: none; }
|
| 232 |
-
.ta-sel-try-lead { flex: none; }
|
| 233 |
}
|
| 234 |
/* The chip a shortcut picked pulses as the card opens, so the reader sees where it lives. */
|
| 235 |
.ta-sel .ta-chip.ta-flash { animation: ta-sel-flash 0.9s ease-out 2; }
|
|
@@ -390,31 +392,135 @@ CSS = """
|
|
| 390 |
.ta-sel .ta-chip[role="switch"][aria-checked="true"] .ta-chip-mark { background: var(--ta-page-color); }
|
| 391 |
.ta-sel .ta-chip[role="switch"][aria-checked="true"] .ta-chip-mark::after { transform: translateX(12px); }
|
| 392 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 393 |
/* What the selection covers: the number of datasets, beside the bar and the lines. */
|
| 394 |
.ta-sel-result {
|
| 395 |
grid-area: result;
|
| 396 |
display: flex;
|
| 397 |
-
|
| 398 |
-
justify-content: center;
|
| 399 |
min-width: 0;
|
| 400 |
-
padding:
|
| 401 |
border-left: 1px solid var(--ta-line-soft);
|
| 402 |
-
background: linear-gradient(
|
| 403 |
}
|
|
|
|
| 404 |
.ta-sel-total {
|
| 405 |
display: flex;
|
| 406 |
-
flex-wrap: wrap;
|
| 407 |
align-items: baseline;
|
| 408 |
-
gap:
|
| 409 |
margin: 0;
|
| 410 |
color: var(--ta-ink);
|
| 411 |
-
font-size: 0.
|
| 412 |
font-weight: 700;
|
|
|
|
| 413 |
}
|
| 414 |
.ta-sel-unit { white-space: nowrap; }
|
| 415 |
.ta-sel-num {
|
| 416 |
color: var(--ta-page-color);
|
| 417 |
-
font-size:
|
| 418 |
font-weight: 800;
|
| 419 |
font-variant-numeric: tabular-nums;
|
| 420 |
letter-spacing: -0.03em;
|
|
@@ -454,25 +560,6 @@ CSS = """
|
|
| 454 |
.ta-sel-warn-body ul { padding-left: 1.2em; }
|
| 455 |
.ta-sel-warn-body > :last-child { margin-bottom: 0; }
|
| 456 |
|
| 457 |
-
/* Where the lines need the card's width, the number stays beside the bar alone and the lines take the
|
| 458 |
-
whole width under both. */
|
| 459 |
-
@media (max-width: 1420px) {
|
| 460 |
-
.ta-sel { grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: none; grid-template-areas: "bar result" "main main" "warns warns"; }
|
| 461 |
-
.ta-sel-result { padding: 10px 18px; }
|
| 462 |
-
.ta-sel[data-open="true"] .ta-sel-result { border-bottom: 1px solid var(--ta-line-soft); }
|
| 463 |
-
.ta-sel-num { font-size: 1.45rem; }
|
| 464 |
-
}
|
| 465 |
-
/* On a phone the number goes under the bar, as one line. */
|
| 466 |
-
@media (max-width: 640px) {
|
| 467 |
-
.ta-sel { grid-template-columns: minmax(0, 1fr); grid-template-areas: "bar" "result" "main" "warns"; }
|
| 468 |
-
.ta-sel-result {
|
| 469 |
-
flex-direction: row;
|
| 470 |
-
justify-content: flex-start;
|
| 471 |
-
border-top: 1px solid var(--ta-line-soft);
|
| 472 |
-
border-left: 0;
|
| 473 |
-
background: linear-gradient(100deg, color-mix(in srgb, var(--ta-page-color) 13%, transparent), transparent 60%);
|
| 474 |
-
}
|
| 475 |
-
}
|
| 476 |
/* Where the line cannot hold both rows, the second takes a line of its own, caption in the column. */
|
| 477 |
@media (max-width: 1180px) {
|
| 478 |
.ta-sel-line { flex-direction: column; }
|
|
@@ -526,6 +613,8 @@ CSS = """
|
|
| 526 |
--ta-card: rgba(255, 255, 255, 0.04);
|
| 527 |
--ta-strip: rgba(255, 255, 255, 0.06);
|
| 528 |
--ta-raised: #1b1b22;
|
|
|
|
|
|
|
| 529 |
--ta-line: rgba(255, 255, 255, 0.2);
|
| 530 |
--ta-line-soft: rgba(255, 255, 255, 0.1);
|
| 531 |
--ta-ink: #f4f4f5;
|
|
@@ -543,137 +632,8 @@ CSS = """
|
|
| 543 |
orange of its old tab, BeyondArena the teal of its hero. */
|
| 544 |
--ta-tabarena: #fb923c;
|
| 545 |
--ta-beyondarena: #2dd4bf;
|
| 546 |
-
/* The dot that marks a benchmark as alive (its latest release). */
|
| 547 |
-
--ta-live: #4ade80;
|
| 548 |
-
}
|
| 549 |
-
|
| 550 |
-
/* The bar is fixed, so the block that holds it takes no room, and its column gives back the gap
|
| 551 |
-
before it. */
|
| 552 |
-
.ta-selbar-host, .ta-selbar-host > .html-container { padding: 0; }
|
| 553 |
-
.column:has(> .ta-selbar-host) { margin-top: -16px; }
|
| 554 |
-
/* Sticky summary of the current selection, revealed once the control card scrolls away (see
|
| 555 |
-
main.taWatchControls), with the page's "Jump to" menu at its end. Bottom-centre: it is a
|
| 556 |
-
status line for the whole page and the one element that floats over it. */
|
| 557 |
-
.ta-selbar {
|
| 558 |
-
position: fixed;
|
| 559 |
-
left: 50%;
|
| 560 |
-
top: calc(var(--ta-vp-h) - 18px);
|
| 561 |
-
z-index: 60;
|
| 562 |
-
display: flex;
|
| 563 |
-
align-items: center;
|
| 564 |
-
gap: 4px;
|
| 565 |
-
max-width: min(94vw, 1100px);
|
| 566 |
-
padding: 5px;
|
| 567 |
-
border: 1px solid var(--ta-line);
|
| 568 |
-
border-radius: 999px;
|
| 569 |
-
background: rgba(24, 24, 28, 0.94);
|
| 570 |
-
box-shadow: var(--ta-shadow);
|
| 571 |
-
color: #dfe5f5;
|
| 572 |
-
font-family: inherit;
|
| 573 |
-
/* Hidden until the observer says the controls are off screen. `top` anchors the bar's own
|
| 574 |
-
top edge, so it is pulled back up by its full height to sit on the line above. */
|
| 575 |
-
opacity: 0;
|
| 576 |
-
pointer-events: none;
|
| 577 |
-
transform: translate(-50%, calc(-100% + 12px)) translateY(var(--ta-vp-top));
|
| 578 |
-
/* The band offset rides in the same transform, so following the screen costs no layout;
|
| 579 |
-
only opacity and the reveal slide are transitioned, or every scroll would ease. */
|
| 580 |
-
transition: opacity .16s ease;
|
| 581 |
-
}
|
| 582 |
-
.ta-selbar.ta-show {
|
| 583 |
-
opacity: 1;
|
| 584 |
-
pointer-events: auto;
|
| 585 |
-
transform: translate(-50%, -100%) translateY(var(--ta-vp-top));
|
| 586 |
-
}
|
| 587 |
-
/* The summary half scrolls sideways on a narrow screen; the menu beside it cannot sit inside
|
| 588 |
-
that scroller, or the list opening above it would be clipped. */
|
| 589 |
-
.ta-selbar-view {
|
| 590 |
-
display: flex;
|
| 591 |
-
align-items: center;
|
| 592 |
-
gap: 7px;
|
| 593 |
-
min-width: 0;
|
| 594 |
-
padding: 3px 6px 3px 10px;
|
| 595 |
-
border-radius: 999px;
|
| 596 |
-
color: inherit !important;
|
| 597 |
-
text-decoration: none !important;
|
| 598 |
-
overflow-x: auto;
|
| 599 |
-
scrollbar-width: none;
|
| 600 |
-
}
|
| 601 |
-
.ta-selbar-view:hover { background: var(--ta-chip); }
|
| 602 |
-
.ta-selbar-lead {
|
| 603 |
-
flex: 0 0 auto;
|
| 604 |
-
font-size: 0.66em;
|
| 605 |
-
font-weight: 700;
|
| 606 |
-
letter-spacing: 0.09em;
|
| 607 |
-
text-transform: uppercase;
|
| 608 |
-
opacity: 0.5;
|
| 609 |
-
}
|
| 610 |
-
.ta-selchip {
|
| 611 |
-
flex: 0 0 auto;
|
| 612 |
-
padding: 3px 9px;
|
| 613 |
-
border-radius: 999px;
|
| 614 |
-
background: rgba(158, 176, 208, 0.16);
|
| 615 |
-
font-size: 0.8em;
|
| 616 |
-
font-weight: 600;
|
| 617 |
-
white-space: nowrap;
|
| 618 |
}
|
| 619 |
|
| 620 |
-
.ta-selbar-go {
|
| 621 |
-
flex: 0 0 auto;
|
| 622 |
-
margin-left: 3px;
|
| 623 |
-
padding: 3px 10px;
|
| 624 |
-
border-radius: 999px;
|
| 625 |
-
background: rgba(110, 140, 245, 0.34);
|
| 626 |
-
color: #eef2ff;
|
| 627 |
-
font-size: 0.78em;
|
| 628 |
-
font-weight: 700;
|
| 629 |
-
white-space: nowrap;
|
| 630 |
-
}
|
| 631 |
-
.ta-jumpmenu { position: relative; flex: 0 0 auto; }
|
| 632 |
-
.ta-jumpmenu > summary {
|
| 633 |
-
padding: 6px 12px;
|
| 634 |
-
border-left: 1px solid var(--ta-line-soft);
|
| 635 |
-
border-radius: 0 999px 999px 0;
|
| 636 |
-
font-size: 0.8em;
|
| 637 |
-
font-weight: 700;
|
| 638 |
-
white-space: nowrap;
|
| 639 |
-
list-style: none;
|
| 640 |
-
cursor: pointer;
|
| 641 |
-
user-select: none;
|
| 642 |
-
}
|
| 643 |
-
.ta-jumpmenu > summary::-webkit-details-marker { display: none; }
|
| 644 |
-
.ta-jumpmenu > summary::after { content: " \\25B4"; opacity: 0.6; }
|
| 645 |
-
.ta-jumpmenu > summary:hover,
|
| 646 |
-
.ta-jumpmenu[open] > summary { background: var(--ta-chip); }
|
| 647 |
-
.ta-jumpmenu-list {
|
| 648 |
-
position: absolute;
|
| 649 |
-
right: 0;
|
| 650 |
-
bottom: calc(100% + 10px);
|
| 651 |
-
display: flex;
|
| 652 |
-
flex-direction: column;
|
| 653 |
-
min-width: 250px;
|
| 654 |
-
padding: 6px;
|
| 655 |
-
border: 1px solid var(--ta-line);
|
| 656 |
-
border-radius: 12px;
|
| 657 |
-
background: var(--ta-raised);
|
| 658 |
-
box-shadow: var(--ta-shadow);
|
| 659 |
-
}
|
| 660 |
-
.ta-jumpmenu-list a,
|
| 661 |
-
.ta-jumpmenu-list button {
|
| 662 |
-
display: block;
|
| 663 |
-
padding: 7px 10px;
|
| 664 |
-
border: 0;
|
| 665 |
-
border-radius: 7px;
|
| 666 |
-
background: none;
|
| 667 |
-
color: var(--ta-ink) !important;
|
| 668 |
-
font: inherit;
|
| 669 |
-
font-size: 0.86em;
|
| 670 |
-
font-weight: 600;
|
| 671 |
-
text-align: left;
|
| 672 |
-
text-decoration: none !important;
|
| 673 |
-
cursor: pointer;
|
| 674 |
-
}
|
| 675 |
-
.ta-jumpmenu-list a:hover,
|
| 676 |
-
.ta-jumpmenu-list button:hover { background: var(--ta-accent-tint); }
|
| 677 |
|
| 678 |
|
| 679 |
/* The models-vs-systems warning. It appears the moment a system joins the field, and it is the
|
|
@@ -910,25 +870,7 @@ CSS = """
|
|
| 910 |
.ta-expand { padding: 4px 10px !important; font-size: 0.95rem !important; line-height: 1; }
|
| 911 |
/* The full table's card (views.make_leaderboard) takes the tile look, below the grid. */
|
| 912 |
.ta-lbtile { margin: 0 0 18px 0; }
|
| 913 |
-
/* The
|
| 914 |
-
On TabArena it is the table's own bottom bar: pulled up over the 16px between blocks so its top
|
| 915 |
-
border lies on the table's bottom one, the corners where they meet squared. BeyondArena's sits
|
| 916 |
-
under its overview figures instead, a block of its own. */
|
| 917 |
-
.ta-pdrawer { margin-top: 2px !important; }
|
| 918 |
-
.ta-pdrawer:has(#ta-perdataset-section) {
|
| 919 |
-
margin-top: -17px !important;
|
| 920 |
-
border-top-left-radius: 0 !important;
|
| 921 |
-
border-top-right-radius: 0 !important;
|
| 922 |
-
}
|
| 923 |
-
.ta-page:has(#ta-perdataset-section) .ta-xo-scroll {
|
| 924 |
-
border-bottom-left-radius: 0;
|
| 925 |
-
border-bottom-right-radius: 0;
|
| 926 |
-
}
|
| 927 |
-
/* Its bar asks to be opened: a wash of the page's own colour (TabArena orange, BeyondArena teal, as in
|
| 928 |
-
the top bar and the overview table above it), an icon, the count in the caption and a filled
|
| 929 |
-
button, and the whole bar takes the click (main.taPdBarClick). Open, the button goes quiet. */
|
| 930 |
-
.ta-pdrawer { --ta-pd-color: var(--ta-tabarena); }
|
| 931 |
-
.ta-pdrawer:has(#beyond-perdataset-section) { --ta-pd-color: var(--ta-beyondarena); }
|
| 932 |
.ta-pdbar {
|
| 933 |
cursor: pointer;
|
| 934 |
flex-wrap: nowrap !important;
|
|
@@ -955,48 +897,9 @@ CSS = """
|
|
| 955 |
color: var(--ta-pd-color);
|
| 956 |
background: color-mix(in srgb, var(--ta-pd-color) 20%, transparent);
|
| 957 |
}
|
| 958 |
-
.ta-pdtext { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
|
| 959 |
-
.ta-pdbar .ta-figbar-title { font-size: 1.08rem; }
|
| 960 |
-
.ta-pdtoggle {
|
| 961 |
-
flex: none;
|
| 962 |
-
margin: 0 !important;
|
| 963 |
-
padding: 9px 18px;
|
| 964 |
-
border: 1px solid transparent;
|
| 965 |
-
border-radius: 999px;
|
| 966 |
-
background: var(--ta-pd-color);
|
| 967 |
-
color: var(--ta-on-accent);
|
| 968 |
-
font: inherit;
|
| 969 |
-
font-size: 0.9rem;
|
| 970 |
-
font-weight: 700;
|
| 971 |
-
white-space: nowrap;
|
| 972 |
-
cursor: pointer;
|
| 973 |
-
box-shadow: 0 4px 14px color-mix(in srgb, var(--ta-pd-color) 32%, transparent);
|
| 974 |
-
transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
|
| 975 |
-
}
|
| 976 |
-
.ta-pdbar:hover .ta-pdtoggle {
|
| 977 |
-
filter: brightness(1.08);
|
| 978 |
-
transform: translateY(-1px);
|
| 979 |
-
box-shadow: 0 6px 18px color-mix(in srgb, var(--ta-pd-color) 42%, transparent);
|
| 980 |
-
}
|
| 981 |
-
.ta-pdtoggle:focus-visible { outline: 2px solid var(--ta-pd-color); outline-offset: 3px; }
|
| 982 |
-
.ta-pdbar.is-open .ta-pdtoggle,
|
| 983 |
-
.ta-pdbar.is-open:hover .ta-pdtoggle {
|
| 984 |
-
padding: 5px 13px;
|
| 985 |
-
border-color: var(--ta-line-soft);
|
| 986 |
-
background: transparent;
|
| 987 |
-
color: var(--ta-ink);
|
| 988 |
-
font-weight: 600;
|
| 989 |
-
box-shadow: none;
|
| 990 |
-
filter: none;
|
| 991 |
-
transform: none;
|
| 992 |
-
}
|
| 993 |
@media (max-width: 640px) {
|
| 994 |
.ta-pdbar { flex-wrap: wrap !important; }
|
| 995 |
-
.ta-pdbar .ta-pdtext { flex-basis: 0; }
|
| 996 |
-
.ta-pdbar .ta-figbar-actions { width: 100%; }
|
| 997 |
-
.ta-pdbar:not(.is-open) .ta-pdtoggle { width: 100%; }
|
| 998 |
}
|
| 999 |
-
html.ta-tile-open .ta-selbar { display: none !important; }
|
| 1000 |
|
| 1001 |
/* --- Follow a method (views.follow_picker, the ◎ on each overview row, main.taToggleFollow) ----- */
|
| 1002 |
.ta-follow { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 2px 0 4px 0; }
|
|
@@ -1173,7 +1076,6 @@ html.ta-tile-open .ta-selbar { display: none !important; }
|
|
| 1173 |
.ta-xo-scroll {
|
| 1174 |
--ta-xo-bg: color-mix(in srgb, #ffffff 4%, var(--ta-page));
|
| 1175 |
overflow: auto;
|
| 1176 |
-
max-height: 680px;
|
| 1177 |
border: 1px solid var(--ta-line-soft);
|
| 1178 |
border-radius: 12px;
|
| 1179 |
background: var(--ta-xo-bg);
|
|
@@ -1200,12 +1102,14 @@ html.ta-tile-open .ta-selbar { display: none !important; }
|
|
| 1200 |
top: 0;
|
| 1201 |
z-index: 3;
|
| 1202 |
height: 32px;
|
| 1203 |
-
background: var(--ta-
|
| 1204 |
color: var(--ta-ink);
|
| 1205 |
font-size: 0.8rem;
|
| 1206 |
font-weight: 700;
|
| 1207 |
}
|
| 1208 |
.ta-xo thead tr:nth-child(2) th { top: 32px; }
|
|
|
|
|
|
|
| 1209 |
.ta-xo .ta-group-h {
|
| 1210 |
border-bottom-color: var(--ta-line);
|
| 1211 |
color: var(--ta-muted);
|
|
@@ -1348,7 +1252,7 @@ html.ta-tile-open .ta-selbar { display: none !important; }
|
|
| 1348 |
background: var(--ta-xo-bg);
|
| 1349 |
text-align: left;
|
| 1350 |
}
|
| 1351 |
-
.ta-xo thead .ta-xo-model { z-index: 4; background: var(--ta-
|
| 1352 |
.ta-xo tbody tr:hover .ta-xo-model { background: color-mix(in srgb, var(--ta-ink) 5%, var(--ta-xo-bg)); }
|
| 1353 |
.ta-xo-id { display: inline-flex; align-items: center; gap: 8px; }
|
| 1354 |
/* A logo fills its tile at its own shape and colours; the few whose artwork would vanish on a dark
|
|
@@ -1712,33 +1616,24 @@ button.ta-jump { background: none; color: inherit; font: inherit; font-size: 0.9
|
|
| 1712 |
.ta-ci-head { opacity: 0.55; font-weight: 400; font-size: 0.82em; }
|
| 1713 |
|
| 1714 |
/* --- A benchmark page's hero (views._page_hero) ---------------------------------------------
|
| 1715 |
-
One sentence on what the benchmark is with its links beside it,
|
| 1716 |
-
|
| 1717 |
-
|
| 1718 |
-
|
| 1719 |
-
faintly in the page's colour, headed by a small "Meet …" eyebrow. */
|
| 1720 |
.ta-phero {
|
| 1721 |
--ta-page-color: var(--ta-accent);
|
| 1722 |
display: flex;
|
| 1723 |
flex-direction: column;
|
| 1724 |
-
gap:
|
| 1725 |
-
padding:
|
| 1726 |
border: 1px solid color-mix(in srgb, var(--ta-page-color) 16%, var(--ta-line-soft));
|
| 1727 |
border-radius: 16px;
|
| 1728 |
background: linear-gradient(
|
| 1729 |
160deg, color-mix(in srgb, var(--ta-page-color) 7%, transparent), color-mix(in srgb, var(--ta-ink) 2%, transparent) 70%
|
| 1730 |
);
|
| 1731 |
}
|
| 1732 |
-
.ta-phero-eyebrow {
|
| 1733 |
-
margin-bottom: -4px;
|
| 1734 |
-
color: var(--ta-page-color);
|
| 1735 |
-
font-size: 0.7rem;
|
| 1736 |
-
font-weight: 700;
|
| 1737 |
-
letter-spacing: 0.1em;
|
| 1738 |
-
text-transform: uppercase;
|
| 1739 |
-
}
|
| 1740 |
@media (max-width: 560px) {
|
| 1741 |
-
.ta-phero { padding: 12px
|
| 1742 |
}
|
| 1743 |
/* The block gap already parts the hero from the top bar and the card under it, and the panel's
|
| 1744 |
edges line up with the cards below, so Gradio's padding around the block goes. */
|
|
@@ -1834,93 +1729,6 @@ button.ta-jump { background: none; color: inherit; font: inherit; font-size: 0.9
|
|
| 1834 |
.ta-split > :focus-visible { outline: none; }
|
| 1835 |
.ta-split:has(:focus-visible) { outline: 2px solid var(--ta-accent); outline-offset: 2px; }
|
| 1836 |
|
| 1837 |
-
/* The selling points: one band of four, each a big value with a label and a line under it, and
|
| 1838 |
-
each opening the details behind it. A numeric value counts up when the hero first shows: the
|
| 1839 |
-
number is drawn from a CSS counter animated by `ta-count-up` (HEAD), while the text in the
|
| 1840 |
-
page stays the real number for screen readers and copying. */
|
| 1841 |
-
.ta-stats {
|
| 1842 |
-
display: grid;
|
| 1843 |
-
grid-template-columns: repeat(4, minmax(0, 1fr));
|
| 1844 |
-
overflow: hidden;
|
| 1845 |
-
border: 1px solid var(--ta-line-soft);
|
| 1846 |
-
border-radius: 14px;
|
| 1847 |
-
background:
|
| 1848 |
-
linear-gradient(100deg, color-mix(in srgb, var(--ta-page-color) 10%, transparent), transparent 60%),
|
| 1849 |
-
var(--ta-card);
|
| 1850 |
-
}
|
| 1851 |
-
.ta-stat {
|
| 1852 |
-
display: flex;
|
| 1853 |
-
align-items: center;
|
| 1854 |
-
gap: 14px;
|
| 1855 |
-
min-width: 0;
|
| 1856 |
-
margin: 0;
|
| 1857 |
-
padding: 12px 18px;
|
| 1858 |
-
border: 0;
|
| 1859 |
-
border-left: 1px solid var(--ta-line-soft);
|
| 1860 |
-
border-radius: 0;
|
| 1861 |
-
background: none;
|
| 1862 |
-
color: inherit;
|
| 1863 |
-
font: inherit;
|
| 1864 |
-
text-align: left;
|
| 1865 |
-
text-decoration: none;
|
| 1866 |
-
cursor: pointer;
|
| 1867 |
-
transition: background .14s ease;
|
| 1868 |
-
}
|
| 1869 |
-
.ta-stat:first-child { border-left: 0; }
|
| 1870 |
-
.ta-stat:hover { background: var(--ta-chip); }
|
| 1871 |
-
.ta-stat:focus-visible { outline: 2px solid var(--ta-accent); outline-offset: -2px; }
|
| 1872 |
-
.ta-stat-num {
|
| 1873 |
-
flex: 0 0 auto;
|
| 1874 |
-
color: var(--ta-page-color);
|
| 1875 |
-
font-size: 2.15rem;
|
| 1876 |
-
font-weight: 800;
|
| 1877 |
-
font-variant-numeric: tabular-nums;
|
| 1878 |
-
letter-spacing: -0.03em;
|
| 1879 |
-
line-height: 1;
|
| 1880 |
-
}
|
| 1881 |
-
.ta-stat-num[data-count] {
|
| 1882 |
-
--ta-count: var(--ta-count-to);
|
| 1883 |
-
counter-reset: ta-count var(--ta-count);
|
| 1884 |
-
animation: ta-count-up 1.3s cubic-bezier(0.16, 1, 0.3, 1) both;
|
| 1885 |
-
}
|
| 1886 |
-
.ta-stat-num[data-count]::after {
|
| 1887 |
-
content: counter(ta-count);
|
| 1888 |
-
content: counter(ta-count) / "";
|
| 1889 |
-
}
|
| 1890 |
-
.ta-stat-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
| 1891 |
-
.ta-stat-lbl { color: var(--ta-ink); font-size: 0.95rem; font-weight: 700; line-height: 1.25; }
|
| 1892 |
-
.ta-stat-line { color: var(--ta-muted); font-size: 0.8rem; line-height: 1.35; }
|
| 1893 |
-
.ta-stat[data-live] .ta-stat-line::before {
|
| 1894 |
-
content: "";
|
| 1895 |
-
display: inline-block;
|
| 1896 |
-
width: 7px;
|
| 1897 |
-
height: 7px;
|
| 1898 |
-
margin-right: 6px;
|
| 1899 |
-
border-radius: 50%;
|
| 1900 |
-
background: var(--ta-live);
|
| 1901 |
-
vertical-align: 1px;
|
| 1902 |
-
animation: ta-live-ping 2.4s ease-out infinite;
|
| 1903 |
-
}
|
| 1904 |
-
.ta-sr-only {
|
| 1905 |
-
position: absolute;
|
| 1906 |
-
width: 1px;
|
| 1907 |
-
height: 1px;
|
| 1908 |
-
overflow: hidden;
|
| 1909 |
-
clip-path: inset(50%);
|
| 1910 |
-
white-space: nowrap;
|
| 1911 |
-
}
|
| 1912 |
-
@media (prefers-reduced-motion: reduce) {
|
| 1913 |
-
.ta-stat-num[data-count], .ta-stat[data-live] .ta-stat-line::before { animation: none; }
|
| 1914 |
-
}
|
| 1915 |
-
@media (max-width: 1100px) {
|
| 1916 |
-
.ta-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
| 1917 |
-
.ta-stat:nth-child(3) { border-left: 0; }
|
| 1918 |
-
.ta-stat:nth-child(n + 3) { border-top: 1px solid var(--ta-line-soft); }
|
| 1919 |
-
}
|
| 1920 |
-
@media (max-width: 560px) {
|
| 1921 |
-
.ta-stat { flex-direction: column; align-items: flex-start; gap: 6px; padding: 12px 14px; }
|
| 1922 |
-
.ta-stat-num { font-size: 1.85rem; }
|
| 1923 |
-
}
|
| 1924 |
|
| 1925 |
/* "Your Benchmark?" invite page: two "path" cards side by side. */
|
| 1926 |
.ta-paths {
|
|
@@ -2114,11 +1922,9 @@ button.ta-jump { background: none; color: inherit; font: inherit; font-size: 0.9
|
|
| 2114 |
into the page's top-right corner, above the bar's actions; the bar steps down below it. */
|
| 2115 |
html:has(#huggingface-space-header) .ta-topbar { margin-top: 50px; }
|
| 2116 |
|
| 2117 |
-
/* A little air above a section that a link jumped to
|
| 2118 |
-
|
| 2119 |
-
|
| 2120 |
-
#ta-controls-anchor, #ta-overview-section, #lb-detailed, #ta-perdataset-section,
|
| 2121 |
-
#beyond-controls-anchor, #beyond-lb-detailed, #beyond-perdataset-section,
|
| 2122 |
[id^="ta-fig-"] { scroll-margin-top: 16px; }
|
| 2123 |
/* Anchor navigation is the only jump that works inside the Space (a scripted scroll cannot move
|
| 2124 |
a cross-origin parent), so the easing has to come from CSS rather than from `scrollIntoView`. */
|
|
@@ -2399,6 +2205,18 @@ html { scroll-behavior: smooth; }
|
|
| 2399 |
}
|
| 2400 |
"""
|
| 2401 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2402 |
# --- The opt-in light theme -------------------------------------------------
|
| 2403 |
# Everything `CSS` above draws in dark-theme colours, restated for a light page. Every selector
|
| 2404 |
# is scoped to `html.ta-light`, which only the top bar's theme toggle sets (`taSetTheme` in
|
|
@@ -2439,7 +2257,6 @@ html.ta-light {
|
|
| 2439 |
--ta-shadow: 0 1px 2px rgba(60, 50, 30, 0.08);
|
| 2440 |
--ta-tabarena: #c2410c;
|
| 2441 |
--ta-beyondarena: #0f766e;
|
| 2442 |
-
--ta-live: #16a34a;
|
| 2443 |
/* THEME points Gradio's light body pair at the dark values (see THEME below); the rest of
|
| 2444 |
its light theme is white, restated here on the soft surfaces. */
|
| 2445 |
--body-background-fill: var(--ta-page);
|
|
@@ -2513,17 +2330,6 @@ __TA_FAMILY_INK__
|
|
| 2513 |
html.ta-light .ta-theme-toggle .ta-ico-sun { display: none; }
|
| 2514 |
html.ta-light .ta-theme-toggle .ta-ico-moon { display: inline; }
|
| 2515 |
|
| 2516 |
-
/* Section chips, sticky selection bar */
|
| 2517 |
-
html.ta-light .ta-selbar {
|
| 2518 |
-
border-color: var(--ta-line);
|
| 2519 |
-
background: rgba(246, 245, 241, 0.96);
|
| 2520 |
-
box-shadow: 0 6px 22px rgba(60, 50, 30, 0.2);
|
| 2521 |
-
color: #1f2740;
|
| 2522 |
-
}
|
| 2523 |
-
html.ta-light .ta-selchip { background: var(--ta-chip); }
|
| 2524 |
-
html.ta-light .ta-selbar-go { background: var(--ta-accent-tint); color: var(--ta-accent-ink); }
|
| 2525 |
-
html.ta-light .ta-jumpmenu-list { box-shadow: 0 10px 30px rgba(60, 50, 30, 0.2); }
|
| 2526 |
-
|
| 2527 |
/* Figure panels and the full-table card. The figures inside stay on their white paper. */
|
| 2528 |
html.ta-light .ta-figpanel,
|
| 2529 |
html.ta-light .ta-tile,
|
|
@@ -2592,15 +2398,6 @@ HEAD = """
|
|
| 2592 |
the same side; the script below does the rest. */
|
| 2593 |
:root { color-scheme: dark; }
|
| 2594 |
html, body, gradio-app { background: #0f0f11; }
|
| 2595 |
-
/* The hero's animations (see `.ta-stat-num` and `.ta-stat[data-live]` in `CSS`). They live here
|
| 2596 |
-
rather than in `CSS`, whose rescoping is written for rules with selectors, not at-rules.
|
| 2597 |
-
`--ta-count` is registered as an integer so that it animates rather than flips. */
|
| 2598 |
-
@property --ta-count { syntax: "<integer>"; inherits: false; initial-value: 0; }
|
| 2599 |
-
@keyframes ta-count-up { from { --ta-count: 0; } }
|
| 2600 |
-
@keyframes ta-live-ping {
|
| 2601 |
-
0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ta-live) 55%, transparent); }
|
| 2602 |
-
70%, 100% { box-shadow: 0 0 0 6px transparent; }
|
| 2603 |
-
}
|
| 2604 |
/* The selector chip a shortcut picked (`.ta-sel .ta-chip.ta-flash` in `CSS`). */
|
| 2605 |
@keyframes ta-sel-flash {
|
| 2606 |
0%, 100% { box-shadow: 0 0 0 0 transparent; }
|
|
@@ -2830,8 +2627,6 @@ window.taExpandTile = function (uid) {
|
|
| 2830 |
tile.before(backdrop);
|
| 2831 |
tile.classList.add("ta-tile-max");
|
| 2832 |
tile.querySelector(".ta-expand").setAttribute("aria-pressed", "true");
|
| 2833 |
-
// The bottom pill would sit on top of the backdrop.
|
| 2834 |
-
document.documentElement.classList.add("ta-tile-open");
|
| 2835 |
taSetBand(taBand);
|
| 2836 |
};
|
| 2837 |
function taCollapseTile(tile) {
|
|
@@ -2839,7 +2634,6 @@ function taCollapseTile(tile) {
|
|
| 2839 |
const btn = tile.querySelector(".ta-expand");
|
| 2840 |
if (btn) btn.setAttribute("aria-pressed", "false");
|
| 2841 |
document.querySelectorAll(".ta-tile-backdrop").forEach((backdrop) => backdrop.remove());
|
| 2842 |
-
document.documentElement.classList.remove("ta-tile-open");
|
| 2843 |
}
|
| 2844 |
document.addEventListener("keydown", (ev) => {
|
| 2845 |
if (ev.key === "Escape") document.querySelectorAll(".ta-tile-max").forEach(taCollapseTile);
|
|
@@ -3015,7 +2809,11 @@ window.taGoToPage = function (link) {
|
|
| 3015 |
const target = taTabButton(link.dataset.tab);
|
| 3016 |
if (target) target.click();
|
| 3017 |
const slug = link.dataset.slug;
|
| 3018 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3019 |
try { history.replaceState(null, "", location.pathname + query + location.hash); } catch (err) {}
|
| 3020 |
if (window.parent !== window) {
|
| 3021 |
try { window.parent.postMessage({ queryString: query }, "https://huggingface.co"); } catch (err) {}
|
|
@@ -3419,15 +3217,69 @@ window.taSelector = function (root, send) {
|
|
| 3419 |
});
|
| 3420 |
paint();
|
| 3421 |
};
|
| 3422 |
-
/* A
|
| 3423 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3424 |
document.addEventListener("click", (event) => {
|
| 3425 |
const path = typeof event.composedPath === "function" ? event.composedPath() : [event.target];
|
| 3426 |
-
const
|
| 3427 |
-
|
| 3428 |
-
const card = block && block.querySelector(".ta-sel");
|
| 3429 |
-
if (card && card._taSetOpen) card._taSetOpen(true);
|
| 3430 |
}, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3431 |
/* Copy a block's text, as the citation dialog's button does. Where the clipboard is not offered
|
| 3432 |
(some embeds refuse it), the text is selected instead so the reader can copy it by hand. */
|
| 3433 |
window.taCopy = function (button, id) {
|
|
@@ -3461,8 +3313,8 @@ window.taCloseDialogs = function () {
|
|
| 3461 |
document.addEventListener("click", (ev) => {
|
| 3462 |
if (ev.target.classList && ev.target.classList.contains("ta-dialog-overlay")) window.taCloseDialogs();
|
| 3463 |
});
|
| 3464 |
-
function
|
| 3465 |
-
const open = "details.ta-
|
| 3466 |
document.querySelectorAll(open).forEach((menu) => {
|
| 3467 |
if (menu !== except) menu.open = false;
|
| 3468 |
});
|
|
@@ -3470,34 +3322,25 @@ function taCloseJumpMenus(except) {
|
|
| 3470 |
document.addEventListener("keydown", (ev) => {
|
| 3471 |
if (ev.key !== "Escape") return;
|
| 3472 |
window.taCloseDialogs();
|
| 3473 |
-
|
| 3474 |
});
|
| 3475 |
-
/* A pick closes
|
| 3476 |
-
|
| 3477 |
-
|
| 3478 |
document.addEventListener("click", (ev) => {
|
| 3479 |
-
const menus = "details.ta-
|
| 3480 |
const menu = ev.target.closest && ev.target.closest(menus);
|
| 3481 |
-
|
| 3482 |
-
if (menu && ev.target.closest(".ta-
|
| 3483 |
});
|
| 3484 |
|
| 3485 |
-
/* Reveal the selection bar once the control card has scrolled out of view, and hide it again
|
| 3486 |
-
while an open dataset browser fills the view (taOverDataBrowser): that browser has its own
|
| 3487 |
-
contender, sort and filter controls, so a second floating bar of selectors over it competes for
|
| 3488 |
-
the same job.
|
| 3489 |
-
|
| 3490 |
-
IntersectionObservers rather than a scroll handler: no work on frames where nothing crossed a
|
| 3491 |
-
boundary. Re-attached after Gradio re-renders, since the elements are replaced. */
|
| 3492 |
-
let taControlsSeen = null;
|
| 3493 |
-
|
| 3494 |
/* The visible band, written onto the elements pinned to it rather than onto :root. A custom
|
| 3495 |
property set on the root is inherited by every element on the page, so each scroll report
|
| 3496 |
restyled all six thousand of them (~15 ms) while the reader was scrolling, in the frame whose
|
| 3497 |
main thread also has to paint what scrolls into view; on these few it restyles only them.
|
| 3498 |
`taBand` keeps the numbers for the scripts below; null while our viewport is the screen,
|
| 3499 |
where the stylesheet's own defaults apply. */
|
| 3500 |
-
const TA_BAND_READERS = ".ta-
|
| 3501 |
let taBand = null;
|
| 3502 |
function taSetBand(band) {
|
| 3503 |
taBand = band;
|
|
@@ -3513,46 +3356,12 @@ function taSetBand(band) {
|
|
| 3513 |
taLoadFramesInBand();
|
| 3514 |
}
|
| 3515 |
|
| 3516 |
-
/* Is an open dataset browser across the middle of the reader's view? It has its own contender,
|
| 3517 |
-
filter and sort controls, so the selection bar would compete with it there. Asked of the visible
|
| 3518 |
-
band rather than of an IntersectionObserver, because the two environments move different
|
| 3519 |
-
things: top-level the page scrolls, so the frame's own top moves and --ta-vp-top stays 0;
|
| 3520 |
-
embedded, the Space's frame is as tall as its content and never scrolls, so the browser's top is
|
| 3521 |
-
a fixed document position and the band moves instead. Comparing the two covers both. */
|
| 3522 |
-
function taOverDataBrowser() {
|
| 3523 |
-
const frame = document.querySelector("iframe.ta-explorer[title^='Per-dataset'][src]");
|
| 3524 |
-
if (!frame) return false;
|
| 3525 |
-
const bandTop = taBand ? taBand.top : 0;
|
| 3526 |
-
const bandH = taBand ? taBand.h : window.innerHeight;
|
| 3527 |
-
const box = frame.getBoundingClientRect();
|
| 3528 |
-
const middle = bandTop + bandH * 0.5;
|
| 3529 |
-
return box.top <= middle && box.bottom >= middle;
|
| 3530 |
-
}
|
| 3531 |
-
|
| 3532 |
-
function taSyncSelbar() {
|
| 3533 |
-
const bar = document.querySelector(".ta-selbar");
|
| 3534 |
-
if (bar) bar.classList.toggle("ta-show", taControlsSeen === false && !taOverDataBrowser());
|
| 3535 |
-
}
|
| 3536 |
-
function taWatchControls() {
|
| 3537 |
-
const anchor = document.getElementById("ta-controls-anchor");
|
| 3538 |
-
const bar = document.querySelector(".ta-selbar");
|
| 3539 |
-
if (!anchor || !bar) return;
|
| 3540 |
-
taSyncSelbar();
|
| 3541 |
-
if (anchor.dataset.taWatched) return;
|
| 3542 |
-
anchor.dataset.taWatched = "1";
|
| 3543 |
-
new IntersectionObserver((entries) => {
|
| 3544 |
-
taControlsSeen = entries[0].isIntersecting;
|
| 3545 |
-
taSyncSelbar();
|
| 3546 |
-
}, { rootMargin: "-40px 0px 0px 0px" }).observe(anchor);
|
| 3547 |
-
}
|
| 3548 |
-
|
| 3549 |
/* --- Keep --ta-vp-top / --ta-vp-h on the visible band ----------------------
|
| 3550 |
Only does anything when this page's viewport is not the screen. Embedded in a Hugging Face
|
| 3551 |
Space it is not: HF sizes the Space iframe to the app's whole content, so the iframe never
|
| 3552 |
scrolls, the outer page does, and our viewport is the entire document. Everything pinned to a
|
| 3553 |
-
screen edge then pins to the top of a six-thousand-pixel page instead:
|
| 3554 |
-
|
| 3555 |
-
parked far above the screen.
|
| 3556 |
|
| 3557 |
The parent is cross-origin, so its scroll position is unreadable. IntersectionObserver's
|
| 3558 |
implicit root is the top-level viewport though, and it reports the intersection in *our*
|
|
@@ -3637,7 +3446,6 @@ function taOnPageInfo(info) {
|
|
| 3637 |
taSetBand(null);
|
| 3638 |
} else {
|
| 3639 |
taSetBand({ top: Math.round(top), h: Math.round(bottom - top) });
|
| 3640 |
-
taSyncSelbar(); // the band moved, so what the reader has reached changed with it
|
| 3641 |
}
|
| 3642 |
taReportViewport();
|
| 3643 |
}
|
|
@@ -3752,7 +3560,6 @@ function taTrackViewport() {
|
|
| 3752 |
// then there are two scrollports rather than none. Both cases come out right here,
|
| 3753 |
// because a page that cannot scroll has `scrollY === 0` anyway.
|
| 3754 |
taSetBand({ top: Math.round(top), h: Math.round(bottom - top) });
|
| 3755 |
-
taSyncSelbar();
|
| 3756 |
taReportViewport();
|
| 3757 |
}, { threshold: TA_STEPS });
|
| 3758 |
|
|
@@ -3773,7 +3580,6 @@ new MutationObserver(() => {
|
|
| 3773 |
// Coalesce a burst of mutations into one pass; the guards above make it idempotent.
|
| 3774 |
clearTimeout(window._taStampTimer);
|
| 3775 |
window._taStampTimer = setTimeout(() => {
|
| 3776 |
-
taWatchControls();
|
| 3777 |
taTrackViewport();
|
| 3778 |
taSetBand(taBand);
|
| 3779 |
// A re-render brings fresh frames to load, a page switch a new page.
|
|
@@ -3786,10 +3592,7 @@ new MutationObserver(() => {
|
|
| 3786 |
taFitTopBar();
|
| 3787 |
}, 60);
|
| 3788 |
}).observe(document.body, { childList: true, subtree: true });
|
| 3789 |
-
// Top-level there is no band to track, so the section's own position is what moves.
|
| 3790 |
-
window.addEventListener("scroll", taSyncSelbar, { passive: true });
|
| 3791 |
document.addEventListener("DOMContentLoaded", () => {
|
| 3792 |
-
taWatchControls();
|
| 3793 |
taTrackViewport();
|
| 3794 |
taReportViewport();
|
| 3795 |
taSyncThemeChip();
|
|
@@ -3868,7 +3671,7 @@ window.taSendExclude = function (frame) {
|
|
| 3868 |
/* How tall the reader's visible band is, for the per-dataset browser's "fit to screen" button.
|
| 3869 |
The frame cannot work this out for itself: it is sized to its own content, so its
|
| 3870 |
`innerHeight` is the length of its page rather than of the screen. We already track the band
|
| 3871 |
-
for the
|
| 3872 |
window.taSendPerDatasetViewport = function (frame) {
|
| 3873 |
if (frame.dataset.task === undefined) return;
|
| 3874 |
const height = taBand && taBand.h > 200 ? taBand.h : window.innerHeight;
|
|
@@ -3878,22 +3681,6 @@ window.taSendPerDatasetViewport = function (frame) {
|
|
| 3878 |
} catch (err) { /* not ready; it will ask again with its next height report */ }
|
| 3879 |
};
|
| 3880 |
|
| 3881 |
-
/* That button is HTML inside the panel's title bar, so it cannot be a Gradio component itself;
|
| 3882 |
-
it forwards the click to the hidden one that actually reaches the server. */
|
| 3883 |
-
/* The dataset browser's bar opens and closes it from anywhere on it, not only from its button; the
|
| 3884 |
-
download menu inside it keeps its own clicks. */
|
| 3885 |
-
window.taPdBarClick = function (ev, uid) {
|
| 3886 |
-
if (ev.target.closest(".ta-dl")) return;
|
| 3887 |
-
window.taTogglePerDataset(uid);
|
| 3888 |
-
};
|
| 3889 |
-
window.taTogglePerDataset = function (uid) {
|
| 3890 |
-
// Gradio puts `elem_id` on the <button> itself for gr.Button, and on a wrapper for most
|
| 3891 |
-
// other components; accept either so this does not depend on which.
|
| 3892 |
-
const node = document.getElementById(uid + "-toggle");
|
| 3893 |
-
const real = node && (node.tagName === "BUTTON" ? node : node.querySelector("button"));
|
| 3894 |
-
if (real) real.click();
|
| 3895 |
-
};
|
| 3896 |
-
|
| 3897 |
/* --- Leaderboard table sorting ---------------------------------------------
|
| 3898 |
Click a header to sort the rows beneath it; click again to reverse. Numeric
|
| 3899 |
columns are marked `data-type="num"` and every cell carries the raw value in
|
|
|
|
| 4 |
|
| 5 |
import json
|
| 6 |
|
| 7 |
+
import website_texts
|
| 8 |
from api import register_api
|
| 9 |
from data_loading import BEYOND_DATA_DIR, DATA_DIR
|
| 10 |
from pages import PAGES, render_page
|
|
|
|
| 14 |
CSS = """
|
| 15 |
/* Use the full page width instead of gradio's narrow centered column. */
|
| 16 |
.gradio-container { max-width: 100% !important; }
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
.gradio-container { padding-top: 6px !important; }
|
| 18 |
|
| 19 |
/* --- Colour emoji ----------------------------------------------------------
|
|
|
|
| 115 |
then one line per choice with the captions in one column down the left, and beside the lines a
|
| 116 |
column that says what the selection covers, its number set like the hero's. A chip in a row that
|
| 117 |
filters the datasets carries the number of datasets the leaderboard would cover with it picked.
|
| 118 |
+
The card starts closed, as its bar alone, one row: the title is the button, small shortcuts into
|
| 119 |
+
the card follow it, and the number of datasets the selection covers ends it. Opened, the lines
|
| 120 |
+
grow under the bar, headed by what the choices change. */
|
| 121 |
.ta-sel-block .html-container { padding: 0; }
|
| 122 |
.ta-sel {
|
| 123 |
--ta-page-color: var(--ta-accent);
|
| 124 |
--ta-pd-color: var(--ta-page-color);
|
| 125 |
display: grid;
|
| 126 |
+
grid-template-columns: minmax(0, 1fr) auto;
|
| 127 |
+
grid-template-areas: "bar result" "main main" "warns warns";
|
|
|
|
| 128 |
overflow: hidden;
|
| 129 |
border: 1px solid var(--ta-line-soft);
|
| 130 |
border-radius: 14px;
|
|
|
|
| 136 |
selling points, a second orange band read as more of the same. The icon, the chevron and the
|
| 137 |
shortcuts carry the colour instead. */
|
| 138 |
.ta-sel-bar { grid-area: bar; }
|
| 139 |
+
.ta-sel .ta-sel-bar { gap: 12px !important; padding: 7px 14px !important; background: transparent; }
|
| 140 |
.ta-sel .ta-sel-bar:hover { background: color-mix(in srgb, var(--ta-ink) 4%, transparent); }
|
| 141 |
+
.ta-sel:not([data-open="true"]) > :is(.ta-sel-main, .ta-sel-warns) { display: none; }
|
|
|
|
| 142 |
.ta-sel-main { grid-area: main; min-width: 0; padding: 0 18px 2px; }
|
| 143 |
+
.ta-sel-lead { margin: 0; padding: 10px 0 2px; color: var(--ta-muted); font-size: 0.84rem; }
|
| 144 |
+
.ta-sel-main > .ta-sel-lead + .ta-sel-line { border-top: 0; }
|
| 145 |
+
.ta-sel .ta-pdicon { width: 28px; height: 28px; border-radius: 8px; }
|
| 146 |
+
.ta-sel .ta-pdicon svg { width: 15px; height: 15px; }
|
| 147 |
+
.ta-sel .ta-sel-title { flex: none; margin: 0; font-size: 1rem; letter-spacing: -0.01em; white-space: nowrap; }
|
| 148 |
/* The title opens the card, its chevron filled in the page's colour while there is more to see,
|
| 149 |
quiet and turned once the card is open. */
|
| 150 |
.ta-sel-toggle {
|
| 151 |
display: inline-flex;
|
| 152 |
align-items: center;
|
| 153 |
+
gap: 8px;
|
| 154 |
margin: 0;
|
| 155 |
padding: 0;
|
| 156 |
border: 0;
|
|
|
|
| 164 |
display: grid;
|
| 165 |
place-items: center;
|
| 166 |
flex: none;
|
| 167 |
+
width: 20px;
|
| 168 |
+
height: 20px;
|
| 169 |
border: 1px solid transparent;
|
| 170 |
border-radius: 50%;
|
| 171 |
background: var(--ta-page-color);
|
|
|
|
| 174 |
}
|
| 175 |
.ta-sel-chev::before {
|
| 176 |
content: "";
|
| 177 |
+
width: 6px;
|
| 178 |
+
height: 6px;
|
| 179 |
border-style: solid;
|
| 180 |
border-color: var(--ta-on-accent);
|
| 181 |
border-width: 0 2px 2px 0;
|
|
|
|
| 189 |
transform: rotate(180deg);
|
| 190 |
}
|
| 191 |
.ta-sel[data-open="true"] .ta-sel-chev::before { border-color: var(--ta-ink); }
|
| 192 |
+
/* The shortcuts: small and dashed, as suggestions rather than settings, each a "+" until it is
|
| 193 |
+
picked. They keep to the bar's row, which scrolls sideways where it cannot hold them, fading out
|
| 194 |
+
at the edge it continues past. */
|
| 195 |
+
.ta-sel-try {
|
| 196 |
+
display: flex;
|
| 197 |
+
flex: 1 1 auto;
|
| 198 |
+
align-items: center;
|
| 199 |
+
gap: 5px;
|
| 200 |
+
min-width: 0;
|
| 201 |
+
overflow-x: auto;
|
| 202 |
+
scrollbar-width: none;
|
| 203 |
+
}
|
| 204 |
+
.ta-sel-try::-webkit-scrollbar { display: none; }
|
| 205 |
.ta-sel-ex {
|
| 206 |
+
flex: none;
|
| 207 |
margin: 0;
|
| 208 |
+
padding: 2px 9px 2px 7px;
|
| 209 |
border: 1px dashed color-mix(in srgb, var(--ta-page-color) 60%, transparent);
|
| 210 |
border-radius: 999px;
|
| 211 |
background: transparent;
|
| 212 |
color: var(--ta-ink);
|
| 213 |
font: inherit;
|
| 214 |
+
font-size: 0.74rem;
|
| 215 |
font-weight: 600;
|
| 216 |
white-space: nowrap;
|
| 217 |
cursor: pointer;
|
| 218 |
transition: background .14s ease, border-color .14s ease;
|
| 219 |
}
|
| 220 |
+
.ta-sel-ex::before { content: "+"; margin-right: 4px; color: var(--ta-page-color); font-weight: 800; }
|
| 221 |
.ta-sel-ex:hover,
|
| 222 |
.ta-sel-ex[aria-pressed="true"] {
|
| 223 |
border-style: solid;
|
|
|
|
| 226 |
.ta-sel-ex[aria-pressed="true"]::before { content: "\\2713"; }
|
| 227 |
.ta-sel-ex:focus-visible { outline: 2px solid var(--ta-page-color); outline-offset: 2px; }
|
| 228 |
.ta-sel-ex:disabled { opacity: 0.4; cursor: not-allowed; }
|
| 229 |
+
@media (max-width: 1100px) {
|
| 230 |
+
.ta-sel-try { mask-image: linear-gradient(90deg, #000 85%, transparent); }
|
| 231 |
+
}
|
| 232 |
+
/* On a phone the shortcuts take a line of their own under the title. */
|
| 233 |
@media (max-width: 640px) {
|
| 234 |
+
.ta-sel .ta-sel-try { flex-basis: 100%; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
}
|
| 236 |
/* The chip a shortcut picked pulses as the card opens, so the reader sees where it lives. */
|
| 237 |
.ta-sel .ta-chip.ta-flash { animation: ta-sel-flash 0.9s ease-out 2; }
|
|
|
|
| 392 |
.ta-sel .ta-chip[role="switch"][aria-checked="true"] .ta-chip-mark { background: var(--ta-page-color); }
|
| 393 |
.ta-sel .ta-chip[role="switch"][aria-checked="true"] .ta-chip-mark::after { transform: translateX(12px); }
|
| 394 |
|
| 395 |
+
/* The page's views (views.view_bar): tabs at the top of its controls, quiet labels with the shown one
|
| 396 |
+
in ink over a rail in the page's colour, like the top bar's page links, each saying on hover what
|
| 397 |
+
its view shows; Follow at the right. The selector card hangs under the bar, joined to it as one
|
| 398 |
+
card, so its choices read as applying to every view. On a phone the tabs scroll sideways in one
|
| 399 |
+
row and Follow takes a line of its own. */
|
| 400 |
+
.ta-viewbar-block .html-container { padding: 0 !important; }
|
| 401 |
+
.ta-viewbar {
|
| 402 |
+
--ta-page-color: var(--ta-tabarena);
|
| 403 |
+
display: flex;
|
| 404 |
+
flex-wrap: wrap;
|
| 405 |
+
align-items: center;
|
| 406 |
+
gap: 0 16px;
|
| 407 |
+
padding: 0 12px 0 10px;
|
| 408 |
+
border: 1px solid var(--ta-line-soft);
|
| 409 |
+
border-bottom: 0;
|
| 410 |
+
border-radius: 14px 14px 0 0;
|
| 411 |
+
background: var(--ta-toolbar);
|
| 412 |
+
}
|
| 413 |
+
.ta-viewbar[data-page="beyondarena"] { --ta-page-color: var(--ta-beyondarena); }
|
| 414 |
+
/* Pulled up over the gap between blocks so the card's top border lies on the bar's foot. Gradio puts
|
| 415 |
+
the class on the block and on its inner element too, so only the block (`.block`) moves. */
|
| 416 |
+
.ta-page:has(.ta-viewbar) .block.ta-sel-block { margin-top: -16px !important; }
|
| 417 |
+
/* The tabs and the card share a surface a shade apart from the view under them, as a toolbar over its
|
| 418 |
+
page, with a firmer line where the view starts. */
|
| 419 |
+
.ta-page:has(.ta-viewbar) .ta-sel { border-radius: 0; border-bottom-color: var(--ta-line); background: var(--ta-toolbar); }
|
| 420 |
+
/* The shown view starts on the card's foot: its first card, or the first row of a figure grid, takes
|
| 421 |
+
the card's bottom border for its top edge, with square corners where the two meet. Which tiles make
|
| 422 |
+
that row follows "I care about" (the order rules at `.ta-figgrid`). */
|
| 423 |
+
.ta-page:has(.ta-viewbar) .ta-view { margin-top: -16px !important; }
|
| 424 |
+
.ta-view .ta-figpanel { margin-top: 0; }
|
| 425 |
+
.ta-view :is(.ta-xo-scroll, .ta-figpanel, .ta-view-card:not(.ta-view-card ~ .ta-view-card)),
|
| 426 |
+
.ta-view .ta-figgrid > .ta-tile:first-child,
|
| 427 |
+
.ta-page[data-care="total"] .ta-view .ta-tile[data-key="total"],
|
| 428 |
+
.ta-page[data-care="train"] .ta-view .ta-tile[data-key="train"] {
|
| 429 |
+
border-top: 0 !important;
|
| 430 |
+
border-top-left-radius: 0 !important;
|
| 431 |
+
border-top-right-radius: 0 !important;
|
| 432 |
+
}
|
| 433 |
+
@media (min-width: 1101px) {
|
| 434 |
+
.ta-view .ta-figgrid > .ta-tile:not(.ta-tile-wide):first-child + .ta-tile:not(.ta-tile-wide) {
|
| 435 |
+
border-top: 0;
|
| 436 |
+
border-top-left-radius: 0;
|
| 437 |
+
border-top-right-radius: 0;
|
| 438 |
+
}
|
| 439 |
+
.ta-page[data-care="train"] .ta-view .ta-figgrid:has(> [data-key="train"]) > .ta-tile[data-key="total"] {
|
| 440 |
+
border-top: 1px solid var(--ta-line-soft);
|
| 441 |
+
border-top-left-radius: 14px;
|
| 442 |
+
border-top-right-radius: 14px;
|
| 443 |
+
}
|
| 444 |
+
}
|
| 445 |
+
/* One figure per row: only the one put first joins. */
|
| 446 |
+
@media (max-width: 1100px) {
|
| 447 |
+
.ta-page[data-care="total"] .ta-view .ta-figgrid:has(> [data-key="total"]) > .ta-tile:first-child:not([data-key="total"]),
|
| 448 |
+
.ta-page[data-care="train"] .ta-view .ta-figgrid:has(> [data-key="train"]) > .ta-tile:first-child:not([data-key="train"]) {
|
| 449 |
+
border-top: 1px solid var(--ta-line-soft) !important;
|
| 450 |
+
border-top-left-radius: 14px !important;
|
| 451 |
+
border-top-right-radius: 14px !important;
|
| 452 |
+
}
|
| 453 |
+
}
|
| 454 |
+
.ta-viewtabs { display: flex; flex: none; gap: 2px; max-width: 100%; overflow-x: auto; scrollbar-width: none; }
|
| 455 |
+
.ta-viewtabs::-webkit-scrollbar { display: none; }
|
| 456 |
+
.ta-viewtab {
|
| 457 |
+
flex: none;
|
| 458 |
+
margin: 0;
|
| 459 |
+
padding: 12px 14px 10px;
|
| 460 |
+
border: 0;
|
| 461 |
+
border-bottom: 2px solid transparent;
|
| 462 |
+
background: none;
|
| 463 |
+
color: var(--ta-muted);
|
| 464 |
+
font: inherit;
|
| 465 |
+
font-size: 0.95rem;
|
| 466 |
+
font-weight: 600;
|
| 467 |
+
white-space: nowrap;
|
| 468 |
+
cursor: pointer;
|
| 469 |
+
transition: color .14s ease, border-color .14s ease;
|
| 470 |
+
}
|
| 471 |
+
.ta-viewtab:hover { color: var(--ta-ink); }
|
| 472 |
+
.ta-viewtab[aria-selected="true"] { border-bottom-color: var(--ta-page-color); color: var(--ta-ink); }
|
| 473 |
+
.ta-viewtab:focus-visible { outline: 2px solid var(--ta-page-color); outline-offset: -2px; border-radius: 6px; }
|
| 474 |
+
/* What follows the tabs: a warning about the selection, or a note of the shown view. */
|
| 475 |
+
.ta-viewnotes { flex: 1 1 auto; min-width: 0; margin: 0; padding: 8px 0; color: var(--ta-muted); font-size: 0.84rem; line-height: 1.4; }
|
| 476 |
+
.ta-viewnotes:empty { display: none; }
|
| 477 |
+
.ta-viewnote-link {
|
| 478 |
+
margin: 0 0 0 6px;
|
| 479 |
+
padding: 0;
|
| 480 |
+
border: 0;
|
| 481 |
+
background: none;
|
| 482 |
+
color: var(--ta-ink);
|
| 483 |
+
font: inherit;
|
| 484 |
+
font-weight: 600;
|
| 485 |
+
text-decoration: underline dotted;
|
| 486 |
+
text-underline-offset: 3px;
|
| 487 |
+
cursor: pointer;
|
| 488 |
+
}
|
| 489 |
+
.ta-viewnotes .ta-head-warn { margin-left: 8px; }
|
| 490 |
+
.ta-viewbar .ta-follow { flex: none; margin: 0 0 0 auto; }
|
| 491 |
+
@media (max-width: 640px) {
|
| 492 |
+
.ta-viewbar { padding: 0 8px 8px; }
|
| 493 |
+
.ta-viewnotes { flex-basis: 100%; padding: 2px 4px 6px; }
|
| 494 |
+
}
|
| 495 |
+
/* One view shows at a time: the one the page names (`data-view`, main.taShowView), the first until
|
| 496 |
+
it names one. */
|
| 497 |
+
__TA_VIEW_RULES__
|
| 498 |
+
|
| 499 |
/* What the selection covers: the number of datasets, beside the bar and the lines. */
|
| 500 |
.ta-sel-result {
|
| 501 |
grid-area: result;
|
| 502 |
display: flex;
|
| 503 |
+
align-items: center;
|
|
|
|
| 504 |
min-width: 0;
|
| 505 |
+
padding: 6px 16px;
|
| 506 |
border-left: 1px solid var(--ta-line-soft);
|
| 507 |
+
background: linear-gradient(260deg, color-mix(in srgb, var(--ta-page-color) 13%, transparent), transparent 90%);
|
| 508 |
}
|
| 509 |
+
.ta-sel[data-open="true"] .ta-sel-result { border-bottom: 1px solid var(--ta-line-soft); }
|
| 510 |
.ta-sel-total {
|
| 511 |
display: flex;
|
|
|
|
| 512 |
align-items: baseline;
|
| 513 |
+
gap: 6px;
|
| 514 |
margin: 0;
|
| 515 |
color: var(--ta-ink);
|
| 516 |
+
font-size: 0.84rem;
|
| 517 |
font-weight: 700;
|
| 518 |
+
white-space: nowrap;
|
| 519 |
}
|
| 520 |
.ta-sel-unit { white-space: nowrap; }
|
| 521 |
.ta-sel-num {
|
| 522 |
color: var(--ta-page-color);
|
| 523 |
+
font-size: 1.2rem;
|
| 524 |
font-weight: 800;
|
| 525 |
font-variant-numeric: tabular-nums;
|
| 526 |
letter-spacing: -0.03em;
|
|
|
|
| 560 |
.ta-sel-warn-body ul { padding-left: 1.2em; }
|
| 561 |
.ta-sel-warn-body > :last-child { margin-bottom: 0; }
|
| 562 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 563 |
/* Where the line cannot hold both rows, the second takes a line of its own, caption in the column. */
|
| 564 |
@media (max-width: 1180px) {
|
| 565 |
.ta-sel-line { flex-direction: column; }
|
|
|
|
| 613 |
--ta-card: rgba(255, 255, 255, 0.04);
|
| 614 |
--ta-strip: rgba(255, 255, 255, 0.06);
|
| 615 |
--ta-raised: #1b1b22;
|
| 616 |
+
/* The controls over a page's views (the tabs and the selector card). */
|
| 617 |
+
--ta-toolbar: color-mix(in srgb, var(--ta-ink) 7%, var(--ta-page));
|
| 618 |
--ta-line: rgba(255, 255, 255, 0.2);
|
| 619 |
--ta-line-soft: rgba(255, 255, 255, 0.1);
|
| 620 |
--ta-ink: #f4f4f5;
|
|
|
|
| 632 |
orange of its old tab, BeyondArena the teal of its hero. */
|
| 633 |
--ta-tabarena: #fb923c;
|
| 634 |
--ta-beyondarena: #2dd4bf;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 635 |
}
|
| 636 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 637 |
|
| 638 |
|
| 639 |
/* The models-vs-systems warning. It appears the moment a system joins the field, and it is the
|
|
|
|
| 870 |
.ta-expand { padding: 4px 10px !important; font-size: 0.95rem !important; line-height: 1; }
|
| 871 |
/* The full table's card (views.make_leaderboard) takes the tile look, below the grid. */
|
| 872 |
.ta-lbtile { margin: 0 0 18px 0; }
|
| 873 |
+
/* The selector card's bar (views.selector_card), washed in the page's colour (`--ta-pd-color`). */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 874 |
.ta-pdbar {
|
| 875 |
cursor: pointer;
|
| 876 |
flex-wrap: nowrap !important;
|
|
|
|
| 897 |
color: var(--ta-pd-color);
|
| 898 |
background: color-mix(in srgb, var(--ta-pd-color) 20%, transparent);
|
| 899 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 900 |
@media (max-width: 640px) {
|
| 901 |
.ta-pdbar { flex-wrap: wrap !important; }
|
|
|
|
|
|
|
|
|
|
| 902 |
}
|
|
|
|
| 903 |
|
| 904 |
/* --- Follow a method (views.follow_picker, the ◎ on each overview row, main.taToggleFollow) ----- */
|
| 905 |
.ta-follow { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 2px 0 4px 0; }
|
|
|
|
| 1076 |
.ta-xo-scroll {
|
| 1077 |
--ta-xo-bg: color-mix(in srgb, #ffffff 4%, var(--ta-page));
|
| 1078 |
overflow: auto;
|
|
|
|
| 1079 |
border: 1px solid var(--ta-line-soft);
|
| 1080 |
border-radius: 12px;
|
| 1081 |
background: var(--ta-xo-bg);
|
|
|
|
| 1102 |
top: 0;
|
| 1103 |
z-index: 3;
|
| 1104 |
height: 32px;
|
| 1105 |
+
background: var(--ta-xo-bg);
|
| 1106 |
color: var(--ta-ink);
|
| 1107 |
font-size: 0.8rem;
|
| 1108 |
font-weight: 700;
|
| 1109 |
}
|
| 1110 |
.ta-xo thead tr:nth-child(2) th { top: 32px; }
|
| 1111 |
+
/* The heading is on the table's own surface; a firmer line under it starts the rows. */
|
| 1112 |
+
.ta-xo thead :is(tr:last-child th, th[rowspan]) { border-bottom-color: var(--ta-line); }
|
| 1113 |
.ta-xo .ta-group-h {
|
| 1114 |
border-bottom-color: var(--ta-line);
|
| 1115 |
color: var(--ta-muted);
|
|
|
|
| 1252 |
background: var(--ta-xo-bg);
|
| 1253 |
text-align: left;
|
| 1254 |
}
|
| 1255 |
+
.ta-xo thead .ta-xo-model { z-index: 4; background: var(--ta-xo-bg); }
|
| 1256 |
.ta-xo tbody tr:hover .ta-xo-model { background: color-mix(in srgb, var(--ta-ink) 5%, var(--ta-xo-bg)); }
|
| 1257 |
.ta-xo-id { display: inline-flex; align-items: center; gap: 8px; }
|
| 1258 |
/* A logo fills its tile at its own shape and colours; the few whose artwork would vanish on a dark
|
|
|
|
| 1616 |
.ta-ci-head { opacity: 0.55; font-weight: 400; font-size: 0.82em; }
|
| 1617 |
|
| 1618 |
/* --- A benchmark page's hero (views._page_hero) ---------------------------------------------
|
| 1619 |
+
One sentence on what the benchmark is with its links beside it, then the Learn more row, whose
|
| 1620 |
+
pills quote the benchmark's numbers from the data. Its colour is the page's own, as on the
|
| 1621 |
+
page's link in the top bar. The hero is the page's background, so it sits apart from the
|
| 1622 |
+
results under it: one panel washed faintly in the page's colour. */
|
|
|
|
| 1623 |
.ta-phero {
|
| 1624 |
--ta-page-color: var(--ta-accent);
|
| 1625 |
display: flex;
|
| 1626 |
flex-direction: column;
|
| 1627 |
+
gap: 10px;
|
| 1628 |
+
padding: 12px 18px;
|
| 1629 |
border: 1px solid color-mix(in srgb, var(--ta-page-color) 16%, var(--ta-line-soft));
|
| 1630 |
border-radius: 16px;
|
| 1631 |
background: linear-gradient(
|
| 1632 |
160deg, color-mix(in srgb, var(--ta-page-color) 7%, transparent), color-mix(in srgb, var(--ta-ink) 2%, transparent) 70%
|
| 1633 |
);
|
| 1634 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1635 |
@media (max-width: 560px) {
|
| 1636 |
+
.ta-phero { padding: 12px; }
|
| 1637 |
}
|
| 1638 |
/* The block gap already parts the hero from the top bar and the card under it, and the panel's
|
| 1639 |
edges line up with the cards below, so Gradio's padding around the block goes. */
|
|
|
|
| 1729 |
.ta-split > :focus-visible { outline: none; }
|
| 1730 |
.ta-split:has(:focus-visible) { outline: 2px solid var(--ta-accent); outline-offset: 2px; }
|
| 1731 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1732 |
|
| 1733 |
/* "Your Benchmark?" invite page: two "path" cards side by side. */
|
| 1734 |
.ta-paths {
|
|
|
|
| 1922 |
into the page's top-right corner, above the bar's actions; the bar steps down below it. */
|
| 1923 |
html:has(#huggingface-space-header) .ta-topbar { margin-top: 50px; }
|
| 1924 |
|
| 1925 |
+
/* A little air above a section that a link jumped to: the view bars, the selector cards, and the
|
| 1926 |
+
figure panels, addressed by prefix because their ids carry the subset they belong to. */
|
| 1927 |
+
#ta-views-anchor, #beyond-views-anchor, #ta-controls-anchor, #beyond-controls-anchor,
|
|
|
|
|
|
|
| 1928 |
[id^="ta-fig-"] { scroll-margin-top: 16px; }
|
| 1929 |
/* Anchor navigation is the only jump that works inside the Space (a scripted scroll cannot move
|
| 1930 |
a cross-origin parent), so the easing has to come from CSS rather than from `scrollIntoView`. */
|
|
|
|
| 2205 |
}
|
| 2206 |
"""
|
| 2207 |
|
| 2208 |
+
|
| 2209 |
+
def _view_rules(keys: list[str]) -> str:
|
| 2210 |
+
"""The rules that show one view and its notes: the one a page names in ``data-view``, the
|
| 2211 |
+
first until it names one."""
|
| 2212 |
+
pages = [(".ta-page:not([data-view])", keys[0])] + [(f'.ta-page[data-view="{key}"]', key) for key in keys]
|
| 2213 |
+
views = ",\n".join(f"{page} .ta-view:not(.ta-view-{key})" for page, key in pages)
|
| 2214 |
+
notes = ",\n".join(f'{page} .ta-viewnote:not([data-view="{key}"])' for page, key in pages)
|
| 2215 |
+
return f"{views} {{ display: none !important; }}\n{notes} {{ display: none; }}"
|
| 2216 |
+
|
| 2217 |
+
|
| 2218 |
+
CSS = CSS.replace("__TA_VIEW_RULES__", _view_rules([key for key, _label in website_texts.VIEW_TABS]))
|
| 2219 |
+
|
| 2220 |
# --- The opt-in light theme -------------------------------------------------
|
| 2221 |
# Everything `CSS` above draws in dark-theme colours, restated for a light page. Every selector
|
| 2222 |
# is scoped to `html.ta-light`, which only the top bar's theme toggle sets (`taSetTheme` in
|
|
|
|
| 2257 |
--ta-shadow: 0 1px 2px rgba(60, 50, 30, 0.08);
|
| 2258 |
--ta-tabarena: #c2410c;
|
| 2259 |
--ta-beyondarena: #0f766e;
|
|
|
|
| 2260 |
/* THEME points Gradio's light body pair at the dark values (see THEME below); the rest of
|
| 2261 |
its light theme is white, restated here on the soft surfaces. */
|
| 2262 |
--body-background-fill: var(--ta-page);
|
|
|
|
| 2330 |
html.ta-light .ta-theme-toggle .ta-ico-sun { display: none; }
|
| 2331 |
html.ta-light .ta-theme-toggle .ta-ico-moon { display: inline; }
|
| 2332 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2333 |
/* Figure panels and the full-table card. The figures inside stay on their white paper. */
|
| 2334 |
html.ta-light .ta-figpanel,
|
| 2335 |
html.ta-light .ta-tile,
|
|
|
|
| 2398 |
the same side; the script below does the rest. */
|
| 2399 |
:root { color-scheme: dark; }
|
| 2400 |
html, body, gradio-app { background: #0f0f11; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2401 |
/* The selector chip a shortcut picked (`.ta-sel .ta-chip.ta-flash` in `CSS`). */
|
| 2402 |
@keyframes ta-sel-flash {
|
| 2403 |
0%, 100% { box-shadow: 0 0 0 0 transparent; }
|
|
|
|
| 2627 |
tile.before(backdrop);
|
| 2628 |
tile.classList.add("ta-tile-max");
|
| 2629 |
tile.querySelector(".ta-expand").setAttribute("aria-pressed", "true");
|
|
|
|
|
|
|
| 2630 |
taSetBand(taBand);
|
| 2631 |
};
|
| 2632 |
function taCollapseTile(tile) {
|
|
|
|
| 2634 |
const btn = tile.querySelector(".ta-expand");
|
| 2635 |
if (btn) btn.setAttribute("aria-pressed", "false");
|
| 2636 |
document.querySelectorAll(".ta-tile-backdrop").forEach((backdrop) => backdrop.remove());
|
|
|
|
| 2637 |
}
|
| 2638 |
document.addEventListener("keydown", (ev) => {
|
| 2639 |
if (ev.key === "Escape") document.querySelectorAll(".ta-tile-max").forEach(taCollapseTile);
|
|
|
|
| 2809 |
const target = taTabButton(link.dataset.tab);
|
| 2810 |
if (target) target.click();
|
| 2811 |
const slug = link.dataset.slug;
|
| 2812 |
+
const params = new URLSearchParams(slug === window.taPageSlugs[0] ? "" : "tab=" + slug);
|
| 2813 |
+
const tabs = document.querySelector(`.ta-viewbar[data-page="${slug}"]`);
|
| 2814 |
+
const view = tabs && tabs.closest(".ta-page") && tabs.closest(".ta-page").dataset.view;
|
| 2815 |
+
if (view && view !== taFirstView()) params.set("view", view);
|
| 2816 |
+
const query = params.toString() ? "?" + params.toString() : "";
|
| 2817 |
try { history.replaceState(null, "", location.pathname + query + location.hash); } catch (err) {}
|
| 2818 |
if (window.parent !== window) {
|
| 2819 |
try { window.parent.postMessage({ queryString: query }, "https://huggingface.co"); } catch (err) {}
|
|
|
|
| 3217 |
});
|
| 3218 |
paint();
|
| 3219 |
};
|
| 3220 |
+
/* --- A page's views (views.view_bar) ----------------------------------------------------------
|
| 3221 |
+
Every view is on the page from the start; the page shows the one its `data-view` names (the
|
| 3222 |
+
stylesheet's view rules, the first until it names one). A tab switches it in the browser: the tabs mark the shown one, its explorers load (they wait until
|
| 3223 |
+
they are seen, `taLoadFrames`), tile captions are measured again now that they have a width
|
| 3224 |
+
(`taFitCaptions`), and the view goes into the address as `?view=<key>` (dropped for the first),
|
| 3225 |
+
inside the Space into the Hugging Face page's URL too, so the address opens it again. */
|
| 3226 |
+
function taFirstView() {
|
| 3227 |
+
const tab = document.querySelector(".ta-viewtab");
|
| 3228 |
+
return tab ? tab.dataset.view : "";
|
| 3229 |
+
}
|
| 3230 |
+
/* The tab bar is drawn again with every new selection (for its Follow list), so it marks the view
|
| 3231 |
+
the page already shows. */
|
| 3232 |
+
window.taSyncViewTabs = function (root) {
|
| 3233 |
+
const page = root.closest(".ta-page");
|
| 3234 |
+
const view = (page && page.dataset.view) || taFirstView();
|
| 3235 |
+
root.querySelectorAll(".ta-viewtab").forEach((tab) => {
|
| 3236 |
+
tab.setAttribute("aria-selected", String(tab.dataset.view === view));
|
| 3237 |
+
});
|
| 3238 |
+
if (page) taSyncFollow(page);
|
| 3239 |
+
};
|
| 3240 |
+
window.taShowView = function (page, view, record = true) {
|
| 3241 |
+
if (!page || !view) return;
|
| 3242 |
+
page.dataset.view = view;
|
| 3243 |
+
page.querySelectorAll(".ta-viewtab").forEach((tab) => {
|
| 3244 |
+
tab.setAttribute("aria-selected", String(tab.dataset.view === view));
|
| 3245 |
+
});
|
| 3246 |
+
window.taLoadFrames();
|
| 3247 |
+
taFitCaptions();
|
| 3248 |
+
if (record) taSetViewParam(view);
|
| 3249 |
+
};
|
| 3250 |
+
function taSetViewParam(view) {
|
| 3251 |
+
const params = new URLSearchParams(location.search);
|
| 3252 |
+
if (view && view !== taFirstView()) params.set("view", view);
|
| 3253 |
+
else params.delete("view");
|
| 3254 |
+
const query = params.toString() ? "?" + params.toString() : "";
|
| 3255 |
+
if (query === location.search) return;
|
| 3256 |
+
try { history.replaceState(null, "", location.pathname + query + location.hash); } catch (err) {}
|
| 3257 |
+
if (window.parent !== window) {
|
| 3258 |
+
try { window.parent.postMessage({ queryString: query }, "https://huggingface.co"); } catch (err) {}
|
| 3259 |
+
}
|
| 3260 |
+
}
|
| 3261 |
document.addEventListener("click", (event) => {
|
| 3262 |
const path = typeof event.composedPath === "function" ? event.composedPath() : [event.target];
|
| 3263 |
+
const tab = path.find((node) => node && node.matches && node.matches(".ta-viewtab"));
|
| 3264 |
+
if (tab) window.taShowView(tab.closest(".ta-page"), tab.dataset.view);
|
|
|
|
|
|
|
| 3265 |
}, true);
|
| 3266 |
+
/* A shared link's view belongs to the page the link names, which shows only once the server has
|
| 3267 |
+
selected it, so this waits for that page's tabs (up to 15 s); a name the page has no view for is
|
| 3268 |
+
dropped from the address. */
|
| 3269 |
+
(function taOpenLinkedView() {
|
| 3270 |
+
const params = new URLSearchParams(location.search);
|
| 3271 |
+
const view = params.get("view");
|
| 3272 |
+
if (!view || !/^[a-z0-9]+$/.test(view)) return;
|
| 3273 |
+
const slug = params.get("tab") || window.taPageSlugs[0];
|
| 3274 |
+
let tries = 0;
|
| 3275 |
+
const attempt = () => {
|
| 3276 |
+
const tab = document.querySelector(`.ta-viewbar[data-page="${slug}"] .ta-viewtab[data-view="${view}"]`);
|
| 3277 |
+
if (tab) window.taShowView(tab.closest(".ta-page"), view, false);
|
| 3278 |
+
else if (document.querySelector(`.ta-viewbar[data-page="${slug}"]`) || ++tries >= 60) taSetViewParam("");
|
| 3279 |
+
else setTimeout(attempt, 250);
|
| 3280 |
+
};
|
| 3281 |
+
attempt();
|
| 3282 |
+
})();
|
| 3283 |
/* Copy a block's text, as the citation dialog's button does. Where the clipboard is not offered
|
| 3284 |
(some embeds refuse it), the text is selected instead so the reader can copy it by hand. */
|
| 3285 |
window.taCopy = function (button, id) {
|
|
|
|
| 3313 |
document.addEventListener("click", (ev) => {
|
| 3314 |
if (ev.target.classList && ev.target.classList.contains("ta-dialog-overlay")) window.taCloseDialogs();
|
| 3315 |
});
|
| 3316 |
+
function taCloseMenus(except) {
|
| 3317 |
+
const open = "details.ta-dl[open], details.ta-follow-pick[open]";
|
| 3318 |
document.querySelectorAll(open).forEach((menu) => {
|
| 3319 |
if (menu !== except) menu.open = false;
|
| 3320 |
});
|
|
|
|
| 3322 |
document.addEventListener("keydown", (ev) => {
|
| 3323 |
if (ev.key !== "Escape") return;
|
| 3324 |
window.taCloseDialogs();
|
| 3325 |
+
taCloseMenus(null);
|
| 3326 |
});
|
| 3327 |
+
/* A pick closes a panel's download menu, and so does a click anywhere else. Clicks on its own
|
| 3328 |
+
summary are left to the browser, which opens and closes it. The Follow picker stays open
|
| 3329 |
+
through its picks, since it takes several. */
|
| 3330 |
document.addEventListener("click", (ev) => {
|
| 3331 |
+
const menus = "details.ta-dl, details.ta-follow-pick";
|
| 3332 |
const menu = ev.target.closest && ev.target.closest(menus);
|
| 3333 |
+
taCloseMenus(menu);
|
| 3334 |
+
if (menu && ev.target.closest(".ta-dl-menu button")) menu.open = false;
|
| 3335 |
});
|
| 3336 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3337 |
/* The visible band, written onto the elements pinned to it rather than onto :root. A custom
|
| 3338 |
property set on the root is inherited by every element on the page, so each scroll report
|
| 3339 |
restyled all six thousand of them (~15 ms) while the reader was scrolling, in the frame whose
|
| 3340 |
main thread also has to paint what scrolls into view; on these few it restyles only them.
|
| 3341 |
`taBand` keeps the numbers for the scripts below; null while our viewport is the screen,
|
| 3342 |
where the stylesheet's own defaults apply. */
|
| 3343 |
+
const TA_BAND_READERS = ".ta-dialog-overlay, .ta-tile-max, .ta-tile-backdrop, #ta-debug-readout";
|
| 3344 |
let taBand = null;
|
| 3345 |
function taSetBand(band) {
|
| 3346 |
taBand = band;
|
|
|
|
| 3356 |
taLoadFramesInBand();
|
| 3357 |
}
|
| 3358 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3359 |
/* --- Keep --ta-vp-top / --ta-vp-h on the visible band ----------------------
|
| 3360 |
Only does anything when this page's viewport is not the screen. Embedded in a Hugging Face
|
| 3361 |
Space it is not: HF sizes the Space iframe to the app's whole content, so the iframe never
|
| 3362 |
scrolls, the outer page does, and our viewport is the entire document. Everything pinned to a
|
| 3363 |
+
screen edge then pins to the top of a six-thousand-pixel page instead: opening a dialog
|
| 3364 |
+
blacks out the whole page with its content parked far above the screen.
|
|
|
|
| 3365 |
|
| 3366 |
The parent is cross-origin, so its scroll position is unreadable. IntersectionObserver's
|
| 3367 |
implicit root is the top-level viewport though, and it reports the intersection in *our*
|
|
|
|
| 3446 |
taSetBand(null);
|
| 3447 |
} else {
|
| 3448 |
taSetBand({ top: Math.round(top), h: Math.round(bottom - top) });
|
|
|
|
| 3449 |
}
|
| 3450 |
taReportViewport();
|
| 3451 |
}
|
|
|
|
| 3560 |
// then there are two scrollports rather than none. Both cases come out right here,
|
| 3561 |
// because a page that cannot scroll has `scrollY === 0` anyway.
|
| 3562 |
taSetBand({ top: Math.round(top), h: Math.round(bottom - top) });
|
|
|
|
| 3563 |
taReportViewport();
|
| 3564 |
}, { threshold: TA_STEPS });
|
| 3565 |
|
|
|
|
| 3580 |
// Coalesce a burst of mutations into one pass; the guards above make it idempotent.
|
| 3581 |
clearTimeout(window._taStampTimer);
|
| 3582 |
window._taStampTimer = setTimeout(() => {
|
|
|
|
| 3583 |
taTrackViewport();
|
| 3584 |
taSetBand(taBand);
|
| 3585 |
// A re-render brings fresh frames to load, a page switch a new page.
|
|
|
|
| 3592 |
taFitTopBar();
|
| 3593 |
}, 60);
|
| 3594 |
}).observe(document.body, { childList: true, subtree: true });
|
|
|
|
|
|
|
| 3595 |
document.addEventListener("DOMContentLoaded", () => {
|
|
|
|
| 3596 |
taTrackViewport();
|
| 3597 |
taReportViewport();
|
| 3598 |
taSyncThemeChip();
|
|
|
|
| 3671 |
/* How tall the reader's visible band is, for the per-dataset browser's "fit to screen" button.
|
| 3672 |
The frame cannot work this out for itself: it is sized to its own content, so its
|
| 3673 |
`innerHeight` is the length of its page rather than of the screen. We already track the band
|
| 3674 |
+
for the dialogs (`taBand`), so send that. */
|
| 3675 |
window.taSendPerDatasetViewport = function (frame) {
|
| 3676 |
if (frame.dataset.task === undefined) return;
|
| 3677 |
const height = taBand && taBand.h > 200 ? taBand.h : window.innerHeight;
|
|
|
|
| 3681 |
} catch (err) { /* not ready; it will ask again with its next height report */ }
|
| 3682 |
};
|
| 3683 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3684 |
/* --- Leaderboard table sorting ---------------------------------------------
|
| 3685 |
Click a header to sort the rows beneath it; click again to reverse. Numeric
|
| 3686 |
columns are marked `data-type="num"` and every cell carries the raw value in
|
|
@@ -8,8 +8,8 @@ hosted elsewhere). Adding a leaderboard is a one-entry edit to :data:`PAGES`.
|
|
| 8 |
|
| 9 |
from __future__ import annotations
|
| 10 |
|
| 11 |
-
import html
|
| 12 |
import itertools
|
|
|
|
| 13 |
from dataclasses import dataclass
|
| 14 |
from pathlib import Path
|
| 15 |
|
|
@@ -46,7 +46,6 @@ from views import (
|
|
| 46 |
METRIC_NOTES,
|
| 47 |
Choice,
|
| 48 |
ChoiceRow,
|
| 49 |
-
make_selection_bar,
|
| 50 |
METRIC_LABELS,
|
| 51 |
make_beyond_hero,
|
| 52 |
make_beyond_overview_figure,
|
|
@@ -54,16 +53,16 @@ from views import (
|
|
| 54 |
has_end_to_end,
|
| 55 |
make_tabarena_hero,
|
| 56 |
lb_spec,
|
| 57 |
-
open_doc,
|
| 58 |
follow_picker,
|
|
|
|
| 59 |
make_figure_grid,
|
| 60 |
make_leaderboard,
|
| 61 |
make_per_dataset_block,
|
| 62 |
metric_definitions_html,
|
| 63 |
picked,
|
| 64 |
render_markdown,
|
| 65 |
-
section_head,
|
| 66 |
selector_card,
|
|
|
|
| 67 |
)
|
| 68 |
|
| 69 |
|
|
@@ -316,31 +315,6 @@ def _render_control_band(
|
|
| 316 |
api_visibility="private",
|
| 317 |
)
|
| 318 |
|
| 319 |
-
# The bottom bar re-renders on any selector change, so it can never describe a stale view.
|
| 320 |
-
@gr.render(
|
| 321 |
-
inputs=[
|
| 322 |
-
entrants_state,
|
| 323 |
-
care_state,
|
| 324 |
-
metric_state,
|
| 325 |
-
tasks_state,
|
| 326 |
-
datasets_state,
|
| 327 |
-
impute_state,
|
| 328 |
-
splits_state,
|
| 329 |
-
commercial_state,
|
| 330 |
-
]
|
| 331 |
-
)
|
| 332 |
-
def _render_selection_bar(entrants, care, metric, tasks, datasets, imputation, splits, noncommercial):
|
| 333 |
-
make_selection_bar(
|
| 334 |
-
entrants=entrants,
|
| 335 |
-
care=care,
|
| 336 |
-
metric=metric,
|
| 337 |
-
tasks=tasks,
|
| 338 |
-
datasets=datasets,
|
| 339 |
-
imputation=imputation,
|
| 340 |
-
splits=splits,
|
| 341 |
-
include_noncommercial=noncommercial,
|
| 342 |
-
)
|
| 343 |
-
|
| 344 |
|
| 345 |
def render_internal_page(page: LeaderboardPage) -> None:
|
| 346 |
make_tabarena_hero(page.data_root, _tabarena_docs())
|
|
@@ -353,6 +327,21 @@ def render_internal_page(page: LeaderboardPage) -> None:
|
|
| 353 |
tasks_state = gr.State("all")
|
| 354 |
datasets_state = gr.State("all")
|
| 355 |
commercial_state = gr.State(True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 356 |
|
| 357 |
_render_control_band(
|
| 358 |
page.data_root,
|
|
@@ -366,105 +355,82 @@ def render_internal_page(page: LeaderboardPage) -> None:
|
|
| 366 |
commercial_state,
|
| 367 |
)
|
| 368 |
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 381 |
|
| 382 |
-
#
|
| 383 |
-
#
|
| 384 |
-
|
| 385 |
-
|
| 386 |
|
| 387 |
-
|
| 388 |
-
|
| 389 |
-
|
| 390 |
-
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
| 394 |
-
datasets_state,
|
| 395 |
-
commercial_state,
|
| 396 |
-
]
|
| 397 |
-
)
|
| 398 |
-
def _render_per_dataset(opened, ent, imp, spl, tsk, dst, noncommercial):
|
| 399 |
-
subset = Subset(entrants=ent, imputation=imp, splits=spl, tasks=tsk, datasets=dst)
|
| 400 |
-
lb = LBContainer(
|
| 401 |
-
data_root=page.data_root, subset=subset, name=subset_name(subset), include_noncommercial=noncommercial
|
| 402 |
-
)
|
| 403 |
-
toggle = make_per_dataset_block(lb, opened=opened, anchor="ta-perdataset-section")
|
| 404 |
-
toggle.click(lambda now: not now, per_dataset_open, per_dataset_open, api_visibility="private")
|
| 405 |
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
subset = Subset(entrants=ent, imputation=imp, splits=spl, tasks=tsk, datasets=dst)
|
| 420 |
-
lb = LBContainer(
|
| 421 |
-
data_root=page.data_root, subset=subset, name=subset_name(subset), include_noncommercial=noncommercial
|
| 422 |
-
)
|
| 423 |
-
# The table is the one file every published cell has; a folder alone can be an empty
|
| 424 |
-
# shell left by a skipped evaluation (a subset with no dataset of that task type).
|
| 425 |
-
if not (lb.base_path / "website_leaderboard.csv").is_file():
|
| 426 |
-
gr.HTML(section_head(website_texts.LB_TITLE, anchor="lb-detailed", hint=website_texts.LB_HINT))
|
| 427 |
-
gr.Markdown(website_texts.SUBSET_MISSING, elem_classes="ta-warnbox", container=False)
|
| 428 |
-
return
|
| 429 |
line, notes = lb_spec(lb)
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
)
|
| 435 |
-
|
| 436 |
)
|
| 437 |
-
|
| 438 |
-
# reference is for.
|
| 439 |
-
make_figure_grid(lb)
|
| 440 |
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
datasets_state,
|
| 448 |
-
commercial_state,
|
| 449 |
-
]
|
| 450 |
-
)
|
| 451 |
-
def _render_leaderboard_table(ent, imp, spl, tsk, dst, noncommercial):
|
| 452 |
-
subset = Subset(entrants=ent, imputation=imp, splits=spl, tasks=tsk, datasets=dst)
|
| 453 |
-
lb = LBContainer(
|
| 454 |
-
data_root=page.data_root, subset=subset, name=subset_name(subset), include_noncommercial=noncommercial
|
| 455 |
-
)
|
| 456 |
-
if not (lb.base_path / "website_leaderboard.csv").is_file():
|
| 457 |
-
return
|
| 458 |
-
make_leaderboard(lb)
|
| 459 |
|
| 460 |
|
| 461 |
def render_beyondarena_page(page: LeaderboardPage) -> None:
|
| 462 |
"""The BeyondArena leaderboard: four crossed filter axes, always on the ``core2k`` protocol.
|
| 463 |
|
| 464 |
-
The
|
| 465 |
-
|
| 466 |
-
|
| 467 |
-
the selected cell's ``data_beyondarena/subsets/split_*/size_*/features_*/tasks_*/``.
|
| 468 |
"""
|
| 469 |
# Graceful fallback until the artifacts are generated (see
|
| 470 |
# scripts/run_generate_beyondarena_website_artifacts.py in the tabarena repo).
|
|
@@ -485,31 +451,15 @@ def render_beyondarena_page(page: LeaderboardPage) -> None:
|
|
| 485 |
|
| 486 |
make_beyond_hero(page.data_root, _beyond_docs())
|
| 487 |
|
| 488 |
-
#
|
| 489 |
-
gr.HTML(
|
| 490 |
-
section_head(
|
| 491 |
-
website_texts.OVERVIEW_TITLE,
|
| 492 |
-
html.escape(website_texts.BEYOND_OVERVIEW_LINE),
|
| 493 |
-
hint=website_texts.BEYOND_OVERVIEW_HINT,
|
| 494 |
-
actions=(
|
| 495 |
-
'<span class="ta-section-links">'
|
| 496 |
-
f'<button type="button" class="ta-jump" onclick="{open_doc("beyondarena", "subsets")}">'
|
| 497 |
-
f"{website_texts.BEYOND_SUBSETS_LINK}</button>"
|
| 498 |
-
f'<a href="#beyond-lb-detailed" class="ta-jump">{website_texts.BEYOND_JUMP_DETAILS}</a></span>'
|
| 499 |
-
),
|
| 500 |
-
)
|
| 501 |
-
)
|
| 502 |
-
make_beyond_overview_figure(page.data_root)
|
| 503 |
-
|
| 504 |
-
# One state per filter axis, in BEYOND_AXES order, each starting on its "all" chip. Made here,
|
| 505 |
-
# above the control card that sets them, because the dataset browser under the overview reads
|
| 506 |
-
# them too.
|
| 507 |
axis_states = [gr.State("all") for _ in BEYOND_AXES]
|
| 508 |
care_state = gr.State("quality")
|
| 509 |
metric_state = gr.State("elo")
|
| 510 |
commercial_state = gr.State(True)
|
|
|
|
| 511 |
|
| 512 |
-
def _lb(
|
|
|
|
| 513 |
subset = BeyondSubset(**{field: key for (field, _caption, _labels), key in zip(BEYOND_AXES, keys, strict=True)})
|
| 514 |
return LBContainer(
|
| 515 |
data_root=page.data_root,
|
|
@@ -518,59 +468,51 @@ def render_beyondarena_page(page: LeaderboardPage) -> None:
|
|
| 518 |
include_noncommercial=noncommercial,
|
| 519 |
)
|
| 520 |
|
| 521 |
-
|
| 522 |
-
|
| 523 |
-
|
|
|
|
|
|
|
| 524 |
|
| 525 |
-
@gr.render(inputs=
|
| 526 |
-
def
|
| 527 |
-
|
| 528 |
-
lb = _lb(tuple(keys), noncommercial)
|
| 529 |
-
toggle = make_per_dataset_block(
|
| 530 |
-
lb,
|
| 531 |
-
opened=opened,
|
| 532 |
-
source_subset=BeyondSubset(),
|
| 533 |
-
filter_attrs=beyond_per_dataset_attrs(lb.subset),
|
| 534 |
-
anchor="beyond-perdataset-section",
|
| 535 |
-
)
|
| 536 |
-
toggle.click(lambda now: not now, per_dataset_open, per_dataset_open, api_visibility="private")
|
| 537 |
|
| 538 |
_render_beyond_control_band(page.data_root, axis_states, care_state, metric_state, commercial_state)
|
| 539 |
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
|
| 545 |
-
|
| 546 |
-
|
| 547 |
-
|
| 548 |
-
|
| 549 |
-
|
| 550 |
-
|
| 551 |
-
|
| 552 |
-
|
| 553 |
-
|
| 554 |
-
|
| 555 |
-
|
| 556 |
-
|
| 557 |
-
|
| 558 |
-
|
| 559 |
-
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
|
| 568 |
-
|
| 569 |
-
|
| 570 |
-
|
| 571 |
-
|
| 572 |
-
|
| 573 |
-
make_leaderboard(lb)
|
| 574 |
|
| 575 |
|
| 576 |
def _render_beyond_control_band(
|
|
|
|
| 8 |
|
| 9 |
from __future__ import annotations
|
| 10 |
|
|
|
|
| 11 |
import itertools
|
| 12 |
+
import re
|
| 13 |
from dataclasses import dataclass
|
| 14 |
from pathlib import Path
|
| 15 |
|
|
|
|
| 46 |
METRIC_NOTES,
|
| 47 |
Choice,
|
| 48 |
ChoiceRow,
|
|
|
|
| 49 |
METRIC_LABELS,
|
| 50 |
make_beyond_hero,
|
| 51 |
make_beyond_overview_figure,
|
|
|
|
| 53 |
has_end_to_end,
|
| 54 |
make_tabarena_hero,
|
| 55 |
lb_spec,
|
|
|
|
| 56 |
follow_picker,
|
| 57 |
+
VIEW_TILES,
|
| 58 |
make_figure_grid,
|
| 59 |
make_leaderboard,
|
| 60 |
make_per_dataset_block,
|
| 61 |
metric_definitions_html,
|
| 62 |
picked,
|
| 63 |
render_markdown,
|
|
|
|
| 64 |
selector_card,
|
| 65 |
+
view_bar,
|
| 66 |
)
|
| 67 |
|
| 68 |
|
|
|
|
| 315 |
api_visibility="private",
|
| 316 |
)
|
| 317 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 318 |
|
| 319 |
def render_internal_page(page: LeaderboardPage) -> None:
|
| 320 |
make_tabarena_hero(page.data_root, _tabarena_docs())
|
|
|
|
| 327 |
tasks_state = gr.State("all")
|
| 328 |
datasets_state = gr.State("all")
|
| 329 |
commercial_state = gr.State(True)
|
| 330 |
+
selection = [entrants_state, impute_state, splits_state, tasks_state, datasets_state, commercial_state]
|
| 331 |
+
|
| 332 |
+
def _lb(ent, imp, spl, tsk, dst, noncommercial) -> LBContainer:
|
| 333 |
+
subset = Subset(entrants=ent, imputation=imp, splits=spl, tasks=tsk, datasets=dst)
|
| 334 |
+
return LBContainer(
|
| 335 |
+
data_root=page.data_root, subset=subset, name=subset_name(subset), include_noncommercial=noncommercial
|
| 336 |
+
)
|
| 337 |
+
|
| 338 |
+
# -- The views' tabs, then the selector card joined under them, then the views. Every view is on
|
| 339 |
+
# the page from the start and the browser shows one (main.taShowView), so a tab switch costs no
|
| 340 |
+
# round trip; each view's content renders from the selection it follows. The tab bar renders
|
| 341 |
+
# with the selection too, for the Follow picker's list.
|
| 342 |
+
@gr.render(inputs=selection)
|
| 343 |
+
def _render_view_bar(*args):
|
| 344 |
+
_view_bar_block("tabarena", _lb(*args), website_texts.LB_HINT)
|
| 345 |
|
| 346 |
_render_control_band(
|
| 347 |
page.data_root,
|
|
|
|
| 355 |
commercial_state,
|
| 356 |
)
|
| 357 |
|
| 358 |
+
with gr.Column(elem_classes=["ta-view", "ta-view-leaderboard"]):
|
| 359 |
+
|
| 360 |
+
@gr.render(inputs=selection)
|
| 361 |
+
def _render_leaderboard(*args):
|
| 362 |
+
lb = _lb(*args)
|
| 363 |
+
if not _published(lb):
|
| 364 |
+
gr.Markdown(website_texts.SUBSET_MISSING, elem_classes="ta-warnbox", container=False)
|
| 365 |
+
return
|
| 366 |
+
make_figure_grid(lb, VIEW_TILES["leaderboard"])
|
| 367 |
+
make_leaderboard(lb, opened=True)
|
| 368 |
+
|
| 369 |
+
# The Summary across all subsets follows the selectors too: the column each one points at leads
|
| 370 |
+
# its group and is tinted, so the reader's own view is where their eye already is.
|
| 371 |
+
with gr.Column(elem_classes=["ta-view", "ta-view-summary"]):
|
| 372 |
+
|
| 373 |
+
@gr.render(inputs=[entrants_state, tasks_state, datasets_state, care_state, commercial_state])
|
| 374 |
+
def _render_overview(entrants, tasks, datasets, care, noncommercial):
|
| 375 |
+
make_cross_subset_overview(
|
| 376 |
+
page.data_root,
|
| 377 |
+
entrants=entrants,
|
| 378 |
+
tasks=tasks,
|
| 379 |
+
datasets=datasets,
|
| 380 |
+
care=care,
|
| 381 |
+
include_noncommercial=noncommercial,
|
| 382 |
+
)
|
| 383 |
|
| 384 |
+
# "I care about" and "Measured by" are not inputs of the figure views: their grids follow them
|
| 385 |
+
# in the browser.
|
| 386 |
+
for view in ("time", "h2h"):
|
| 387 |
+
with gr.Column(elem_classes=["ta-view", f"ta-view-{view}"]):
|
| 388 |
|
| 389 |
+
@gr.render(inputs=selection)
|
| 390 |
+
def _render_figures(*args, view=view):
|
| 391 |
+
lb = _lb(*args)
|
| 392 |
+
if not _published(lb):
|
| 393 |
+
gr.Markdown(website_texts.SUBSET_MISSING, elem_classes="ta-warnbox", container=False)
|
| 394 |
+
return
|
| 395 |
+
make_figure_grid(lb, VIEW_TILES[view])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
|
| 397 |
+
with gr.Column(elem_classes=["ta-view", "ta-view-datasets"]):
|
| 398 |
+
|
| 399 |
+
@gr.render(inputs=selection)
|
| 400 |
+
def _render_per_dataset(*args):
|
| 401 |
+
make_per_dataset_block(_lb(*args))
|
| 402 |
+
|
| 403 |
+
|
| 404 |
+
def _view_bar_block(slug: str, lb: LBContainer, hint: str) -> None:
|
| 405 |
+
"""A page's view tabs with Follow (views.view_bar), for the selection ``lb``; each tab's hover text
|
| 406 |
+
ends with what the selection covers, and a warning follows the tabs where it has one."""
|
| 407 |
+
if not _published(lb):
|
| 408 |
+
bar = view_bar(slug)
|
| 409 |
+
else:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 410 |
line, notes = lb_spec(lb)
|
| 411 |
+
warn = re.search(r'<span class="ta-head-warn".*?</span>', line)
|
| 412 |
+
bar = view_bar(
|
| 413 |
+
slug,
|
| 414 |
+
follow=follow_picker(lb),
|
| 415 |
+
hint=f"{re.sub(r'<[^>]+>', '', line)}. {hint} {notes}".strip(),
|
| 416 |
+
extra=warn.group(0) if warn else "",
|
| 417 |
)
|
| 418 |
+
gr.HTML(bar, js_on_load="taSyncViewTabs(element);", apply_default_css=False, elem_classes="ta-viewbar-block")
|
|
|
|
|
|
|
| 419 |
|
| 420 |
+
|
| 421 |
+
def _published(lb: LBContainer) -> bool:
|
| 422 |
+
"""Whether the selected cell has a leaderboard. The table is the one file every published cell
|
| 423 |
+
has; a folder alone can be an empty shell left by a skipped evaluation (a subset with no
|
| 424 |
+
dataset of that task type)."""
|
| 425 |
+
return (lb.base_path / "website_leaderboard.csv").is_file()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
|
| 427 |
|
| 428 |
def render_beyondarena_page(page: LeaderboardPage) -> None:
|
| 429 |
"""The BeyondArena leaderboard: four crossed filter axes, always on the ``core2k`` protocol.
|
| 430 |
|
| 431 |
+
The views are TabArena's, under the same tabs, except the Summary, which stays the two
|
| 432 |
+
``plot_subset_results`` images rather than TabArena's HTML table. The others read the selected
|
| 433 |
+
cell's ``data_beyondarena/subsets/split_*/size_*/features_*/tasks_*/``.
|
|
|
|
| 434 |
"""
|
| 435 |
# Graceful fallback until the artifacts are generated (see
|
| 436 |
# scripts/run_generate_beyondarena_website_artifacts.py in the tabarena repo).
|
|
|
|
| 451 |
|
| 452 |
make_beyond_hero(page.data_root, _beyond_docs())
|
| 453 |
|
| 454 |
+
# One state per filter axis, in BEYOND_AXES order, each starting on its "all" chip.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 455 |
axis_states = [gr.State("all") for _ in BEYOND_AXES]
|
| 456 |
care_state = gr.State("quality")
|
| 457 |
metric_state = gr.State("elo")
|
| 458 |
commercial_state = gr.State(True)
|
| 459 |
+
selection = [*axis_states, commercial_state]
|
| 460 |
|
| 461 |
+
def _lb(*args) -> LBContainer:
|
| 462 |
+
*keys, noncommercial = args
|
| 463 |
subset = BeyondSubset(**{field: key for (field, _caption, _labels), key in zip(BEYOND_AXES, keys, strict=True)})
|
| 464 |
return LBContainer(
|
| 465 |
data_root=page.data_root,
|
|
|
|
| 468 |
include_noncommercial=noncommercial,
|
| 469 |
)
|
| 470 |
|
| 471 |
+
def _missing(lb: LBContainer) -> None:
|
| 472 |
+
# The generator skips exactly the cells no dataset falls into, so a missing folder with
|
| 473 |
+
# filters set means an empty intersection, not a deployment gap.
|
| 474 |
+
missing = website_texts.BEYOND_CELL_EMPTY if lb.subset.filters else website_texts.SUBSET_MISSING
|
| 475 |
+
gr.Markdown(missing, elem_classes="ta-warnbox", container=False)
|
| 476 |
|
| 477 |
+
@gr.render(inputs=selection)
|
| 478 |
+
def _render_beyond_view_bar(*args):
|
| 479 |
+
_view_bar_block("beyondarena", _lb(*args), website_texts.BEYOND_LB_HINT)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 480 |
|
| 481 |
_render_beyond_control_band(page.data_root, axis_states, care_state, metric_state, commercial_state)
|
| 482 |
|
| 483 |
+
with gr.Column(elem_classes=["ta-view", "ta-view-leaderboard"]):
|
| 484 |
+
|
| 485 |
+
@gr.render(inputs=selection)
|
| 486 |
+
def _render_beyond_leaderboard(*args):
|
| 487 |
+
lb = _lb(*args)
|
| 488 |
+
if not _published(lb):
|
| 489 |
+
_missing(lb)
|
| 490 |
+
return
|
| 491 |
+
make_figure_grid(lb, VIEW_TILES["leaderboard"])
|
| 492 |
+
make_leaderboard(lb, opened=True)
|
| 493 |
+
|
| 494 |
+
# The Summary: the overview images, which hold every subset whatever is selected.
|
| 495 |
+
with gr.Column(elem_classes=["ta-view", "ta-view-summary"]):
|
| 496 |
+
make_beyond_overview_figure(page.data_root)
|
| 497 |
+
|
| 498 |
+
for view in ("time", "h2h"):
|
| 499 |
+
with gr.Column(elem_classes=["ta-view", f"ta-view-{view}"]):
|
| 500 |
+
|
| 501 |
+
@gr.render(inputs=selection)
|
| 502 |
+
def _render_beyond_figures(*args, view=view):
|
| 503 |
+
lb = _lb(*args)
|
| 504 |
+
if not _published(lb):
|
| 505 |
+
_missing(lb)
|
| 506 |
+
return
|
| 507 |
+
make_figure_grid(lb, VIEW_TILES[view])
|
| 508 |
+
|
| 509 |
+
# Per dataset: read from the "full" subset and told which slice is selected.
|
| 510 |
+
with gr.Column(elem_classes=["ta-view", "ta-view-datasets"]):
|
| 511 |
+
|
| 512 |
+
@gr.render(inputs=selection)
|
| 513 |
+
def _render_beyond_per_dataset(*args):
|
| 514 |
+
lb = _lb(*args)
|
| 515 |
+
make_per_dataset_block(lb, source_subset=BeyondSubset(), filter_attrs=beyond_per_dataset_attrs(lb.subset))
|
|
|
|
| 516 |
|
| 517 |
|
| 518 |
def _render_beyond_control_band(
|
|
@@ -419,8 +419,9 @@ def leaderboard_table_html(df: pd.DataFrame, columns: list[str], table_id: str)
|
|
| 419 |
)
|
| 420 |
|
| 421 |
|
| 422 |
-
def make_leaderboard(lb: LBContainer) -> None:
|
| 423 |
-
"""The full leaderboard table for one subset, as a card like the figure tiles
|
|
|
|
| 424 |
|
| 425 |
The table is a generated artifact (`leaderboard_table.html`, built by
|
| 426 |
`tabarena.plot.interactive.leaderboard_table`), embedded the same way as the
|
|
@@ -428,8 +429,8 @@ def make_leaderboard(lb: LBContainer) -> None:
|
|
| 428 |
family and variant colours, chip components and imputation markers rather than
|
| 429 |
reimplementing them here, where they drifted.
|
| 430 |
|
| 431 |
-
|
| 432 |
-
|
| 433 |
frame's own (``main.taLeaderboardCsv``): only the frame knows the current filters, columns and
|
| 434 |
sort order. On TabArena the frame is also told which methods the latest releases added, for
|
| 435 |
its "new" badges (``data-new``, ``main.taSendNew``).
|
|
@@ -452,12 +453,13 @@ def make_leaderboard(lb: LBContainer) -> None:
|
|
| 452 |
f'<section class="ta-tile ta-lbtile" id="{uid}" data-role="table"><div class="ta-figbar">'
|
| 453 |
f'<span class="ta-figbar-title" title="{caption}">{website_texts.TABLE_TITLE}</span>'
|
| 454 |
f'<span class="ta-figbar-sub" title="{caption}">{caption}</span><span class="ta-figbar-actions">'
|
| 455 |
-
'<button type="button" class="ta-viewbtn ta-csvbtn" hidden onclick="taLeaderboardCsv(this)" '
|
| 456 |
'title="Download the rows and columns shown, in the current sort order">Download CSV</button>'
|
| 457 |
-
'<button type="button" class="ta-viewbtn ta-tabletoggle" aria-expanded="
|
| 458 |
f'data-show="{website_texts.TABLE_SHOW}" data-hide="{website_texts.TABLE_HIDE}" '
|
| 459 |
-
f'onclick="taToggleTable(this)">{website_texts.TABLE_SHOW}</button>
|
| 460 |
-
|
|
|
|
| 461 |
padding=False,
|
| 462 |
apply_default_css=False,
|
| 463 |
elem_classes="ta-flush",
|
|
@@ -787,6 +789,14 @@ _TILES = (
|
|
| 787 |
)
|
| 788 |
|
| 789 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 790 |
def _figure_tiles(lb: LBContainer) -> list[_Tile]:
|
| 791 |
"""The tiles this subset has a figure for.
|
| 792 |
|
|
@@ -865,16 +875,17 @@ def _tile_html(lb: LBContainer, tile: _Tile) -> str:
|
|
| 865 |
)
|
| 866 |
|
| 867 |
|
| 868 |
-
def make_figure_grid(lb: LBContainer) -> None:
|
| 869 |
-
"""The subset's figures
|
| 870 |
-
scatter plots (the three Pareto fronts and the tuning
|
|
|
|
| 871 |
|
| 872 |
One HTML block, so "I care about" and "Measured by" reach it without a render: the page
|
| 873 |
carries the reader's choice as ``data-care`` / ``data-metric`` (``main.taSelector`` writes
|
| 874 |
them), the stylesheet orders the tiles from those, and ``main.taSendMetric`` tells each
|
| 875 |
explorer which metric to open on.
|
| 876 |
"""
|
| 877 |
-
tiles = _figure_tiles(lb)
|
| 878 |
no_total = "" if any(tile.key == "total" for tile in tiles) else " ta-no-total"
|
| 879 |
gr.HTML(
|
| 880 |
f'<div class="ta-figgrid{no_total}">' + "".join(_tile_html(lb, tile) for tile in tiles) + "</div>",
|
|
@@ -896,27 +907,17 @@ _PD_ICON = (
|
|
| 896 |
def make_per_dataset_block(
|
| 897 |
lb: LBContainer,
|
| 898 |
*,
|
| 899 |
-
opened: bool,
|
| 900 |
source_subset: Subset | BeyondSubset | None = None,
|
| 901 |
filter_attrs: str | None = None,
|
| 902 |
-
|
| 903 |
-
|
| 904 |
-
"""The per-dataset browser panel, returned so the caller can wire its show/hide button.
|
| 905 |
-
|
| 906 |
-
It hangs under the cross-subset overview, collapsed: both look across the whole benchmark.
|
| 907 |
-
``anchor`` is the id its header carries for the Jump to menu.
|
| 908 |
|
| 909 |
The artifact is published once per (entrants, imputation, splits) rather than for all 60
|
| 910 |
task/dataset cells: a dataset's own numbers do not depend on which *other* datasets share
|
| 911 |
its leaderboard, so the browser is read from the unrestricted cell and told which slice the
|
| 912 |
reader currently has selected. It filters itself from there, and the reader can widen it
|
| 913 |
-
again from inside without leaving the page.
|
| 914 |
-
|
| 915 |
-
The show/hide control lives in the panel's own title bar rather than in an accordion around
|
| 916 |
-
it: an accordion would wrap this panel in a second box with its own padding and its own
|
| 917 |
-
title, for one button. That button is HTML inside the bar, so it needs a real Gradio button
|
| 918 |
-
to reach the server (`main.taTogglePerDataset` clicks the hidden one) — the frame is only
|
| 919 |
-
built when ``opened``, since the page it embeds carries every dataset's results and is the
|
| 920 |
largest artifact the site ships.
|
| 921 |
|
| 922 |
``source_subset`` and ``filter_attrs`` are for BeyondArena, whose cells have no
|
|
@@ -937,44 +938,33 @@ def make_per_dataset_block(
|
|
| 937 |
f'data-size="{lb.subset.datasets if lb.subset.datasets in DATASET_SIZE_LABELS else "all"}" '
|
| 938 |
f'data-balance="{lb.subset.datasets if lb.subset.datasets in DATASET_DISTRIBUTION_LABELS else "all"}" '
|
| 939 |
)
|
| 940 |
-
url = source.html_url("per_dataset_explorer")
|
| 941 |
-
anchor = f' id="{anchor}"' if anchor else ""
|
| 942 |
teaser = html.escape(website_texts.PER_DATASET_TEASER, quote=True)
|
| 943 |
n = source.n_datasets
|
| 944 |
caption = website_texts.PER_DATASET_CAPTION.format(n=n) if n else website_texts.FIGURE_CAPTIONS["per_dataset"]
|
| 945 |
-
|
| 946 |
-
with gr.Column(elem_classes=["ta-figpanel", "ta-pdrawer"], elem_id=uid):
|
| 947 |
-
# The whole bar opens it (main.taPdBarClick); the button inside is what a keyboard reaches.
|
| 948 |
gr.HTML(
|
| 949 |
-
f'<div class="ta-figbar ta-
|
| 950 |
-
f"onclick=\"taPdBarClick(event, '{uid}')\">"
|
| 951 |
-
f'<span class="ta-pdicon" aria-hidden="true">{_PD_ICON}</span>'
|
| 952 |
-
f'<span class="ta-pdtext"><span class="ta-figbar-title" title="{teaser}">'
|
| 953 |
f"{website_texts.PER_DATASET_TITLE}</span>"
|
| 954 |
-
f'<span class="ta-figbar-sub">{html.escape(caption)}</span>
|
| 955 |
-
'<span class="ta-figbar-actions">'
|
| 956 |
-
+ (_download_menu(uid, "Download the chart") if opened and url else "")
|
| 957 |
-
+ f'<button type="button" class="ta-pdtoggle" aria-expanded="{str(opened).lower()}">{label}</button>'
|
| 958 |
-
+ "</span></div>"
|
| 959 |
)
|
| 960 |
-
|
| 961 |
-
if opened and url is None:
|
| 962 |
gr.HTML(f'<p class="ta-pd-teaser">{website_texts.PER_DATASET_MISSING}</p>')
|
| 963 |
-
|
| 964 |
-
|
| 965 |
-
|
| 966 |
-
|
| 967 |
-
|
| 968 |
-
|
| 969 |
-
|
| 970 |
-
|
| 971 |
-
|
| 972 |
-
|
| 973 |
-
|
| 974 |
-
|
| 975 |
-
)
|
| 976 |
)
|
| 977 |
-
|
| 978 |
|
| 979 |
|
| 980 |
# --------------------------------------------------------------------------- #
|
|
@@ -1441,12 +1431,11 @@ def selector_card(
|
|
| 1441 |
) -> gr.HTML:
|
| 1442 |
"""Every selector of a page, as one card of chips that answers a click at once.
|
| 1443 |
|
| 1444 |
-
The card starts closed, as
|
| 1445 |
-
button that opens it,
|
| 1446 |
-
|
| 1447 |
-
|
| 1448 |
-
|
| 1449 |
-
selection covers, open or closed. A click updates the card in the browser
|
| 1450 |
(main.taSelector): the chip, the dataset counts and the ``warnings``, as (selection
|
| 1451 |
field, value, headline, details in Markdown), each shown while that value is selected. The whole
|
| 1452 |
selection then goes to Python as one ``pick`` event, whose listener writes the page's states.
|
|
@@ -1462,7 +1451,7 @@ def selector_card(
|
|
| 1462 |
shortcuts = _selector_examples(rows, examples)
|
| 1463 |
if shortcuts:
|
| 1464 |
shortcuts = (
|
| 1465 |
-
f'<span class="ta-sel-try"
|
| 1466 |
f"{shortcuts}</span>"
|
| 1467 |
)
|
| 1468 |
# The whole bar opens and closes the card (main.taSelector); the title is the button a keyboard
|
|
@@ -1470,10 +1459,9 @@ def selector_card(
|
|
| 1470 |
bar = (
|
| 1471 |
'<div class="ta-figbar ta-pdbar ta-sel-bar">'
|
| 1472 |
f'<span class="ta-pdicon" aria-hidden="true">{_SELECTOR_ICON}</span>'
|
| 1473 |
-
'<span class="ta-pdtext"><span class="ta-sel-head">'
|
| 1474 |
'<h2 class="ta-figbar-title ta-sel-title"><button type="button" class="ta-sel-toggle" aria-expanded="false">'
|
| 1475 |
f'{html.escape(title)}<span class="ta-sel-chev" aria-hidden="true"></span></button></h2>'
|
| 1476 |
-
f
|
| 1477 |
)
|
| 1478 |
warns = "".join(
|
| 1479 |
f'<details class="ta-sel-warn" data-field="{field}" data-when="{value}" hidden>'
|
|
@@ -1492,7 +1480,7 @@ def selector_card(
|
|
| 1492 |
}
|
| 1493 |
return gr.HTML(
|
| 1494 |
f'<div class="ta-sel" data-page="{page}" data-open="false" data-config="{html.escape(json.dumps(data))}">'
|
| 1495 |
-
f'{bar}<div class="ta-sel-main">{body}</div>'
|
| 1496 |
'<div class="ta-sel-result" aria-live="polite">'
|
| 1497 |
'<p class="ta-sel-total"><b class="ta-sel-num"></b><span class="ta-sel-unit"></span></p></div>'
|
| 1498 |
f'<div class="ta-sel-warns">{warns}</div></div>',
|
|
@@ -1503,81 +1491,54 @@ def selector_card(
|
|
| 1503 |
)
|
| 1504 |
|
| 1505 |
|
| 1506 |
-
|
| 1507 |
-
|
| 1508 |
|
| 1509 |
-
The selection comes from the browser, so nothing in it is used before it is checked.
|
| 1510 |
-
"""
|
| 1511 |
-
return value if isinstance(value, str) and value in labels else next(iter(labels))
|
| 1512 |
|
|
|
|
|
|
|
|
|
|
| 1513 |
|
| 1514 |
-
|
| 1515 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1516 |
|
| 1517 |
|
| 1518 |
-
def
|
| 1519 |
-
|
| 1520 |
-
entrants: str,
|
| 1521 |
-
care: str,
|
| 1522 |
-
metric: str,
|
| 1523 |
-
tasks: str,
|
| 1524 |
-
datasets: str,
|
| 1525 |
-
imputation: str,
|
| 1526 |
-
splits: str,
|
| 1527 |
-
include_noncommercial: bool = True,
|
| 1528 |
-
) -> None:
|
| 1529 |
-
"""A fixed bar summarising the current selection, shown once the controls scroll away.
|
| 1530 |
|
| 1531 |
-
The
|
| 1532 |
-
nothing left saying which leaderboard you are reading. This restates it and links back up
|
| 1533 |
-
to the card. Read-only on purpose: a second set of live controls means two widgets per axis
|
| 1534 |
-
to keep in step, and the card is one scroll away. It also carries the page's "Jump to"
|
| 1535 |
-
menu, so the bar is the one element that floats over the page.
|
| 1536 |
"""
|
| 1537 |
-
|
| 1538 |
-
TASK_LABELS[tasks],
|
| 1539 |
-
DATASET_LABELS[datasets],
|
| 1540 |
-
_entrants_short(entrants),
|
| 1541 |
-
CARE_LABELS[care],
|
| 1542 |
-
METRIC_LABELS[metric],
|
| 1543 |
-
]
|
| 1544 |
-
if imputation == "no":
|
| 1545 |
-
parts.append("no imputed")
|
| 1546 |
-
if splits == "lite":
|
| 1547 |
-
parts.append("Lite")
|
| 1548 |
-
if not include_noncommercial:
|
| 1549 |
-
parts.append("commercial use only")
|
| 1550 |
-
chips = "".join(f'<span class="ta-selchip">{html.escape(p)}</span>' for p in parts)
|
| 1551 |
-
jumps = "".join(f'<a href="#{anchor}">{html.escape(label)}</a>' for anchor, label in website_texts.JUMP_LINKS)
|
| 1552 |
-
# The bar is TabArena's, as are its anchors.
|
| 1553 |
-
jumps += (
|
| 1554 |
-
f'<button type="button" onclick="{open_doc("tabarena", website_texts.AGENTS_TOPIC[0])}">'
|
| 1555 |
-
f"{html.escape(website_texts.JUMP_AGENTS)}</button>"
|
| 1556 |
-
f'<button type="button" onclick="taOpenDialog(\'{VERSION_HISTORY_TOGGLE}\')">'
|
| 1557 |
-
f"{html.escape(website_texts.VERSION_HISTORY_TITLE)}</button>"
|
| 1558 |
-
)
|
| 1559 |
-
# A link rather than a scripted scroll: inside the Space only `taJumpToAnchor` can move the
|
| 1560 |
-
# page the reader is looking at, and it acts on anchors.
|
| 1561 |
-
gr.HTML(
|
| 1562 |
-
'<div class="ta-selbar">'
|
| 1563 |
-
f'<a class="ta-selbar-view" href="#{CONTROLS_ANCHOR}" title="Back to the selectors">'
|
| 1564 |
-
'<span class="ta-selbar-lead">Viewing</span>'
|
| 1565 |
-
f"{chips}"
|
| 1566 |
-
'<span class="ta-selbar-go">change</span>'
|
| 1567 |
-
"</a>"
|
| 1568 |
-
f'<details class="ta-jumpmenu"><summary>Jump to</summary><div class="ta-jumpmenu-list">{jumps}</div></details>'
|
| 1569 |
-
"</div>",
|
| 1570 |
-
apply_default_css=False,
|
| 1571 |
-
elem_classes="ta-selbar-host",
|
| 1572 |
-
)
|
| 1573 |
|
| 1574 |
|
| 1575 |
-
|
| 1576 |
-
|
| 1577 |
-
selected = entrants_categories(key)
|
| 1578 |
-
if not selected:
|
| 1579 |
-
return "🤖 Models only"
|
| 1580 |
-
return "🤖 + " + " + ".join(SYSTEM_CATEGORY_LABELS[k].split(" ", 1)[0] for k in selected)
|
| 1581 |
|
| 1582 |
|
| 1583 |
def make_cross_subset_overview(
|
|
@@ -1588,7 +1549,7 @@ def make_cross_subset_overview(
|
|
| 1588 |
care: str = "quality",
|
| 1589 |
include_noncommercial: bool = True,
|
| 1590 |
) -> gr.HTML:
|
| 1591 |
-
"""The Summary: every entrant (rows) on every subset (columns), within one pool,
|
| 1592 |
|
| 1593 |
A row is one model *variant* — default, tuned, or tuned + ensembled — so its quality and its
|
| 1594 |
cost are always the same run's.
|
|
@@ -1879,9 +1840,8 @@ def make_cross_subset_overview(
|
|
| 1879 |
)
|
| 1880 |
|
| 1881 |
table = f'<table class="ta-xo" data-auto="{auto_open}">{header}<tbody>{"".join(body)}</tbody></table>'
|
| 1882 |
-
head = section_head(website_texts.OVERVIEW_TITLE, anchor="ta-overview-section", hint=website_texts.OVERVIEW_SUB)
|
| 1883 |
return gr.HTML(
|
| 1884 |
-
f'{
|
| 1885 |
js_on_load="taOverviewTable(element);",
|
| 1886 |
apply_default_css=False,
|
| 1887 |
elem_classes="ta-overview-block",
|
|
@@ -1889,9 +1849,8 @@ def make_cross_subset_overview(
|
|
| 1889 |
|
| 1890 |
|
| 1891 |
def _no_overview() -> gr.HTML:
|
| 1892 |
-
"""
|
| 1893 |
-
|
| 1894 |
-
return gr.HTML(f"{head}<p>No overview data available.</p>", elem_classes="ta-overview-block")
|
| 1895 |
|
| 1896 |
|
| 1897 |
#: An overview column as its hover text names it.
|
|
@@ -2108,12 +2067,6 @@ def _added_entrants(releases: Sequence[Release]) -> list[tuple[str, Release]]:
|
|
| 2108 |
return added
|
| 2109 |
|
| 2110 |
|
| 2111 |
-
def _newest_entrant(releases: Sequence[Release]) -> str:
|
| 2112 |
-
"""The entrant the newest release that adds one names, or "" when none does."""
|
| 2113 |
-
added = _added_entrants(releases)
|
| 2114 |
-
return added[0][0] if added else ""
|
| 2115 |
-
|
| 2116 |
-
|
| 2117 |
def _entrant_facts(df: pd.DataFrame) -> dict[str, str]:
|
| 2118 |
"""How many models and systems a leaderboard lists, a method counting once whatever its variants."""
|
| 2119 |
method = df["Model"].map(lambda m: parse_model(m)[0])
|
|
@@ -2137,27 +2090,13 @@ def _entrant_facts(df: pd.DataFrame) -> dict[str, str]:
|
|
| 2137 |
|
| 2138 |
|
| 2139 |
def hero_facts(data_root: Path) -> dict[str, str]:
|
| 2140 |
-
"""The numbers the TabArena hero quotes, read from the published data
|
| 2141 |
|
| 2142 |
Methods are counted in the widest entrant pool, so the hero names everything TabArena covers
|
| 2143 |
rather than whichever pool the page opens on.
|
| 2144 |
"""
|
| 2145 |
df = LBContainer(data_root, Subset(entrants=widest_entrants_key()), "").load_df()
|
| 2146 |
-
|
| 2147 |
-
updated = releases[0].when if releases else "—"
|
| 2148 |
-
newest = _newest_entrant(releases)
|
| 2149 |
-
if newest:
|
| 2150 |
-
fresh = website_texts.HERO_FRESH_NEWEST.format(newest=newest)
|
| 2151 |
-
else:
|
| 2152 |
-
fresh = website_texts.HERO_FRESH_UPDATED.format(updated=updated)
|
| 2153 |
-
return {
|
| 2154 |
-
"datasets": str(LBContainer(data_root, Subset(), "").n_datasets or "—"),
|
| 2155 |
-
**_entrant_facts(df),
|
| 2156 |
-
"releases": str(len(releases)),
|
| 2157 |
-
"since": f"{releases[-1].date:%b %Y}" if releases else "—",
|
| 2158 |
-
"updated": updated,
|
| 2159 |
-
"fresh": fresh,
|
| 2160 |
-
}
|
| 2161 |
|
| 2162 |
|
| 2163 |
def _dialog(toggle: str, label: str, body: str, *, cls: str, head: str = "") -> str:
|
|
@@ -2197,20 +2136,28 @@ def metric_definitions_html() -> str:
|
|
| 2197 |
|
| 2198 |
|
| 2199 |
def learn_more(
|
| 2200 |
-
toggle: str,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2201 |
) -> tuple[str, str]:
|
| 2202 |
"""A page's Learn more row and the dialog it opens, for (key, label, HTML) topics.
|
| 2203 |
|
| 2204 |
Every topic is in the page from the start, so a pill opens at once without a round trip to the
|
| 2205 |
server, and the tabs at the top of the dialog switch topic without closing it. Returned apart,
|
| 2206 |
-
so the row can sit inside a layout the dialog would otherwise add a gap to. ``
|
| 2207 |
-
link), ends the row as a highlighted link out,
|
|
|
|
| 2208 |
"""
|
| 2209 |
-
pills = ""
|
| 2210 |
-
|
| 2211 |
-
|
| 2212 |
-
|
| 2213 |
-
|
|
|
|
|
|
|
|
|
|
| 2214 |
if cta:
|
| 2215 |
cta_label, url = cta
|
| 2216 |
pills += (
|
|
@@ -2257,56 +2204,25 @@ def _team_dialog(toggle: str, title: str, team: Sequence[tuple[str, str]]) -> st
|
|
| 2257 |
return _dialog(toggle, title, body, cls="ta-dialog-team")
|
| 2258 |
|
| 2259 |
|
| 2260 |
-
def _hero_stat(
|
| 2261 |
-
value: str, label: str, line: str, hint: str, target: str, *, facts: dict[str, str], docs_toggle: str
|
| 2262 |
-
) -> str:
|
| 2263 |
-
"""One selling point: a big value, what it counts and a short line, opening its target.
|
| 2264 |
-
|
| 2265 |
-
A numeric value counts up when the hero first shows (the ``ta-count-up`` animation in main.py).
|
| 2266 |
-
"""
|
| 2267 |
-
value, label, line, hint = (part.format(**facts) for part in (value, label, line, hint))
|
| 2268 |
-
if value.isdigit():
|
| 2269 |
-
num = (
|
| 2270 |
-
f'<span class="ta-stat-num" data-count style="--ta-count-to: {value}">'
|
| 2271 |
-
f'<span class="ta-sr-only">{value}</span></span>'
|
| 2272 |
-
)
|
| 2273 |
-
else:
|
| 2274 |
-
num = f'<span class="ta-stat-num">{html.escape(value)}</span>'
|
| 2275 |
-
inner = (
|
| 2276 |
-
f'{num}<span class="ta-stat-text"><span class="ta-stat-lbl">{html.escape(label)}</span>'
|
| 2277 |
-
f'<span class="ta-stat-line">{html.escape(line)}</span></span>'
|
| 2278 |
-
)
|
| 2279 |
-
title = html.escape(hint)
|
| 2280 |
-
if target.startswith("doc:"):
|
| 2281 |
-
action = f"taOpenDoc('{docs_toggle}', '{target[4:]}')"
|
| 2282 |
-
return f'<button type="button" class="ta-stat" title="{title}" onclick="{action}">{inner}</button>'
|
| 2283 |
-
if target == "history":
|
| 2284 |
-
# The version history is the proof that the benchmark is alive, so its line has a live dot.
|
| 2285 |
-
action = f"taOpenDialog('{VERSION_HISTORY_TOGGLE}')"
|
| 2286 |
-
return f'<button type="button" class="ta-stat" data-live title="{title}" onclick="{action}">{inner}</button>'
|
| 2287 |
-
return f'<a class="ta-stat" href="{target}" target="_blank" rel="noopener noreferrer" title="{title}">{inner}</a>'
|
| 2288 |
-
|
| 2289 |
-
|
| 2290 |
def _page_hero(
|
| 2291 |
slug: str,
|
| 2292 |
facts: dict[str, str],
|
| 2293 |
*,
|
| 2294 |
-
eyebrow: str,
|
| 2295 |
lead: str,
|
| 2296 |
paper_url: str,
|
| 2297 |
citation: tuple[str, str],
|
| 2298 |
cta: tuple[str, str],
|
| 2299 |
team: tuple[str, Sequence[tuple[str, str]]],
|
| 2300 |
-
|
| 2301 |
docs: Sequence[tuple[str, str, str]],
|
| 2302 |
) -> gr.HTML:
|
| 2303 |
-
"""The top of a benchmark's page: what it is, its links, and
|
| 2304 |
|
| 2305 |
-
The
|
| 2306 |
-
|
| 2307 |
-
|
| 2308 |
-
|
| 2309 |
-
|
| 2310 |
"""
|
| 2311 |
name = website_texts.TOPBAR_NAV[slug][1]
|
| 2312 |
cite_toggle, team_toggle, docs_toggle = (_hero_toggle(slug, kind) for kind in ("cite", "team", "docs"))
|
|
@@ -2326,17 +2242,15 @@ def _page_hero(
|
|
| 2326 |
f'<span class="ta-avatars" aria-hidden="true">{avatars}</span>{html.escape(website_texts.HERO_TEAM_LABEL)}'
|
| 2327 |
"</button>"
|
| 2328 |
)
|
| 2329 |
-
|
| 2330 |
-
learn_row, docs_dialog = learn_more(docs_toggle, f"Learn more about {name}", docs, cta=cta)
|
| 2331 |
cite = f"<h2>Cite {html.escape(name)}</h2>" + citation_html(f"{cite_toggle}-bibtex", *citation)
|
| 2332 |
dialogs = _dialog(cite_toggle, f"Cite {name}", cite, cls="ta-dialog-cite")
|
| 2333 |
dialogs += _team_dialog(team_toggle, *team) + docs_dialog
|
| 2334 |
return gr.HTML(
|
| 2335 |
f'<section class="ta-phero" data-page="{slug}">'
|
| 2336 |
-
f'<span class="ta-phero-eyebrow">{html.escape(eyebrow)}</span>'
|
| 2337 |
f'<div class="ta-phero-head"><p class="ta-phero-lead">{_MARKDOWN.renderInline(lead)}</p>'
|
| 2338 |
f'<div class="ta-phero-links">{head}</div></div>'
|
| 2339 |
-
f'<div class="ta-stats">{band}</div>'
|
| 2340 |
f"{learn_row}"
|
| 2341 |
f"</section>{dialogs}",
|
| 2342 |
apply_default_css=False,
|
|
@@ -2349,13 +2263,12 @@ def make_tabarena_hero(data_root: Path, docs: Sequence[tuple[str, str, str]]) ->
|
|
| 2349 |
return _page_hero(
|
| 2350 |
"tabarena",
|
| 2351 |
hero_facts(data_root),
|
| 2352 |
-
eyebrow=website_texts.HERO_EYEBROW,
|
| 2353 |
lead=website_texts.HERO_LEAD,
|
| 2354 |
paper_url=website_texts.HERO_PAPER_URL,
|
| 2355 |
citation=(website_texts.CITATION_BUTTON_LABEL, website_texts.CITATION_BUTTON_TEXT),
|
| 2356 |
cta=website_texts.HERO_CTA,
|
| 2357 |
team=(website_texts.TEAM_TITLE, website_texts.TEAM),
|
| 2358 |
-
|
| 2359 |
docs=docs,
|
| 2360 |
)
|
| 2361 |
|
|
@@ -2587,13 +2500,12 @@ def make_beyond_hero(data_root: Path, docs: Sequence[tuple[str, str, str]]) -> g
|
|
| 2587 |
return _page_hero(
|
| 2588 |
"beyondarena",
|
| 2589 |
beyond_hero_facts(data_root),
|
| 2590 |
-
eyebrow=website_texts.BEYOND_HERO_EYEBROW,
|
| 2591 |
lead=website_texts.BEYOND_HERO_LEAD,
|
| 2592 |
paper_url=website_texts.BEYOND_HERO_PAPER_URL,
|
| 2593 |
citation=(website_texts.BEYOND_CITATION_BUTTON_LABEL, website_texts.BEYOND_CITATION_BUTTON_TEXT),
|
| 2594 |
cta=website_texts.BEYOND_HERO_CTA,
|
| 2595 |
team=(website_texts.BEYOND_TEAM_TITLE, website_texts.BEYOND_TEAM),
|
| 2596 |
-
|
| 2597 |
docs=docs,
|
| 2598 |
)
|
| 2599 |
|
|
@@ -2617,6 +2529,7 @@ def make_beyond_overview_figure(data_root: Path) -> None:
|
|
| 2617 |
unzip_png(result_dir, name),
|
| 2618 |
label=label,
|
| 2619 |
show_label=True,
|
|
|
|
| 2620 |
)
|
| 2621 |
shown = True
|
| 2622 |
if not shown:
|
|
|
|
| 419 |
)
|
| 420 |
|
| 421 |
|
| 422 |
+
def make_leaderboard(lb: LBContainer, *, opened: bool = False) -> None:
|
| 423 |
+
"""The full leaderboard table for one subset, as a card like the figure tiles, ``opened`` or
|
| 424 |
+
closed.
|
| 425 |
|
| 426 |
The table is a generated artifact (`leaderboard_table.html`, built by
|
| 427 |
`tabarena.plot.interactive.leaderboard_table`), embedded the same way as the
|
|
|
|
| 429 |
family and variant colours, chip components and imputation markers rather than
|
| 430 |
reimplementing them here, where they drifted.
|
| 431 |
|
| 432 |
+
Its button shows and hides it in the browser (``main.taToggleTable``); its frame loads only
|
| 433 |
+
while it is shown. The download sits in the card's header but is the
|
| 434 |
frame's own (``main.taLeaderboardCsv``): only the frame knows the current filters, columns and
|
| 435 |
sort order. On TabArena the frame is also told which methods the latest releases added, for
|
| 436 |
its "new" badges (``data-new``, ``main.taSendNew``).
|
|
|
|
| 453 |
f'<section class="ta-tile ta-lbtile" id="{uid}" data-role="table"><div class="ta-figbar">'
|
| 454 |
f'<span class="ta-figbar-title" title="{caption}">{website_texts.TABLE_TITLE}</span>'
|
| 455 |
f'<span class="ta-figbar-sub" title="{caption}">{caption}</span><span class="ta-figbar-actions">'
|
| 456 |
+
f'<button type="button" class="ta-viewbtn ta-csvbtn"{"" if opened else " hidden"} onclick="taLeaderboardCsv(this)" '
|
| 457 |
'title="Download the rows and columns shown, in the current sort order">Download CSV</button>'
|
| 458 |
+
f'<button type="button" class="ta-viewbtn ta-tabletoggle" aria-expanded="{str(opened).lower()}" '
|
| 459 |
f'data-show="{website_texts.TABLE_SHOW}" data-hide="{website_texts.TABLE_HIDE}" '
|
| 460 |
+
f'onclick="taToggleTable(this)">{website_texts.TABLE_HIDE if opened else website_texts.TABLE_SHOW}</button>'
|
| 461 |
+
"</span></div>"
|
| 462 |
+
f'<div class="ta-figview ta-lbtile-body"{"" if opened else " hidden"}>{frame}</div></section>',
|
| 463 |
padding=False,
|
| 464 |
apply_default_css=False,
|
| 465 |
elem_classes="ta-flush",
|
|
|
|
| 789 |
)
|
| 790 |
|
| 791 |
|
| 792 |
+
#: The figures of each view that shows them, by their ``_TILES`` keys.
|
| 793 |
+
VIEW_TILES = {
|
| 794 |
+
"leaderboard": ("overview",),
|
| 795 |
+
"time": ("infer", "total", "train", "trajectories"),
|
| 796 |
+
"h2h": ("winrate",),
|
| 797 |
+
}
|
| 798 |
+
|
| 799 |
+
|
| 800 |
def _figure_tiles(lb: LBContainer) -> list[_Tile]:
|
| 801 |
"""The tiles this subset has a figure for.
|
| 802 |
|
|
|
|
| 875 |
)
|
| 876 |
|
| 877 |
|
| 878 |
+
def make_figure_grid(lb: LBContainer, keys: Sequence[str]) -> None:
|
| 879 |
+
"""The subset's figures of one view, by their ``_TILES`` keys, as one grid: the overview and
|
| 880 |
+
the win rates span the width, the scatter plots (the three Pareto fronts and the tuning
|
| 881 |
+
trajectories) sit two to a row.
|
| 882 |
|
| 883 |
One HTML block, so "I care about" and "Measured by" reach it without a render: the page
|
| 884 |
carries the reader's choice as ``data-care`` / ``data-metric`` (``main.taSelector`` writes
|
| 885 |
them), the stylesheet orders the tiles from those, and ``main.taSendMetric`` tells each
|
| 886 |
explorer which metric to open on.
|
| 887 |
"""
|
| 888 |
+
tiles = [tile for tile in _figure_tiles(lb) if tile.key in keys]
|
| 889 |
no_total = "" if any(tile.key == "total" for tile in tiles) else " ta-no-total"
|
| 890 |
gr.HTML(
|
| 891 |
f'<div class="ta-figgrid{no_total}">' + "".join(_tile_html(lb, tile) for tile in tiles) + "</div>",
|
|
|
|
| 907 |
def make_per_dataset_block(
|
| 908 |
lb: LBContainer,
|
| 909 |
*,
|
|
|
|
| 910 |
source_subset: Subset | BeyondSubset | None = None,
|
| 911 |
filter_attrs: str | None = None,
|
| 912 |
+
) -> None:
|
| 913 |
+
"""The per-dataset browser, the page's Datasets view: a panel like the figure tiles, open.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 914 |
|
| 915 |
The artifact is published once per (entrants, imputation, splits) rather than for all 60
|
| 916 |
task/dataset cells: a dataset's own numbers do not depend on which *other* datasets share
|
| 917 |
its leaderboard, so the browser is read from the unrestricted cell and told which slice the
|
| 918 |
reader currently has selected. It filters itself from there, and the reader can widen it
|
| 919 |
+
again from inside without leaving the page. Its frame loads only once the view is shown
|
| 920 |
+
(main.taLoadFrames), since the page it embeds carries every dataset's results and is the
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 921 |
largest artifact the site ships.
|
| 922 |
|
| 923 |
``source_subset`` and ``filter_attrs`` are for BeyondArena, whose cells have no
|
|
|
|
| 938 |
f'data-size="{lb.subset.datasets if lb.subset.datasets in DATASET_SIZE_LABELS else "all"}" '
|
| 939 |
f'data-balance="{lb.subset.datasets if lb.subset.datasets in DATASET_DISTRIBUTION_LABELS else "all"}" '
|
| 940 |
)
|
| 941 |
+
url = source.html_url("per_dataset_explorer")
|
|
|
|
| 942 |
teaser = html.escape(website_texts.PER_DATASET_TEASER, quote=True)
|
| 943 |
n = source.n_datasets
|
| 944 |
caption = website_texts.PER_DATASET_CAPTION.format(n=n) if n else website_texts.FIGURE_CAPTIONS["per_dataset"]
|
| 945 |
+
with gr.Column(elem_classes="ta-figpanel", elem_id=uid):
|
|
|
|
|
|
|
| 946 |
gr.HTML(
|
| 947 |
+
f'<div class="ta-figbar"><span class="ta-figbar-title" title="{teaser}">'
|
|
|
|
|
|
|
|
|
|
| 948 |
f"{website_texts.PER_DATASET_TITLE}</span>"
|
| 949 |
+
f'<span class="ta-figbar-sub">{html.escape(caption)}</span>'
|
| 950 |
+
f'<span class="ta-figbar-actions">{_download_menu(uid, "Download the chart") if url else ""}</span></div>'
|
|
|
|
|
|
|
|
|
|
| 951 |
)
|
| 952 |
+
if url is None:
|
|
|
|
| 953 |
gr.HTML(f'<p class="ta-pd-teaser">{website_texts.PER_DATASET_MISSING}</p>')
|
| 954 |
+
return
|
| 955 |
+
# `-i` matches what `taExport` and `taPaperView` look for on the other panels.
|
| 956 |
+
with gr.Column(elem_id=f"{uid}-i", elem_classes=["ta-figview", "ta-figview-flush"]):
|
| 957 |
+
gr.HTML(
|
| 958 |
+
_explorer_frame(
|
| 959 |
+
url,
|
| 960 |
+
f"Per-dataset results, {lb.name}",
|
| 961 |
+
height=1020,
|
| 962 |
+
# Read back by `main.taSendPerDatasetFilter` once the frame reports its
|
| 963 |
+
# height, so the browser opens on the slice selected above it.
|
| 964 |
+
extra_attrs=filter_attrs,
|
| 965 |
+
exclude=lb.excluded_methods(),
|
|
|
|
| 966 |
)
|
| 967 |
+
)
|
| 968 |
|
| 969 |
|
| 970 |
# --------------------------------------------------------------------------- #
|
|
|
|
| 1431 |
) -> gr.HTML:
|
| 1432 |
"""Every selector of a page, as one card of chips that answers a click at once.
|
| 1433 |
|
| 1434 |
+
The card starts closed, as one row like the per-dataset browser's bar: its ``title``, which is the
|
| 1435 |
+
button that opens it, the ``examples`` (see :func:`_selector_examples`), shortcuts that pick a
|
| 1436 |
+
chip and open the card on it, and at its end how many datasets the selection covers, open or
|
| 1437 |
+
closed. Open, the ``lead`` heads the ``lines`` under the bar. Each line holds one row, or several
|
| 1438 |
+
that read as one choice, the later ones with their caption inline. A click updates the card in the browser
|
|
|
|
| 1439 |
(main.taSelector): the chip, the dataset counts and the ``warnings``, as (selection
|
| 1440 |
field, value, headline, details in Markdown), each shown while that value is selected. The whole
|
| 1441 |
selection then goes to Python as one ``pick`` event, whose listener writes the page's states.
|
|
|
|
| 1451 |
shortcuts = _selector_examples(rows, examples)
|
| 1452 |
if shortcuts:
|
| 1453 |
shortcuts = (
|
| 1454 |
+
f'<span class="ta-sel-try" role="group" aria-label="{html.escape(website_texts.SELECTOR_TRY)}">'
|
| 1455 |
f"{shortcuts}</span>"
|
| 1456 |
)
|
| 1457 |
# The whole bar opens and closes the card (main.taSelector); the title is the button a keyboard
|
|
|
|
| 1459 |
bar = (
|
| 1460 |
'<div class="ta-figbar ta-pdbar ta-sel-bar">'
|
| 1461 |
f'<span class="ta-pdicon" aria-hidden="true">{_SELECTOR_ICON}</span>'
|
|
|
|
| 1462 |
'<h2 class="ta-figbar-title ta-sel-title"><button type="button" class="ta-sel-toggle" aria-expanded="false">'
|
| 1463 |
f'{html.escape(title)}<span class="ta-sel-chev" aria-hidden="true"></span></button></h2>'
|
| 1464 |
+
f"{shortcuts}</div>"
|
| 1465 |
)
|
| 1466 |
warns = "".join(
|
| 1467 |
f'<details class="ta-sel-warn" data-field="{field}" data-when="{value}" hidden>'
|
|
|
|
| 1480 |
}
|
| 1481 |
return gr.HTML(
|
| 1482 |
f'<div class="ta-sel" data-page="{page}" data-open="false" data-config="{html.escape(json.dumps(data))}">'
|
| 1483 |
+
f'{bar}<div class="ta-sel-main"><p class="ta-sel-lead">{html.escape(lead)}</p>{body}</div>'
|
| 1484 |
'<div class="ta-sel-result" aria-live="polite">'
|
| 1485 |
'<p class="ta-sel-total"><b class="ta-sel-num"></b><span class="ta-sel-unit"></span></p></div>'
|
| 1486 |
f'<div class="ta-sel-warns">{warns}</div></div>',
|
|
|
|
| 1491 |
)
|
| 1492 |
|
| 1493 |
|
| 1494 |
+
#: The view bar's anchor per page.
|
| 1495 |
+
VIEW_ANCHORS = {"tabarena": "ta-views-anchor", "beyondarena": "beyond-views-anchor"}
|
| 1496 |
|
|
|
|
|
|
|
|
|
|
| 1497 |
|
| 1498 |
+
def view_bar(slug: str, *, follow: str = "", hint: str = "", extra: str = "") -> str:
|
| 1499 |
+
"""A page's view tabs (``website_texts.VIEW_TABS``), the top of its controls, with ``follow`` (the
|
| 1500 |
+
Follow picker, HTML) at the right.
|
| 1501 |
|
| 1502 |
+
Plain buttons: the browser shows the view a tab names (``main.taShowView``), every view being on
|
| 1503 |
+
the page from the start, so a switch costs no round trip, and marks the page's shown one
|
| 1504 |
+
whenever the bar is drawn again (``main.taSyncViewTabs``). A tab's hover text says what its view
|
| 1505 |
+
shows, ending with ``hint``, what the selection covers; ``extra`` (HTML) follows the tabs, such as
|
| 1506 |
+
a warning, and so does a note that only one view has, shown with it.
|
| 1507 |
+
"""
|
| 1508 |
+
hints = dict(website_texts.VIEW_HINTS)
|
| 1509 |
+
notes = {}
|
| 1510 |
+
if slug == "beyondarena":
|
| 1511 |
+
hints.update(website_texts.BEYOND_VIEW_HINTS)
|
| 1512 |
+
# Its Summary charts the subsets, whose meaning is a Learn more topic.
|
| 1513 |
+
notes["summary"] = (
|
| 1514 |
+
f'<button type="button" class="ta-viewnote-link" onclick="{open_doc("beyondarena", "subsets")}">'
|
| 1515 |
+
f"{html.escape(website_texts.BEYOND_SUBSETS_LINK)}</button>"
|
| 1516 |
+
)
|
| 1517 |
+
buttons = "".join(
|
| 1518 |
+
f'<button type="button" class="ta-viewtab" role="tab" data-view="{key}" '
|
| 1519 |
+
f'aria-selected="{str(i == 0).lower()}" '
|
| 1520 |
+
f'title="{html.escape(" ".join(part for part in (hints.get(key, ""), hint) if part), quote=True)}">'
|
| 1521 |
+
f"{html.escape(label)}</button>"
|
| 1522 |
+
for i, (key, label) in enumerate(website_texts.VIEW_TABS)
|
| 1523 |
+
)
|
| 1524 |
+
shown = "".join(f'<span class="ta-viewnote" data-view="{key}">{note}</span>' for key, note in notes.items())
|
| 1525 |
+
return (
|
| 1526 |
+
f'<div class="ta-viewbar" id="{VIEW_ANCHORS[slug]}" data-page="{slug}">'
|
| 1527 |
+
f'<nav class="ta-viewtabs" role="tablist" aria-label="Views">{buttons}</nav>'
|
| 1528 |
+
f'<p class="ta-viewnotes">{shown}{extra}</p>{follow}</div>'
|
| 1529 |
+
)
|
| 1530 |
|
| 1531 |
|
| 1532 |
+
def picked(value: object, labels: dict[str, str]) -> str:
|
| 1533 |
+
"""``value`` when it is one of the ``labels`` keys, else the first key (the row's default).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1534 |
|
| 1535 |
+
The selection comes from the browser, so nothing in it is used before it is checked.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1536 |
"""
|
| 1537 |
+
return value if isinstance(value, str) and value in labels else next(iter(labels))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1538 |
|
| 1539 |
|
| 1540 |
+
#: Anchor on TabArena's selector card.
|
| 1541 |
+
CONTROLS_ANCHOR = "ta-controls-anchor"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1542 |
|
| 1543 |
|
| 1544 |
def make_cross_subset_overview(
|
|
|
|
| 1549 |
care: str = "quality",
|
| 1550 |
include_noncommercial: bool = True,
|
| 1551 |
) -> gr.HTML:
|
| 1552 |
+
"""The Summary: every entrant (rows) on every subset (columns), within one pool, as one table.
|
| 1553 |
|
| 1554 |
A row is one model *variant* — default, tuned, or tuned + ensembled — so its quality and its
|
| 1555 |
cost are always the same run's.
|
|
|
|
| 1840 |
)
|
| 1841 |
|
| 1842 |
table = f'<table class="ta-xo" data-auto="{auto_open}">{header}<tbody>{"".join(body)}</tbody></table>'
|
|
|
|
| 1843 |
return gr.HTML(
|
| 1844 |
+
f'{_OVERVIEW_CSS}<div class="ta-xo-scroll">{table}</div>',
|
| 1845 |
js_on_load="taOverviewTable(element);",
|
| 1846 |
apply_default_css=False,
|
| 1847 |
elem_classes="ta-overview-block",
|
|
|
|
| 1849 |
|
| 1850 |
|
| 1851 |
def _no_overview() -> gr.HTML:
|
| 1852 |
+
"""A note in place of the overview, when its pool has no data."""
|
| 1853 |
+
return gr.HTML("<p>No overview data available.</p>", elem_classes="ta-overview-block")
|
|
|
|
| 1854 |
|
| 1855 |
|
| 1856 |
#: An overview column as its hover text names it.
|
|
|
|
| 2067 |
return added
|
| 2068 |
|
| 2069 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2070 |
def _entrant_facts(df: pd.DataFrame) -> dict[str, str]:
|
| 2071 |
"""How many models and systems a leaderboard lists, a method counting once whatever its variants."""
|
| 2072 |
method = df["Model"].map(lambda m: parse_model(m)[0])
|
|
|
|
| 2090 |
|
| 2091 |
|
| 2092 |
def hero_facts(data_root: Path) -> dict[str, str]:
|
| 2093 |
+
"""The numbers the TabArena hero quotes, read from the published data.
|
| 2094 |
|
| 2095 |
Methods are counted in the widest entrant pool, so the hero names everything TabArena covers
|
| 2096 |
rather than whichever pool the page opens on.
|
| 2097 |
"""
|
| 2098 |
df = LBContainer(data_root, Subset(entrants=widest_entrants_key()), "").load_df()
|
| 2099 |
+
return {"datasets": str(LBContainer(data_root, Subset(), "").n_datasets or "—"), **_entrant_facts(df)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2100 |
|
| 2101 |
|
| 2102 |
def _dialog(toggle: str, label: str, body: str, *, cls: str, head: str = "") -> str:
|
|
|
|
| 2136 |
|
| 2137 |
|
| 2138 |
def learn_more(
|
| 2139 |
+
toggle: str,
|
| 2140 |
+
label: str,
|
| 2141 |
+
topics: Sequence[tuple[str, str, str]],
|
| 2142 |
+
cta: tuple[str, str] | None = None,
|
| 2143 |
+
hints: dict[str, str] | None = None,
|
| 2144 |
) -> tuple[str, str]:
|
| 2145 |
"""A page's Learn more row and the dialog it opens, for (key, label, HTML) topics.
|
| 2146 |
|
| 2147 |
Every topic is in the page from the start, so a pill opens at once without a round trip to the
|
| 2148 |
server, and the tabs at the top of the dialog switch topic without closing it. Returned apart,
|
| 2149 |
+
so the row can sit inside a layout the dialog would otherwise add a gap to. ``hints`` maps a
|
| 2150 |
+
topic to its pill's hover text. ``cta``, as (label, link), ends the row as a highlighted link out,
|
| 2151 |
+
which also draws the eye to the pills.
|
| 2152 |
"""
|
| 2153 |
+
pills = ""
|
| 2154 |
+
for key, name, _ in topics:
|
| 2155 |
+
hint = (hints or {}).get(key)
|
| 2156 |
+
title = f' title="{html.escape(hint)}"' if hint else ""
|
| 2157 |
+
pills += (
|
| 2158 |
+
f'<button type="button" class="ta-learn-pill"{title} onclick="taOpenDoc(\'{toggle}\', \'{key}\')">'
|
| 2159 |
+
f"{html.escape(name)}</button>"
|
| 2160 |
+
)
|
| 2161 |
if cta:
|
| 2162 |
cta_label, url = cta
|
| 2163 |
pills += (
|
|
|
|
| 2204 |
return _dialog(toggle, title, body, cls="ta-dialog-team")
|
| 2205 |
|
| 2206 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2207 |
def _page_hero(
|
| 2208 |
slug: str,
|
| 2209 |
facts: dict[str, str],
|
| 2210 |
*,
|
|
|
|
| 2211 |
lead: str,
|
| 2212 |
paper_url: str,
|
| 2213 |
citation: tuple[str, str],
|
| 2214 |
cta: tuple[str, str],
|
| 2215 |
team: tuple[str, Sequence[tuple[str, str]]],
|
| 2216 |
+
hints: dict[str, str],
|
| 2217 |
docs: Sequence[tuple[str, str, str]],
|
| 2218 |
) -> gr.HTML:
|
| 2219 |
+
"""The top of a benchmark's page: what it is, its links, and the topics to learn more.
|
| 2220 |
|
| 2221 |
+
The Learn more pills' ``hints`` quote ``facts`` read from the data, so the numbers in them cannot
|
| 2222 |
+
drift from what the page shows. The citation (``citation`` is its label and BibTeX), the
|
| 2223 |
+
team (``team`` is its title and members) and the ``docs`` topics open as dialogs rather than
|
| 2224 |
+
panels on the page, and ``cta`` ends the Learn more row. The hero takes its name from the page's
|
| 2225 |
+
link in the top bar and its colour from ``slug``.
|
| 2226 |
"""
|
| 2227 |
name = website_texts.TOPBAR_NAV[slug][1]
|
| 2228 |
cite_toggle, team_toggle, docs_toggle = (_hero_toggle(slug, kind) for kind in ("cite", "team", "docs"))
|
|
|
|
| 2242 |
f'<span class="ta-avatars" aria-hidden="true">{avatars}</span>{html.escape(website_texts.HERO_TEAM_LABEL)}'
|
| 2243 |
"</button>"
|
| 2244 |
)
|
| 2245 |
+
hints = {key: hint.format(**facts) for key, hint in hints.items()}
|
| 2246 |
+
learn_row, docs_dialog = learn_more(docs_toggle, f"Learn more about {name}", docs, cta=cta, hints=hints)
|
| 2247 |
cite = f"<h2>Cite {html.escape(name)}</h2>" + citation_html(f"{cite_toggle}-bibtex", *citation)
|
| 2248 |
dialogs = _dialog(cite_toggle, f"Cite {name}", cite, cls="ta-dialog-cite")
|
| 2249 |
dialogs += _team_dialog(team_toggle, *team) + docs_dialog
|
| 2250 |
return gr.HTML(
|
| 2251 |
f'<section class="ta-phero" data-page="{slug}">'
|
|
|
|
| 2252 |
f'<div class="ta-phero-head"><p class="ta-phero-lead">{_MARKDOWN.renderInline(lead)}</p>'
|
| 2253 |
f'<div class="ta-phero-links">{head}</div></div>'
|
|
|
|
| 2254 |
f"{learn_row}"
|
| 2255 |
f"</section>{dialogs}",
|
| 2256 |
apply_default_css=False,
|
|
|
|
| 2263 |
return _page_hero(
|
| 2264 |
"tabarena",
|
| 2265 |
hero_facts(data_root),
|
|
|
|
| 2266 |
lead=website_texts.HERO_LEAD,
|
| 2267 |
paper_url=website_texts.HERO_PAPER_URL,
|
| 2268 |
citation=(website_texts.CITATION_BUTTON_LABEL, website_texts.CITATION_BUTTON_TEXT),
|
| 2269 |
cta=website_texts.HERO_CTA,
|
| 2270 |
team=(website_texts.TEAM_TITLE, website_texts.TEAM),
|
| 2271 |
+
hints=website_texts.HERO_HINTS,
|
| 2272 |
docs=docs,
|
| 2273 |
)
|
| 2274 |
|
|
|
|
| 2500 |
return _page_hero(
|
| 2501 |
"beyondarena",
|
| 2502 |
beyond_hero_facts(data_root),
|
|
|
|
| 2503 |
lead=website_texts.BEYOND_HERO_LEAD,
|
| 2504 |
paper_url=website_texts.BEYOND_HERO_PAPER_URL,
|
| 2505 |
citation=(website_texts.BEYOND_CITATION_BUTTON_LABEL, website_texts.BEYOND_CITATION_BUTTON_TEXT),
|
| 2506 |
cta=website_texts.BEYOND_HERO_CTA,
|
| 2507 |
team=(website_texts.BEYOND_TEAM_TITLE, website_texts.BEYOND_TEAM),
|
| 2508 |
+
hints=website_texts.BEYOND_HERO_HINTS,
|
| 2509 |
docs=docs,
|
| 2510 |
)
|
| 2511 |
|
|
|
|
| 2529 |
unzip_png(result_dir, name),
|
| 2530 |
label=label,
|
| 2531 |
show_label=True,
|
| 2532 |
+
elem_classes="ta-view-card",
|
| 2533 |
)
|
| 2534 |
shown = True
|
| 2535 |
if not shown:
|
|
@@ -29,20 +29,32 @@ VERSION_HISTORY_TITLE = "Version history"
|
|
| 29 |
VERSION_HISTORY_HINT = "Version history: what changed in each release"
|
| 30 |
VERSION_HISTORY_SUB = "Every change to the leaderboard, newest first."
|
| 31 |
|
| 32 |
-
# The
|
| 33 |
-
#
|
| 34 |
-
|
| 35 |
-
("
|
| 36 |
-
("
|
| 37 |
-
("
|
| 38 |
-
("
|
|
|
|
| 39 |
]
|
| 40 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
# --- The page heroes (views.make_tabarena_hero, views.make_beyond_hero) -------
|
| 43 |
-
# What the benchmark is, in one sentence (`**…**` is bold).
|
| 44 |
-
# Heads the hero, which is the page's background: what the benchmark is, before its results.
|
| 45 |
-
HERO_EYEBROW = "Meet our benchmark"
|
| 46 |
HERO_LEAD = (
|
| 47 |
"**TabArena-v0.1** is a living benchmark for predictive machine learning on IID tabular data, built to "
|
| 48 |
"measure the peak performance of model-specific pipelines."
|
|
@@ -54,49 +66,16 @@ HERO_TEAM_LABEL = "Team"
|
|
| 54 |
HERO_PAPER_URL = "https://tabarena.ai/paper-tabular-ml-iid-study"
|
| 55 |
# The call to submit, as (label, link): the highlighted pill that ends the Learn more row.
|
| 56 |
HERO_CTA = ("Benchmark your model", "https://tabarena.ai/code-examples")
|
| 57 |
-
# The
|
| 58 |
-
#
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
(
|
| 62 |
-
"{
|
| 63 |
-
"
|
| 64 |
-
"
|
| 65 |
-
"Hand-picked from 1,053 real-world candidates for IID tabular data",
|
| 66 |
-
"doc:datasets",
|
| 67 |
),
|
| 68 |
-
|
| 69 |
-
"{methods}",
|
| 70 |
-
"{methods_label}",
|
| 71 |
-
"each tuned to its peak",
|
| 72 |
-
(
|
| 73 |
-
"{entrants}, run on the same protocol and budget. Every model is scored at its default, "
|
| 74 |
-
"tuned, and as an ensemble of tuned configurations"
|
| 75 |
-
),
|
| 76 |
-
"doc:models",
|
| 77 |
-
),
|
| 78 |
-
(
|
| 79 |
-
"{releases}",
|
| 80 |
-
"live updates",
|
| 81 |
-
"{fresh}",
|
| 82 |
-
"{releases} releases since {since}, as new models join. Last update: {updated}",
|
| 83 |
-
"history",
|
| 84 |
-
),
|
| 85 |
-
(
|
| 86 |
-
"Open",
|
| 87 |
-
"source & data",
|
| 88 |
-
"verified implementations",
|
| 89 |
-
(
|
| 90 |
-
"The code, the datasets and every prediction are public, and {verified} of the {models} "
|
| 91 |
-
"models are verified by their authors or the maintainers"
|
| 92 |
-
),
|
| 93 |
-
TOPBAR_CODE_URL,
|
| 94 |
-
),
|
| 95 |
-
]
|
| 96 |
-
# The third selling point's line on TabArena: the newest entrant in the version history, or the date of the
|
| 97 |
-
# last update when no release names one.
|
| 98 |
-
HERO_FRESH_NEWEST = "newest: {newest}"
|
| 99 |
-
HERO_FRESH_UPDATED = "last update {updated}"
|
| 100 |
|
| 101 |
# The "Learn more" row: each topic opens one dialog, which switches between them.
|
| 102 |
LEARN_MORE_LABEL = "Learn more"
|
|
@@ -234,14 +213,7 @@ benchmark should not rank as if it covered all of it.
|
|
| 234 |
**Repeats:** Toggle *TabArena-Lite* to score each experiment on a single repeat instead of several. It is
|
| 235 |
noisier than the full setting, but much cheaper to compute and usually close enough to be worth it.
|
| 236 |
"""
|
| 237 |
-
# --- The summary table (views.make_cross_subset_overview) ----------
|
| 238 |
-
OVERVIEW_TITLE = "Summary"
|
| 239 |
-
# The title's hover text.
|
| 240 |
-
OVERVIEW_SUB = (
|
| 241 |
-
"Every method variant on every task and dataset subset: the quickest way to tell the ones that are "
|
| 242 |
-
"strong everywhere from those that shine on one subset, and to see what tuning buys. Per subset, "
|
| 243 |
-
"with imputation, over all repeats."
|
| 244 |
-
)
|
| 245 |
# The search at the heading's right, which keeps the rows whose name holds its text.
|
| 246 |
OVERVIEW_FIND = "Find a method"
|
| 247 |
# The table's two metrics, as (headline column name, the name a breakdown's switch shows).
|
|
@@ -253,14 +225,14 @@ OVERVIEW_STUB = "{n} subsets"
|
|
| 253 |
OVERVIEW_FOLD = "Fold these columns"
|
| 254 |
|
| 255 |
# --- The selector card (views.selector_card) ---------------------------------
|
| 256 |
-
SELECTOR_TITLE = "Customize
|
| 257 |
SELECTOR_SUB = "Every number below is relative to who competes and which datasets count."
|
| 258 |
BEYOND_SELECTOR_SUB = "Every number below is relative to the datasets compared, so each subset is its own evaluation."
|
| 259 |
-
# The bar's shortcuts into the card
|
| 260 |
-
# picks that chip of the row and opens the card on it, a second click undoes
|
| 261 |
-
# the value can be a tuple of chips turned on together; a switch names itself as
|
| 262 |
-
# state the shortcut puts it in as the value. Chips that cannot be picked yet are left out.
|
| 263 |
-
SELECTOR_TRY = "Make it yours
|
| 264 |
SELECTOR_EXAMPLES = [
|
| 265 |
(
|
| 266 |
"Add systems",
|
|
@@ -363,24 +335,12 @@ SYSTEM_WARNINGS = {
|
|
| 363 |
}
|
| 364 |
|
| 365 |
# --- Section headings (views.section_head) ----------------------------------
|
| 366 |
-
#
|
| 367 |
-
|
| 368 |
-
LB_TITLE = "Your leaderboard"
|
| 369 |
-
LB_HINT = (
|
| 370 |
-
"The full picture for the leaderboard selected above: how tuning moves each method, the "
|
| 371 |
-
"accuracy-versus-time trade-off, and the complete table."
|
| 372 |
-
)
|
| 373 |
BEYOND_LB_HINT = LB_HINT + " Every BeyondArena leaderboard is computed on the core2k protocol."
|
| 374 |
PER_DATASET_TITLE = "Dataset by dataset"
|
| 375 |
-
#
|
| 376 |
-
# datasets the browser covers.
|
| 377 |
PER_DATASET_CAPTION = "Where each method wins and loses, on each of the {n} datasets"
|
| 378 |
-
PER_DATASET_OPEN = "Explore all {n} datasets ▾"
|
| 379 |
-
PER_DATASET_HIDE = "Hide ▴"
|
| 380 |
-
# BeyondArena's overview figures, above its selector.
|
| 381 |
-
BEYOND_OVERVIEW_LINE = "Best result per model and per model family on every BeyondArena subset"
|
| 382 |
-
BEYOND_OVERVIEW_HINT = "The quickest way to see which methods hold up beyond the IID assumption."
|
| 383 |
-
BEYOND_JUMP_DETAILS = "Jump to your leaderboard"
|
| 384 |
# What each figure panel shows, in its header beside the title.
|
| 385 |
FIGURE_CAPTIONS = {
|
| 386 |
"overview": "Each method at its default, tuned, and tuned + ensembled settings",
|
|
@@ -624,7 +584,6 @@ under 0.5 s per 1000 rows?"*
|
|
| 624 |
# BeyondArena is the second internal leaderboard: the first unified benchmark for
|
| 625 |
# tabular data that goes beyond the IID assumption. Copy mirrors the TabArena
|
| 626 |
# HERO_* / OVERVIEW_* / CITATION_* structure, plus a Subsets topic, with BeyondArena specifics.
|
| 627 |
-
BEYOND_HERO_EYEBROW = "Meet our benchmark"
|
| 628 |
BEYOND_HERO_LEAD = (
|
| 629 |
"**BeyondArena** is the first unified benchmark for tabular data beyond the IID assumption, with "
|
| 630 |
"IID, temporal and grouped splits across dataset sizes and feature types."
|
|
@@ -641,44 +600,18 @@ BEYOND_TEAM = [
|
|
| 641 |
("Alan Arazi", "alanarazi7"),
|
| 642 |
]
|
| 643 |
BEYOND_HERO_CTA = ("Benchmark your model", "https://github.com/autogluon/tabarena/tree/main/examples/beyondarena")
|
| 644 |
-
# As
|
| 645 |
-
|
| 646 |
-
(
|
| 647 |
-
"{datasets}
|
| 648 |
-
"
|
| 649 |
-
"IID, temporal & grouped splits",
|
| 650 |
-
(
|
| 651 |
-
"Split at random, by time or by group, from tiny to large and with text or high-cardinality "
|
| 652 |
-
"columns. Every leaderboard uses the core2k protocol: 2,000 splits over all {datasets} datasets"
|
| 653 |
-
),
|
| 654 |
-
"doc:datasets",
|
| 655 |
-
),
|
| 656 |
-
(
|
| 657 |
-
"{subsets}",
|
| 658 |
-
"subsets to combine",
|
| 659 |
-
"by split, size, features & task",
|
| 660 |
-
"Pick one chip per row in the selector below, and each combination is its own leaderboard",
|
| 661 |
-
"doc:subsets",
|
| 662 |
),
|
| 663 |
-
|
| 664 |
-
|
| 665 |
-
"{
|
| 666 |
-
"
|
| 667 |
-
"{entrants}, each scored at its default, tuned, and as an ensemble of tuned configurations",
|
| 668 |
-
"doc:models",
|
| 669 |
-
),
|
| 670 |
-
(
|
| 671 |
-
"Open",
|
| 672 |
-
"source & data",
|
| 673 |
-
"built on TabArena's code",
|
| 674 |
-
(
|
| 675 |
-
"The code, the datasets and every prediction are public, BeyondArena runs on TabArena's "
|
| 676 |
-
"experiment and evaluation code, and {verified} of the {models} models are verified by their "
|
| 677 |
-
"authors or the maintainers"
|
| 678 |
-
),
|
| 679 |
-
TOPBAR_CODE_URL,
|
| 680 |
),
|
| 681 |
-
|
| 682 |
|
| 683 |
BEYOND_OVERVIEW_DATASETS = """
|
| 684 |
BeyondArena is built on a curated collection of **142 datasets** that deliberately go **beyond the IID
|
|
@@ -730,7 +663,7 @@ everywhere. A `[X% IMPUTED]` tag marks affected models.
|
|
| 730 |
|
| 731 |
# The Subsets topic of the Learn more dialog, also opened from the overview figures (whose axes name
|
| 732 |
# the subsets) by this link.
|
| 733 |
-
BEYOND_SUBSETS_LINK = "
|
| 734 |
BEYOND_SUBSETS_EXPLAINER = """
|
| 735 |
BeyondArena is sliced into **curated subsets** so you can see how methods hold up *beyond* the IID
|
| 736 |
assumption, and specifically on the kinds of data where an average hides big differences.
|
|
|
|
| 29 |
VERSION_HISTORY_HINT = "Version history: what changed in each release"
|
| 30 |
VERSION_HISTORY_SUB = "Every change to the leaderboard, newest first."
|
| 31 |
|
| 32 |
+
# The views of a benchmark page, as tabs at the top of its controls (views.view_bar), as (key, tab
|
| 33 |
+
# label). The first, the Summary, is the default, and `?view=<key>` opens another.
|
| 34 |
+
VIEW_TABS = [
|
| 35 |
+
("summary", "Summary"),
|
| 36 |
+
("leaderboard", "Leaderboard"),
|
| 37 |
+
("time", "Quality vs time"),
|
| 38 |
+
("h2h", "Head to head"),
|
| 39 |
+
("datasets", "Per dataset"),
|
| 40 |
]
|
| 41 |
+
# A tab's hover text: what its view shows.
|
| 42 |
+
VIEW_HINTS = {
|
| 43 |
+
"summary": "Every method on every task and dataset subset at once, with its cost: who is strong "
|
| 44 |
+
"everywhere and who shines on one subset. Per subset, with imputation, over all repeats.",
|
| 45 |
+
"leaderboard": "The Elo ratings, then every number in the full table, on the datasets selected below.",
|
| 46 |
+
"time": "The quality against training and prediction time, and what tuning buys.",
|
| 47 |
+
"h2h": "The win rate of every pair of methods, on the datasets selected below.",
|
| 48 |
+
"datasets": "Each method's rank and gap to the best on each dataset, as the chart and its ranking.",
|
| 49 |
+
}
|
| 50 |
+
# BeyondArena's hover texts where its views differ from TabArena's.
|
| 51 |
+
BEYOND_VIEW_HINTS = {
|
| 52 |
+
"summary": "Best result per model and per model family on every BeyondArena subset: which methods "
|
| 53 |
+
"hold up beyond the IID assumption.",
|
| 54 |
+
}
|
| 55 |
|
| 56 |
# --- The page heroes (views.make_tabarena_hero, views.make_beyond_hero) -------
|
| 57 |
+
# What the benchmark is, in one sentence (`**…**` is bold), heading the hero.
|
|
|
|
|
|
|
| 58 |
HERO_LEAD = (
|
| 59 |
"**TabArena-v0.1** is a living benchmark for predictive machine learning on IID tabular data, built to "
|
| 60 |
"measure the peak performance of model-specific pipelines."
|
|
|
|
| 66 |
HERO_PAPER_URL = "https://tabarena.ai/paper-tabular-ml-iid-study"
|
| 67 |
# The call to submit, as (label, link): the highlighted pill that ends the Learn more row.
|
| 68 |
HERO_CTA = ("Benchmark your model", "https://tabarena.ai/code-examples")
|
| 69 |
+
# The Learn more pills' hover texts, as {topic: text}. The fields in braces are read from the data when
|
| 70 |
+
# the page is built (views.hero_facts).
|
| 71 |
+
HERO_HINTS = {
|
| 72 |
+
"datasets": "{datasets} datasets, hand-picked from 1,053 real-world candidates for IID tabular data",
|
| 73 |
+
"models": (
|
| 74 |
+
"{entrants}, run on the same protocol and budget, each scored at its default, tuned, and as an "
|
| 75 |
+
"ensemble of tuned configurations. {verified} of the {models} models are verified by their authors "
|
| 76 |
+
"or the maintainers"
|
|
|
|
|
|
|
| 77 |
),
|
| 78 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
|
| 80 |
# The "Learn more" row: each topic opens one dialog, which switches between them.
|
| 81 |
LEARN_MORE_LABEL = "Learn more"
|
|
|
|
| 213 |
**Repeats:** Toggle *TabArena-Lite* to score each experiment on a single repeat instead of several. It is
|
| 214 |
noisier than the full setting, but much cheaper to compute and usually close enough to be worth it.
|
| 215 |
"""
|
| 216 |
+
# --- The summary table, the Summary view (views.make_cross_subset_overview) ----------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
# The search at the heading's right, which keeps the rows whose name holds its text.
|
| 218 |
OVERVIEW_FIND = "Find a method"
|
| 219 |
# The table's two metrics, as (headline column name, the name a breakdown's switch shows).
|
|
|
|
| 225 |
OVERVIEW_FOLD = "Fold these columns"
|
| 226 |
|
| 227 |
# --- The selector card (views.selector_card) ---------------------------------
|
| 228 |
+
SELECTOR_TITLE = "Customize"
|
| 229 |
SELECTOR_SUB = "Every number below is relative to who competes and which datasets count."
|
| 230 |
BEYOND_SELECTOR_SUB = "Every number below is relative to the datasets compared, so each subset is its own evaluation."
|
| 231 |
+
# The bar's shortcuts into the card (SELECTOR_TRY names the group for screen readers), as (label, hover
|
| 232 |
+
# text, row, value). A click picks that chip of the row and opens the card on it, a second click undoes
|
| 233 |
+
# it. In a row of toggles the value can be a tuple of chips turned on together; a switch names itself as
|
| 234 |
+
# the row and the state the shortcut puts it in as the value. Chips that cannot be picked yet are left out.
|
| 235 |
+
SELECTOR_TRY = "Make it yours"
|
| 236 |
SELECTOR_EXAMPLES = [
|
| 237 |
(
|
| 238 |
"Add systems",
|
|
|
|
| 335 |
}
|
| 336 |
|
| 337 |
# --- Section headings (views.section_head) ----------------------------------
|
| 338 |
+
# Ends the view bar's hover text after what the selection covers (views.lb_spec).
|
| 339 |
+
LB_HINT = "The leaderboard selected below: the datasets it covers, who competes and how it is computed."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 340 |
BEYOND_LB_HINT = LB_HINT + " Every BeyondArena leaderboard is computed on the core2k protocol."
|
| 341 |
PER_DATASET_TITLE = "Dataset by dataset"
|
| 342 |
+
# The browser's header in the Datasets view. `{n}` is the number of datasets it covers.
|
|
|
|
| 343 |
PER_DATASET_CAPTION = "Where each method wins and loses, on each of the {n} datasets"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 344 |
# What each figure panel shows, in its header beside the title.
|
| 345 |
FIGURE_CAPTIONS = {
|
| 346 |
"overview": "Each method at its default, tuned, and tuned + ensembled settings",
|
|
|
|
| 584 |
# BeyondArena is the second internal leaderboard: the first unified benchmark for
|
| 585 |
# tabular data that goes beyond the IID assumption. Copy mirrors the TabArena
|
| 586 |
# HERO_* / OVERVIEW_* / CITATION_* structure, plus a Subsets topic, with BeyondArena specifics.
|
|
|
|
| 587 |
BEYOND_HERO_LEAD = (
|
| 588 |
"**BeyondArena** is the first unified benchmark for tabular data beyond the IID assumption, with "
|
| 589 |
"IID, temporal and grouped splits across dataset sizes and feature types."
|
|
|
|
| 600 |
("Alan Arazi", "alanarazi7"),
|
| 601 |
]
|
| 602 |
BEYOND_HERO_CTA = ("Benchmark your model", "https://github.com/autogluon/tabarena/tree/main/examples/beyondarena")
|
| 603 |
+
# As HERO_HINTS; the fields in braces come from views.beyond_hero_facts.
|
| 604 |
+
BEYOND_HERO_HINTS = {
|
| 605 |
+
"datasets": (
|
| 606 |
+
"{datasets} datasets, split at random, by time or by group, from tiny to large and with text or "
|
| 607 |
+
"high-cardinality columns. Every leaderboard uses the core2k protocol: 2,000 splits over all of them"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 608 |
),
|
| 609 |
+
"subsets": "{subsets} subsets: pick one chip per row in the selector below, and each combination is its own leaderboard",
|
| 610 |
+
"models": (
|
| 611 |
+
"{entrants}, each scored at its default, tuned, and as an ensemble of tuned configurations. "
|
| 612 |
+
"{verified} of the {models} models are verified by their authors or the maintainers"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 613 |
),
|
| 614 |
+
}
|
| 615 |
|
| 616 |
BEYOND_OVERVIEW_DATASETS = """
|
| 617 |
BeyondArena is built on a curated collection of **142 datasets** that deliberately go **beyond the IID
|
|
|
|
| 663 |
|
| 664 |
# The Subsets topic of the Learn more dialog, also opened from the overview figures (whose axes name
|
| 665 |
# the subsets) by this link.
|
| 666 |
+
BEYOND_SUBSETS_LINK = "What do the subsets mean?"
|
| 667 |
BEYOND_SUBSETS_EXPLAINER = """
|
| 668 |
BeyondArena is sliced into **curated subsets** so you can see how methods hold up *beyond* the IID
|
| 669 |
assumption, and specifically on the kinds of data where an average hides big differences.
|