patch: fix EmptyLogits TypeError in pad_across_processes#6035
patch: fix EmptyLogits TypeError in pad_across_processes#6035MdHussain121 wants to merge 4 commits into
Conversation
for more information, see https://pre-commit.ci
There was a problem hiding this comment.
Code Review
This pull request introduces a patch patch_accelerate_recursively_apply to override accelerate.utils.operations.recursively_apply (and its re-export in accelerate.utils) to bypass Unsloth's EmptyLogits class, preventing potential TypeError exceptions. This patch is integrated into the GPU initialization process, and a corresponding unit test is added. The review feedback suggests refactoring the patch implementation to eliminate duplicated wrapper code and correcting a PEP 8 style violation regarding spaces around keyword arguments in the test file.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| def patch_accelerate_recursively_apply(): | ||
| """ | ||
| Patch accelerate.utils.operations.recursively_apply to avoid raising | ||
| TypeError when encountering Unsloth's EmptyLogits class. | ||
| """ | ||
| try: | ||
| import accelerate.utils.operations as acc_ops | ||
|
|
||
| original_recursively_apply = acc_ops.recursively_apply | ||
|
|
||
| @functools.wraps(original_recursively_apply) | ||
| def _patched_recursively_apply(func, data, *args, **kwargs): | ||
| if type(data).__name__ == "EmptyLogits": | ||
| return data | ||
| return original_recursively_apply(func, data, *args, **kwargs) | ||
|
|
||
| acc_ops.recursively_apply = _patched_recursively_apply | ||
| except Exception: | ||
| pass | ||
|
|
||
| try: | ||
| import accelerate.utils as acc_utils | ||
|
|
||
| if hasattr(acc_utils, "recursively_apply"): | ||
| original_recursively_apply = acc_utils.recursively_apply | ||
|
|
||
| @functools.wraps(original_recursively_apply) | ||
| def _patched_recursively_apply(func, data, *args, **kwargs): | ||
| if type(data).__name__ == "EmptyLogits": | ||
| return data | ||
| return original_recursively_apply(func, data, *args, **kwargs) | ||
|
|
||
| acc_utils.recursively_apply = _patched_recursively_apply |
There was a problem hiding this comment.
The implementation of patch_accelerate_recursively_apply contains duplicated code for defining and applying _patched_recursively_apply. Since accelerate.utils.recursively_apply is just a re-export of accelerate.utils.operations.recursively_apply, we can define the wrapper once and reuse it, which improves maintainability and readability.
def patch_accelerate_recursively_apply():
"""
Patch accelerate.utils.operations.recursively_apply to avoid raising
TypeError when encountering Unsloth's EmptyLogits class.
"""
try:
import accelerate.utils.operations as acc_ops
original_recursively_apply = acc_ops.recursively_apply
@functools.wraps(original_recursively_apply)
def _patched_recursively_apply(func, data, *args, **kwargs):
if type(data).__name__ == "EmptyLogits":
return data
return original_recursively_apply(func, data, *args, **kwargs)
acc_ops.recursively_apply = _patched_recursively_apply
try:
import accelerate.utils as acc_utils
if hasattr(acc_utils, "recursively_apply"):
acc_utils.recursively_apply = _patched_recursively_apply
except Exception:
pass
except Exception:
pass| e = EmptyLogits() | ||
| patch_accelerate_recursively_apply() | ||
|
|
||
| res = acc_ops.recursively_apply(lambda x: x, e, error_on_other_type = True) |
There was a problem hiding this comment.
According to PEP 8, spaces should not be used around the = sign when used to indicate a keyword argument or a default parameter value. Please remove the spaces around = in error_on_other_type = True.
| res = acc_ops.recursively_apply(lambda x: x, e, error_on_other_type = True) | |
| res = acc_ops.recursively_apply(lambda x: x, e, error_on_other_type=True) |
References
- PEP 8: Don't use spaces around the = sign when used to indicate a keyword argument or a default parameter value. (link)
… kwargs to conform with PEP 8
for more information, see https://pre-commit.ci
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 769151b13f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if type(data).__name__ == "EmptyLogits": | ||
| return data |
There was a problem hiding this comment.
Handle EmptyLogits before Accelerate debug verification
When Accelerate debug mode is enabled in distributed evaluation (ACCELERATE_DEBUG_MODE=1 / PartialState().debug), gather runs its verification wrapper before it reaches _gpu_gather and this patched recursively_apply; that wrapper calls find_device/get_shape on the logits structure, so a top-level EmptyLogits still raises before the bypass, and a nested one can make shape comparison fail across processes. This means the evaluation path this patch is meant to fix still breaks under Accelerate's debug mode unless the EmptyLogits case is handled at the operation/wrapper level as well.
Useful? React with 👍 / 👎.
This PR fixes the TypeError raised during evaluation loops when using Hugging Face Trainer and accelerate.
Problem
During evaluation, Trainer gathers logits using \�ccelerate.utils.operations.pad_across_processes\ (or \gather), which traverses datasets using
ecursively_apply\ with \error_on_other_type=True. Because Unsloth's \EmptyLogits\ is not a standard PyTorch Tensor or container,
ecursively_apply\ fails with:
\TypeError: Unsupported types (<class 'unsloth.models._utils.EmptyLogits'>) passed to _pad_across_processes\
Solution
Added a monkeypatch \patch_accelerate_recursively_apply\ in \unsloth.import_fixes\ that intercepts
ecursively_apply\ for \EmptyLogits\ inputs and returns them unmodified.
A drift detector test has been added to \ ests/test_import_fixes_drift.py\ to verify this behavior.