Fix KTO evaluate crash on streaming datasets with unpaired-preference data#6325
Fix KTO evaluate crash on streaming datasets with unpaired-preference data#6325albertvillanova wants to merge 4 commits into
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. |
Why this isn't gated on an Accelerate versionWhile debugging the Turns out that's misleading: Accelerate 1.13.0 added a short-circuit in concatenate() that returns a single gathered batch as-is instead of type-checking it.
Confirmed with the Accelerate maintainers themselves in the PR review thread (huggingface/accelerate#3850 (comment)): they explicitly acknowledged multi-process support was out of scope for that fix
I opened a GH issue to track this as a documented, discoverable limitation: So: real distributed streaming evaluation with KTO's unpaired-preference collator would still crash today, on any Accelerate version, without this fix. The fix here ("label" as a tensor, matching every other collated field) is the correct, version-independent solution, not something to conditionally apply only for old Accelerate. |
This PR fixes streaming evaluation for KTOTrainer with unpaired-preference data, where a batch field returned as a plain list broke Accelerate's dispatch mechanism for IterableDataset.
See: https://github.com/huggingface/trl/actions/runs/28934157283/job/85840257000?pr=6326
Traceback:
Motivation
DataCollatorForUnpairedPreferenceandDataCollatorForVisionUnpairedPreferencereturned the "label" batch field as a plain Python list of booleans instead of a tensor, while every other field in the batch was a tensor. This works fine with a map-styleDataset, but Accelerate'sDataLoaderDispatcher, used for streaming IterableDatasets, needs every batch field to be a tensor so it can concatenate and redistribute sub-batches across processes. Passing a streaming eval dataset toKTOTrainer.evaluate()therefore raisedTypeError: Can only concatenate tensors but got <class 'bool'>.Note this is not an Accelerate-version-specific issue. Accelerate ≥1.13.0 added a short-circuit in
concatenate()that happens to skip the crash whennum_processes == 1(see huggingface/accelerate#4111, which the Accelerate maintainers confirm is a partial, single-process-only fix). Real multi-process/distributed streaming evaluation still crashes on every Accelerate version, old and new. So this fix is required unconditionally, regardless of installed Accelerate version.Solution
"label" is now built with
torch.tensor(...)in both collators, consistent with every other returned field. Docstrings and doctest examples were updated to reflect the new tensor output.Changes
DataCollatorForUnpairedPreference.torch_callandDataCollatorForVisionUnpairedPreference.torch_calltest_padding_and_masksassertion for the new tensor typeKTOTrainer.evaluate()with anIterableDatasetNote
Low Risk
Narrow collator output change; loss paths already accept tensor labels via
torch.tensor/torch.as_tensor. Risk is mainly if any custom code assumedlabelwas always a list.Overview
Fixes KTOTrainer.evaluate crashing on streaming (
IterableDataset) eval when Accelerate’s dataloader dispatch tries to merge batch fields that must all be tensors.DataCollatorForUnpairedPreference and DataCollatorForVisionUnpairedPreference now set
labelwithtorch.tensor([...])instead of a Pythonlistof booleans, matching other batch keys and satisfying Accelerate’s concatenation (see accelerate#4111). Docstrings and doctest examples were updated accordingly.Tests assert tensor labels in the collator padding test and add
test_evaluate_with_iterable_dataset, which runs a real streaming eval withapo_zero_unpaired(no KL term on streaming data).Reviewed by Cursor Bugbot for commit 7929cf2. Bugbot is set up for automated code reviews on this repo. Configure here.