relbench 3.0.0__tar.gz → 3.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {relbench-3.0.0 → relbench-3.0.2}/PKG-INFO +13 -39
- {relbench-3.0.0 → relbench-3.0.2}/README.md +12 -38
- {relbench-3.0.0 → relbench-3.0.2}/pyproject.toml +1 -1
- {relbench-3.0.0 → relbench-3.0.2}/relbench/base/task_autocomplete.py +1 -1
- {relbench-3.0.0 → relbench-3.0.2}/relbench/submit.py +208 -10
- {relbench-3.0.0 → relbench-3.0.2}/LICENSE +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/__init__.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/base/__init__.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/base/database.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/base/dataset.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/base/table.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/base/task_base.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/base/task_entity.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/base/task_recommendation.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/hf.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/load.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/manifest.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/metrics.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/modeling/__init__.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/modeling/graph.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/modeling/loader.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/modeling/nn.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/modeling/utils.py +0 -0
- {relbench-3.0.0 → relbench-3.0.2}/relbench/schema.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: relbench
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.2
|
|
4
4
|
Summary: RelBench: Relational Deep Learning Benchmark
|
|
5
5
|
Keywords: relational deep learning,graph neural networks,relational databases,benchmark,machine learning
|
|
6
6
|
Author-email: RelBench Team <relbench@cs.stanford.edu>
|
|
@@ -60,16 +60,7 @@ Provides-Extra: schema
|
|
|
60
60
|
|
|
61
61
|
## News
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
`relbench.load_dataset("<org>/<repo>/<name>")` — the core databases
|
|
65
|
-
([`stanford-star/relbench-v1`](https://huggingface.co/datasets/stanford-star/relbench-v1),
|
|
66
|
-
[`stanford-star/relbench-v2-extra`](https://huggingface.co/datasets/stanford-star/relbench-v2-extra)),
|
|
67
|
-
CTU/ReDeLEx ([`stanford-star/redelex`](https://huggingface.co/datasets/stanford-star/redelex)),
|
|
68
|
-
4DBInfer ([`stanford-star/dbinfer`](https://huggingface.co/datasets/stanford-star/dbinfer)) and
|
|
69
|
-
TGB ([`stanford-star/tgb`](https://huggingface.co/datasets/stanford-star/tgb)); the `[ctu]` extra is
|
|
70
|
-
gone. MIMIC-IV requires PhysioNet credentials and is not hosted. TGB and 4DBInfer tasks that
|
|
71
|
-
use their own scoring protocols load as data only (see [`MIGRATION.md`](MIGRATION.md)).
|
|
72
|
-
|
|
63
|
+
- **Oct 2026** — [Agentic leaderboard submissions](leaderboard/README.md#automatically-eg-from-an-ai-agent): point your AI agent at the [leaderboard README](leaderboard/README.md) and it can submit end to end. Entries can now carry an optional repro link for reproducibility.
|
|
73
64
|
- **Aug 2026** — RelBench v3 released: datasets and tasks load straight from [Hugging Face](https://huggingface.co/stanford-star), a new [leaderboard](https://star-project.stanford.edu/relbench/leaderboard/) with automated submissions, and bug fixes ([migration guide](MIGRATION.md)).
|
|
74
65
|
- **Jun 2026** — Datasets, models, and community hub migrated to [Hugging Face](https://huggingface.co/stanford-star).
|
|
75
66
|
- **Mar 2026** — [RelBench v2 paper](https://arxiv.org/abs/2602.12606) accepted at the [ICLR 2026 DATA-FM workshop](https://data-fm-iclr2026.github.io/).
|
|
@@ -123,31 +114,15 @@ Open these directly in Google Colab — no setup required:
|
|
|
123
114
|
## Leaderboard
|
|
124
115
|
|
|
125
116
|
The [**RelBench leaderboard**](https://star-project.stanford.edu/relbench/leaderboard/)
|
|
126
|
-
ranks methods by their test-set performance, averaged over a fixed task set
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
1. **Write one prediction CSV per task**, named `<dataset>__<task>.csv`, into a directory:
|
|
134
|
-
|
|
135
|
-
```python
|
|
136
|
-
relbench.submit.write_prediction_table(task, test_pred, "preds/rel-f1__driver-position.csv")
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
2. **Validate and package** the directory — this scores every CSV against the test tables,
|
|
140
|
-
prints a verdict per leaderboard, and writes clean submission zip file(s):
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
python -m relbench.submit preds/
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
3. **[Open a submission issue](https://github.com/stanford-star/relbench/issues/new?template=submit.yml)**
|
|
147
|
-
on this repository: fill in the short form and upload the zip file(s) into it.
|
|
117
|
+
ranks methods by their test-set performance, averaged over a fixed task set, with three
|
|
118
|
+
independent boards: **classification**, **regression**, and **recommendation**.
|
|
119
|
+
To submit, write one prediction CSV per task, validate and package them with
|
|
120
|
+
`python -m relbench.submit`, and open a
|
|
121
|
+
[submission issue](https://github.com/stanford-star/relbench/issues/new?template=submit.yml)
|
|
122
|
+
— or let `python -m relbench.submit --submit` do the upload and open the issue for you.
|
|
148
123
|
|
|
149
|
-
|
|
150
|
-
|
|
124
|
+
[**`leaderboard/README.md`**](leaderboard/README.md) has the full instructions, including
|
|
125
|
+
the prediction CSV format for writing predictions with your own code.
|
|
151
126
|
|
|
152
127
|
## BYOD (Bring Your Own Data)
|
|
153
128
|
|
|
@@ -178,13 +153,12 @@ If you use RelBench, please cite the benchmark papers:
|
|
|
178
153
|
year={2024}
|
|
179
154
|
}
|
|
180
155
|
|
|
181
|
-
@
|
|
156
|
+
@inproceedings{relbenchv2,
|
|
182
157
|
title={RelBench v2: A Large-Scale Benchmark and Repository for Relational Data},
|
|
183
158
|
author={Gu, Justin and Ranjan, Rishabh and Kanatsoulis, Charilaos and Tang, Haiming and Jurkovic, Martin and Hudovernik, Valter and Znidar, Mark and Chaturvedi, Pranshu and Shroff, Parth and Li, Fengyu and Leskovec, Jure},
|
|
159
|
+
booktitle={3rd Workshop on Navigating and Addressing Data Problems for Foundation Models (DATA-FM) at ICLR 2026},
|
|
184
160
|
year={2026},
|
|
185
|
-
|
|
186
|
-
archivePrefix={arXiv},
|
|
187
|
-
primaryClass={cs.LG},
|
|
161
|
+
note={arXiv:2602.12606 [cs.LG]},
|
|
188
162
|
url={https://arxiv.org/abs/2602.12606}
|
|
189
163
|
}
|
|
190
164
|
```
|
|
@@ -21,16 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
## News
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
`relbench.load_dataset("<org>/<repo>/<name>")` — the core databases
|
|
26
|
-
([`stanford-star/relbench-v1`](https://huggingface.co/datasets/stanford-star/relbench-v1),
|
|
27
|
-
[`stanford-star/relbench-v2-extra`](https://huggingface.co/datasets/stanford-star/relbench-v2-extra)),
|
|
28
|
-
CTU/ReDeLEx ([`stanford-star/redelex`](https://huggingface.co/datasets/stanford-star/redelex)),
|
|
29
|
-
4DBInfer ([`stanford-star/dbinfer`](https://huggingface.co/datasets/stanford-star/dbinfer)) and
|
|
30
|
-
TGB ([`stanford-star/tgb`](https://huggingface.co/datasets/stanford-star/tgb)); the `[ctu]` extra is
|
|
31
|
-
gone. MIMIC-IV requires PhysioNet credentials and is not hosted. TGB and 4DBInfer tasks that
|
|
32
|
-
use their own scoring protocols load as data only (see [`MIGRATION.md`](MIGRATION.md)).
|
|
33
|
-
|
|
24
|
+
- **Oct 2026** — [Agentic leaderboard submissions](leaderboard/README.md#automatically-eg-from-an-ai-agent): point your AI agent at the [leaderboard README](leaderboard/README.md) and it can submit end to end. Entries can now carry an optional repro link for reproducibility.
|
|
34
25
|
- **Aug 2026** — RelBench v3 released: datasets and tasks load straight from [Hugging Face](https://huggingface.co/stanford-star), a new [leaderboard](https://star-project.stanford.edu/relbench/leaderboard/) with automated submissions, and bug fixes ([migration guide](MIGRATION.md)).
|
|
35
26
|
- **Jun 2026** — Datasets, models, and community hub migrated to [Hugging Face](https://huggingface.co/stanford-star).
|
|
36
27
|
- **Mar 2026** — [RelBench v2 paper](https://arxiv.org/abs/2602.12606) accepted at the [ICLR 2026 DATA-FM workshop](https://data-fm-iclr2026.github.io/).
|
|
@@ -84,31 +75,15 @@ Open these directly in Google Colab — no setup required:
|
|
|
84
75
|
## Leaderboard
|
|
85
76
|
|
|
86
77
|
The [**RelBench leaderboard**](https://star-project.stanford.edu/relbench/leaderboard/)
|
|
87
|
-
ranks methods by their test-set performance, averaged over a fixed task set
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
1. **Write one prediction CSV per task**, named `<dataset>__<task>.csv`, into a directory:
|
|
95
|
-
|
|
96
|
-
```python
|
|
97
|
-
relbench.submit.write_prediction_table(task, test_pred, "preds/rel-f1__driver-position.csv")
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
2. **Validate and package** the directory — this scores every CSV against the test tables,
|
|
101
|
-
prints a verdict per leaderboard, and writes clean submission zip file(s):
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
python -m relbench.submit preds/
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
3. **[Open a submission issue](https://github.com/stanford-star/relbench/issues/new?template=submit.yml)**
|
|
108
|
-
on this repository: fill in the short form and upload the zip file(s) into it.
|
|
78
|
+
ranks methods by their test-set performance, averaged over a fixed task set, with three
|
|
79
|
+
independent boards: **classification**, **regression**, and **recommendation**.
|
|
80
|
+
To submit, write one prediction CSV per task, validate and package them with
|
|
81
|
+
`python -m relbench.submit`, and open a
|
|
82
|
+
[submission issue](https://github.com/stanford-star/relbench/issues/new?template=submit.yml)
|
|
83
|
+
— or let `python -m relbench.submit --submit` do the upload and open the issue for you.
|
|
109
84
|
|
|
110
|
-
|
|
111
|
-
|
|
85
|
+
[**`leaderboard/README.md`**](leaderboard/README.md) has the full instructions, including
|
|
86
|
+
the prediction CSV format for writing predictions with your own code.
|
|
112
87
|
|
|
113
88
|
## BYOD (Bring Your Own Data)
|
|
114
89
|
|
|
@@ -139,13 +114,12 @@ If you use RelBench, please cite the benchmark papers:
|
|
|
139
114
|
year={2024}
|
|
140
115
|
}
|
|
141
116
|
|
|
142
|
-
@
|
|
117
|
+
@inproceedings{relbenchv2,
|
|
143
118
|
title={RelBench v2: A Large-Scale Benchmark and Repository for Relational Data},
|
|
144
119
|
author={Gu, Justin and Ranjan, Rishabh and Kanatsoulis, Charilaos and Tang, Haiming and Jurkovic, Martin and Hudovernik, Valter and Znidar, Mark and Chaturvedi, Pranshu and Shroff, Parth and Li, Fengyu and Leskovec, Jure},
|
|
120
|
+
booktitle={3rd Workshop on Navigating and Addressing Data Problems for Foundation Models (DATA-FM) at ICLR 2026},
|
|
145
121
|
year={2026},
|
|
146
|
-
|
|
147
|
-
archivePrefix={arXiv},
|
|
148
|
-
primaryClass={cs.LG},
|
|
122
|
+
note={arXiv:2602.12606 [cs.LG]},
|
|
149
123
|
url={https://arxiv.org/abs/2602.12606}
|
|
150
124
|
}
|
|
151
125
|
```
|
|
@@ -4,7 +4,7 @@ build-backend = "flit_core.buildapi"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "relbench"
|
|
7
|
-
version = "3.0.
|
|
7
|
+
version = "3.0.2"
|
|
8
8
|
description = "RelBench: Relational Deep Learning Benchmark"
|
|
9
9
|
authors = [{name = "RelBench Team", email = "relbench@cs.stanford.edu"}]
|
|
10
10
|
readme = "README.md"
|
|
@@ -139,7 +139,7 @@ class AutoCompleteTask(EntityTask):
|
|
|
139
139
|
db = full_db if split == "test" else full_db.upto(self.dataset.test_timestamp)
|
|
140
140
|
|
|
141
141
|
if split == "train":
|
|
142
|
-
start = db.min_timestamp -
|
|
142
|
+
start = db.min_timestamp - self.timedelta
|
|
143
143
|
end = self.dataset.val_timestamp
|
|
144
144
|
elif split == "val":
|
|
145
145
|
start, end = self.dataset.val_timestamp, self.dataset.test_timestamp
|
|
@@ -5,8 +5,8 @@ library, ``pandas``/``numpy`` and the rest of RelBench's data layer (no torch /
|
|
|
5
5
|
torch_geometric / pyg), so it imports cleanly in a minimal environment and can score a
|
|
6
6
|
submission produced by any modelling stack.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
The prediction table
|
|
9
|
+
====================
|
|
10
10
|
The test split of a task is a *task table*. A *prediction table* is the same table with
|
|
11
11
|
the target column replaced by predictions:
|
|
12
12
|
|
|
@@ -46,6 +46,7 @@ from __future__ import annotations
|
|
|
46
46
|
import argparse
|
|
47
47
|
import json
|
|
48
48
|
import os
|
|
49
|
+
import sys
|
|
49
50
|
from concurrent.futures import ProcessPoolExecutor
|
|
50
51
|
from pathlib import Path
|
|
51
52
|
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
|
|
@@ -806,6 +807,15 @@ def _use_color() -> bool:
|
|
|
806
807
|
return False
|
|
807
808
|
|
|
808
809
|
|
|
810
|
+
def _glyph(unicode: str, ascii_fallback: str) -> str:
|
|
811
|
+
encoding = getattr(sys.stdout, "encoding", None) or "ascii"
|
|
812
|
+
try:
|
|
813
|
+
unicode.encode(encoding)
|
|
814
|
+
except (UnicodeEncodeError, LookupError):
|
|
815
|
+
return ascii_fallback
|
|
816
|
+
return unicode
|
|
817
|
+
|
|
818
|
+
|
|
809
819
|
class _Style:
|
|
810
820
|
r"""Tiny ANSI styler; every method degrades to the identity without a TTY."""
|
|
811
821
|
|
|
@@ -933,18 +943,18 @@ def _print_report(result: Dict[str, Any]) -> None:
|
|
|
933
943
|
for task_name in group_tasks:
|
|
934
944
|
entry = tasks[task_name]
|
|
935
945
|
if entry["status"] == "ok":
|
|
936
|
-
mark = st.green("✓")
|
|
946
|
+
mark = st.green(_glyph("✓", "OK"))
|
|
937
947
|
value = _format_value(entry["metric_name"], entry["metric"])
|
|
938
948
|
print(f" {mark} {task_name.ljust(name_w)} {value.rjust(7)}")
|
|
939
949
|
else:
|
|
940
|
-
mark = st.red("✗")
|
|
950
|
+
mark = st.red(_glyph("✗", "X"))
|
|
941
951
|
print(f" {mark} {task_name.ljust(name_w)} {st.red('failed')}")
|
|
942
952
|
for line in _wrap_text(entry["error"] or "unknown error", indent=6):
|
|
943
953
|
print(st.dim(line))
|
|
944
954
|
if fam is not None and fam["missing"]:
|
|
945
955
|
for task_name in fam["missing"]:
|
|
946
956
|
print(
|
|
947
|
-
f" {st.yellow('·')} {task_name.ljust(name_w)} "
|
|
957
|
+
f" {st.yellow(_glyph('·', '-'))} {task_name.ljust(name_w)} "
|
|
948
958
|
+ st.dim("missing")
|
|
949
959
|
)
|
|
950
960
|
if fam is not None and fam["aggregate"] is not None:
|
|
@@ -1045,9 +1055,11 @@ def _markdown_report(result: Dict[str, Any]) -> str:
|
|
|
1045
1055
|
# Where validated submissions are turned into leaderboard entries: a submission is a GitHub
|
|
1046
1056
|
# issue on the RelBench repository, created from the submission form with the prediction
|
|
1047
1057
|
# tables attached. CI validates it and a maintainer approval publishes the entry.
|
|
1058
|
+
SUBMISSION_REPO = "stanford-star/relbench"
|
|
1048
1059
|
SUBMISSION_ISSUE_URL = (
|
|
1049
|
-
"https://github.com/
|
|
1060
|
+
f"https://github.com/{SUBMISSION_REPO}/issues/new?template=submit.yml"
|
|
1050
1061
|
)
|
|
1062
|
+
SUBMISSION_HF_REPO = "relbench-submissions"
|
|
1051
1063
|
|
|
1052
1064
|
|
|
1053
1065
|
def _zip_files(pred_dir: Path, filenames: Sequence[str]) -> bytes:
|
|
@@ -1068,7 +1080,8 @@ def _package(
|
|
|
1068
1080
|
validated: Sequence[str],
|
|
1069
1081
|
extra: Sequence[str],
|
|
1070
1082
|
out: Path,
|
|
1071
|
-
|
|
1083
|
+
show_next_step: bool = True,
|
|
1084
|
+
) -> List[Path]:
|
|
1072
1085
|
r"""Write one submission zip per validated family and print how to submit them.
|
|
1073
1086
|
|
|
1074
1087
|
A single all-in-one zip easily exceeds GitHub's issue-attachment size limit; the
|
|
@@ -1091,11 +1104,134 @@ def _package(
|
|
|
1091
1104
|
fam_out.write_bytes(zip_bytes)
|
|
1092
1105
|
outputs.append((fam_out, len(zip_bytes)))
|
|
1093
1106
|
print("\r", end="", flush=True)
|
|
1107
|
+
if not show_next_step:
|
|
1108
|
+
return [p for p, _ in outputs]
|
|
1094
1109
|
print(st.bold("Next step "))
|
|
1095
1110
|
print(f" Upload these files at {st.underline_cyan(SUBMISSION_ISSUE_URL)}:")
|
|
1096
1111
|
for fam_out, size in outputs:
|
|
1097
1112
|
print(f" {st.bold(str(fam_out))} " + st.italic(f"({size / 1e6:.1f} MB)"))
|
|
1098
1113
|
print()
|
|
1114
|
+
return [p for p, _ in outputs]
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
def _github_token() -> str:
|
|
1118
|
+
import subprocess
|
|
1119
|
+
|
|
1120
|
+
for var in ("GH_TOKEN", "GITHUB_TOKEN"):
|
|
1121
|
+
if os.environ.get(var):
|
|
1122
|
+
return os.environ[var]
|
|
1123
|
+
try:
|
|
1124
|
+
token = subprocess.run(
|
|
1125
|
+
["gh", "auth", "token"], capture_output=True, text=True, check=True
|
|
1126
|
+
).stdout.strip()
|
|
1127
|
+
except (OSError, subprocess.CalledProcessError):
|
|
1128
|
+
token = ""
|
|
1129
|
+
if not token:
|
|
1130
|
+
raise RuntimeError(
|
|
1131
|
+
"no GitHub token: set GH_TOKEN or GITHUB_TOKEN, or run `gh auth login`"
|
|
1132
|
+
)
|
|
1133
|
+
return token
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
def _upload_to_hf(zips: Sequence[Path]) -> List[str]:
|
|
1137
|
+
import tempfile
|
|
1138
|
+
from datetime import datetime, timezone
|
|
1139
|
+
|
|
1140
|
+
from huggingface_hub import CommitOperationAdd, HfApi
|
|
1141
|
+
|
|
1142
|
+
api = HfApi()
|
|
1143
|
+
user = api.whoami()["name"]
|
|
1144
|
+
repo_id = f"{user}/{SUBMISSION_HF_REPO}"
|
|
1145
|
+
api.create_repo(repo_id, repo_type="dataset", private=False, exist_ok=True)
|
|
1146
|
+
folder = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
|
|
1147
|
+
ops = [
|
|
1148
|
+
CommitOperationAdd(path_in_repo=f"{folder}/{z.name}", path_or_fileobj=str(z))
|
|
1149
|
+
for z in zips
|
|
1150
|
+
]
|
|
1151
|
+
commit = api.create_commit(
|
|
1152
|
+
repo_id,
|
|
1153
|
+
operations=ops,
|
|
1154
|
+
repo_type="dataset",
|
|
1155
|
+
commit_message=f"RelBench leaderboard submission {folder}",
|
|
1156
|
+
)
|
|
1157
|
+
return [
|
|
1158
|
+
f"https://huggingface.co/datasets/{repo_id}/resolve/{commit.oid}/{op.path_in_repo}"
|
|
1159
|
+
for op in ops
|
|
1160
|
+
]
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
def _issue_body(
|
|
1164
|
+
name: str,
|
|
1165
|
+
url: str,
|
|
1166
|
+
in_context: bool,
|
|
1167
|
+
note: str,
|
|
1168
|
+
links: Sequence[str],
|
|
1169
|
+
repro_link: str = "",
|
|
1170
|
+
) -> str:
|
|
1171
|
+
files = "\n".join(f"[{u.rsplit('/', 1)[-1]}]({u})" for u in links)
|
|
1172
|
+
return (
|
|
1173
|
+
f"### Name\n\n{name}\n\n"
|
|
1174
|
+
f"### Note\n\n{note or '_No response_'}\n\n"
|
|
1175
|
+
f"### In-context?\n\n{'Yes' if in_context else 'No'}\n\n"
|
|
1176
|
+
f"### URL\n\n{url}\n\n"
|
|
1177
|
+
f"### Repro link\n\n{repro_link or '_No response_'}\n\n"
|
|
1178
|
+
f"### File(s)\n\n{files}\n"
|
|
1179
|
+
)
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
def _edit_issue_body(
|
|
1183
|
+
entry: int, name: str = "", url: str = "", repro_link: str = "", note: str = ""
|
|
1184
|
+
) -> str:
|
|
1185
|
+
return "".join(
|
|
1186
|
+
f"### {h}\n\n{v or '_No response_'}\n\n"
|
|
1187
|
+
for h, v in [
|
|
1188
|
+
("Entry", str(entry)),
|
|
1189
|
+
("Name", name),
|
|
1190
|
+
("URL", url),
|
|
1191
|
+
("Repro link", repro_link),
|
|
1192
|
+
("Note", note),
|
|
1193
|
+
]
|
|
1194
|
+
)
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
def _open_issue(
|
|
1198
|
+
body: str, title: str = "Leaderboard submission", label: str = "submit"
|
|
1199
|
+
) -> str:
|
|
1200
|
+
import urllib.request
|
|
1201
|
+
|
|
1202
|
+
req = urllib.request.Request(
|
|
1203
|
+
f"https://api.github.com/repos/{SUBMISSION_REPO}/issues",
|
|
1204
|
+
data=json.dumps({"title": title, "body": body, "labels": [label]}).encode(),
|
|
1205
|
+
headers={
|
|
1206
|
+
"Authorization": f"Bearer {_github_token()}",
|
|
1207
|
+
"Accept": "application/vnd.github+json",
|
|
1208
|
+
"User-Agent": "relbench-submit",
|
|
1209
|
+
},
|
|
1210
|
+
method="POST",
|
|
1211
|
+
)
|
|
1212
|
+
with urllib.request.urlopen(req, timeout=60) as r:
|
|
1213
|
+
return json.load(r)["html_url"]
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
def _submit(zips: Sequence[Path], args: argparse.Namespace) -> None:
|
|
1217
|
+
st = _Style(_use_color())
|
|
1218
|
+
print("Uploading to the Hugging Face Hub...", flush=True)
|
|
1219
|
+
links = _upload_to_hf(zips)
|
|
1220
|
+
for u in links:
|
|
1221
|
+
print(f" {u}")
|
|
1222
|
+
body = _issue_body(
|
|
1223
|
+
args.name,
|
|
1224
|
+
args.url,
|
|
1225
|
+
args.in_context == "yes",
|
|
1226
|
+
args.note or "",
|
|
1227
|
+
links,
|
|
1228
|
+
args.repro_link or "",
|
|
1229
|
+
)
|
|
1230
|
+
issue = _open_issue(body)
|
|
1231
|
+
print()
|
|
1232
|
+
print(st.bold("Submitted ") + st.underline_cyan(issue))
|
|
1233
|
+
print(" Validation results will be posted on the issue.")
|
|
1234
|
+
print()
|
|
1099
1235
|
|
|
1100
1236
|
|
|
1101
1237
|
def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
@@ -1113,7 +1249,9 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
1113
1249
|
),
|
|
1114
1250
|
)
|
|
1115
1251
|
parser.add_argument(
|
|
1116
|
-
"pred_dir",
|
|
1252
|
+
"pred_dir",
|
|
1253
|
+
nargs="?",
|
|
1254
|
+
help="directory of <dataset>__<task>.csv prediction files",
|
|
1117
1255
|
)
|
|
1118
1256
|
parser.add_argument(
|
|
1119
1257
|
"--num-workers",
|
|
@@ -1129,7 +1267,64 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
1129
1267
|
"<base>-<family>.zip (default base: <dir-name>.zip in the cwd)"
|
|
1130
1268
|
),
|
|
1131
1269
|
)
|
|
1270
|
+
parser.add_argument(
|
|
1271
|
+
"--submit",
|
|
1272
|
+
action="store_true",
|
|
1273
|
+
help=(
|
|
1274
|
+
"upload the zips to <hf-user>/relbench-submissions on the Hugging Face Hub "
|
|
1275
|
+
"(needs a Hugging Face login) and open the submission issue on GitHub "
|
|
1276
|
+
"(needs GH_TOKEN / GITHUB_TOKEN or `gh auth login`)"
|
|
1277
|
+
),
|
|
1278
|
+
)
|
|
1279
|
+
parser.add_argument("--name", help="with --submit: display name on the leaderboard")
|
|
1280
|
+
parser.add_argument("--url", help="with --submit: project / code / paper link")
|
|
1281
|
+
parser.add_argument(
|
|
1282
|
+
"--in-context",
|
|
1283
|
+
choices=["yes", "no"],
|
|
1284
|
+
help="with --submit: yes if the method did NOT train on the target database",
|
|
1285
|
+
)
|
|
1286
|
+
parser.add_argument("--note", help="with --submit: optional note, shown on hover")
|
|
1287
|
+
parser.add_argument(
|
|
1288
|
+
"--repro-link",
|
|
1289
|
+
help="with --submit: optional link to code / instructions to reproduce the results",
|
|
1290
|
+
)
|
|
1291
|
+
parser.add_argument(
|
|
1292
|
+
"--edit",
|
|
1293
|
+
type=int,
|
|
1294
|
+
metavar="ISSUE",
|
|
1295
|
+
help=(
|
|
1296
|
+
"instead of submitting, open an issue that updates the --name, --url, "
|
|
1297
|
+
"--repro-link, and/or --note of the leaderboard entry published from "
|
|
1298
|
+
"submission issue ISSUE (needs a GitHub token, as for --submit)"
|
|
1299
|
+
),
|
|
1300
|
+
)
|
|
1132
1301
|
args = parser.parse_args(argv)
|
|
1302
|
+
if args.edit is not None:
|
|
1303
|
+
if not (args.name or args.url or args.repro_link or args.note):
|
|
1304
|
+
parser.error("--edit requires --name, --url, --repro-link, or --note")
|
|
1305
|
+
issue = _open_issue(
|
|
1306
|
+
_edit_issue_body(
|
|
1307
|
+
args.edit,
|
|
1308
|
+
args.name or "",
|
|
1309
|
+
args.url or "",
|
|
1310
|
+
args.repro_link or "",
|
|
1311
|
+
args.note or "",
|
|
1312
|
+
),
|
|
1313
|
+
title="Leaderboard entry edit",
|
|
1314
|
+
label="edit",
|
|
1315
|
+
)
|
|
1316
|
+
print(f"Opened {issue}")
|
|
1317
|
+
return 0
|
|
1318
|
+
if args.pred_dir is None:
|
|
1319
|
+
parser.error("pred_dir is required unless --edit is given")
|
|
1320
|
+
if args.submit:
|
|
1321
|
+
missing = [
|
|
1322
|
+
f"--{k.replace('_', '-')}"
|
|
1323
|
+
for k in ("name", "url", "in_context")
|
|
1324
|
+
if not getattr(args, k)
|
|
1325
|
+
]
|
|
1326
|
+
if missing:
|
|
1327
|
+
parser.error("--submit requires " + ", ".join(missing))
|
|
1133
1328
|
if args.out is not None and not args.out.endswith(".zip"):
|
|
1134
1329
|
args.out += ".zip"
|
|
1135
1330
|
|
|
@@ -1139,18 +1334,21 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
1139
1334
|
st = _Style(_use_color())
|
|
1140
1335
|
print(
|
|
1141
1336
|
st.bold_red("Cannot package")
|
|
1142
|
-
+ " — no leaderboard was validated; fix the prediction tables first."
|
|
1337
|
+
+ f" {_glyph('—', '-')} no leaderboard was validated; fix the prediction tables first."
|
|
1143
1338
|
)
|
|
1144
1339
|
print()
|
|
1145
1340
|
return 1
|
|
1146
1341
|
out = Path(args.out or f"{Path(args.pred_dir).resolve().name}.zip")
|
|
1147
|
-
_package(
|
|
1342
|
+
zips = _package(
|
|
1148
1343
|
args.pred_dir,
|
|
1149
1344
|
result["families"],
|
|
1150
1345
|
result["validated"],
|
|
1151
1346
|
result.get("extra_files") or [],
|
|
1152
1347
|
out,
|
|
1348
|
+
show_next_step=not args.submit,
|
|
1153
1349
|
)
|
|
1350
|
+
if args.submit:
|
|
1351
|
+
_submit(zips, args)
|
|
1154
1352
|
return 0
|
|
1155
1353
|
|
|
1156
1354
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|