90489e7bfc
New suites: - MMLU-Pro: Professional-level 10-choice QA (14 subjects) - GPQA-Diamond: Graduate-level science QA - BigBench Extra Hard: Challenging reasoning tasks - MMMLU: Multilingual MMLU across 10 languages - HLE: Humanity's Last Exam (extremely hard) - Tau2: Tool-augmented reasoning (retail/airline/finance) - Codeforces: Competitive programming with ELO scoring Updates: - AIME now supports aime_2026.jsonl for 2026 problems - Registry expanded to 17 suites in 5 categories - download_datasets.py supports HF downloads for new suites - README.md updated with full documentation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
279 lines
10 KiB
Python
279 lines
10 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Standard evaluation benchmark runner for claw-code-agent.
|
|
|
|
Runs the agent against well-known evaluation suites and reports scores.
|
|
|
|
Usage:
|
|
# List available benchmark suites
|
|
python3 -m benchmarks.run_suite --list
|
|
|
|
# Run a specific suite (built-in subset)
|
|
python3 -m benchmarks.run_suite --suite humaneval
|
|
python3 -m benchmarks.run_suite --suite mbpp
|
|
python3 -m benchmarks.run_suite --suite swe-bench
|
|
python3 -m benchmarks.run_suite --suite aider
|
|
python3 -m benchmarks.run_suite --suite livecodebench
|
|
python3 -m benchmarks.run_suite --suite math
|
|
python3 -m benchmarks.run_suite --suite gsm8k
|
|
python3 -m benchmarks.run_suite --suite aime
|
|
python3 -m benchmarks.run_suite --suite ifeval
|
|
python3 -m benchmarks.run_suite --suite bfcl
|
|
|
|
# Run ALL suites
|
|
python3 -m benchmarks.run_suite --all
|
|
|
|
# Run by category
|
|
python3 -m benchmarks.run_suite --category coding
|
|
python3 -m benchmarks.run_suite --category math
|
|
python3 -m benchmarks.run_suite --category instruction-following
|
|
|
|
# Limit problems per suite (for quick testing)
|
|
python3 -m benchmarks.run_suite --suite humaneval --limit 5
|
|
|
|
# Verbose output + save results
|
|
python3 -m benchmarks.run_suite --suite humaneval -v -o results.json
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
import time
|
|
|
|
from benchmarks.suites.base import BenchmarkSuite, SuiteReport
|
|
|
|
# Import all suites
|
|
from benchmarks.suites.humaneval import HumanEvalBenchmark
|
|
from benchmarks.suites.mbpp import MBPPBenchmark
|
|
from benchmarks.suites.swe_bench import SWEBenchBenchmark
|
|
from benchmarks.suites.aider import AiderBenchmark
|
|
from benchmarks.suites.livecodebench import LiveCodeBenchBenchmark
|
|
from benchmarks.suites.math_bench import MATHBenchmark
|
|
from benchmarks.suites.gsm8k import GSM8KBenchmark
|
|
from benchmarks.suites.aime import AIMEBenchmark
|
|
from benchmarks.suites.ifeval import IFEvalBenchmark
|
|
from benchmarks.suites.bfcl import BFCLBenchmark
|
|
from benchmarks.suites.mmlu_pro import MMLUProBenchmark
|
|
from benchmarks.suites.gpqa import GPQABenchmark
|
|
from benchmarks.suites.bigbench import BigBenchHardBenchmark
|
|
from benchmarks.suites.mmmlu import MMMMLUBenchmark
|
|
from benchmarks.suites.hle import HLEBenchmark
|
|
from benchmarks.suites.tau2 import Tau2Benchmark
|
|
from benchmarks.suites.codeforces import CodeforcesBenchmark
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Registry
|
|
# ---------------------------------------------------------------------------
|
|
|
|
SUITE_REGISTRY: dict[str, type[BenchmarkSuite]] = {
|
|
"humaneval": HumanEvalBenchmark,
|
|
"mbpp": MBPPBenchmark,
|
|
"swe-bench": SWEBenchBenchmark,
|
|
"aider": AiderBenchmark,
|
|
"livecodebench": LiveCodeBenchBenchmark,
|
|
"math": MATHBenchmark,
|
|
"gsm8k": GSM8KBenchmark,
|
|
"aime": AIMEBenchmark,
|
|
"ifeval": IFEvalBenchmark,
|
|
"bfcl": BFCLBenchmark,
|
|
"mmlu-pro": MMLUProBenchmark,
|
|
"gpqa-diamond": GPQABenchmark,
|
|
"bigbench-hard": BigBenchHardBenchmark,
|
|
"mmmlu": MMMMLUBenchmark,
|
|
"hle": HLEBenchmark,
|
|
"tau2": Tau2Benchmark,
|
|
"codeforces": CodeforcesBenchmark,
|
|
}
|
|
|
|
CATEGORY_MAP: dict[str, list[str]] = {
|
|
"coding": ["humaneval", "mbpp", "swe-bench", "aider", "livecodebench", "codeforces"],
|
|
"math": ["math", "gsm8k", "aime"],
|
|
"instruction-following": ["ifeval", "bfcl"],
|
|
"knowledge": ["mmlu-pro", "gpqa-diamond", "mmmlu", "hle"],
|
|
"reasoning": ["bigbench-hard", "tau2"],
|
|
}
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Multi-suite reporting
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def print_combined_report(reports: list[SuiteReport]) -> None:
|
|
"""Print a combined summary of all suite runs."""
|
|
print()
|
|
print("=" * 80)
|
|
print(" COMBINED BENCHMARK REPORT")
|
|
print("=" * 80)
|
|
print()
|
|
print(f" {'Suite':<20} {'Category':<22} {'Passed':>8} {'Total':>8} {'Score':>8} {'Time':>8}")
|
|
print(f" {'─' * 20} {'─' * 22} {'─' * 8} {'─' * 8} {'─' * 8} {'─' * 8}")
|
|
|
|
total_passed = 0
|
|
total_problems = 0
|
|
total_time = 0.0
|
|
|
|
for r in reports:
|
|
suite_cls = SUITE_REGISTRY.get(r.suite_name.lower().replace("-", "").replace("_", ""))
|
|
cat = suite_cls.category if suite_cls else "unknown"
|
|
print(
|
|
f" {r.suite_name:<20} {cat:<22} "
|
|
f"{r.passed:>8} {r.total:>8} "
|
|
f"{r.score_pct:>7.1f}% {r.duration_sec:>7.1f}s"
|
|
)
|
|
total_passed += r.passed
|
|
total_problems += r.total
|
|
total_time += r.duration_sec
|
|
|
|
print()
|
|
print("─" * 80)
|
|
overall_pct = round(100.0 * total_passed / total_problems, 1) if total_problems else 0.0
|
|
print(
|
|
f" OVERALL: {total_passed}/{total_problems} ({overall_pct}%) "
|
|
f"in {total_time:.1f}s"
|
|
)
|
|
print("─" * 80)
|
|
|
|
# Category breakdown
|
|
print()
|
|
print(" Category Breakdown:")
|
|
for cat_name, suite_names in CATEGORY_MAP.items():
|
|
cat_reports = [r for r in reports if r.suite_name.lower().replace("-", "").replace("_", "") in
|
|
[s.replace("-", "").replace("_", "") for s in suite_names]]
|
|
if cat_reports:
|
|
cp = sum(r.passed for r in cat_reports)
|
|
ct = sum(r.total for r in cat_reports)
|
|
cpct = round(100.0 * cp / ct, 1) if ct else 0.0
|
|
bar_len = 20
|
|
filled = round(bar_len * cp / ct) if ct else 0
|
|
bar = "█" * filled + "░" * (bar_len - filled)
|
|
print(f" {cat_name:<22} {bar} {cp}/{ct} ({cpct}%)")
|
|
|
|
print()
|
|
|
|
|
|
def save_combined_report(reports: list[SuiteReport], path: str) -> None:
|
|
data = {
|
|
"benchmark_run": "claw-code-agent-evaluation",
|
|
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S"),
|
|
"suites": [r.to_dict() for r in reports],
|
|
"summary": {
|
|
"total_suites": len(reports),
|
|
"total_problems": sum(r.total for r in reports),
|
|
"total_passed": sum(r.passed for r in reports),
|
|
"overall_score_pct": round(
|
|
100.0 * sum(r.passed for r in reports) / sum(r.total for r in reports), 1
|
|
) if any(r.total for r in reports) else 0.0,
|
|
},
|
|
}
|
|
with open(path, "w") as fh:
|
|
json.dump(data, fh, indent=2)
|
|
print(f" Combined results saved to {path}")
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# CLI
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(
|
|
description="Run standard evaluation benchmarks against claw-code-agent",
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog=(
|
|
"Examples:\n"
|
|
" python3 -m benchmarks.run_suite --list\n"
|
|
" python3 -m benchmarks.run_suite --suite humaneval\n"
|
|
" python3 -m benchmarks.run_suite --suite humaneval --limit 5 -v\n"
|
|
" python3 -m benchmarks.run_suite --category coding\n"
|
|
" python3 -m benchmarks.run_suite --all\n"
|
|
" python3 -m benchmarks.run_suite --all -o results.json\n"
|
|
),
|
|
)
|
|
parser.add_argument("--suite", action="append", default=[],
|
|
help="Run a specific benchmark suite (can be repeated)")
|
|
parser.add_argument("--category", choices=list(CATEGORY_MAP.keys()),
|
|
help="Run all suites in a category")
|
|
parser.add_argument("--all", action="store_true",
|
|
help="Run ALL benchmark suites")
|
|
parser.add_argument("--list", action="store_true",
|
|
help="List available benchmark suites")
|
|
parser.add_argument("--limit", type=int, default=None,
|
|
help="Max problems per suite (for quick testing)")
|
|
parser.add_argument("--timeout", type=float, default=300.0,
|
|
help="Agent timeout per problem in seconds (default: 300)")
|
|
parser.add_argument("--verbose", "-v", action="store_true",
|
|
help="Verbose output")
|
|
parser.add_argument("--output", "-o",
|
|
help="Save results to JSON file")
|
|
parser.add_argument("--data-dir",
|
|
help="Directory containing dataset files (JSONL)")
|
|
parser.add_argument("--artifacts-dir",
|
|
help="Directory where per-problem artifacts will be saved")
|
|
parser.add_argument("--save-passing-artifacts", action="store_true",
|
|
help="Also save artifacts for passing problems")
|
|
args = parser.parse_args()
|
|
|
|
if args.list:
|
|
print()
|
|
print(" Available Benchmark Suites:")
|
|
print(" " + "─" * 68)
|
|
print(f" {'Name':<18} {'Category':<22} {'Description'}")
|
|
print(" " + "─" * 68)
|
|
for name, cls in SUITE_REGISTRY.items():
|
|
print(f" {name:<18} {cls.category:<22} {cls.description}")
|
|
print()
|
|
print(" Categories:")
|
|
for cat, suites in CATEGORY_MAP.items():
|
|
print(f" {cat}: {', '.join(suites)}")
|
|
print()
|
|
return
|
|
|
|
# Determine which suites to run
|
|
suite_names: list[str] = []
|
|
if args.all:
|
|
suite_names = list(SUITE_REGISTRY.keys())
|
|
elif args.category:
|
|
suite_names = CATEGORY_MAP.get(args.category, [])
|
|
elif args.suite:
|
|
for s in args.suite:
|
|
if s not in SUITE_REGISTRY:
|
|
print(f"Error: unknown suite '{s}'. Available: {', '.join(SUITE_REGISTRY)}")
|
|
sys.exit(1)
|
|
suite_names = list(args.suite)
|
|
else:
|
|
parser.print_help()
|
|
print("\nError: specify --suite, --category, or --all")
|
|
sys.exit(1)
|
|
|
|
if not suite_names:
|
|
print("No suites matched.")
|
|
sys.exit(1)
|
|
|
|
# Run suites
|
|
reports: list[SuiteReport] = []
|
|
for name in suite_names:
|
|
cls = SUITE_REGISTRY[name]
|
|
suite = cls(
|
|
data_dir=args.data_dir,
|
|
limit=args.limit,
|
|
agent_timeout=args.timeout,
|
|
verbose=args.verbose,
|
|
artifacts_dir=args.artifacts_dir,
|
|
save_passing_artifacts=args.save_passing_artifacts,
|
|
)
|
|
report = suite.run_all()
|
|
reports.append(report)
|
|
|
|
# Combined report
|
|
if len(reports) > 1:
|
|
print_combined_report(reports)
|
|
|
|
if args.output:
|
|
save_combined_report(reports, args.output)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|