CP Legendre commited on
Commit
f0eabe1
·
1 Parent(s): 7bb515c

Combine leaderboard and cost performance charts

Browse files
app.py CHANGED
@@ -43,20 +43,27 @@ def patch_gradio_leaderboard():
43
  patch_gradio_leaderboard()
44
 
45
  import gradio as gr
46
- from gradio_leaderboard import Leaderboard, ColumnFilter, SelectColumns
47
  from apscheduler.schedulers.background import BackgroundScheduler
 
48
  from huggingface_hub import HfApi
49
 
50
- from src.leaderboard import get_leaderboard_df, get_benchmark_run_df
 
 
 
 
51
  from src.display.text_blocks import (
52
  HOW_TO_USE_TEXT,
53
  INTRODUCTION_TEXT,
54
  LLM_BENCHMARKS_TEXT,
55
  )
 
56
 
57
  REPO_ID = "taagarwa/coding-agent-leaderboard"
58
  TOKEN = os.environ.get("HF_TOKEN")
59
  API = HfApi(token=TOKEN)
 
 
60
 
61
  def restart_space():
62
  API.restart_space(repo_id=REPO_ID)
@@ -64,9 +71,41 @@ def restart_space():
64
 
65
  LEADERBOARD_DF = get_leaderboard_df()
66
  BENCHMARK_RUN_DF = get_benchmark_run_df()
 
 
67
 
68
  def extract_body(s: str):
69
- return re.match(r'\[(.*?)\]', s).group(1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
 
72
  def build_header_html(df):
@@ -96,11 +135,12 @@ def build_header_html(df):
96
  </div>
97
  </div>
98
  """
99
-
 
100
  def init_leaderboard(dataframe):
101
  if dataframe is None or dataframe.empty:
102
  raise ValueError("Leaderboard DataFrame is empty or None.")
103
-
104
  label_choices = [("🟠 Fully FOSS", "🟠"), ("🔶 Proprietary", "🔶")]
105
  meta_columns = [" ", "Harness", "Model", "Harness License", "Model License", "Model Num Params (B)", "Precision"]
106
  benchmark_columns = [col for col in dataframe.columns if col not in meta_columns]
@@ -126,14 +166,14 @@ def init_leaderboard(dataframe):
126
  interactive=False,
127
  )
128
 
 
129
  def init_benchmark_runs(dataframe):
130
  if dataframe is None or dataframe.empty:
131
  raise ValueError("Leaderboard DataFrame is empty or None.")
132
-
133
- # Make ColumnFilter choices
134
  label_choices = [("🟠 Fully FOSS", "🟠"), ("🔶 Proprietary", "🔶")]
135
- benchmark_choices = sorted({(extract_body(v), v) for v in dataframe["Benchmark"]})
136
-
137
  return Leaderboard(
138
  value=dataframe,
139
  select_columns=SelectColumns(
@@ -162,22 +202,64 @@ def init_benchmark_runs(dataframe):
162
  interactive=False,
163
  )
164
 
 
 
 
165
  demo = gr.Blocks(theme="citrus")
166
  with demo:
167
  gr.HTML(build_header_html(BENCHMARK_RUN_DF))
168
  gr.Markdown(INTRODUCTION_TEXT, elem_classes="markdown-text")
169
 
170
  with gr.Tabs():
171
- with gr.Tab("🏆 Leaderboard"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  leaderboard = init_leaderboard(LEADERBOARD_DF)
173
 
174
- with gr.Tab("🏃 Benchmark Runs"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  benchmark_runs = init_benchmark_runs(BENCHMARK_RUN_DF)
176
 
177
- with gr.Tab("📝 About"):
178
  gr.Markdown(LLM_BENCHMARKS_TEXT, elem_classes="markdown-text")
179
-
180
- gr.Markdown(HOW_TO_USE_TEXT, elem_classes="markdown-text")
181
 
182
  scheduler = BackgroundScheduler()
183
  scheduler.add_job(restart_space, "interval", seconds=1800)
 
43
  patch_gradio_leaderboard()
44
 
45
  import gradio as gr
 
46
  from apscheduler.schedulers.background import BackgroundScheduler
47
+ from gradio_leaderboard import ColumnFilter, Leaderboard, SelectColumns
48
  from huggingface_hub import HfApi
49
 
50
+ from src.charts import (
51
+ clean_markdown_link,
52
+ create_leaderboard_benchmark_plot,
53
+ create_score_vs_cost_plot,
54
+ )
55
  from src.display.text_blocks import (
56
  HOW_TO_USE_TEXT,
57
  INTRODUCTION_TEXT,
58
  LLM_BENCHMARKS_TEXT,
59
  )
60
+ from src.leaderboard import get_benchmark_run_df, get_leaderboard_df, get_score_vs_cost_df
61
 
62
  REPO_ID = "taagarwa/coding-agent-leaderboard"
63
  TOKEN = os.environ.get("HF_TOKEN")
64
  API = HfApi(token=TOKEN)
65
+ COLOR_BY_CHOICES = ["Model", "Harness"]
66
+
67
 
68
  def restart_space():
69
  API.restart_space(repo_id=REPO_ID)
 
71
 
72
  LEADERBOARD_DF = get_leaderboard_df()
73
  BENCHMARK_RUN_DF = get_benchmark_run_df()
74
+ SCORE_VS_COST_DF = get_score_vs_cost_df()
75
+
76
 
77
  def extract_body(s: str):
78
+ match = re.match(r"\[(.*?)\]", str(s))
79
+ return match.group(1) if match else str(s)
80
+
81
+
82
+ def get_leaderboard_benchmark_names(dataframe):
83
+ meta_columns = {
84
+ " ",
85
+ "Harness",
86
+ "Model",
87
+ "Harness License",
88
+ "Model License",
89
+ "Model Num Params (B)",
90
+ "Precision",
91
+ "Avg Score",
92
+ }
93
+ return [col for col in dataframe.columns if col not in meta_columns]
94
+
95
+
96
+ def render_leaderboard_benchmark_plot(benchmark_name, color_by):
97
+ return create_leaderboard_benchmark_plot(
98
+ BENCHMARK_RUN_DF,
99
+ benchmark_name=benchmark_name,
100
+ color_by=color_by,
101
+ )
102
+
103
+
104
+ def render_score_vs_cost_plot(color_by):
105
+ return create_score_vs_cost_plot(
106
+ SCORE_VS_COST_DF,
107
+ color_by=color_by,
108
+ )
109
 
110
 
111
  def build_header_html(df):
 
135
  </div>
136
  </div>
137
  """
138
+
139
+
140
  def init_leaderboard(dataframe):
141
  if dataframe is None or dataframe.empty:
142
  raise ValueError("Leaderboard DataFrame is empty or None.")
143
+
144
  label_choices = [("🟠 Fully FOSS", "🟠"), ("🔶 Proprietary", "🔶")]
145
  meta_columns = [" ", "Harness", "Model", "Harness License", "Model License", "Model Num Params (B)", "Precision"]
146
  benchmark_columns = [col for col in dataframe.columns if col not in meta_columns]
 
166
  interactive=False,
167
  )
