Skip to content

feat: swe bench scorer#342

Open
tianmu-li wants to merge 25 commits into
mlcommons:mainfrom
tianmu-li:feat/swe_bench_scorer
Open

feat: swe bench scorer#342
tianmu-li wants to merge 25 commits into
mlcommons:mainfrom
tianmu-li:feat/swe_bench_scorer

Conversation

@tianmu-li

@tianmu-li tianmu-li commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Adds SWE-bench accuracy evaluation to the agentic inference workflow (per #310). A new SWEBench dataset loads SWE-bench_Verified/_Lite, and SWEBenchScorer drives the eval by shelling out to mini-swe-agent and the swebench harness in an isolated uv subproject, bypassing the built-in accuracy phase.

Agent-run parallelism (extras.workers) defaults to the load pattern's target_concurrency when unset. Includes example configs, an optional Qwen tool-call patch, and docs.

Type of change

  • New feature
  • Documentation update

Related issues

Closes #310

Testing

  • Tests added/updated
  • All tests pass locally
  • Manual testing completed

Checklist

  • Code follows project style
  • Pre-commit hooks pass
  • Documentation updated

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

MLCommons CLA bot All contributors have signed the MLCommons CLA ✍️ ✅

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for SWE-bench accuracy evaluation by adding a new accuracy-only SWEBench dataset, a SWEBenchScorer that runs evaluations using mini-swe-agent in an isolated environment, and associated configuration templates, tests, and runbooks. Feedback on the changes focuses on improving the robustness of the SWEBenchScorer implementation, specifically by safely handling missing or null values when parsing configuration templates, benchmark configurations, and evaluation results, as well as gracefully handling cases where the Docker binary is missing from the system's PATH during preflight checks.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
@tianmu-li
tianmu-li force-pushed the feat/swe_bench_scorer branch 2 times, most recently from aa7f559 to bb9b307 Compare June 15, 2026 05:16
@tianmu-li
tianmu-li marked this pull request as ready for review June 21, 2026 17:28
@tianmu-li
tianmu-li requested review from a team and Copilot June 21, 2026 17:28
@tianmu-li tianmu-li changed the title WIP feat: swe bench scorer feat: swe bench scorer Jun 21, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds first-class SWE-bench accuracy support to the benchmarking system by introducing an external (subprocess-driven) scorer and a predefined SWE-bench dataset, plus wiring in config/schema handling and examples to run the workflow.

Changes:

  • Introduces SWEBenchScorer (external evaluation via uv run --project ... mini-extra + swebench harness) and integrates it into the scoring/benchmark lifecycle (preflight, phase skipping, reporting).
  • Adds predefined swe_bench dataset with caching + an ACCURACY_ONLY guard to prevent using it as a performance dataset.
  • Updates schema/templates/examples and adds unit tests for the scorer + dataset + benchmark wiring.

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
uv.lock Locks pyyaml as a direct dependency.
pyproject.toml Adds pyyaml==6.0.3 to runtime dependencies.
src/inference_endpoint/evaluation/scoring.py Adds scorer preflight hooks, shared subprocess logging helper, and new SWEBenchScorer implementation.
src/inference_endpoint/dataset_manager/predefined/swe_bench/init.py Adds SWE-bench predefined dataset with HF download + parquet cache and ACCURACY_ONLY=True.
src/inference_endpoint/dataset_manager/dataset.py Introduces Dataset.ACCURACY_ONLY class flag.
src/inference_endpoint/dataset_manager/init.py Exposes/imports SWEBench dataset.
src/inference_endpoint/config/schema.py Adds swe_bench_scorer to ScorerMethod and injects concurrency → SWE-bench workers default.
src/inference_endpoint/commands/benchmark/execute.py Runs scorer preflight(), prevents accuracy-only datasets as perf, skips endpoint phases for external scorers, and improves sample counting/reporting.
src/inference_endpoint/config/templates/online_template_full.yaml Documents swe_bench_scorer as an accuracy scorer option.
src/inference_endpoint/config/templates/offline_template_full.yaml Documents swe_bench_scorer as an accuracy scorer option.
src/inference_endpoint/config/templates/concurrency_template_full.yaml Documents swe_bench_scorer as an accuracy scorer option.
examples/10_Agentic_Inference/swebench_template.yaml Adds a SWE-bench/mini-swe-agent config template used by the external scorer.
examples/10_Agentic_Inference/swe_bench_accuracy.yaml Adds a runnable example config for SWE-bench external accuracy evaluation.
examples/10_Agentic_Inference/README.md Documents how to sync/run the SWE-bench accuracy subproject.
examples/10_Agentic_Inference/qwen_agentic_benchmark.yaml Adds SWE-bench accuracy dataset to an agentic benchmark example.
examples/10_Agentic_Inference/kimi_agentic_benchmark.yaml Adds SWE-bench accuracy dataset to an agentic benchmark example.
examples/10_Agentic_Inference/accuracy/RUNBOOK.md Adds an ops runbook for validating the SWE-bench accuracy pipeline.
examples/10_Agentic_Inference/accuracy/pyproject.toml Adds isolated uv subproject deps for SWE-bench evaluation tooling.
tests/unit/evaluation/test_swe_bench_scorer.py Adds unit coverage for scorer behavior, config patching, and preflight.
tests/unit/dataset_manager/test_swe_bench_dataset.py Adds unit coverage for dataset registration, caching, and subset mapping.
tests/unit/commands/test_benchmark.py Adds tests for concurrency→workers injection, ACCURACY_ONLY enforcement, preflight propagation, and phase skipping behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Comment thread src/inference_endpoint/dataset_manager/predefined/swe_bench/__init__.py Outdated
Copilot AI review requested due to automatic review settings June 21, 2026 23:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 7 comments.

Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Comment thread examples/10_Agentic_Inference/swebench_template.yaml
Comment thread examples/10_Agentic_Inference/README.md Outdated
Comment thread examples/10_Agentic_Inference/swe_bench_accuracy.yaml Outdated
Copilot AI review requested due to automatic review settings June 25, 2026 13:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 22 changed files in this pull request and generated 2 comments.

Comment thread examples/10_Agentic_Inference/accuracy/RUNBOOK.md Outdated
Comment thread examples/10_Agentic_Inference/qwen_agentic_benchmark.yaml Outdated
Copilot AI review requested due to automatic review settings July 6, 2026 18:13
@tianmu-li
tianmu-li force-pushed the feat/swe_bench_scorer branch from 8d66f43 to ae04494 Compare July 6, 2026 18:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 3 comments.

Comment thread src/inference_endpoint/commands/benchmark/execute.py
Comment thread src/inference_endpoint/commands/benchmark/execute.py Outdated
Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
@codecov-commenter

codecov-commenter commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.20827% with 154 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@bf9d12b). Learn more about missing BASE report.

