agentscope-ai / agentscope-ai/PawBench
Proposal: an EvalPort adapter for PawBench's tasks + submissions (interchange format for portable eval data)
- Linguagem predominante
- Python
- Estrelas
- 109
- Forks
- 19
- Métricas de merge de PRs
- Nenhum PR com merge em 30d
Descrição
## Proposal: an `evalport` adapter for PawBench's tasks + submissions
Hi — I maintain [EvalPort](https://github.com/adhabnr-ux/evalport), an Apache-2.0 interchange format (JSON Schema + Python/TS SDK, `evalport-sdk`) for portable LLM eval test cases, graders, and results. I read through the actual task/grading/submission code in this repo before writing this (not just the README), and I think PawBench's data model is a genuinely good fit — enough that I'd like to build and contribute the adapter myself if that's welcome.
### What I actually looked at
- `data/pawbench-v1.0/tasks/T001_claweval_M005_score_canon.md` (and neighboring task files) — the YAML front-matter + Prompt/Expected Behavior/Grading Criteria/Automated Checks/LLM Judge Rubric structure
- `pawbench/grader.py` — `grade_task()`, the three `grading_type`s (`automated`/`llm_judge`/`hybrid`), `GradeResult` (`task_id`, `score`, `max_score`, `grading_type`, `breakdown`, `notes`, `score_simple`), and `_combine_grades()`'s weighted combination
- `submissions/pawbench-4models-opusjudge-20260529__qwen3.6-plus__qwenpaw.json` — a real committed submission (`run`, `model`, `harness`, `overall`, `automated`, `judge`, `tasks`, `tasks_errored`, `tasks_missing`, plus the `by_complexity`/`by_environment`/`by_scenario`/`by_scenario_top`/`by_modality`/`by_channel`/`by_capability`/`by_source`/`by_category`/`by_subcategory`/`by_grading` slice breakdowns)
### The mapping
**Task → `TestCase`**
| PawBench (real fields, `T001_claweval_M005_score_canon.md`) | EvalPort `TestCase` |
|---|---|
| front-matter `id: M005_score_canon` | `id` |
| `## Prompt` body | `input` |
| `## Expected Behavior` body | `expected_output` |
| `labels.capabilities`, `labels.modality.type/.channels`, `labels.scenario`, `labels.complexity`, `labels.environment`, plus the submission's `by_source`/`by_category` keys | `tags` (e.g. `["capability:Tool_Use", "scenario:Content_Creation/Design", "complexity:L3", "environment:closed", "modality:multimodal", "source:claweval"]`) |
| `timeout_seconds: 1200` | `timeout_ms` (×1000) |
**Grading → `graders[]`, using the real `grading_weights`**
`T001` has `grading_type: hybrid` with `grading_weights: {automated: 0.3, llm_judge: 0.7}`. That maps onto two `Grader` entries on the same `TestCase`, weighted the same way EvalPort's own `weight` field already supports:
```python
graders = [
{
"id": "T001_automated",
"type": "code",
"weight": 0.3,
"params": {"language": "python", "source": automated_checks_source}, # the grade() body, verbatim
},
{
"id": "T001_llm_judge",
"type": "llm_judge",
"weight": 0.7,
"params": {"model": "claude-opus-4-5-20251101", "prompt": llm_judge_rubric_text}, # real default from grader.py
},
]
```
One honest wrinkle I want to flag rather than paper over: PawBench's `grade()` function signature is `grade(transcript: list, workspace_path: str) -> dict` — it scores the *whole agent transcript plus final workspace filesystem state*, not a single `actual_output` string. EvalPort's `code` grader type doesn't currently pin down a calling convention for `params.source` beyond "language + source," so this isn't a hard blocker, but it's worth resolving explicitly (e.g. does the adapter serialize workspace file contents into `TestCase.context`, or is this a case for a `pawbench.transcript`/`pawbench.workspace_snapshot` `metadata` extension?) before I write code that guesses.
**Submission JSON → `ResultSet`**
The committed `submissions/*.json` files are already *aggregated* (one JSON per model×harness run, not one row per task) — there's no raw per-task `GradeResult` dump in the repo, only the rolled-up `overall`/`by_*` breakdowns. So a faithful adapter has to be honest about what's actually round-trippable:
- `run` + `model` + `harness` → `ResultSet.run_id` (e.g. `"qwen3.6-plus__qwenpaw"`), `suite_id: "pawbench-v1.0"`
- `overall`/`automated`/`judge` → `ResultSet.summary.avg_score` plus `summary.metadata["pawbench.automated"]` / `["pawbench.judge"]` (EvalPort's built-in `summary.by_grader` is keyed by grader id, not by PawBench's five-dimension taxonomy, so the `by_scenario`/`by_capability`/`by_complexity`/`by_modality`/`by_environment`/`by_source`/`by_category`/`by_subcategory` blocks would live under `ResultSet.metadata["pawbench.by_scenario"]` etc. — preserved verbatim, not recomputed, the same `.` metadata convention this repo's other adapters already use)
- `tasks_errored`/`tasks_missing` → `summary.failed`/`summary.skipped` (best-effort; PawBench doesn't distinguish per-task which specific tasks errored vs. went missing in the aggregate file, so per-`Result` fidelity is limited to what's actually in the file)
### Comparable adapters already in the repo (verified, not asserted from memory)
- [`financebench-openeval-adapter`](https://github.com/adhabnr-ux/evalport/tree/main/adapters/financebench-openeval-adapter) — closest shape match: a fixed benchmark with real questions + gold answers + an `llm_judge` grader (because FinanceBench's free-text answers don't fit `exact_match` either) + real per-model result files with an existing human-annotated label, carried into EvalPort's `Result`/`GraderResult` verbatim rather than re-graded.
- [`lm-eval-harness-openeval-adapter`](https://github.com/adhabnr-ux/evalport/tree/main/adapters/lm-eval-harness-openeval-adapter) — comparable on the "harness" side: documents two real discrepancies it found between `lm-eval`'s docstrings and its actually-installed behavior, and is explicit about what does/doesn't round-trip (it can't reconstruct a live `lm_eval.api.task.Task`, same category of limitation I'm flagging above for PawBench's transcript+workspace grader signature).
### What I'd propose
If this is a direction the maintainers are open to, I'd build `pawbench-openeval-adapter` under `adapters/` in the EvalPort repo (not a PR against PawBench itself — no code changes needed here), following the same pattern: `to_openeval()`/`from_openeval()` for tasks, `result_to_openeval()` for submissions, real fixtures pulled from files actually in this repo, tests run against the real `openeval.validate.validate_suite()`/`validate_result_set()`. I'd rather get a maintainer's read on the grader-signature question above (and on whether `by_scenario`-style slice metadata under a `pawbench.` namespace is a reasonable round-trip target, versus something you'd want expressed differently) before writing it, rather than build first and ask later.
Happy to close this out if PawBench↔EvalPort interop isn't something you want to carry, no worries either way.
— Sahi, independent contributor (not affiliated with agentscope-ai)
Guia de contribuição
Nenhum guia de contribuição indexado para este repositório
Avaliação
Esta issue ainda não foi avaliada.