168
 
169
+
170
  def init_benchmark_runs(dataframe):
171
  if dataframe is None or dataframe.empty:
172
  raise ValueError("Leaderboard DataFrame is empty or None.")
173
+
 
174
  label_choices = [("🟠 Fully FOSS", "🟠"), ("🔶 Proprietary", "🔶")]
175
+ benchmark_choices = sorted({(clean_markdown_link(v), v) for v in dataframe["Benchmark"]})
176
+
177
  return Leaderboard(
178
  value=dataframe,
179
  select_columns=SelectColumns(
 
202
  interactive=False,
203
  )
204
 
205
+
206
+ leaderboard_benchmark_names = get_leaderboard_benchmark_names(LEADERBOARD_DF)
207
+
208
  demo = gr.Blocks(theme="citrus")
209
  with demo:
210
  gr.HTML(build_header_html(BENCHMARK_RUN_DF))
211
  gr.Markdown(INTRODUCTION_TEXT, elem_classes="markdown-text")
212
 
213
  with gr.Tabs():
214
+ with gr.Tab("Leaderboard"):
215
+ gr.Markdown("### Benchmark scores")
216
+ leaderboard_color_by = gr.Radio(
217
+ choices=COLOR_BY_CHOICES,
218
+ value="Model",
219
+ label="Color by",
220
+ )
221
+
222
+ leaderboard_plots = []
223
+ for benchmark_name in leaderboard_benchmark_names:
224
+ gr.Markdown(f"#### {benchmark_name}")
225
+ plot = gr.Plot(
226
+ value=render_leaderboard_benchmark_plot(benchmark_name, "Model"),
227
+ show_label=False,
228
+ )
229
+ leaderboard_plots.append((benchmark_name, plot))
230
+
231
+ for benchmark_name, plot in leaderboard_plots:
232
+ leaderboard_color_by.change(
233
+ fn=lambda color_by, name=benchmark_name: render_leaderboard_benchmark_plot(name, color_by),
234
+ inputs=leaderboard_color_by,
235
+ outputs=plot,
236
+ )
237
+
238
+ gr.Markdown("### Leaderboard table")
239
  leaderboard = init_leaderboard(LEADERBOARD_DF)
240
 
241
+ with gr.Tab("Cost vs Performance"):
242
+ cost_color_by = gr.Radio(
243
+ choices=COLOR_BY_CHOICES,
244
+ value="Model",
245
+ label="Color by",
246
+ )
247
+ score_vs_cost_plot = gr.Plot(
248
+ value=render_score_vs_cost_plot("Model"),
249
+ show_label=False,
250
+ )
251
+ cost_color_by.change(
252
+ fn=render_score_vs_cost_plot,
253
+ inputs=cost_color_by,
254
+ outputs=score_vs_cost_plot,
255
+ )
256
+
257
+ with gr.Tab("Benchmark Runs"):
258
  benchmark_runs = init_benchmark_runs(BENCHMARK_RUN_DF)
259
 
260
+ with gr.Tab("About"):
261
  gr.Markdown(LLM_BENCHMARKS_TEXT, elem_classes="markdown-text")
262
+ gr.Markdown(HOW_TO_USE_TEXT, elem_classes="markdown-text")
 
263
 
264
  scheduler = BackgroundScheduler()
265
  scheduler.add_job(restart_space, "interval", seconds=1800)
requirements.txt CHANGED
@@ -9,8 +9,9 @@ huggingface-hub>=0.18.0
9
  matplotlib
10
  numpy
11
  pandas
 
12
  python-dateutil
13
  tqdm
14
  transformers
15
  tokenizers>=0.15.0
16
- sentencepiece
 
9
  matplotlib
10
  numpy
11
  pandas
12
+ plotly
13
  python-dateutil
14
  tqdm
15
  transformers
16
  tokenizers>=0.15.0
17
+ sentencepiece
results/swe-bench-pro--ansible-claude-opus-4-8-claude-code.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-pro--ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
@@ -57,4 +57,4 @@
57
  "mean_total_time_seconds_per_task": 406,
58
  "mean_agent_time_seconds_per_task": 341
59
  }
60
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Pro -- Ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
 
57
  "mean_total_time_seconds_per_task": 406,
58
  "mean_agent_time_seconds_per_task": 341
59
  }
60
+ }
results/swe-bench-pro--ansible-claude-opus-4-8-opencode.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-pro--ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
@@ -57,4 +57,4 @@
57
  "mean_total_time_seconds_per_task": 409,
58
  "mean_agent_time_seconds_per_task": 319
59
  }
60
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Pro -- Ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
 
57
  "mean_total_time_seconds_per_task": 409,
58
  "mean_agent_time_seconds_per_task": 319
59
  }