Files with missing lines Patch % Lines
.../inference_endpoint/evaluation/swe_bench_scorer.py 82.35% 72 Missing ⚠️
...uation/swebench_service/swebench_service/runner.py 88.40% 32 Missing ⚠️
...uation/swebench_service/swebench_service/server.py 90.40% 26 Missing ⚠️
...on/swebench_service/swebench_service/qwen_tools.py 79.20% 21 Missing ⚠️
...c/inference_endpoint/commands/benchmark/execute.py 96.72% 2 Missing ⚠️
...ion/swebench_service/swebench_service/artifacts.py 97.72% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #342   +/-   ##
=======================================
  Coverage        ?   81.26%           
=======================================
  Files           ?      142           
  Lines           ?    18763           
  Branches        ?        0           
=======================================
  Hits            ?    15247           
  Misses          ?     3516           
  Partials        ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI review requested due to automatic review settings July 6, 2026 22:49

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 3 comments.

Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Copilot AI review requested due to automatic review settings July 9, 2026 22:09
@tianmu-li
tianmu-li force-pushed the feat/swe_bench_scorer branch from da45a99 to fe442f8 Compare July 9, 2026 22:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 2 comments.

Comment thread examples/10_Agentic_Inference/accuracy/actions_toolcall.py
Comment thread examples/10_Agentic_Inference/accuracy/actions_toolcall.py
Copilot AI review requested due to automatic review settings July 9, 2026 23:10
options["swebench_service_url"] = cls._normalize_service_url(
extras.get("swebench_service_url")
)
auth_token = extras.get("swebench_service_auth_token")

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.

