Spaces:
Running
Running
Publish the arXiv-linked v1.3 leaderboard
Browse filesEmbeds the bound stability analysis, exposes the 342 optimizer-facing reward maps while keeping the 84-task transfer split out of the reward endpoint, and links the canonical arXiv record.
- README.md +11 -3
- app.py +46 -4
- build_complete_core_space_bundle.py +25 -6
- data-complete-core/flavourbench-complete-core-space.json +2 -2
README.md
CHANGED
|
@@ -83,15 +83,18 @@ The Space exposes four named endpoints:
|
|
| 83 |
|---|---|
|
| 84 |
| `/score_completion` | Score one completion on one official task |
|
| 85 |
| `/score_submission` | Score a complete JSON or JSONL artifact supplied as text |
|
| 86 |
-
| `/training_reward` | Query one of
|
| 87 |
| `/score_uploaded_submission` | Score an uploaded artifact and return a report |
|
| 88 |
|
| 89 |
Use **Use via API** in the running Space for generated Python, JavaScript, and curl clients. For
|
| 90 |
high-throughput RL, use the local deterministic reward function. The linked dataset includes
|
| 91 |
ready-to-load SFT, DPO, and GRPO views plus runnable LoRA recipes for Hugging Face Jobs.
|
| 92 |
|
|
|
|
|
|
|
|
|
|
| 93 |
[Dataset and lab kit](https://huggingface.co/datasets/josefchen/flavourbench)
|
| 94 |
-
[Paper](https://
|
| 95 |
[Source](https://github.com/josefchen/flavourbench)
|
| 96 |
|
| 97 |
Josef Chen, Independent Researcher<br>
|
|
@@ -101,6 +104,11 @@ Erim Hayretci, Imperial College London
|
|
| 101 |
@article{chen2026flavourbench,
|
| 102 |
title = {FlavourBench: Ranking Frontier Language Models with Executable Culinary Ground Truth},
|
| 103 |
author = {Chen, Josef and Hayretci, Erim},
|
| 104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
}
|
| 106 |
```
|
|
|
|
| 83 |
|---|---|
|
| 84 |
| `/score_completion` | Score one completion on one official task |
|
| 85 |
| `/score_submission` | Score a complete JSON or JSONL artifact supplied as text |
|
| 86 |
+
| `/training_reward` | Query one of 342 anchor-disjoint train/validation reward maps |
|
| 87 |
| `/score_uploaded_submission` | Score an uploaded artifact and return a report |
|
| 88 |
|
| 89 |
Use **Use via API** in the running Space for generated Python, JavaScript, and curl clients. For
|
| 90 |
high-throughput RL, use the local deterministic reward function. The linked dataset includes
|
| 91 |
ready-to-load SFT, DPO, and GRPO views plus runnable LoRA recipes for Hugging Face Jobs.
|
| 92 |
|
| 93 |
+
The [prospective reward-transfer protocol](https://github.com/josefchen/flavourbench/blob/main/docs/reward-transfer-study.md)
|
| 94 |
+
defines the 84-task transfer split, seeds, six confirmatory contrasts, and multiplicity control.
|
| 95 |
+
|
| 96 |
[Dataset and lab kit](https://huggingface.co/datasets/josefchen/flavourbench)
|
| 97 |
+
[Paper](https://arxiv.org/abs/2608.20574)
|
| 98 |
[Source](https://github.com/josefchen/flavourbench)
|
| 99 |
|
| 100 |
Josef Chen, Independent Researcher<br>
|
|
|
|
| 104 |
@article{chen2026flavourbench,
|
| 105 |
title = {FlavourBench: Ranking Frontier Language Models with Executable Culinary Ground Truth},
|
| 106 |
author = {Chen, Josef and Hayretci, Erim},
|
| 107 |
+
journal = {arXiv preprint arXiv:2608.20574},
|
| 108 |
+
year = {2026},
|
| 109 |
+
eprint = {2608.20574},
|
| 110 |
+
archivePrefix = {arXiv},
|
| 111 |
+
primaryClass = {cs.CL},
|
| 112 |
+
url = {https://arxiv.org/abs/2608.20574}
|
| 113 |
}
|
| 114 |
```
|
app.py
CHANGED
|
@@ -30,7 +30,7 @@ BUNDLE_PATH = Path(
|
|
| 30 |
|
| 31 |
RUST = "#A83D34"
|
| 32 |
INK = "#161817"
|
| 33 |
-
PAPER_URL = "https://
|
| 34 |
DATASET_URL = "https://huggingface.co/datasets/josefchen/flavourbench"
|
| 35 |
SOURCE_URL = "https://github.com/josefchen/flavourbench"
|
| 36 |
DATASET_RESULTS_URL = (
|
|
@@ -1140,6 +1140,7 @@ MODELS = BUNDLE["models"]
|
|
| 1140 |
TASKS = BUNDLE["tasks"]
|
| 1141 |
LAB_TASKS = BUNDLE.get("lab_tasks", [])
|
| 1142 |
PAIRWISE = BUNDLE["pairwise_comparisons"]
|
|
|
|
| 1143 |
MODEL_COUNT = len(MODELS)
|
| 1144 |
TASK_COUNT = len(TASKS)
|
| 1145 |
PAIR_COUNT = len(PAIRWISE)
|
|
@@ -1658,6 +1659,23 @@ def _insights_html() -> str:
|
|
| 1658 |
"mean_difference", float(DISPLAY_MODELS[0]["flavourbench_score"]) - chance
|
| 1659 |
)
|
| 1660 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1661 |
return f"""
|
| 1662 |
<div class="fb-insight-layout">
|
| 1663 |
<section>
|
|
@@ -1675,6 +1693,29 @@ def _insights_html() -> str:
|
|
| 1675 |
</div>
|
| 1676 |
</aside>
|
| 1677 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1678 |
<section class="fb-family-insight">
|
| 1679 |
<h3>Where the leading labs differ</h3>
|
| 1680 |
<p>Scores are out of 100. Red marks each column leader.</p>
|
|
@@ -2417,8 +2458,9 @@ and GRPO recipes in the source repository. The full publication contract is in t
|
|
| 2417 |
sign flips, Holm correction, exact tests against a random legal choice, bootstrap rank intervals,
|
| 2418 |
and an independently compiled second panel.</p>
|
| 2419 |
<h3>Training boundary</h3>
|
| 2420 |
-
<p>The
|
| 2421 |
-
the
|
|
|
|
| 2422 |
<aside class="fb-evidence">
|
| 2423 |
<strong>Content-addressed release</strong><br>
|
| 2424 |
<span class="fb-hash">{BUNDLE["release_artifact_sha256"]}</span><br><br>
|
|
@@ -2467,7 +2509,7 @@ pytest -q tests/lab_cli_test.py tests/hf_lab_space_api_test.py
|
|
| 2467 |
<span>Erim Hayretci, Imperial College London</span>
|
| 2468 |
</div>
|
| 2469 |
<nav class="fb-footer-links" aria-label="Project resources">
|
| 2470 |
-
<a href="https://
|
| 2471 |
<a href="https://huggingface.co/datasets/josefchen/flavourbench">Dataset</a>
|
| 2472 |
<a href="https://github.com/josefchen/flavourbench">Source</a>
|
| 2473 |
</nav>
|
|
|
|
| 30 |
|
| 31 |
RUST = "#A83D34"
|
| 32 |
INK = "#161817"
|
| 33 |
+
PAPER_URL = "https://arxiv.org/abs/2608.20574"
|
| 34 |
DATASET_URL = "https://huggingface.co/datasets/josefchen/flavourbench"
|
| 35 |
SOURCE_URL = "https://github.com/josefchen/flavourbench"
|
| 36 |
DATASET_RESULTS_URL = (
|
|
|
|
| 1140 |
TASKS = BUNDLE["tasks"]
|
| 1141 |
LAB_TASKS = BUNDLE.get("lab_tasks", [])
|
| 1142 |
PAIRWISE = BUNDLE["pairwise_comparisons"]
|
| 1143 |
+
STABILITY = BUNDLE["stability_analysis"]
|
| 1144 |
MODEL_COUNT = len(MODELS)
|
| 1145 |
TASK_COUNT = len(TASKS)
|
| 1146 |
PAIR_COUNT = len(PAIRWISE)
|
|
|
|
| 1659 |
"mean_difference", float(DISPLAY_MODELS[0]["flavourbench_score"]) - chance
|
| 1660 |
)
|
| 1661 |
)
|
| 1662 |
+
stability_rows = []
|
| 1663 |
+
for row in STABILITY["task_count_stability"]:
|
| 1664 |
+
rank = row["metrics"]["rank_spearman"]
|
| 1665 |
+
top_five = row["metrics"]["top_5_overlap"]
|
| 1666 |
+
leader = row["metrics"]["top_1_preserved"]
|
| 1667 |
+
stability_rows.append(
|
| 1668 |
+
"<tr>"
|
| 1669 |
+
f"<td>{int(row['tasks'])}</td>"
|
| 1670 |
+
f"<td>{float(rank['median']):.3f}</td>"
|
| 1671 |
+
f"<td>{float(rank['p2_5']):.3f}–{float(rank['p97_5']):.3f}</td>"
|
| 1672 |
+
f"<td>{float(top_five['median']) * 100:.0f}%</td>"
|
| 1673 |
+
f"<td>{float(leader['mean']) * 100:.1f}%</td>"
|
| 1674 |
+
"</tr>"
|
| 1675 |
+
)
|
| 1676 |
+
variance = STABILITY["variance_partition"]
|
| 1677 |
+
generalizability = float(variance["relative_decision_generalizability_at_534_tasks"])
|
| 1678 |
+
tasks_for_g_90 = int(variance["estimated_balanced_tasks_for_relative_g_0_90"])
|
| 1679 |
return f"""
|
| 1680 |
<div class="fb-insight-layout">
|
| 1681 |
<section>
|
|
|
|
| 1693 |
</div>
|
| 1694 |
</aside>
|
| 1695 |
</div>
|
| 1696 |
+
<section class="fb-family-insight">
|
| 1697 |
+
<h3>Why 534 tasks?</h3>
|
| 1698 |
+
<p>The crossed design's descriptive relative-decision generalizability is
|
| 1699 |
+
<strong>{generalizability:.3f}</strong>; the same variance model estimates
|
| 1700 |
+
<strong>{tasks_for_g_90}</strong> balanced tasks for 0.90. The table below repeatedly takes
|
| 1701 |
+
score-blind, balanced subsets and compares them with the complete point order.</p>
|
| 1702 |
+
<div class="fb-table-wrap">
|
| 1703 |
+
<table class="fb-table">
|
| 1704 |
+
<caption>5,000 family-by-panel stratified subsets at each non-complete task count</caption>
|
| 1705 |
+
<thead><tr>
|
| 1706 |
+
<th scope="col">Tasks</th>
|
| 1707 |
+
<th scope="col">Median rank ρ</th>
|
| 1708 |
+
<th scope="col">Empirical 95%</th>
|
| 1709 |
+
<th scope="col">Top-five overlap</th>
|
| 1710 |
+
<th scope="col">Point leader kept</th>
|
| 1711 |
+
</tr></thead>
|
| 1712 |
+
<tbody>{"".join(stability_rows)}</tbody>
|
| 1713 |
+
</table>
|
| 1714 |
+
</div>
|
| 1715 |
+
<p class="fb-resolution-note">This is a precision diagnostic relative to the complete
|
| 1716 |
+
release, not a post-hoc power claim. The point leader remains unstable in smaller subsets;
|
| 1717 |
+
the simultaneous score bands and rank intervals remain the inferential result.</p>
|
| 1718 |
+
</section>
|
| 1719 |
<section class="fb-family-insight">
|
| 1720 |
<h3>Where the leading labs differ</h3>
|
| 1721 |
<p>Scores are out of 100. Red marks each column leader.</p>
|
|
|
|
| 2458 |
sign flips, Holm correction, exact tests against a random legal choice, bootstrap rank intervals,
|
| 2459 |
and an independently compiled second panel.</p>
|
| 2460 |
<h3>Training boundary</h3>
|
| 2461 |
+
<p>The 342 optimizer-facing SFT, DPO, and GRPO maps use anchors that do not
|
| 2462 |
+
occur in the 84-task transfer split or the {TASK_COUNT}-task leaderboard.
|
| 2463 |
+
Training cannot query either evaluation map through the reward endpoint.</p>
|
| 2464 |
<aside class="fb-evidence">
|
| 2465 |
<strong>Content-addressed release</strong><br>
|
| 2466 |
<span class="fb-hash">{BUNDLE["release_artifact_sha256"]}</span><br><br>
|
|
|
|
| 2509 |
<span>Erim Hayretci, Imperial College London</span>
|
| 2510 |
</div>
|
| 2511 |
<nav class="fb-footer-links" aria-label="Project resources">
|
| 2512 |
+
<a href="https://arxiv.org/abs/2608.20574">Paper</a>
|
| 2513 |
<a href="https://huggingface.co/datasets/josefchen/flavourbench">Dataset</a>
|
| 2514 |
<a href="https://github.com/josefchen/flavourbench">Source</a>
|
| 2515 |
</nav>
|
build_complete_core_space_bundle.py
CHANGED
|
@@ -11,6 +11,9 @@ from typing import Any
|
|
| 11 |
HERE = Path(__file__).resolve().parent
|
| 12 |
DEFAULT_DATASET = HERE.parent / "dataset" / "data-complete-core"
|
| 13 |
DEFAULT_LAB_DATASET = HERE.parent / "dataset" / "data-lab"
|
|
|
|
|
|
|
|
|
|
| 14 |
DEFAULT_OUTPUT = HERE / "data-complete-core" / "flavourbench-complete-core-space.json"
|
| 15 |
|
| 16 |
|
|
@@ -53,7 +56,12 @@ def _jsonl(path: Path, *, expected_sha256: str, expected_rows: int) -> list[dict
|
|
| 53 |
return rows
|
| 54 |
|
| 55 |
|
| 56 |
-
def build_bundle(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
manifest = _load(dataset_directory / "DATA_MANIFEST.json")
|
| 58 |
if (
|
| 59 |
not _semantic_valid(manifest)
|
|
@@ -92,8 +100,8 @@ def build_bundle(*, dataset_directory: Path, lab_dataset_directory: Path) -> dic
|
|
| 92 |
lab_manifest = _load(lab_dataset_directory / "DATA_MANIFEST.json")
|
| 93 |
if (
|
| 94 |
not _semantic_valid(lab_manifest)
|
| 95 |
-
or lab_manifest.get("schema_version") != "flavourbench-lab-dataset-
|
| 96 |
-
or lab_manifest.get("status") != "
|
| 97 |
):
|
| 98 |
raise CompleteCoreSpaceBuildError("lab dataset manifest failed verification")
|
| 99 |
lab_records = {str(row["name"]): row for row in lab_manifest["files"]}
|
|
@@ -107,14 +115,21 @@ def build_bundle(*, dataset_directory: Path, lab_dataset_directory: Path) -> dic
|
|
| 107 |
)
|
| 108 |
|
| 109 |
lab_tasks = [*lab_rows("train_tasks.jsonl"), *lab_rows("validation_tasks.jsonl")]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
official_ids = {str(row["task_id"]) for row in tasks}
|
| 111 |
official_anchors = {str(row["anchor_ingredient"]) for row in tasks}
|
| 112 |
lab_ids = {str(row["task_id"]) for row in lab_tasks}
|
| 113 |
lab_anchors = {str(row["anchor_ingredient"]) for row in lab_tasks}
|
| 114 |
if (
|
| 115 |
-
len(lab_tasks) !=
|
| 116 |
-
or len(lab_ids) !=
|
| 117 |
-
or len(lab_anchors) !=
|
| 118 |
or lab_ids & official_ids
|
| 119 |
or lab_anchors & official_anchors
|
| 120 |
):
|
|
@@ -160,9 +175,11 @@ def build_bundle(*, dataset_directory: Path, lab_dataset_directory: Path) -> dic
|
|
| 160 |
"task_count": len(lab_tasks),
|
| 161 |
"train_tasks": int(lab_manifest["counts"]["train_tasks"]),
|
| 162 |
"validation_tasks": int(lab_manifest["counts"]["validation_tasks"]),
|
|
|
|
| 163 |
"official_anchor_overlap": 0,
|
| 164 |
},
|
| 165 |
"lab_tasks": lab_tasks,
|
|
|
|
| 166 |
"primary_observations": compact_observations,
|
| 167 |
"pairwise_comparisons": pairwise,
|
| 168 |
}
|
|
@@ -199,12 +216,14 @@ def main() -> None:
|
|
| 199 |
parser = argparse.ArgumentParser(description="Build the final FlavourBench Space bundle")
|
| 200 |
parser.add_argument("--dataset-directory", type=Path, default=DEFAULT_DATASET)
|
| 201 |
parser.add_argument("--lab-dataset-directory", type=Path, default=DEFAULT_LAB_DATASET)
|
|
|
|
| 202 |
parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT)
|
| 203 |
parser.add_argument("--check", action="store_true")
|
| 204 |
args = parser.parse_args()
|
| 205 |
bundle = build_bundle(
|
| 206 |
dataset_directory=args.dataset_directory,
|
| 207 |
lab_dataset_directory=args.lab_dataset_directory,
|
|
|
|
| 208 |
)
|
| 209 |
payload = _bytes(bundle)
|
| 210 |
if args.check:
|
|
|
|
| 11 |
HERE = Path(__file__).resolve().parent
|
| 12 |
DEFAULT_DATASET = HERE.parent / "dataset" / "data-complete-core"
|
| 13 |
DEFAULT_LAB_DATASET = HERE.parent / "dataset" / "data-lab"
|
| 14 |
+
DEFAULT_STABILITY = (
|
| 15 |
+
HERE.parents[1] / "paper/generated/complete-core/complete-core-stability-analysis.json"
|
| 16 |
+
)
|
| 17 |
DEFAULT_OUTPUT = HERE / "data-complete-core" / "flavourbench-complete-core-space.json"
|
| 18 |
|
| 19 |
|
|
|
|
| 56 |
return rows
|
| 57 |
|
| 58 |
|
| 59 |
+
def build_bundle(
|
| 60 |
+
*,
|
| 61 |
+
dataset_directory: Path,
|
| 62 |
+
lab_dataset_directory: Path,
|
| 63 |
+
stability_path: Path = DEFAULT_STABILITY,
|
| 64 |
+
) -> dict[str, Any]:
|
| 65 |
manifest = _load(dataset_directory / "DATA_MANIFEST.json")
|
| 66 |
if (
|
| 67 |
not _semantic_valid(manifest)
|
|
|
|
| 100 |
lab_manifest = _load(lab_dataset_directory / "DATA_MANIFEST.json")
|
| 101 |
if (
|
| 102 |
not _semantic_valid(lab_manifest)
|
| 103 |
+
or lab_manifest.get("schema_version") != "flavourbench-lab-dataset-v2"
|
| 104 |
+
or lab_manifest.get("status") != "preregistered_transfer_maps_not_official_leaderboard_test"
|
| 105 |
):
|
| 106 |
raise CompleteCoreSpaceBuildError("lab dataset manifest failed verification")
|
| 107 |
lab_records = {str(row["name"]): row for row in lab_manifest["files"]}
|
|
|
|
| 115 |
)
|
| 116 |
|
| 117 |
lab_tasks = [*lab_rows("train_tasks.jsonl"), *lab_rows("validation_tasks.jsonl")]
|
| 118 |
+
stability = _load(stability_path)
|
| 119 |
+
if (
|
| 120 |
+
not _semantic_valid(stability)
|
| 121 |
+
or stability.get("schema_version") != "flavourbench-task-count-stability-v1"
|
| 122 |
+
or stability.get("status") != "retrospective_precision_and_stability_analysis"
|
| 123 |
+
):
|
| 124 |
+
raise CompleteCoreSpaceBuildError("task-count stability analysis failed verification")
|
| 125 |
official_ids = {str(row["task_id"]) for row in tasks}
|
| 126 |
official_anchors = {str(row["anchor_ingredient"]) for row in tasks}
|
| 127 |
lab_ids = {str(row["task_id"]) for row in lab_tasks}
|
| 128 |
lab_anchors = {str(row["anchor_ingredient"]) for row in lab_tasks}
|
| 129 |
if (
|
| 130 |
+
len(lab_tasks) != 342
|
| 131 |
+
or len(lab_ids) != 342
|
| 132 |
+
or len(lab_anchors) != 342
|
| 133 |
or lab_ids & official_ids
|
| 134 |
or lab_anchors & official_anchors
|
| 135 |
):
|
|
|
|
| 175 |
"task_count": len(lab_tasks),
|
| 176 |
"train_tasks": int(lab_manifest["counts"]["train_tasks"]),
|
| 177 |
"validation_tasks": int(lab_manifest["counts"]["validation_tasks"]),
|
| 178 |
+
"evaluation_tasks": int(lab_manifest["counts"]["evaluation_tasks"]),
|
| 179 |
"official_anchor_overlap": 0,
|
| 180 |
},
|
| 181 |
"lab_tasks": lab_tasks,
|
| 182 |
+
"stability_analysis": stability,
|
| 183 |
"primary_observations": compact_observations,
|
| 184 |
"pairwise_comparisons": pairwise,
|
| 185 |
}
|
|
|
|
| 216 |
parser = argparse.ArgumentParser(description="Build the final FlavourBench Space bundle")
|
| 217 |
parser.add_argument("--dataset-directory", type=Path, default=DEFAULT_DATASET)
|
| 218 |
parser.add_argument("--lab-dataset-directory", type=Path, default=DEFAULT_LAB_DATASET)
|
| 219 |
+
parser.add_argument("--stability", type=Path, default=DEFAULT_STABILITY)
|
| 220 |
parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT)
|
| 221 |
parser.add_argument("--check", action="store_true")
|
| 222 |
args = parser.parse_args()
|
| 223 |
bundle = build_bundle(
|
| 224 |
dataset_directory=args.dataset_directory,
|
| 225 |
lab_dataset_directory=args.lab_dataset_directory,
|
| 226 |
+
stability_path=args.stability,
|
| 227 |
)
|
| 228 |
payload = _bytes(bundle)
|
| 229 |
if args.check:
|
data-complete-core/flavourbench-complete-core-space.json
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7bb9959b2a73d1c5ef2cafe064805ec874b5f4fa91c05b1d005e4b6e22e4d1ff
|
| 3 |
+
size 14353273
|