60
+ }
results/swe-bench-pro--ansible-claude-sonnet-4-6-claude-code.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-pro--ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
@@ -57,4 +57,4 @@
57
  "mean_total_time_seconds_per_task": 518,
58
  "mean_agent_time_seconds_per_task": 422
59
  }
60
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Pro -- Ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
 
57
  "mean_total_time_seconds_per_task": 518,
58
  "mean_agent_time_seconds_per_task": 422
59
  }
60
+ }
results/swe-bench-pro--ansible-gpt-5-5-codex.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-pro--ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
@@ -57,4 +57,4 @@
57
  "mean_total_time_seconds_per_task": 411,
58
  "mean_agent_time_seconds_per_task": 342
59
  }
60
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Pro -- Ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
 
57
  "mean_total_time_seconds_per_task": 411,
58
  "mean_agent_time_seconds_per_task": 342
59
  }
60
+ }
results/swe-bench-pro--ansible-qwen3-6-35b-nvfp4-claude-code.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-pro--ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
@@ -12,7 +12,7 @@
12
  "url": "https://github.com/anthropics/claude-code"
13
  },
14
  "model": {
15
- "name": "Qwen3.6-35B-A3B",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
@@ -57,4 +57,4 @@
57
  "mean_total_time_seconds_per_task": 487,
58
  "mean_agent_time_seconds_per_task": 406
59
  }
60
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Pro -- Ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
 
12
  "url": "https://github.com/anthropics/claude-code"
13
  },
14
  "model": {
15
+ "name": "Qwen3.6-35B-A3B-NVFP4",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
 
57
  "mean_total_time_seconds_per_task": 487,
58
  "mean_agent_time_seconds_per_task": 406
59
  }
60
+ }
results/swe-bench-pro--ansible-qwen3-6-35b-nvfp4-opencode.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-pro--ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
@@ -12,7 +12,7 @@
12
  "url": "https://github.com/anomalyco/opencode"
13
  },
14
  "model": {
15
- "name": "Qwen3.6-35B-A3B",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
@@ -57,4 +57,4 @@
57
  "mean_total_time_seconds_per_task": 596,
58
  "mean_agent_time_seconds_per_task": 515
59
  }
60
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Pro -- Ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
 
12
  "url": "https://github.com/anomalyco/opencode"
13
  },
14
  "model": {
15
+ "name": "Qwen3.6-35B-A3B-NVFP4",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
 
57
  "mean_total_time_seconds_per_task": 596,
58
  "mean_agent_time_seconds_per_task": 515
59
  }
60
+ }
results/swe-bench-pro--ansible-qwen3-6-36b-nvfp4-openclaw.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-pro--ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
@@ -12,7 +12,7 @@
12
  "url": "https://github.com/openclaw/openclaw"
13
  },
14
  "model": {
15
- "name": "Qwen3.6-35B-A3B",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
@@ -57,4 +57,4 @@
57
  "mean_total_time_seconds_per_task": 528,
58
  "mean_agent_time_seconds_per_task": 396
59
  }
60
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Pro -- Ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
 
12
  "url": "https://github.com/openclaw/openclaw"
13
  },
14
  "model": {
15
+ "name": "Qwen3.6-35B-A3B-NVFP4",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
 
57
  "mean_total_time_seconds_per_task": 528,
58
  "mean_agent_time_seconds_per_task": 396
59
  }
60
+ }
results/swe-bench-pro--ansible-qwen3-6-36b-nvfp4-pi.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-pro--ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
@@ -12,7 +12,7 @@
12
  "url": "https://github.com/earendil-works/pi/tree/main"
13
  },
14
  "model": {
15
- "name": "Qwen3.6-35B-A3B",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
@@ -57,4 +57,4 @@
57
  "mean_total_time_seconds_per_task": 650,
58
  "mean_agent_time_seconds_per_task": 568
59
  }
60
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Pro -- Ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
 
12
  "url": "https://github.com/earendil-works/pi/tree/main"
13
  },
14
  "model": {
15
+ "name": "Qwen3.6-35B-A3B-NVFP4",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
 
57
  "mean_total_time_seconds_per_task": 650,
58
  "mean_agent_time_seconds_per_task": 568
59
  }
60
+ }
results/swe-bench-pro--ansible-qwen3-6-36b-nvfp4-qwen-code.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-pro--ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
@@ -12,7 +12,7 @@
12
  "url": "https://github.com/QwenLM/qwen-code"
13
  },
14
  "model": {
15
- "name": "Qwen3.6-35B-A3B",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
@@ -57,4 +57,4 @@
57
  "mean_total_time_seconds_per_task": 398,
58
  "mean_agent_time_seconds_per_task": 350
59
  }
60
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Pro -- Ansible",
4
  "repo": "ScaleAI/SWE-bench_Pro",
5
  "num_tasks": 96,
6
  "url": "https://huggingface.co/datasets/ScaleAI/SWE-bench_Pro"
 
12
  "url": "https://github.com/QwenLM/qwen-code"
13
  },
14
  "model": {
15
+ "name": "Qwen3.6-35B-A3B-NVFP4",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
 
57
  "mean_total_time_seconds_per_task": 398,
58
  "mean_agent_time_seconds_per_task": 350
59
  }
60
+ }
results/swe-bench-verified-claude-opus-4-8-claude-code.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
@@ -23,7 +23,7 @@
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
- "name": "swe-bench/swe-bench-verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
@@ -55,4 +55,4 @@
55
  "mean_total_time_seconds_per_task": 319,
56
  "mean_agent_time_seconds_per_task": 208
57
  }
58
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
 
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
+ "name": "swe-bench/SWE-Bench Verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
 
55
  "mean_total_time_seconds_per_task": 319,
56
  "mean_agent_time_seconds_per_task": 208
57
  }
58
+ }
results/swe-bench-verified-claude-opus-4-8-opencode.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
@@ -23,7 +23,7 @@
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
- "name": "swe-bench/swe-bench-verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
@@ -55,4 +55,4 @@
55
  "mean_total_time_seconds_per_task": 343,
