OpenHands / OpenHands/benchmarks

Portable result export: to_openeval()/from_openeval() for EvalInstance/EvalOutput?

Open
#776 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
124
Forks
90
Avg merge
1d 6h
Merged PRs (30d)
1

Description

Summary

Would to_openeval() / from_openeval() helpers for this repo's EvalInstance / EvalOutput models be useful, so runs from any of the ~20 benchmark harnesses here (SWE-Bench, GAIA, Harbor/TerminalBench, Commit0, etc.) could be exported into a portable, framework-agnostic result format?

Context

I looked through benchmarks/utils/models.py and CONTRIBUTING.md — this repo already has a clean, shared shape across every benchmark folder:

  • EvalInstance(id: str, data: dict[str, Any]) — the per-task input, produced by every benchmark's prepare_instances().
  • EvalOutput(instance_id, attempt, test_result: dict[str, Any], instruction, metadata: EvalMetadata, history: list[Event], metrics: Metrics, error, instance, runtime_runs) — the per-task result, produced by evaluate_instance() and written out by every eval_infer.py.
  • EvalMetadata(llm, dataset, dataset_split, max_iterations, eval_output_dir, critic, workspace_type, ...) — the run-level config.

That's a real, shared, installable schema (not per-benchmark ad hoc JSON), which is exactly the situation EvalPort (spec: https://github.com/adhabnr-ux/evalport/blob/main/spec/SPEC.md) is meant for: a small JSON-Schema-defined format for portable eval test cases and result sets, with a Python SDK (evalport-sdk on PyPI, openeval.validate.validate_suite() / validate_result_set()) and 35+ community adapter packages (example: autogen-openeval-adapter).

What I'm proposing

Not a change to the harness itself — just two small, optional conversion functions (could live in benchmarks/utils/ or as a separate benchmarks-openeval-adapter package, whichever this repo prefers):

# sketch — field names taken from benchmarks/utils/models.py
from benchmarks.utils.models import EvalInstance, EvalOutput

def to_openeval_case(instance: EvalInstance, suite_id: str) -> dict:
    """EvalInstance -> an EvalPort testcase.json-shaped record."""
    return {
        "case_id": instance.id,
        "suite_id": suite_id,
        "input": instance.data,
    }

def to_openeval_result(output: EvalOutput, suite_id: str) -> dict:
    """EvalOutput -> an EvalPort resultset.json-shaped record."""
    return {
        "suite_id": suite_id,
        "case_id": output.instance_id,
        "attempt": output.attempt,
        "raw_result": output.test_result,
        "error": output.error,
        "cost_usd": getattr(output.metrics, "accumulated_cost", None)
        if output.metrics
        else None,
    }

with the reverse direction (from_openeval_caseEvalInstance) letting an external OpenEval-format suite be dropped straight into prepare_instances().

Why this might be worth it for this repo specifically: with 20+ benchmark integrations already normalized to EvalInstance/EvalOutput, this would be the cheapest path to (a) comparing results across benchmarks and external tools in one place, and (b) letting other eval tooling consume benchmarks/ output without hand-writing a parser per benchmark.

Happy to put together a draft PR (either inside this repo under benchmarks/utils/, or as a standalone adapter package under evalport's adapters/) if this is a direction the maintainers are interested in — or to hear that it isn't a good fit given where the harness is headed.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading benchmarks/utils/models.py and CONTRIBUTING.md, then review the linked EvalPort specification and the existing benchmark output paths. Confirm with maintainers whether an in-repo utility or separate adapter is wanted before defining conversions in both directions. Done means an agreed scope and format mapping, followed by validation and tests for the accepted interface.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.