Support DatasetDict and IterableDatasetDict as eval_dataset in evaluate#6326
Conversation
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
|
Failing test is addressed in: |
|
thanks, we get a CI error, maybe we should bump the datasets version? |
|
Ok you're addressing it in #6326 (comment)! |
|
The KTO streaming test ( That's tracked and fixed independently in (this PR needs merging first): |
| eval_dataset: Dataset | ||
| | IterableDataset | ||
| | DatasetDict | ||
| | IterableDatasetDict | ||
| | dict[str, Dataset | IterableDataset] | ||
| | None = None, |
There was a problem hiding this comment.
ultra nit, can be addressed later: we could have something like a shared AnyDataset = Dataset | IterableDataset | DatasetDict | IterableDatasetDict | dict[str, Dataset | IterableDataset]
This PR extends evaluate() in the stable trainers (DPO, KTO, Reward, SFT) to formally accept a DatasetDict or IterableDatasetDict as eval_dataset, mirroring the support already added to
__init__in:Motivation
load_dataset returns a DatasetDict (or an IterableDatasetDict when streaming) whenever no split is specified, so users commonly hold these types and pass them straight to evaluate() for a held-out evaluation, e.g. trainer.evaluate(eval_dataset=load_dataset(...)). Because both subclass dict, this already worked at runtime in each trainer's evaluate(), since it dispatches per split via isinstance(eval_dataset, dict). But the type annotation only declared a plain dict, so the support was implicit and untested.
Solution
The eval_dataset parameter of each trainer's evaluate() now accepts DatasetDict and IterableDatasetDict explicitly, in its type annotation. Each split is still prepared independently, using the same _prepare_dataset path as passing a single dataset.
Changes
Note
Low Risk
Annotation and test-only alignment with existing dict-based eval preparation; no new eval logic paths.
Overview
DPO, KTO, Reward, and SFT
evaluate()now documents the sameeval_datasetshapes as trainer__init__: singleDataset/IterableDataset, multi-splitDatasetDict/IterableDatasetDict, or a plaindictof splits. Passing something likeload_dataset(...)without asplitis an intended use case; each named split is still prepared via_prepare_datasetand reported aseval_<split>_loss.Runtime handling is unchanged (
DatasetDictsubclassesdict, so per-split preparation already worked). The change is mainly type hints aligned with #6322, plus new tests (map vs streaming) on all four trainers so multi-splitevaluate()is covered end-to-end.Reviewed by Cursor Bugbot for commit fc3067f. Bugbot is set up for automated code reviews on this repo. Configure here.