56
  "mean_agent_time_seconds_per_task": 229
57
  }
58
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
 
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
+ "name": "swe-bench/SWE-Bench Verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
 
55
  "mean_total_time_seconds_per_task": 343,
56
  "mean_agent_time_seconds_per_task": 229
57
  }
58
+ }
results/swe-bench-verified-claude-sonnet-4-6-claude-code.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
@@ -23,7 +23,7 @@
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
- "name": "swe-bench/swe-bench-verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
@@ -39,4 +39,4 @@
39
  "metrics": {
40
  "score": 0.796
41
  }
42
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
 
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
+ "name": "swe-bench/SWE-Bench Verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
 
39
  "metrics": {
40
  "score": 0.796
41
  }
42
+ }
results/swe-bench-verified-gpt-5-5-codex.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
@@ -23,7 +23,7 @@
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
- "name": "swe-bench/swe-bench-verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
@@ -55,4 +55,4 @@
55
  "mean_total_time_seconds_per_task": 283,
56
  "mean_agent_time_seconds_per_task": 185
57
  }
58
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
 
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
+ "name": "swe-bench/SWE-Bench Verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
 
55
  "mean_total_time_seconds_per_task": 283,
56
  "mean_agent_time_seconds_per_task": 185
57
  }
58
+ }
results/swe-bench-verified-qwen3-6-35b-nvfp4-claude-code.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
@@ -12,7 +12,7 @@
12
  "url": "https://github.com/anthropics/claude-code"
13
  },
14
  "model": {
15
- "name": "Qwen3.6-35B-A3B",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
@@ -23,7 +23,7 @@
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
- "name": "swe-bench/swe-bench-verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
@@ -55,4 +55,4 @@
55
  "mean_total_time_seconds_per_task": 343,
56
  "mean_agent_time_seconds_per_task": 245
57
  }
58
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
 
12
  "url": "https://github.com/anthropics/claude-code"
13
  },
14
  "model": {
15
+ "name": "Qwen3.6-35B-A3B-NVFP4",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
 
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
+ "name": "swe-bench/SWE-Bench Verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
 
55
  "mean_total_time_seconds_per_task": 343,
56
  "mean_agent_time_seconds_per_task": 245
57
  }
58
+ }
results/swe-bench-verified-qwen3-6-35b-nvfp4-openclaw.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
@@ -12,7 +12,7 @@
12
  "url": "https://github.com/openclaw/openclaw"
13
  },
14
  "model": {
15
- "name": "Qwen3.6-35B-A3B",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
@@ -23,7 +23,7 @@
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
- "name": "swe-bench/swe-bench-verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
@@ -56,4 +56,4 @@
56
  "mean_total_time_seconds_per_task": 400,
57
  "mean_agent_time_seconds_per_task": 240
58
  }
59
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
 
12
  "url": "https://github.com/openclaw/openclaw"
13
  },
14
  "model": {
15
+ "name": "Qwen3.6-35B-A3B-NVFP4",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
 
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
+ "name": "swe-bench/SWE-Bench Verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
 
56
  "mean_total_time_seconds_per_task": 400,
57
  "mean_agent_time_seconds_per_task": 240
58
  }
59
+ }
results/swe-bench-verified-qwen3-6-35b-nvfp4-opencode.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
@@ -12,7 +12,7 @@
12
  "url": "https://github.com/anomalyco/opencode"
13
  },
14
  "model": {
15
- "name": "Qwen3.6-35B-A3B",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
@@ -23,7 +23,7 @@
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
- "name": "swe-bench/swe-bench-verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
@@ -56,4 +56,4 @@
56
  "mean_total_time_seconds_per_task": 370,
57
  "mean_agent_time_seconds_per_task": 240
58
  }
59
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
 
12
  "url": "https://github.com/anomalyco/opencode"
13
  },
14
  "model": {
15
+ "name": "Qwen3.6-35B-A3B-NVFP4",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
 
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
+ "name": "swe-bench/SWE-Bench Verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
 
56
  "mean_total_time_seconds_per_task": 370,
57
  "mean_agent_time_seconds_per_task": 240
58
  }
59
+ }
results/swe-bench-verified-qwen3-6-36b-nvfp4-pi.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
@@ -12,7 +12,7 @@
12
  "url": "https://github.com/earendil-works/pi/tree/main"
13
  },
14
  "model": {
15
- "name": "Qwen3.6-35B-A3B",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
@@ -23,7 +23,7 @@
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
- "name": "swe-bench/swe-bench-verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
@@ -56,4 +56,4 @@
56
  "mean_total_time_seconds_per_task": 437,
57
  "mean_agent_time_seconds_per_task": 309
58
  }
59
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
 
12
  "url": "https://github.com/earendil-works/pi/tree/main"
13
  },
14
  "model": {
15
+ "name": "Qwen3.6-35B-A3B-NVFP4",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
 
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
+ "name": "swe-bench/SWE-Bench Verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
 
56
  "mean_total_time_seconds_per_task": 437,
57
  "mean_agent_time_seconds_per_task": 309
58
  }
59
+ }
results/swe-bench-verified-qwen3-6-36b-nvfp4-qwen-code.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "benchmark": {
3
- "name": "swe-bench-verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
@@ -12,7 +12,7 @@
12
  "url": "https://github.com/QwenLM/qwen-code"
13
  },
14
  "model": {
15
- "name": "Qwen3.6-35B-A3B",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
@@ -23,7 +23,7 @@
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
- "name": "swe-bench/swe-bench-verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
@@ -56,4 +56,4 @@
56
  "mean_total_time_seconds_per_task": 357,
57
  "mean_agent_time_seconds_per_task": 264
58
  }
59
- }
 
