Skip to content

Commit 837dc32

Browse files
AlexanderSaninpre-commit-ci[bot]ericspod
authored
fix(networks): replace Tensor | None with Optional[Tensor] for TorchScript compatibility (#8879)
## Summary Fixes #7939 The `|` union type syntax (e.g. `torch.Tensor | None`) was introduced in Python 3.10. While `from __future__ import annotations` defers annotation evaluation at runtime, **TorchScript's annotation parser does not support this syntax** and fails when scripting models that include these forward method signatures, producing: ``` RuntimeError: Can't redefine method: forward on class ``` This PR replaces `torch.Tensor | None` with `Optional[torch.Tensor]` (from `typing`) in the `forward` methods of the three blocks that form the ViT/UNETR scripting path: - `monai/networks/blocks/crossattention.py` — `CrossAttentionBlock.forward` - `monai/networks/blocks/selfattention.py` — `SABlock.forward` - `monai/networks/blocks/transformerblock.py` — `TransformerBlock.forward` ## Test plan - [x] `torch.jit.script(CrossAttentionBlock(...))` succeeds after fix - [x] `torch.jit.script(SABlock(...))` succeeds after fix - [x] `torch.jit.script(TransformerBlock(...))` succeeds after fix - [ ] `python -m pytest tests/networks/nets/test_unetr.py -k test_script` - [ ] `python -m pytest tests/networks/blocks/test_crossattention.py` - [ ] `python -m pytest tests/networks/blocks/test_selfattention.py` --------- Signed-off-by: Oleksandr Sanin <alexaaander.sanin@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Eric Kerfoot <17726042+ericspod@users.noreply.github.com>
1 parent dc0f59c commit 837dc32

3 files changed

Lines changed: 17 additions & 3 deletions

File tree

monai/networks/blocks/crossattention.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
from __future__ import annotations
1313

14+
from typing import Optional
15+
1416
import torch
1517
import torch.nn as nn
1618

@@ -139,7 +141,7 @@ def __init__(
139141
)
140142
self.input_size = input_size
141143

142-
def forward(self, x: torch.Tensor, context: torch.Tensor | None = None):
144+
def forward(self, x: torch.Tensor, context: Optional[torch.Tensor] = None): # noqa: UP045
143145
"""
144146
Args:
145147
x (torch.Tensor): input tensor. B x (s_dim_1 * ... * s_dim_n) x C

monai/networks/blocks/selfattention.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
from __future__ import annotations
1313

14+
from typing import Optional
15+
1416
import torch
1517
import torch.nn as nn
1618
import torch.nn.functional as F
@@ -158,7 +160,7 @@ def __init__(
158160
)
159161
self.input_size = input_size
160162

161-
def forward(self, x, attn_mask: torch.Tensor | None = None):
163+
def forward(self, x, attn_mask: Optional[torch.Tensor] = None): # noqa: UP045
162164
"""
163165
Args:
164166
x (torch.Tensor): input tensor. B x (s_dim_1 * ... * s_dim_n) x C

monai/networks/blocks/transformerblock.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
from __future__ import annotations
1313

14+
from typing import Optional
15+
1416
import torch
1517
import torch.nn as nn
1618

@@ -23,6 +25,11 @@ class TransformerBlock(nn.Module):
2325
An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale <https://arxiv.org/abs/2010.11929>"
2426
"""
2527

28+
# Treat ``with_cross_attention`` as a TorchScript constant so the cross-attention branch in
29+
# ``forward`` is pruned when it is False. Otherwise scripting tries to compile the
30+
# ``self.cross_attn(..., context=context)`` call against ``nn.Identity`` and fails.
31+
__constants__ = ["with_cross_attention"]
32+
2633
def __init__(
2734
self,
2835
hidden_size: int,
@@ -102,7 +109,10 @@ def __init__(
102109
self.cross_attn = nn.Identity()
103110

104111
def forward(
105-
self, x: torch.Tensor, context: torch.Tensor | None = None, attn_mask: torch.Tensor | None = None
112+
self,
113+
x: torch.Tensor,
114+
context: Optional[torch.Tensor] = None, # noqa: UP045
115+
attn_mask: Optional[torch.Tensor] = None, # noqa: UP045
106116
) -> torch.Tensor:
107117
x = x + self.attn(self.norm1(x), attn_mask=attn_mask)
108118
if self.with_cross_attention:

0 commit comments

Comments
 (0)