swebench_service_auth_token is retained as an ordinary string under accuracy_config.extras, and setup_benchmark() writes the full resolved configuration to report_dir/config.yaml without redaction. This also happens for PERF-only runs that never contact the service. Since report directories are commonly retained or shared, please exclude/redact this credential during serialization and add a test proving it never appears in config.yaml.

base = ""
model_kwargs["api_base"] = ""

if request.endpoint_api_key:

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 endpoint API key is inserted into model_kwargs. mini-swe-agent serializes the complete model configuration into each trajectory (upstream implementation), and the Qwen overlay does the same. Those trajectories persist under the service artifact root even though request.json and status.json are redacted. Please inject the key through a non-serialized mechanism, or scrub/remove it from every generated trajectory before retaining the run.

@@ -0,0 +1,174 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.

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.

litellm_model.py and actions_toolcall.py appear to be substantial modified copies of mini-swe-agent v2.3.0 (source 1, source 2). They currently contain only the NVIDIA Apache header. Upstream's MIT license requires retaining its copyright and permission notice in copies or substantial portions. Please preserve the upstream notice and add source attribution/third-party notices for all copied Python and YAML templates, subject to the project's OSS guidance.

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.

Why do we need those changes? This will create a substantial burden on us to maintain these files. Can we just use a pinned version from the mini-swe-agent?

)


def _terminate_process(process: subprocess.Popen[str]) -> 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.

Cancellation kills only the mini-extra process group. mini-swe-agent starts containers with detached docker run -d and relies on object destruction for cleanup (upstream Docker environment); SIGTERM/SIGKILL does not run that cleanup. With the configured 10-hour container timeout, repeated cancellations can leave many containers consuming resources. Please label/track containers by service run and clean them in an unconditional service-side finally path for success, failure, timeout, shutdown, and cancellation.


result = status.get("result")
result_path = self.report_dir / "swe_bench_results.json"
if result is None and result_path.exists():

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.

Report directories in the example configs are reused. If artifact download fails, an old swe_bench_results.json remains; this fallback can then score that old result when the current status lacks an inline result. Even when the current inline result exists, the old file is never overwritten, leaving the reported artifact inconsistent with the computed score. Please clear or namespace artifacts by run_id and always atomically write the current result. Any fallback artifact must be explicitly tied to the current run.

@hvagadia

Copy link
Copy Markdown
Collaborator

LGTM overall. Checkout the minor nits I posted. I will test it out on Kimi later. Thanks Tianmu.

Copilot AI review requested due to automatic review settings July 16, 2026 15:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 37 out of 39 changed files in this pull request and generated 2 comments.

Comment thread src/inference_endpoint/commands/benchmark/execute.py Outdated
Comment thread src/inference_endpoint/commands/benchmark/execute.py
Copilot AI review requested due to automatic review settings July 16, 2026 16:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 37 out of 39 changed files in this pull request and generated 2 comments.

Comment thread src/inference_endpoint/evaluation/scoring.py Outdated
Copilot AI review requested due to automatic review settings July 16, 2026 16:37

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 37 out of 39 changed files in this pull request and generated 2 comments.

if command == "view":
view_range = args.get("view_range")
if view_range is not None:
if not isinstance(view_range, list | tuple) or len(view_range) != 2:
Comment on lines +2398 to +2403
submitted_count = result.get("submitted_instances") or 0
resolved = result.get("resolved_instances") or 0
if submitted_count == 0:
logger.warning("SWE-bench: submitted_instances=0; returning None score")
self.complete = False
return None, 1
Comment on lines +125 to +136
@classmethod
def dataset_loader_kwargs(cls, extras: dict[str, Any]) -> dict[str, Any]:
return {}

@classmethod
def external_sample_count(cls, extras: dict[str, Any]) -> int | None:
return None

@classmethod
def preflight(cls, extras: dict[str, Any]) -> None:
return 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.

Doc strings please.

return mean_score, n_repeats


class SWEBenchScorer(Scorer, scorer_id="swe_bench_scorer"):

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 is a huge class, so we can probably move it to a separate file.
Plus please add documentation to give an overview of the functionality.

