Skip to content

Wildbench Integration#72

Open
kargibora wants to merge 3 commits into
mainfrom
feat/wildbench-integration
Open

Wildbench Integration#72
kargibora wants to merge 3 commits into
mainfrom
feat/wildbench-integration

Conversation

@kargibora

Copy link
Copy Markdown
Collaborator

Summary

This PR closes #68.

  • wildbench-score: checklist-based individual scoring.
  • wildbench-reward: pairwise evaluation using one custom baseline or the three
    official reference models.

Implementation

  • Uses the official WildBench V2 dataset, prompts, JSON formats, and metrics.
  • Supports multi-turn conversations and instance-specific checklists.
  • Downloads the official baseline outputs for WB-Reward.
  • Reports overall, per-category, and per-baseline results.
  • Saves annotations, model outputs, resolved configuration, and run metadata.

Example

export OPENROUTER_API_KEY="..."

uv run judgearena \
  --task wildbench-score \
  --model.name OpenRouter/google/gemma-3-4b-it \
  --judge.model OpenRouter/openai/gpt-4.1-mini \
  --generation.n_instructions 10

Example YAML configurations are included under configs/.

## Validation

- Added dataset, metric, parser, configuration, CLI, and artifact tests.
- Verified loading all 1,024 WildBench V2 tasks and official baseline outputs.

@kargibora

Copy link
Copy Markdown
Collaborator Author

Notes:

  • Most of the LOC comes from the wildbench.py which is basically provided by the wildbench repo and adapted to our codebase. It uses styles for extending the dict/tuple objects to multiline which in-fact creates more lines. So content-wise PR is not large
  • Original wildbench does not have system prompt, should we not use You are a helpful assistant.. for models we test?

@kargibora

kargibora commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator Author

Although this PR adds Wildbench, it was hard to ingerate it. Thus I have proposed more cleaner solution in #74. We should discuss this possibly toward making it file-based (task=yaml file)

Comment thread judgearena/config.py
self.wildbench = WildBenchArgs()
if self.model.name is None:
raise ValueError("model.name is required for WildBench tasks.")
if self.judge.temperature is None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WildBench’s judge temperature is defaulted to 0 here, but the evaluated model keeps backend defaults. For vLLM that currently means temperature 0.6/top-p 0.95 and the shared 32k output budget, while the official WildBench launch uses temperature 0/top-p 1/max-tokens 4096. As a result the example configs are stochastic and not leaderboard-comparable. Could we set or require explicit WildBench generation defaults and maybe record deviations?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, we should add this to the config file. Thanks for catching it

Comment thread judgearena/wildbench.py
"baseline_output": baseline,
"prompt": prompt,
}
if not candidate.strip() and not baseline.strip():

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The synthetic empty-response choices match the official evaluator, but the official leaderboard does not feed them into metrics this way. WB-Score keeps score=1 in the overall mean but excludes empty rows from category/task-macro values. WB-Reward excludes empties from win/loss counts and categories; because its overall denominator remains the full result count, an empty row contributes 0 rather than ±100.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add a filtering as the last step, thanks

Comment thread judgearena/wildbench.py
normalized = value.strip().upper().replace(" ", "")
if normalized in _CHOICE_TO_A_REWARD:
return normalized
matches = re.findall(r"A\+\+|B\+\+|A=B|A\+|B\+", strip_thinking_tags(text))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fallback scans the entire response for verdict tokens. The required JSON schema contains a "reason of A=B" key, so a truncated or malformed response without choice is silently parsed as A=B instead of missing. It would be better to restrict fallback parsing to the choice field or a tightly scoped final-choice pattern.

Comment thread judgearena/wildbench.py
pending_ids = []
records = []
for session_id, example in examples.iterrows():
output = candidate_outputs.loc[str(session_id)]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

output is passed directly to the score prompt, unlike the reward path. Consequently, cfg.judge.strip_thinking_before_judging has no effect for WB-Score. I think we should apply strip_thinking_tags(output) here.

@geoalgo geoalgo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM overall we can merge once you have addressed @ErlisLushtaku comments.

@@ -0,0 +1,14 @@
task: wildbench-reward
model:
name: VLLM/utter-project/EuroLLM-9B

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps we can comment this from user POV?

Suggested change
name: VLLM/utter-project/EuroLLM-9B
name: VLLM/utter-project/EuroLLM-9B # model to be evaluated

Comment on lines +12 to +13
# Set an integer K to tie slight wins caused by responses longer by >K chars.
# Omit this field to disable the length penalty.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the default in the paper? If so:

Suggested change
# Set an integer K to tie slight wins caused by responses longer by >K chars.
# Omit this field to disable the length penalty.
# Set an integer K to tie slight wins caused by responses longer by >K chars.
# Omit this field to disable the length penalty. Default to paper value.

model:
name: VLLM/utter-project/EuroLLM-9B
judge:
model: OpenRouter/openai/gpt-4o

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: should we rather use gemma4-31B for such defaults?

I see the point to default to the paper but this model is going to be replaced and is pareto dominated by gemma4.


def load_instructions(dataset: str, n_instructions: int | None = None) -> pd.DataFrame:
if dataset == "mt-bench":
if dataset in {"wildbench-score", "wildbench-reward"}:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, I was wondering about this (lists were more natural to me, this choice is PEP compliant):

# are there in coding guideline for membership tests in python?

Yes. For membership tests against a literal collection, PEP 8 and common style guidance favor a set (or frozenset) when checking in, because set lookups are O(1) versus O(n) for lists. So {"wildbench-score", "wildbench-reward"} is generally preferred.

However, with only two string elements the performance difference is negligible, and some style guides (or linters like Ruff's C0201/SIM rules) actually flag the opposite direction depending on configuration. Ruff's literal-membership rule (PLR6201) specifically recommends converting list/tuple literals to sets in membership tests, which endorses the first form.

Practical guidance: use a set literal for membership checks. Use a tuple ("a", "b") if you want to signal immutability without the set overhead and order matters, or a list only if the collection is used elsewhere as an actual list. For your case, the set version is the idiomatic choice.

Comment thread README.md
## ✨ Key Features

🎯 **Flexible Benchmarking** – Evaluate models on `Alpaca-Eval`, `Arena-Hard`, `m-Arena-Hard` and others
🎯 **Flexible Benchmarking** – Evaluate models on `Alpaca-Eval`, `Arena-Hard`, `m-Arena-Hard`, `WildBench V2` and others

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we add a column for wildbench in the table l18?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support WildBench

3 participants