Treat systems as their own class of entrant - #464
Merged
Conversation
TabArena needs to compare whole systems (AutoGluon, TabFM+, agents, hosted APIs) alongside individual models, and a reader needs to know which entrants use an LLM or sit behind a closed API before trusting a comparison. `method_type` stays a result-shape discriminator: it decides which parquet `load_results` reads and whether HPO simulation applies, and a system's results are recorded as a baseline like any other non-config run. So the entrant class goes in a separate `method_class` field, with `tags` carrying the properties the leaderboard filters and labels on. `tags` is a tuple in `to_info_dict` because that dict becomes a DataFrame cell in `MethodMetadataCollection.info`, where a list is unhashable and breaks the `drop_duplicates`/`.eq` comparison in `website_format.strict_merge`. The YAML writers need the opposite, so `_to_yaml_dict` flattens tuples to lists: `yaml.safe_dump` raises on a tuple outright, and `yaml.dump` would write a `!!python/tuple` that only `unsafe_load` reads back. Two test helpers were writing `yaml.dump(to_info_dict())` directly; they now use the real writer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Systems had no home. TabFM+ sat inside models/tabfm/ despite not being an AutoGluon model, the AutoGluon metadata was spread over baselines/info.py and three dated context modules, and the only worked example of a system was an inline class in an examples/ script. tabarena/systems/ now mirrors tabarena/models/: one subpackage per system with system.py, hpo.py and info.py, walked into SYSTEM_REGISTRY by discover_systems(). SystemInfo is the ModelInfo counterpart and asserts method_class="system", so a system that would classify wrong downstream fails at import instead. Systems stay out of the model registry deliberately: they carry no ag_key and no search space, and they run through the bundle's system_experiments mode. AutoGluon's metadata is now declared once in systems/autogluon/info.py; the dated context modules import from there and keep only their per-suite lists. The example's AutoGluonSystemModel is promoted to systems/autogluon/system.py, with the example keeping its inline copy as teaching material plus a pointer. Portfolio-N200-4h keeps method_type="portfolio" (it reads a different parquet) but gains method_class="system": like AutoGluon it is a multi-model pipeline. TabFM+ is registered in the TabArena collection, so it reaches the leaderboard for the first time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ion/
Every headline TabArena number is relative to who competes: Elo is pairwise over
the participants, improvability is 1 - best_error_in_pool / error, and the ranks
are positions in the field. So "show me models only" cannot be a filter over one
published table, the way the site currently implies. Today AutoGluon sits in the
Elo pool while the Pareto figure, the cross-subset overview and the win-rate
matrix all hide it, which means the models-only view is built on numbers that
were not computed models-only.
The entrant pool therefore becomes a subset axis alongside imputation and splits,
with its own artifact tree per pool. Four pools, cumulative: models only, plus
open-source systems, plus systems with LLMs, plus closed-source API systems. Two
independent checkboxes would imply a fifth field ("closed API, no LLM") that has
no folder, so the leaderboard will render this as one four-stop selector.
The reference lines drawn in a pool's figures are now derived from that pool
rather than hardcoded, so the models-only pool gets none instead of lines for
AutoGluon variants that are not in its field.
eval_all.py leaves nips2025_utils on the way past. It splits into three modules
under evaluation/, next to the LeaderboardReporter it drives: entrants.py (who
competes), subset_grid.py (the grid and its folder layout, shared with the
tuning-trajectory plots so the two cannot disagree), and eval_all.py itself.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"Reference Pipeline" was the old framing where AutoGluon tagged along beside the models. Now that systems are their own entrant class the family is called System, with a 🧰 pill. More than a rename: the family was inferred from name prefixes, with "AutoGluon" and "PORTFOLIO" hardcoded in get_model_family. That is the trap the update-leaderboard skill has a pre-check for, because every new system landed in "❓ Other" until someone remembered to extend the table. add_metadata now reads method_class off the row it already holds, and the figure paths (which see only rendered names) get the declared set via system_display_names. website_leaderboard.csv gains MethodClass and Tags so the leaderboard can render system chips and the API can expose them. add_metadata's missing-method branch returned a different key set than its happy path, which the caller assigns to a fixed column list; both now agree. The win-rate matrix no longer hides systems on load. Which entrants compete is decided upstream by the pool now, so if a system is in the matrix the reader chose a pool containing it, and hiding it would contradict that choice. The train-time Pareto explorer has been generated all along and never shipped; process_one_folder now copies it, which is most of what the "I care about" selector needs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
They were 80.1 of the 105 MB in the Space's data/, and the only reason it needed Git LFS. Every one of them has a self-contained HTML explorer that the site renders by default, with its own SVG / PDF / PNG export in the panel header, so the static view was a second copy of what the reader already had one click away. The figures are still rendered into raw_website_artifacts/ for paper use. Only the copy into the published layout goes away, along with the PNG-to-zip step. This is what makes four entrant pools affordable: a pool drops from ~105 MB to ~24.5 MB, so all four land under today's single-pool footprint and data/ carries no binaries at all. BeyondArena is untouched. It has its own copy path and ships PNGs because most of its figures have no explorer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A reader meets a system in the table, so that is where it has to say what to weigh: 🤖 with LLMs, 🔒 closed-source API, each with hover text explaining why it matters. TAG_SPECS lives in website_format next to the family constants and is handed to the generated table through its config, rather than restated in the JS template. Tables generated before the Tags column existed still build; the chips are simply absent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AGENTS.md gains two sections: what separates a model from a system and how to declare one (method_class, the two-tag vocabulary, the systems/ layout), and why the entrant pool has to be a recompute rather than a filter. The add-system skill is the sibling of add-model. Its first section is the model-or-system question, because that decides everything downstream, and it spells out the tag choice rather than leaving it to be guessed: tags decide which pools a system competes in, and a wrong one silently misplaces it. update-leaderboard: the model-type pre-check no longer applies to systems (they are typed from method_class), the artifact counts are now four pools of 60 with no PNGs, and the stale-unzipped-PNG gotcha is retired for data/ while it still holds for data_beyondarena/. upload-method: the raw-data inspector cannot tell a system from any other baseline, since the runner records both identically, so both the skill and the generated snippet now say so and point at MethodMetadata.system. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A bare `autogluon/` pattern, meant for an AutoGluon checkout at the repo root, matches at any depth. It silently excluded the whole new packages/tabarena/src/tabarena/systems/autogluon/ package: `git status` never listed it as untracked and `git add` on the parent directory skipped it without complaint. The result was a branch that only worked in the tree it was written in. A fresh clone would fail at import, since baselines/info.py, three dated context modules and contexts/tabarena/methods.py all read AutoGluon's metadata from there. Anchoring the pattern to `/autogluon/` keeps the original intent and stops it reaching into the package tree. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Belongs with the previous commit; it was dropped from it because a verification command I ran in between (`git --work-tree=<tmp> checkout HEAD -- .`) writes to the main index and reverted the staged change. The rescued files are tracked either way, since an explicit `git add` overrides an ignore. Without this the pattern still matches at any depth, so the next file added under any `autogluon/` directory would disappear the same way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Collaborator
Author
|
@Innixma fyi here is the PR for the system API re-design. A lot of the leaderboard and plotting code is still in flux from my side right now but the way we would store and treat them inside of TabArena is open for discussion, also if we want to keep the hpo.py style etc |
The four cumulative pools could not express "LLM-based systems but not the plain open-source ones", which is a question people actually have. Systems now fall into three independent categories (open / with-LLM / closed-source-API) and every combination is published, so the leaderboard can offer three checkboxes instead of one four-stop ladder. A system carrying several tags belongs to several categories and needs all of them selected, so a closed-API LLM system never shows up on the strength of a property the reader excluded. The cost is the grid: 8 pools instead of 4, so 480 cells instead of 240 and about twice the generation time. Affordable only because the static PNGs are gone; adding a fourth category would double it again. The System family keeps 📊 rather than moving to 🧰, so it reads the same as it always has in the table. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both explorers already offered Elo and Improvability on their own y-axis selector and simply opened on the first one. They now accept a metric over the existing postMessage channel, so the leaderboard's "I care about" control can decide which one every panel leads with. Doing it at runtime rather than generating an artifact per metric matters: the published grid is already 480 cells, and this would have doubled it for a choice the charts can make. Separately, an empty Tags cell round-trips through CSV as NaN, and `str(nan)` is the string "nan" — so `str(v or "")` gave every untagged system a tag called "nan". Tags are read with an explicit null check now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ding The Pareto and trajectory explorers already accepted a metric over postMessage; the leaderboard-overview explorer uses a different template and did not, so it could never follow the site's "I care about" control. Its dropdown handler and the message now share one setMetric. The tag hover text says what actually matters about each caveat: for an LLM in the loop, that it may already have seen the test data, rather than the vaguer "training data cannot be audited"; for a hosted API, that we cannot inspect what ran, dropping the reproducibility claim. Prose in the user-visible strings follows AGENTS.md's writing rules: em dashes out of the table template's tooltips and headings. The two skills were still describing four cumulative entrant pools. They now describe the eight independent combinations, with the artifact counts to match. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Innixma
approved these changes
Aug 6, 2026
Innixma
left a comment
Collaborator
There was a problem hiding this comment.
Generally seems good to me! We can always adjust after, so I'm fine with merging.
Ports the AutoGluon 1.6 extreme / noncommercial entries (suite tabarena-2026-08-05, artifacts already on r2) into the systems layout rather than contexts/: their MethodMetadata now lives in systems/autogluon/info.py with method_class="system", and the dated contexts module keeps only its list, as the other AutoGluon suites do. autogluon_info points at the 1.6 extreme run. TabFM+ is processed and uploaded: suite tabarena-2026-07-07 (816 tasks over 51 datasets), cache_type="r2". compute stays "gpu" by hand, since the jobs requested one GPU each but the raw results record num_gpus=0. verified stays False: the run predates the 2026-07-13 rerun that stopped reloading models from disk around inference, so its time_infer reads high next to the reruns. The registry test matched AutoGluon by the dated method id of whichever run autogluon_info pointed at; it now matches the wrapper class instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The label map still listed the four pool keys from an earlier design (entrants_systems_open and friends). There are now eight, one per combination of the three system categories, and _subset_label drops any segment it cannot name, so seven of the eight pools produced explorer headlines with no pool in them -- the one part of the label that says which field the numbers were computed against. The map now reads the pools themselves, and an unknown entrants_* segment raises instead of disappearing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
get_pool_reference_lines intersected the pool's admitted methods with a two-entry color map, so it returned AutoGluon 1.4 and 1.5 and nothing else. That list is not only what the figures draw as reference lines: eval() keeps a non-config row only when its method maps to a config framework type or is named in baselines, and a system is neither. So AutoGluon 1.6 and TabFM+ were dropped from every published number in every pool -- 0 of 454 leaderboard CSVs mentioned them, with no warning anywhere. It now returns every system the pool admits and cycles a color list, whose first two entries keep AutoGluon 1.4 and 1.5 in the colors they have always been drawn in. Tested per pool, plus a guard that the widest pool's reference lines cover every system in the shipped collection. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The coupling that dropped AutoGluon 1.6 and TabFM+ from every published number is not visible from either side on its own, so name it where someone registering a system will read it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A pool that admits systems put them in the leaderboard table but not in the plots: entrants_open had 84 leaderboard rows and 73 Pareto points, the missing eleven being the six banned KNN/LR variants and all five systems. That is the same split the entrant pools exist to remove -- a system moving every other number while the figures pretend it is not there. evaluate_single passed plot_with_baselines=False, which kept systems out of the Pareto scatter and the win-rate matrix, and the trajectory figure passed include_baselines=False. Both are now on. A pool that admits no system has no baseline row, so models-only is unaffected, and the trajectory metadata list is already pool-filtered. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The overview kept systems out of `byMethod` and drew them as dashed threshold lines across the plot, with their names in the legend rather than on the axis. That is the reference-pipeline framing: a system as a line the models are measured against, not as one of the entrants. Systems are now ordinary entries. They group, sort, filter, toggle by family chip and colour their axis label like any other method, and their single point gets the Default bar style. The variant toggles cannot hide them, since a system has no tuning variant to toggle; the tooltip labels that row "Whole pipeline" instead of printing a bare colon. Removes the threshold-line drawing, its sticky axis tags, the dash-pattern legend entries and the parallel `state.systems` selection set the chips had to keep in step with `state.methods`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A system fell through to the Default variant style, so it was drawn in the same blue as every model's default bar and read as one. It is not a tuning variant of anything, so it now takes the System family hue and the full bar width, and the legend carries a System swatch next to the three variant swatches. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The inference timing note stays: the run predates the 2026-07-13 rerun that stopped reloading models from disk around inference, so its time_infer still reads high next to the reruns. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ric changes
Two fixes to the same two charts.
A system carries its whole configuration in its name ("AutoGluon 1.6
(noncommercial, 4h)"), which is several times the width they assumed. The
overview cut it with an ellipsis; the Pareto explorer ran it off the plot
whenever its point sat in the right-hand third, and under-counted how far it
reached when spacing labels apart. Both now measure the text they are about to
draw, through one shared helper. The overview breaks a name at its spaces and
widens the columns until the widest line fits, so the ellipsis is only reached
past MAX_NAME_SLOT. The Pareto explorer puts a label on whichever side of its
point has room for the whole name and de-overlaps on measured spans.
The Pareto explorer also computed its highlighted set once, from the metric it
opened on, and kept it as the y-axis changed. Each metric has its own front --
EXAONE-Tabular leads on Elo for regression and is mid-field on relative gain --
so methods were drawn on the front and greyed out at the same time. The set now
follows the metric until the reader picks methods themselves.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The interactive matrix is built to compare model-variant pairs: it offers a toggle per variant and a "One per model" control that collapses them. Neither worked. The reporter fed it the best-variant-per-model frame, so there was nothing to collapse, and it recognised "(tuned + ensembled)" while the reporter writes the tag as "(T+E)", so those rows read as variant-less and the toggles came down to a lone "Default". The matrix is now computed over every variant. Win rates are pairwise and per task, so the one-per-model matrix the static figure and the CSV keep showing is exactly a submatrix of it -- identical numbers, no second computation. Cells and means are rounded to four decimals before they reach the page, which is more precision than it prints and keeps the bigger matrix from dominating the file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Widening every column to fit the widest wrapped line cost more than the ellipsis did: fewer columns fit on screen, so the chart reads worse overall than it did with a couple of long system names trimmed. Back to one line per name, trimmed to the slot. The measured labels on the Pareto fronts and the shared text measurer stay.
A system column stands alone -- there are no variants nested inside it -- so drawing it at the full width of a Tuned + Ensembled bar only made it read as heavier than everything beside it.
An explorer stamps data-theme="light" while paper view is on and puts the embedding page's own choice back when it is switched off. That choice was read on the way *in*, so a page configured to open out of paper view (the leaderboard table) cleared the stamp on its first call and then followed the viewer's OS preference, rendering light inside the always-dark site. Read it once at setup instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The aggregate figure asks compute_tuning_trajectories_leaderboard for Elo, which is a rating over many tasks and says nothing useful about a single one. Everything a per-dataset trajectory needs is an average over that dataset's splits, so compute_per_dataset_trajectories does it in one vectorized pass over every dataset at once rather than one leaderboard per dataset. Improvability keeps the definition the rest of the site uses, and the field it is measured against is the same one the aggregate figure plots. The subset/fill/exclude-imputed preprocessing the two share moves into _subset_trajectory_data so they cannot drift. Written for the cells with no task or dataset restriction only: a dataset's own numbers do not depend on which other datasets share its leaderboard, so 32 frames cover the grid's 480 cells. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The leaderboard answers "which method is best on average". This answers the question a reader asks next: where did it win, and where did it lose. A master-detail page. The list is one row per dataset, carrying the contender's rank and its gap to the best method there plus a strip showing the whole field with a star on the contender; it sorts by any column, searches, and filters by task and size. Selecting a dataset fills the detail pane below with that dataset's tuning trajectories and its full ranking, and the arrow keys step through the list without the chart moving. Two scales needed care. The strip is log(1 + gap): most fields bunch inside a few percent of the best while one or two collapsed models sit at 80%, and linear puts everything that matters in the first two pixels. The chart's y-axis stops at the 90th percentile for the same reason, with the points above it pinned to the top edge as hollow triangles rather than dropped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Like the leaderboard overview and table, it needs nothing beyond the CSVs it sits next to, so a styling fix costs a conversion re-run rather than a re-evaluation. It is built for the cells that carry a per-dataset trajectory frame, which is the evaluation's own marker for "this cell is not restricted by task or dataset size". The dataset metadata is the same for every cell, so the generator reads it once and hands it down instead of the conversion loading it 480 times. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…wn metric Three fixes to the per-dataset browser, all about what a mark means: The green diamond on the winner is gone. It drew a method twice — the winner is by definition the one whose gap is zero, so its own family-coloured dot was already sitting at the left edge and the diamond was painted on top of it. It read as a method because it was one, and its green was close enough to the Tree-based family hue to make that worse. The axis starts at the best method by construction and the Winner column names it. The contender's star now takes one fixed colour whoever the contender is, rather than that method's family hue, which made it compete with the field it exists to stand out from. Yellow rather than gold: the nearest family colour is the System orange, and an amber star sat close enough to reintroduce the same confusion against a different family. The chart opens on the dataset's own metric. Improvability is the axis the aggregate figure needs to make datasets comparable; on one dataset it is the second question. Safe as a default only because the axis clips at the 90th percentile. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…set list Three changes to the per-dataset browser. The row count was the dataset's own size, which is not a number any model here saw: GiveMeSomeCredit read 150,000 while every method trained on 100,000 of it. The column now reports the largest training split, so it agrees with the size filter beside it — which was already keyed on that, making "Rows 129,880" next to a pressed "10k - 100k" chip a contradiction. The detail pane shows both, since the gap between them is itself informative. The list is resizable: it and the detail chart together are taller than a laptop screen, and which of the two you want more of depends on what you are doing. It fits its rows up to a ceiling the drag handle sets, and filtering never undoes that choice. Two measurement traps on the way: the box has no layout on the first render, and `scrollHeight` is never smaller than the element's own height, so neither can report the content's size on its own. The keyboard hint now says the arrow keys need a click first. The page is a sandboxed frame, so it receives no key events at all until the reader has clicked inside it, and without that sentence the keys simply look broken. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The list could be resized and scrolled, but neither said so. The browser's own resize grip is a few pixels in one corner and nobody finds it, so it is replaced by a bar spanning the list that says what it does and takes the arrow keys; the cut-off rows now fade under a "more below" label instead of looking like the end of the list; and the scrollbar thumb moved off the almost-invisible --pt-muted. "Fit table and figure to screen" sizes both against the visible band. It has to move both: on a laptop the detail pane alone is taller than the viewport, so a fit that only shrank the list could do nothing but collapse it. The chart takes what it can up to its normal height, the list gets the rest, and neither goes below a readable floor. The frame cannot measure the band itself -- it is sized to its own content -- so the host sends it. The dataset's facts move under the chart they describe and gain a tinted panel, with the name leading them. Above the chart, as a run-on line of grey text, they were skipped over; and the name was already on screen, highlighted in the selected row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…idth
`scrollIntoView({block: "nearest"})` stops as soon as a row is anywhere inside the scroll box,
so stepping down parked the selection under the "more below" fade: selected in the DOM,
unreadable on screen. Rows get a scroll margin instead, which scrollIntoView honours, at both
ends -- the sticky header covered rows stepped to upward for the same reason.
The page's own side padding drops from the shared 12px to 8px. It fills a panel as an
application rather than sitting in one as a figure, and the panel around it was already adding
its own inset; `body.paper` keeps the roomier figure padding, since there it is one.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ar colour Bar widths are relative *within* a column — tuned + ensembled 1.0, tuned 0.8, default 0.6 — so any column missing the outermost variant drew thin beside its neighbours for a reason nobody could read: a model with no tuned run, a system, or every column at once as soon as the reader switches a variant off. Each column is now scaled so its widest bar fills the slot; the nesting inside it is unchanged. The system bar took the System *family* hue, which sat close enough to the tuned bar's orange to be read as one. It gets its own token in the variant palette instead. Wine, because every other hue in that chart is already spoken for: orange is Tuned, green is Tuned + Ens., blue is Default, and purple is the Foundation Model family, whose colour the method names under the axis are set in — which rules out magenta too, near enough to that purple to be taken for it. The family colour itself is unchanged, and System now appears in the family legend. Systems were filtered out of it, so their names were printed in a colour the legend never explained. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The column reported how far the contender was behind the best method, which is 0.0% for every dataset the contender wins — silent about whether it won by a hair or a mile, on exactly the datasets a reader is most curious about. It now reads from the contender's own point of view: negative against the best method when it trails, positive against the runner-up when it wins. Both are the same quantity — how much lower the better error is than the worse one, as a fraction of the worse one — so the halves stay comparable and only the sign changes. A lead is drawn in the optimal colour, being the exception worth spotting, and clicking the column sorts worst-first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every family has a mark colour and a darkened ink for text on the light surface, and darkening works for purple, green, blue and grey — each stays a readable version of itself. Orange does not: at that lightness it reads as brown, so in paper view a system's name no longer matched the swatch beside it while every other family did. Saturating instead of darkening holds the hue, and at 5.2:1 on white it is better contrast than the brown it replaces, so nothing is traded for it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Wine was too heavy against the pastels it sits among on the paper surface. Rosa keeps a hue no family or variant claims while matching the weight of the other three light-mode bars, and the dark counterpart steps down from it the way each of those pairs does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The overview legend listed "System" twice: once in the row describing how a method was produced and again in the family row, in two different colours, which reads as a contradiction rather than as two facts. The first is now "End-to-end", the phrasing the site's own copy already uses for systems owning their pipeline, and it says why none of the three regimes beside it apply. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A chart sizes itself from its container and lays its labels out from measured text. In a container that is not laid out yet -- a collapsed section, a hidden tab, a panel Gradio is mid-render on -- the container reports 0 and every string measures 0 too. The chart then pinned itself to its 360px minimum and, believing every name to be zero wide, stacked them on top of each other. That is the state a reader finds when the panel finally appears. Nothing healed it. Recovery hung on `window.onresize`, which only fires when the viewport changes, and the text measurer cached its zeros -- in the Pareto template on a cache that lives for the page, so every later redraw read the same zeros back and re-stacked the labels. Three changes: refuse to draw until the box has a width, never cache a zero measurement, and watch the chart's own box with a ResizeObserver rather than the viewport, since that is what actually changes when a hidden panel is revealed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An imputed score is a default RandomForest's result standing in for a model that could not run on that dataset. Averaged over 51 datasets that is a fair penalty, but on the one dataset it belongs to it claims a measurement that never happened -- so the per-dataset browser now drops those pairs, from the list, the field strip, the ranking and the trajectory chart alike. The model keeps its place on every dataset where it did run. The ranks and gaps are computed after the drop, so they are over the methods that actually ran, and the field size now varies by dataset -- 2 to 8 methods missing on each in the current data. The pane says how many could not run, so a smaller field reads as information rather than as an inconsistency. The page also opens on the leaderboard's own leader now. The old fallback picked the best mean rank, which this change biases: with imputed results gone, that average is taken over each method's own datasets, so a model that runs on a handful and does well there outranks one that runs everywhere. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Six cases the previous fixtures could not reach, since every row in them was unimputed: a pair imputed on one dataset disappears from that dataset and stays on the others, in both the results and the trajectory frame; the ranks close up over the methods that actually ran; the per-dataset count of what could not run reaches the page; and an explicit contender beats the mean-rank fallback. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TabArena benchmarks models and carries AutoGluon along as a "Reference Pipeline". This makes systems their own class of entrant: a system is a whole pipeline that picks, tunes and ensembles models inside its own budget, whether that is an AutoML framework, an agent, a hosted API, or a model run through a heavier self-managing interface.
Two problems motivated it.
The reference-pipeline handling was already inconsistent. AutoGluon rows sit in
website_leaderboard.csvand therefore in the Elo pool, so every model's Elo was computed against them. But the Pareto figure, the cross-subset overview and the win-rate matrix all excluded or hid them. The site showed a "models only" view built on numbers that were not computed models-only.A participant filter cannot be client-side. Elo is pairwise over the participants, improvability is
1 - best_error_in_pool / error, and the ranks are positions in the field. Change who competes and everyone's numbers change.What changes
Metadata.
MethodMetadatagainsmethod_class(model/system) andtags(with-llm,closed-source-api).method_typestays what it was, a result-shape discriminator deciding which parquetload_resultsreads and whether HPO simulation applies. Systems record as baselines like any other non-config run, so overloading it would have touched about 30 branch points for nothing.A
systems/package mirroringmodels/: one folder per system withsystem.py,hpo.pyandinfo.py, walked intoSYSTEM_REGISTRYbydiscover_systems(). TabFM+ moves out ofmodels/tabfm/, AutoGluon's metadata is consolidated from four scattered modules intosystems/autogluon/info.py, and the example'sAutoGluonSystemModelis promoted into a real wrapper. TabFM+ is registered in the collection, so it reaches the leaderboard for the first time.Entrant pools as a subset axis. Three independently selectable system categories (
open,llm,api), so every combination is published as its own evaluation: eight pools (models,open,llm,api,open_llm,open_api,llm_api,open_llm_api) over a 480-cell grid.eval_all.pyleavesnips2025_utilson the way past and splits intoevaluation/{entrants,subset_grid,eval_all}.py, next to theLeaderboardReporterit drives.Reference PipelinebecomesSystem, typed frommethod_classrather than name prefixes. That retires the❓ Othertrap theupdate-leaderboardskill has a pre-check for: previouslyAutoGluonandPORTFOLIOwere hardcoded prefixes and every new system landed in Other until someone remembered to extend the table.Static PNGs stop shipping. They were 80.1 of the 105 MB in the Space's
data/and the only reason it needed Git LFS, while every figure already has an explorer that renders by default and exports its own SVG/PDF/PNG. A pool drops from ~105 MB to ~24.5 MB, so four pools land under today's single-pool footprint. BeyondArena is untouched and keeps its PNGs.Docs: AGENTS.md sections on systems and entrant pools, a new
add-systemskill, and refreshes toupload-methodandupdate-leaderboard.Decisions worth a second opinion
Portfolio-N200-4his typed as a system. It is a multi-model pipeline like AutoGluon but a TabArena-internal construct rather than an external one. Easy to flip.raw_website_artifacts/for paper use; only the copy into the published layout goes away.New systems, and two bugs they surfaced
The AutoGluon 1.6 presets from #466 land here in the
systems/layout rather than incontexts/: both areMethodMetadata.system(...)insystems/autogluon/info.py, the dated module keeps only its list, andautogluon_infopoints at 1.6 extreme. TabFM+ is processed and uploaded to r2 (suitetabarena-2026-07-07, 816 tasks over 51 datasets). It staysverified=False: the run predates the 2026-07-13 rerun that stopped reloading models from disk around inference, so itstime_inferreads high next to the models beside it on the Pareto front.Registering them exposed two defects in this branch's own work.
Systems without a pinned reference-line color never reached the leaderboard.
get_pool_reference_linesintersected the pool's admitted methods with a two-entry color map, and that list is not only what the figures draw:LeaderboardReporter.evalkeeps a non-config row only when its method maps to a config framework type or is named inbaselines. AutoGluon 1.6 and TabFM+ were absent from all 454 CSVs of the first generation pass, with nothing logged. It now returns every admitted system and cycles a color list whose first two entries keep AutoGluon 1.4 and 1.5 in their existing colors.Seven of the eight pools had no pool name in their figure headlines. The generator's label map still listed the four keys from the earlier design, and
_subset_labeldrops any segment it cannot name, so the one part of the label that says which field the numbers came from went missing. It readsENTRANT_POOLSnow, and an unknownentrants_*segment raises.Not in this PR
The companion changes to the
leaderboard-testingSpace (the control band at the top of the page, the "Who's competing?" and "I care about" selectors, tag chips, theentrantsAPI axis) live in that repo.Wrappers for LightAutoML, FLAML, TabPFN-3-API and TabPFN-Thinking are deferred; the
add-systemskill covers them. Until an open LLM-based system or a hosted API exists, thellmandapicategories have no entrant, so those four pools are identical to models-only and the Space renders their toggles as "coming soon".Testing
1417 passed, 2 skipped.
ruff checkandruff format --checkclean on every touched file. New tests cover the metadata fields and their two serialization forms, the systems registry, pool admission for each of the eight pools, the subset grid and its folder layout, and system typing inwebsite_format.The artifacts are regenerated at the official 200 bootstrap rounds. Verified across all eight pools: the four admitting
opencarry 84 rows with all five systems, the other four carry 79 with none, and TabM (tuned + ensembled) moves 1422 to 1420 between them, which is the recompute doing its job.Also verified from a clean
git worktreecheckout of HEAD that both systems discover and all three appear in the collection. That check exists because a bareautogluon/pattern in.gitignorematched at any depth and silently swallowed the wholesystems/autogluon/package:git statusnever showed it andgit addon the parent skipped it. Fixed by anchoring the pattern; without that catch the branch would only have worked in the tree it was written in.🤖 Generated with Claude Code