1
  {
2
  "benchmark": {
3
+ "name": "SWE-Bench Verified",
4
  "repo": "SWE-bench/SWE-bench_Verified",
5
  "num_tasks": 500,
6
  "url": "https://huggingface.co/datasets/SWE-bench/SWE-bench_Verified"
 
12
  "url": "https://github.com/QwenLM/qwen-code"
13
  },
14
  "model": {
15
+ "name": "Qwen3.6-35B-A3B-NVFP4",
16
  "repo": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
17
  "is_oss": true,
18
  "num_params": 35,
 
23
  "name": "harbor",
24
  "config": {
25
  "path": null,
26
+ "name": "swe-bench/SWE-Bench Verified",
27
  "version": null,
28
  "ref": "sha256:235d6032d549851a936db3b5fe08807c4d385c12ee10e7be9c9786a1ff60563c",
29
  "registry_url": null,
 
56
  "mean_total_time_seconds_per_task": 357,
57
  "mean_agent_time_seconds_per_task": 264
58
  }
59
+ }
src/charts.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ import re
5
+ from typing import Literal
6
+
7
+ import pandas as pd
8
+ import plotly.graph_objects as go
9
+ from plotly.graph_objs._figure import Figure
10
+
11
+ ColorBy = Literal["Model", "Harness"]
12
+
13
+ # One palette per grouping dimension. These are intentionally muted so they sit
14
+ # comfortably next to Gradio's citrus theme instead of fighting the lime/orange
15
+ # accents in the page header.
16
+ MODEL_COLORS: dict[str, str] = {
17
+ "Opus 4.8": "#486C8F",
18
+ "Sonnet 4.6": "#7B5EA7",
19
+ "GPT 5.5 - high": "#357C76",
20
+ "Qwen3.6-35B-A3B": "#9A6B3F",
21
+ "Qwen3.6-35B-A3B-NVFP4": "#9A6B3F",
22
+ "RedHatAI/Qwen3.6-35B-A3B-NVFP4": "#9A6B3F",
23
+ }
24
+
25
+ HARNESS_COLORS: dict[str, str] = {
26
+ "Claude Code": "#486C8F",
27
+ "Codex": "#7B5EA7",
28
+ "OpenCode": "#357C76",
29
+ "OpenClaw": "#9B5B63",
30
+ "Pi": "#6A7C59",
31
+ "Qwen Code": "#8A6B45",
32
+ "internal": "#697386",
33
+ }
34
+
35
+ FALLBACK_PALETTE = [
36
+ "#486C8F",
37
+ "#357C76",
38
+ "#7B5EA7",
39
+ "#9B5B63",
40
+ "#6A7C59",
41
+ "#8A6B45",
42
+ "#697386",
43
+ "#8C6E8C",
44
+ ]
45
+
46
+
47
+ def clean_markdown_link(value: object) -> str:
48
+ """Return human-readable text from Markdown links used in leaderboard tables."""
49
+ text = str(value).replace("<sup>*</sup>", "")
50
+ match = re.match(r"\[(.*?)\]\((.*?)\)", text)
51
+ if match:
52
+ return match.group(1)
53
+ return text
54
+
55
+
56
+ def stable_color(name: str) -> str:
57
+ digest = hashlib.sha256(name.encode("utf-8")).hexdigest()
58
+ return FALLBACK_PALETTE[int(digest[:8], 16) % len(FALLBACK_PALETTE)]
59
+
60
+
61
+ def get_color(name: str, color_by: ColorBy) -> str:
62
+ palette = MODEL_COLORS if color_by == "Model" else HARNESS_COLORS
63
+ return palette.get(name, stable_color(name))
64
+
65
+
66
+ def color_map_for(values: pd.Series, color_by: ColorBy) -> dict[str, str]:
67
+ return {str(value): get_color(str(value), color_by) for value in sorted(values.dropna().unique())}
68
+
69
+
70
+ def empty_figure(message: str) -> Figure:
71
+ fig = go.Figure()
72
+ fig.add_annotation(
73
+ text=message,
74
+ showarrow=False,
75
+ x=0.5,
76
+ y=0.5,
77
+ xref="paper",
78
+ yref="paper",
79
+ font={"size": 14, "color": "#5F6B75"},
80
+ )
81
+ return apply_plot_theme(fig, height=360)
82
+
83
+
84
+ def apply_plot_theme(fig: Figure, height: int = 520) -> Figure:
85
+ fig.update_layout(
86
+ template="plotly_white",
87
+ height=height,
88
+ paper_bgcolor="rgba(0,0,0,0)",
89
+ plot_bgcolor="rgba(255,255,255,0.84)",
90
+ font={"color": "#2A2F33"},
91
+ margin={"t": 64, "b": 56, "l": 72, "r": 36},
92
+ legend={
93
+ "orientation": "h",
94
+ "yanchor": "bottom",
95
+ "y": 1.02,
96
+ "xanchor": "center",
97
+ "x": 0.5,
98
+ },
99
+ )
100
+ fig.update_xaxes(gridcolor="rgba(42,47,51,0.12)", zerolinecolor="rgba(42,47,51,0.16)")
101
+ fig.update_yaxes(gridcolor="rgba(42,47,51,0.12)", zerolinecolor="rgba(42,47,51,0.16)")
102
+ return fig
103
+
104
+
105
+ def prepare_benchmark_run_plot_df(dataframe: pd.DataFrame) -> pd.DataFrame:
106
+ plot_df = dataframe.copy()
107
+ plot_df["Model Label"] = plot_df["Model"].map(clean_markdown_link)
108
+ plot_df["Harness Label"] = plot_df["Harness"].map(clean_markdown_link)
109
+ plot_df["Benchmark Label"] = plot_df["Benchmark"].map(clean_markdown_link)
110
+ plot_df["Run Label"] = plot_df["Model Label"] + "<br>" + plot_df["Harness Label"]
111
+ plot_df["Score"] = pd.to_numeric(plot_df["Score"], errors="coerce")
112
+ return plot_df
113
+
114
+
115
+ def create_leaderboard_benchmark_plot(
116
+ dataframe: pd.DataFrame,
117
+ benchmark_name: str,
118
+ color_by: ColorBy = "Model",
119
+ ) -> Figure:
120
+ if dataframe is None or dataframe.empty:
121
+ return empty_figure("No benchmark data available.")
122
+
123
+ plot_df = prepare_benchmark_run_plot_df(dataframe)
124
+ plot_df = plot_df[plot_df["Benchmark Label"] == benchmark_name].dropna(subset=["Score"])
125
+ plot_df = plot_df.sort_values("Score", ascending=False)
126
+
127
+ if plot_df.empty:
128
+ return empty_figure(f"No results available for {benchmark_name}.")
129
+
130
+ color_source = "Model Label" if color_by == "Model" else "Harness Label"
131
+ colors = color_map_for(plot_df[color_source], color_by)
132
+ fig = go.Figure()
133
+
134
+ for group, group_df in plot_df.groupby(color_source, sort=True):
135
+ fig.add_trace(
136
+ go.Bar(
137
+ x=group_df["Run Label"],
138
+ y=group_df["Score"],
139
+ name=str(group),
140
+ marker={"color": colors[str(group)]},
141
+ text=group_df["Score"].map(lambda score: f"{score:.1f}"),
142
+ textposition="outside",
143
+ customdata=group_df[["Model Label", "Harness Label", "Score"]],
144
+ hovertemplate=(
145
+ "<b>%{customdata[0]}</b><br>"
146
+ "Harness: %{customdata[1]}<br>"
147
+ "Score: %{customdata[2]:.1f}%"
148
+ "<extra></extra>"
149
+ ),
150
+ )
151
+ )
152
+
153
+ fig.update_layout(
154
+ title={"text": benchmark_name, "font": {"size": 18}},
155
+ xaxis={"title": "Model / Harness", "categoryorder": "array", "categoryarray": plot_df["Run Label"].tolist()},
156
+ yaxis={"title": "Score (%)", "range": [0, 105]},
157
+ legend_title_text=color_by,
158
+ bargap=0.28,
159
+ )
160
+ fig.update_xaxes(tickangle=-28)
161
+ return apply_plot_theme(fig, height=560)
162
+
163
+
164
+ def create_score_vs_cost_plot(
165
+ dataframe: pd.DataFrame,
166
+ color_by: ColorBy = "Model",
167
+ ) -> Figure:
168
+ if dataframe is None or dataframe.empty:
169
+ return empty_figure("No cost data available.")
170
+
171
+ plot_df = dataframe.copy()
172
+ plot_df["Avg Score"] = pd.to_numeric(plot_df["Avg Score"], errors="coerce")
173
+ plot_df["Avg Cost Per Task (USD)"] = pd.to_numeric(plot_df["Avg Cost Per Task (USD)"], errors="coerce")
174
+ plot_df = plot_df.dropna(subset=["Avg Score", "Avg Cost Per Task (USD)"])
175
+
176
+ if plot_df.empty:
177
+ return empty_figure("No cost data available.")
178
+
179
+ colors = color_map_for(plot_df[color_by], color_by)
180
+ fig = go.Figure()
181
+
182
+ for group, group_df in plot_df.groupby(color_by, sort=True):
183
+ fig.add_trace(
184
+ go.Scatter(
185
+ x=group_df["Avg Cost Per Task (USD)"],
186
+ y=group_df["Avg Score"],
187
+ mode="markers+text",
188
+ name=str(group),
189
+ text=group_df["Label"],
190
+ textposition="top center",
191
+ marker={
192
+ "size": 15,
193
+ "color": colors[str(group)],
194
+ "line": {"width": 1, "color": "white"},
195
+ },
196
+ customdata=group_df[["Model", "Harness", "Avg Score", "Avg Cost Per Task (USD)"]],
197
+ hovertemplate=(
198
+ "<b>%{customdata[0]}</b><br>"
199
+ "Harness: %{customdata[1]}<br>"
200
+ "Average score: %{customdata[2]:.1f}%<br>"
201
+ "Average cost: $%{customdata[3]:.2f}/task"
202
+ "<extra></extra>"
203
+ ),
204
+ )
205
+ )
206
+
207
+ fig.update_layout(
208
+ title={"text": "Cost vs Performance", "font": {"size": 18}},
209
+ xaxis={"title": "Average cost per task (USD)", "tickprefix": "$", "tickformat": ".2f"},
210
+ yaxis={"title": "Average score (%)", "range": [0, 105]},
211
+ legend_title_text=color_by,
212
+ )
213
+ return apply_plot_theme(fig, height=580)
src/display/text_blocks.py CHANGED
@@ -43,8 +43,8 @@ All benchmarks are run using Harbor, a sandboxed environment for evaluating codi
43
 
44
  Each benchmark measures the performance of the coding agent on different tasks:
45
 
46
- * **swe-bench-verified**: Measures performance on solving GitHub issues in popular Python repositories.
47
- * **swe-bench-pro--ansible**: Measures performance on solving GitHub issues in the [ansible/ansible](https://github.com/ansible/ansible) repository.
48
  Demonstrates how benchmarking can be used to evaluate coding agents on enterprise-specific tasks.
49
 
50
  Higher scores indicate better performance on the benchmarks.
 
43
 
44
  Each benchmark measures the performance of the coding agent on different tasks:
45
 
46
+ * **SWE-Bench Verified**: Measures performance on solving GitHub issues in popular Python repositories.
47
+ * **SWE-Bench Pro -- Ansible**: Measures performance on solving GitHub issues in the [ansible/ansible](https://github.com/ansible/ansible) repository.
48
  Demonstrates how benchmarking can be used to evaluate coding agents on enterprise-specific tasks.
49
 
50
  Higher scores indicate better performance on the benchmarks.
src/leaderboard.py CHANGED
@@ -1,11 +1,24 @@
1
  from pathlib import Path
2
  import json
 
3
  import pandas as pd
4
 
5
- from src.models import Result, Model, Harness
6
 
7
  RESULTS_DIR = Path(__file__).parent.parent / "results"
8
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  def format_time(seconds: int):
10
  if seconds is None:
11
  return None
@@ -14,70 +27,79 @@ def format_time(seconds: int):
14
  return f"{h}h{m}m{s}s"
15
 
16
 
17
- def get_benchmark_names(results: list[Result]):
18
- return {r.benchmark.name for r in results}
19
-
20
- def get_leaderboard_df():
21
  results: list[Result] = []
22
- for file in RESULTS_DIR.glob("*.json"):
23
  with open(file, "r") as f:
24
  data = json.load(f)
25
- result = Result(**data)
26
- results.append(result)
27
-
28
- # Collect benchmark scores for each model-harness pair, and convert to percent out of 100
29
- benchmark_lookup: dict[tuple[str, str], dict[str, float]] = {}
 
 
 
 
 
 
 
 
 
30
  model_lookup: dict[str, Model] = {}
31
  harness_lookup: dict[str, Harness] = {}
32
  for result in results:
33
- pair = (result.model.repo, result.harness.name)
 
34
  harness_lookup[result.harness.name] = result.harness
35
- model_lookup[result.model.repo] = result.model
36
- if pair not in benchmark_lookup:
37
- benchmark_lookup[pair] = {}
38
- benchmark_lookup[pair][result.benchmark.name] = (round(result.metrics.score * 100, 1), result.benchmark.num_tasks)
39
-
40
- # Collect results into df rows
41
  rows = []
42
  benchmark_names = get_benchmark_names(results=results)
43
  for pair, benchmarks in benchmark_lookup.items():
44
  model = model_lookup[pair[0]]
45
  harness = harness_lookup[pair[1]]
46
- avg_score = sum([score * size for score, size in benchmarks.values()]) / sum([size for _, size in benchmarks.values()])
 
 
47
  row = {
48
  " ": "🟠" if model.is_oss and harness.is_oss else "🔶",
49
- "Model": f'[{model.repo}]({model.url})',
50
- "Harness": f'[{harness.name}]({harness.url})<sup>*</sup>' if result.harness.name == "internal" else f'[{harness.name}]({harness.url})',
 
 
51
  "Precision": model.precision,
52
  "Model License": "FOSS" if model.is_oss else "Proprietary",
53
  "Harness License": "FOSS" if harness.is_oss else "Proprietary",
54
  "Model Num Params (B)": model.num_params,
55
  "Avg Score": round(avg_score, 1),
56
  }
57
- for benchmark_name in sorted(benchmark_names, key=lambda x: (0 if x == "swe-bench-verified" else 1)):
58
- row[benchmark_name] = benchmarks.get(benchmark_name, "")[0]
 
59
  rows.append(row)
60
-
61
  leaderboard_df = pd.DataFrame(rows).sort_values("Avg Score", ascending=False).fillna("")
62
  return leaderboard_df
63
-
64
-
65
  def get_benchmark_run_df():
66
- results: list[Result] = []
67
- for file in RESULTS_DIR.glob("*.json"):
68
- with open(file, "r") as f:
69
- data = json.load(f)
70
- result = Result(**data)
71
- results.append(result)
72
 
73
  rows = []
74
  for result in results:
75
  rows.append(
76
  {
77
  " ": "🟠" if result.model.is_oss and result.harness.is_oss else "🔶",
78
- "Model": f'[{result.model.repo}]({result.model.url})',
79
- "Harness": f'[{result.harness.name}]({result.harness.url})<sup>*</sup>' if result.harness.name == "internal" else f'[{result.harness.name}]({result.harness.url})',
80
- "Benchmark": f'[{result.benchmark.name}]({result.benchmark.url})',
 
 
81
  "Base Model": result.model.name,
82
  "Precision": result.model.precision,
83
  "Skills": str(result.harness.skills) if result.harness.skills else "None",
@@ -94,3 +116,54 @@ def get_benchmark_run_df():
94
 
95
  benchmark_run_df = pd.DataFrame(rows).sort_values(by=["Benchmark", "Score"], ascending=False).fillna("")
96
  return benchmark_run_df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from pathlib import Path
2
  import json
3
+
4
  import pandas as pd
5
 
6
+ from src.models import Harness, Model, Result
7
 
8
  RESULTS_DIR = Path(__file__).parent.parent / "results"
9
 
10
+ BENCHMARK_SORT_ORDER = {
11
+ "SWE-Bench Verified": 0,
12
+ "swe-bench-verified": 0,
13
+ "SWE-Bench Pro -- Ansible": 1,
14
+ "swe-bench-pro--ansible": 1,
15
+ }
16
+
17
+
18
+ def benchmark_sort_key(name: str) -> tuple[int, str]:
19
+ return (BENCHMARK_SORT_ORDER.get(name, 99), name)
20
+
21
+
22
  def format_time(seconds: int):
23
  if seconds is None:
24
  return None
 
27
  return f"{h}h{m}m{s}s"
28
 
29
 
30
+ def get_results() -> list[Result]:
 
 
 
31
  results: list[Result] = []
32
+ for file in sorted(RESULTS_DIR.glob("*.json")):
33
  with open(file, "r") as f:
34
  data = json.load(f)
35
+ results.append(Result(**data))
36
+ return results
37
+
38
+
39
+ def get_benchmark_names(results: list[Result] | None = None) -> list[str]:
40
+ results = results or get_results()
41
+ return sorted({r.benchmark.name for r in results}, key=benchmark_sort_key)
42
+
43
+
44
+ def get_leaderboard_df():
45
+ results = get_results()
46
+
47
+ # Collect benchmark scores for each model-harness pair, and convert to percent out of 100.
48
+ benchmark_lookup: dict[tuple[str, str], dict[str, tuple[float, int]]] = {}
49
  model_lookup: dict[str, Model] = {}
50
  harness_lookup: dict[str, Harness] = {}
51
  for result in results:
52
+ model_key = result.model.repo or result.model.name
53
+ pair = (model_key, result.harness.name)
54
  harness_lookup[result.harness.name] = result.harness
55
+ model_lookup[model_key] = result.model
56
+ benchmark_lookup.setdefault(pair, {})[result.benchmark.name] = (
57
+ round(result.metrics.score * 100, 1),
58
+ result.benchmark.num_tasks,
59
+ )
60
+
61
  rows = []
62
  benchmark_names = get_benchmark_names(results=results)
63
  for pair, benchmarks in benchmark_lookup.items():
64
  model = model_lookup[pair[0]]
65
  harness = harness_lookup[pair[1]]
66
+ avg_score = sum(score * size for score, size in benchmarks.values()) / sum(
67
+ size for _, size in benchmarks.values()
68
+ )
69
  row = {
70
  " ": "🟠" if model.is_oss and harness.is_oss else "🔶",
71
+ "Model": f"[{model.repo or model.name}]({model.url})",
72
+ "Harness": f"[{harness.name}]({harness.url})<sup>*</sup>"
73
+ if harness.name == "internal"
74
+ else f"[{harness.name}]({harness.url})",
75
  "Precision": model.precision,
76
  "Model License": "FOSS" if model.is_oss else "Proprietary",
77
  "Harness License": "FOSS" if harness.is_oss else "Proprietary",
78
  "Model Num Params (B)": model.num_params,
79
  "Avg Score": round(avg_score, 1),
80
  }
81
+ for benchmark_name in benchmark_names:
82
+ benchmark_score = benchmarks.get(benchmark_name)
83
+ row[benchmark_name] = benchmark_score[0] if benchmark_score else ""
84
  rows.append(row)
85
+
86
  leaderboard_df = pd.DataFrame(rows).sort_values("Avg Score", ascending=False).fillna("")
87
  return leaderboard_df
88
+
89
+
90
  def get_benchmark_run_df():
91
+ results = get_results()
 
 
 
 
 
92
 
93
  rows = []
94
  for result in results:
95
  rows.append(
96
  {
97
  " ": "🟠" if result.model.is_oss and result.harness.is_oss else "🔶",
98
+ "Model": f"[{result.model.repo or result.model.name}]({result.model.url})",
99
+ "Harness": f"[{result.harness.name}]({result.harness.url})<sup>*</sup>"
100
+ if result.harness.name == "internal"
101
+ else f"[{result.harness.name}]({result.harness.url})",
102
+ "Benchmark": f"[{result.benchmark.name}]({result.benchmark.url})",
103
  "Base Model": result.model.name,
104
  "Precision": result.model.precision,
105
  "Skills": str(result.harness.skills) if result.harness.skills else "None",
 
116
 
117
  benchmark_run_df = pd.DataFrame(rows).sort_values(by=["Benchmark", "Score"], ascending=False).fillna("")
118
  return benchmark_run_df
119
+
120
+
121
+ def get_score_vs_cost_df():
122
+ results = get_results()
123
+
124
+ score_weighted_sum: dict[tuple[str, str], float] = {}
125
+ cost_weighted_sum: dict[tuple[str, str], float] = {}
126
+ weight_sum: dict[tuple[str, str], int] = {}
127
+ cost_weight_sum: dict[tuple[str, str], int] = {}
128
+ meta_lookup: dict[tuple[str, str], Result] = {}
129
+
130
+ for result in results:
131
+ pair = (result.model.name, result.harness.name)
132
+ weight = result.metrics.n_tasks or result.benchmark.num_tasks or 1
133
+ meta_lookup[pair] = result
134
+ score_weighted_sum[pair] = score_weighted_sum.get(pair, 0) + (result.metrics.score * 100 * weight)
135
+ weight_sum[pair] = weight_sum.get(pair, 0) + weight
136
+
137
+ mean_cost = result.metrics.mean_cost_usd_per_task
138
+ if mean_cost is not None:
139
+ cost_weighted_sum[pair] = cost_weighted_sum.get(pair, 0) + (mean_cost * weight)
140
+ cost_weight_sum[pair] = cost_weight_sum.get(pair, 0) + weight
141
+
142
+ rows = []
143
+ for pair, weighted_score in score_weighted_sum.items():
144
+ if pair not in cost_weighted_sum:
145
+ continue
146
+ result = meta_lookup[pair]
147
+ rows.append(
148
+ {
149
+ "Label": f"{pair[0]} / {pair[1]}",
150
+ "Model": pair[0],
151
+ "Harness": pair[1],
152
+ "Category": "FOSS" if result.model.is_oss and result.harness.is_oss else "Proprietary",
153
+ "Avg Score": round(weighted_score / weight_sum[pair], 1),
154
+ "Avg Cost Per Task (USD)": round(cost_weighted_sum[pair] / cost_weight_sum[pair], 2),
155
+ }
156
+ )
157
+
158
+ columns = [
159
+ "Label",
160
+ "Model",
161
+ "Harness",
162
+ "Category",
163
+ "Avg Score",
164
+ "Avg Cost Per Task (USD)",
165
+ ]
166
+ score_vs_cost_df = pd.DataFrame(rows, columns=columns)
167
+ if score_vs_cost_df.empty:
168
+ return score_vs_cost_df
169
+ return score_vs_cost_df.sort_values("Avg Score", ascending=False)
src/models.py CHANGED
@@ -9,6 +9,9 @@ class Benchmark(BaseModel):
9
  num_tasks: int
10
  url: str
11
 
 
 
 
12
 
13
  class Harness(BaseModel):
14
  name: str
 
9
  num_tasks: int
10
  url: str
11
 
12
+ def __hash__(self):
13
+ return hash(self.name)
14
+
15
 
16
  class Harness(BaseModel):
17
  name: str