PREDEFINED: ClassVar[dict[str, type["Scorer"]]] = {}
SCORER_ID: ClassVar[str]
REQUIRES_EXTRACTOR: ClassVar[bool] = True
SKIP_ENDPOINT_PHASE: ClassVar[bool] = False

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.

Doc explaining what this is intended to do?

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.

Should this be inside templates?



class RunManager:
def __init__(self, *, config: ServiceConfig, runner: Any):

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.

Please add a type for the runner arg.

Comment on lines +194 to +202
def _effective_external_sample_count(
eval_cfg: AccuracyConfiguration,
) -> int | None:
count = eval_cfg.scorer.external_sample_count(eval_cfg.extras)
if count is None:
return None
return min(count, eval_cfg.dataset.num_samples())


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.

Doc string.


accuracy_datasets: list[Dataset] = []
eval_configs: list[AccuracyConfiguration] = []
load_accuracy = test_mode in (TestMode.ACC, TestMode.BOTH)

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.

Can we just use the presence of accuracy config in the yaml file to indicate that accuracy must be run. That will keep it consistent.

Comment on lines +315 to +323
def _validate_accuracy_config_for_scorer(
scorer_cls: type[Scorer],
dataset_name: str,
accuracy_config: Any,
) -> None:
if (
scorer_cls.SCORER_ID == ScorerMethod.SWE_BENCH.value
and accuracy_config.num_repeats != 1
):

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.

Docstring. Plus this looks like it is only needed for swe-bench. Any reason why num_repeats !=1 isn't supported.

Comment on lines +112 to +115
if os.name == "nt":
process.terminate()
else:
os.killpg(process.pid, signal.SIGTERM)

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 necessary?

)


class SwebenchRunner:

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.

nit - rename to SweBenchRunner

Copilot AI review requested due to automatic review settings July 17, 2026 15:48

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 38 out of 40 changed files in this pull request and generated 2 comments.

Comment on lines +128 to +134
def _normalize_service_url(cls, value: Any) -> str:
if value is None or str(value).strip() == "":
raise SetupError(
"accuracy_config.extras.swebench_service_url is required for "
"swe_bench_scorer. Start the SWE-bench service and pass its URL."
)
return str(value).strip().rstrip("/") + "/"
Comment on lines +475 to +489
def _resolve_service_template(cls, extras: dict[str, Any]) -> str:
raw = extras.get("swebench_template")
if raw is None:
raw = (
"qwen_tools"
if cls._get_extra_bool(extras, cls.TOOLCALL_PATCH_EXTRA)
else "default"
)
template = str(raw)
if template not in cls.SERVICE_TEMPLATES:
raise SetupError(
"accuracy_config.extras.swebench_template must be one of "
f"{sorted(cls.SERVICE_TEMPLATES)}; got {template!r}"
)
return template
Copilot AI review requested due to automatic review settings July 17, 2026 16:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 38 out of 40 changed files in this pull request and generated 2 comments.

Comment on lines 1491 to 1495
# Bound the raw-output read to the accuracy population so finalize never holds
# the whole run's (incl. perf) response-text corpus.
accuracy_uuids = (
_accuracy_uuid_bound(ctx.report_dir, ctx.eval_configs)
if has_accuracy
else set()
_accuracy_uuid_bound(ctx.report_dir, eval_configs) if has_accuracy else set()
)
Comment on lines +1405 to +1429
def _redact_secret_fields(value: Any) -> Any:
if isinstance(value, dict):
redacted: dict[str, Any] = {}
for key, item in value.items():
normalized = str(key).strip().lower().replace("-", "_")
if (
normalized
in {
"api_key",
"access_token",
"authorization",
"auth_token",
"password",
"token",
}
or normalized.endswith(("_key", "_token", "_password"))
or "secret" in normalized
):
redacted[key] = "<redacted>"
else:
redacted[key] = BenchmarkConfig._redact_secret_fields(item)
return redacted
if isinstance(value, list):
return [BenchmarkConfig._redact_secret_fields(item) for item in value]
return value
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.

[Feature]: SWE-bench using mini-swe-agent

5 participants