Skip to content

fix(hooks): preserve original forward signature in register_hook#14237

Open
sergioperezcheco wants to merge 1 commit into
huggingface:mainfrom
sergioperezcheco:fix/preserve-hook-forward-signature
Open

fix(hooks): preserve original forward signature in register_hook#14237
sergioperezcheco wants to merge 1 commit into
huggingface:mainfrom
sergioperezcheco:fix/preserve-hook-forward-signature

Conversation

@sergioperezcheco

Copy link
Copy Markdown

Fixes #14135.

HookRegistry.register_hook wraps the module forward through a (module, *args, **kwargs) closure and previously bound the result with functools.update_wrapper pointing wrapped at that closure. Because inspect.signature follows wrapped, the wrapped forward exposed (module, *args, **kwargs) instead of the real parameters, which broke torch.export/torch.compile with "missing a required argument: 'module'" and hid the real signature from tooling.

The fix points wrapped at the original forward captured before it is overwritten, so inspect.signature resolves back to the real parameters. This chains correctly when multiple hooks are stacked, since each wrapper's wrapped points at the previous (now also correctly-wrapped) wrapper. Runtime behaviour is unchanged.

Verified with the issue's reproducer: signature is preserved after one and two hooks, and torch.export.export succeeds where it previously failed. Added a regression test in tests/hooks/test_hooks.py asserting both the signature and name are preserved.

Assisted-by: Hermes Agent

HookRegistry.register_hook wraps the module forward in a
(module, *args, **kwargs) closure and bound it via functools.update_wrapper
pointing __wrapped__ at that closure. As a result
inspect.signature(module.forward) resolved to (module, *args, **kwargs)
instead of the real parameters, and torch.export/torch.compile failed with
"missing a required argument: 'module'".

Point __wrapped__ (via update_wrapper's wrapped argument) at the original
forward captured before it is overwritten, so inspect.signature follows the
chain back to the real signature. The chain works for multiple stacked hooks
because each wrapper's __wrapped__ points at the previous (also-correct)
wrapper. Call-time behaviour is unchanged.

Regression test in tests/hooks/test_hooks.py asserts the signature and
__name__ are preserved after registering one and two hooks.

Fixes huggingface#14135
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hooks size/S PR with diff < 50 LOC tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HookRegistry.register_hook breaks module forward signature

1 participant