aws-samples / aws-samples/sample-GEDD
Proposal: sample-gedd-openeval-adapter — bridge golden datasets/rubrics to EvalPort
- Dominant language
- Python
- Stars
- 12
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
## Proposal: `sample-gedd-openeval-adapter` — bridge GEDD's golden datasets/rubrics to the EvalPort format
Hi maintainers — this looks like a genuinely useful tool (grounded-theory-driven golden dataset + judge rubric generation is a gap most eval tooling doesn't address). I'd like to propose a small adapter package that converts GEDD's native artifacts to/from **[EvalPort](https://github.com/adhabnr-ux/evalport)**, an open interchange format ("Suite" = test cases + graders, "ResultSet" = per-test-case results) for portable LLM eval data. Spec: https://github.com/adhabnr-ux/evalport/blob/main/spec/SPEC.md
### Why this repo is a good fit
`grounded-evals/src/grounded_evals/models/core.py` already defines exactly the kind of native, reusable data objects an adapter needs — not just notebook output:
- `GoldenDataset` / `GoldenPrompt` — a golden set of prompts with full provenance (`category_id`, `code_id`, `is_edge_case`, `is_adversarial`, `expected_behavior`, `rationale`)
- `JudgeRubric` / `JudgeCriterion` — scoring criteria generated from `axial_coding` output (`generate_rubric()` in `judge_builder/rubric.py`), each with a `scoring_rubric: dict[int, str]` and a `weight`
- `Category` / `Code` / `ParadigmModel` — the qualitative-coding backbone that produces the above
That maps cleanly onto EvalPort's `EvalSuite` (test_cases + graders) with no lossy squeeze, since GEDD's prompt-level provenance fits naturally into `TestCase.metadata` / `tags`, and the rubric's per-criterion scoring bands fit into an `llm_judge` grader's `params`.
### Proposed sketch
```python
# adapters/sample-gedd-openeval-adapter/sample_gedd_openeval_adapter/to_openeval.py
from grounded_evals.models.core import GoldenDataset, GoldenPrompt, JudgeRubric, JudgeCriterion
def _criterion_to_grader(c: JudgeCriterion) -> dict:
rubric_text = "\n".join(f"{k}: {v}" for k, v in sorted(c.scoring_rubric.items(), reverse=True))
return {
"id": f"gr_{c.name.lower().replace(' ', '_')}",
"type": "llm_judge",
"weight": c.weight,
"description": c.description,
"params": {
"prompt": f"{c.description}\n\nScoring rubric:\n{rubric_text}",
},
}
def _prompt_to_testcase(p: GoldenPrompt, grader_ids: list[str]) -> dict:
return {
"id": str(p.id),
"input": p.prompt_text,
"graders": grader_ids,
"metadata": {
"category_id": str(p.category_id),
"code_id": str(p.code_id) if p.code_id else None,
"expected_behavior": p.expected_behavior,
"rationale": p.rationale,
"turn_count": p.turn_count,
},
"tags": [t for t, on in (("edge_case", p.is_edge_case), ("adversarial", p.is_adversarial)) if on],
}
def to_openeval(dataset: GoldenDataset, rubric: JudgeRubric) -> dict:
graders = [_criterion_to_grader(c) for c in rubric.criteria]
grader_ids = [g["id"] for g in graders]
return {
"version": "1.0.0",
"id": f"suite_{dataset.agent_name.lower().replace(' ', '_')}_{dataset.version}",
"name": f"{dataset.agent_name} — GEDD Golden Dataset",
"description": dataset.agent_description,
"graders": graders,
"test_cases": [_prompt_to_testcase(p, grader_ids) for p in dataset.prompts],
"metadata": {"source": "gedd", "gedd_version": dataset.version},
}
```
```python
# adapters/sample-gedd-openeval-adapter/sample_gedd_openeval_adapter/from_openeval.py
# A ResultSet produced by *any* EvalPort-speaking runner can feed straight into
# judge_builder/calibrate.py's calibration loop — treating each grader_result's
# score/passed as the signal to calibrate the GEDD-generated judge against.
def from_openeval(result_set: dict) -> list[dict]:
"""Flatten ResultSet.results[].grader_results into calibration records
keyed by test_case_id + grader_id, ready for judge_builder.calibrate."""
records = []
for r in result_set["results"]:
for gr in r["grader_results"]:
records.append({
"test_case_id": r["test_case_id"],
"grader_id": gr["grader_id"],
"score": gr["score"],
"passed": gr["passed"],
})
return records
```
(Sketch only — I haven't run this against the actual UUID/enum types, just laid out the field mapping for discussion. Happy to build it out properly as a PR if the shape looks right to you.)
### What I'm asking
Would you be open to a PR that adds this as a small, separately-versioned adapter package (own `pyproject.toml`, importing `grounded_evals.models.core` and `grounded_evals.judge_builder.rubric`), living either in this repo (e.g. `grounded-evals/adapters/openeval/`) or as a standalone package that depends on `grounded-evals`? Either is fine by me — whichever fits your structure better. I know AWS sample repos may require a CLA; happy to go through whatever process applies before opening the PR itself.
No pressure either way — just flagging the fit since the data model here is unusually well-suited to this. Thanks for the tool, the grounded-theory approach to golden-set generation is a nice idea.
Contributor guide
Research direction
Start with grounded-evals/src/grounded_evals/models/core.py and grounded_evals/judge_builder/rubric.py, then compare their models with the EvalPort SPEC.md. Confirm the adapter package location and field mappings with maintainers, including UUID and enum handling. Done means a separately versioned adapter can convert GEDD datasets and rubrics to EvalPort suites and flatten ResultSet data for calibration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- ai, testing-qa, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100