hyperonnx 1.0.0__tar.gz → 1.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/.github/workflows/lint.yml +3 -1
  2. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/.github/workflows/unittest.yml +4 -2
  3. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/.pre-commit-config.yaml +11 -17
  4. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/PKG-INFO +17 -14
  5. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/README.md +2 -2
  6. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/README_CN.md +1 -1
  7. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/hyperonnx/__init__.py +1 -1
  8. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/hyperonnx/auto.py +8 -8
  9. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/hyperonnx/exporter/__init__.py +1 -2
  10. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/hyperonnx/exporter/dynamo.py +2 -2
  11. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/hyperonnx/exporter/torchscript.py +2 -3
  12. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/hyperonnx/exporter/utils.py +2 -2
  13. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/hyperonnx/function_rewriter.py +21 -24
  14. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/hyperonnx/hyper_export.py +25 -24
  15. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/hyperonnx/torch_export.py +2 -2
  16. hyperonnx-1.0.2/hyperonnx/transformers/__init__.py +10 -0
  17. hyperonnx-1.0.2/hyperonnx/transformers/attention.py +218 -0
  18. hyperonnx-1.0.2/hyperonnx/transformers/cache.py +173 -0
  19. {hyperonnx-1.0.0/hyperonnx → hyperonnx-1.0.2/hyperonnx/transformers}/patch.py +6 -6
  20. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/hyperonnx/typing.py +11 -10
  21. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/pyproject.toml +50 -7
  22. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/tests/expoter/test_dynamo_build_onnxscript.py +3 -1
  23. hyperonnx-1.0.2/tests/expoter/test_non_pod_export.py +105 -0
  24. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/tests/test_auto_trace_method.py +6 -10
  25. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/tests/test_compose_nodes_to_functions.py +4 -4
  26. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/tests/test_export_functions.py +44 -52
  27. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/tests/test_export_hyper_onnx.py +50 -36
  28. hyperonnx-1.0.2/tests/transformers/test_attention.py +126 -0
  29. hyperonnx-1.0.2/tests/transformers/test_static_cache.py +465 -0
  30. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/.github/words_bag.txt +0 -0
  31. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/.gitignore +0 -0
  32. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/LICENSE +0 -0
  33. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/docs/assets/qwen2_omni_vision.gif +0 -0
  34. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/docs/assets/r18-sample.gif +0 -0
  35. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/hyperonnx/utils.py +0 -0
  36. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/tests/expoter/test_detach_module_outputs.py +0 -0
  37. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/tests/expoter/test_dynamo_make_custom_op.py +0 -0
  38. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/tests/expoter/test_dynamo_replace_custom_op.py +0 -0
  39. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/tests/expoter/test_plain_output_tensors.py +0 -0
  40. {hyperonnx-1.0.0 → hyperonnx-1.0.2}/tests/test_fuse_constants_to_function.py +0 -0
@@ -11,6 +11,7 @@ jobs:
11
11
  strategy:
12
12
  matrix:
13
13
  python-version: ["3.12"]
14
+ transformers-version: ["4.53.0", "5.1.0"]
14
15
  steps:
15
16
  - uses: actions/checkout@v5
16
17
  with:
@@ -24,6 +25,7 @@ jobs:
24
25
  node-version: lts/Jod
25
26
  - name: pyright type check
26
27
  run: |
27
- uv sync --extra=test -U
28
+ uv sync --dev --extra=cpu
29
+ uv pip install 'transformers==${{ matrix.transformers-version }}'
28
30
  uv run pyright hyperonnx
29
31
  uv run pre-commit run -s HEAD^ -o HEAD
@@ -12,6 +12,7 @@ jobs:
12
12
  strategy:
13
13
  matrix:
14
14
  python-version: ["3.12"]
15
+ transformers-version: ["4.53.0", "5.1.0"]
15
16
  steps:
16
17
  - uses: actions/checkout@v5
17
18
  - name: Install uv and set the Python version
@@ -20,7 +21,8 @@ jobs:
20
21
  python-version: ${{ matrix.python-version }}
21
22
  - name: Install dependencies
22
23
  run: |
23
- uv sync --extra=test -U
24
+ uv sync --dev --extra=cpu -U
25
+ uv pip install 'transformers==${{ matrix.transformers-version }}'
24
26
  - name: Run pytest and coverage
25
27
  run: |
26
- uv run pytest --cov=hyperonnx tests
28
+ uv run --dev --extra=cpu pytest --cov=hyperonnx tests
@@ -9,32 +9,26 @@ repos:
9
9
  - id: check-toml
10
10
  - id: check-yaml
11
11
  - id: check-added-large-files
12
- - repo: https://github.com/PyCQA/isort
13
- rev: 6.0.1
12
+ - repo: https://github.com/astral-sh/ruff-pre-commit
13
+ # Ruff version.
14
+ rev: v0.15.8
14
15
  hooks:
15
- - id: isort
16
- args: ['--profile=black']
17
- - repo: https://github.com/psf/black
18
- rev: 25.1.0
19
- hooks:
20
- - id: black
16
+ # Run the linter.
17
+ - id: ruff-check
18
+ args: [--fix]
19
+ # Run the formatter.
20
+ - id: ruff-format
21
21
  - repo: https://github.com/codespell-project/codespell
22
- rev: v2.4.1
22
+ rev: v2.4.2
23
23
  hooks:
24
24
  - id: codespell
25
25
  args: [-w, -I=.github/words_bag.txt]
26
26
  exclude: (\.(txt|diff|patch)$)
27
- - repo: https://github.com/pycqa/flake8
28
- rev: 7.3.0
29
- hooks:
30
- - id: flake8
31
- additional_dependencies: [Flake8-pyproject]
32
- args:
33
- - '--ignore=W503,E203,E231,E241'
34
27
  - repo: https://github.com/pre-commit/mirrors-mypy
35
- rev: v1.17.1
28
+ rev: v1.19.1
36
29
  hooks:
37
30
  - id: mypy
38
31
  args:
39
32
  - '--ignore-missing-imports'
40
33
  - '--exclude=tests.*\.py'
34
+ exclude: (^tests/)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperonnx
3
- Version: 1.0.0
3
+ Version: 1.0.2
4
4
  Summary: Copyright (C) 2025 The HYPERONNX Authors.
5
5
  Author-email: Wenyi Tang <wenyitang@outlook.com>
6
6
  Requires-Python: >=3.11
@@ -9,26 +9,29 @@ Classifier: License :: OSI Approved :: Apache Software License
9
9
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
10
10
  Classifier: Topic :: Software Development
11
11
  License-File: LICENSE
12
- Requires-Dist: onnxifier>=2.0.0
13
- Requires-Dist: onnxscript
12
+ Requires-Dist: onnxifier>=2.0.1
13
+ Requires-Dist: onnxscript<0.6.0
14
14
  Requires-Dist: onnx>=1.18.0
15
- Requires-Dist: torch
16
- Requires-Dist: mypy ; extra == "test"
17
- Requires-Dist: onnxruntime ; extra == "test"
18
- Requires-Dist: pre-commit ; extra == "test"
19
- Requires-Dist: pyright>=1.1.408 ; extra == "test"
20
- Requires-Dist: pytest ; extra == "test"
21
- Requires-Dist: pytest-cov ; extra == "test"
22
- Requires-Dist: torchvision ; extra == "test"
15
+ Requires-Dist: torch<2.11 ; extra == "cpu"
16
+ Requires-Dist: torchvision ; extra == "cpu"
17
+ Requires-Dist: triton-windows ; extra == "cpu" and ( sys_platform == 'win32')
18
+ Requires-Dist: torch<2.11 ; extra == "cuda"
19
+ Requires-Dist: torchvision ; extra == "cuda"
20
+ Requires-Dist: triton-windows ; extra == "cuda" and ( sys_platform == 'win32')
21
+ Requires-Dist: torch<2.11 ; extra == "xpu"
22
+ Requires-Dist: torchvision ; extra == "xpu"
23
+ Requires-Dist: pytorch-triton-xpu ; extra == "xpu"
23
24
  Project-URL: Docs, https://loseall.github.io/hyperonnx
24
25
  Project-URL: Home, https://github.com/LoSealL/hyperonnx
25
- Provides-Extra: test
26
+ Provides-Extra: cpu
27
+ Provides-Extra: cuda
28
+ Provides-Extra: xpu
26
29
 
27
30
  # 🚀 HYPER-ONNX
28
31
 
29
32
  [中文](./README_CN.md)|[EN](./README.md)
30
33
 
31
- Hyper-ONNX can export pytorch models (`nn.Module`) in a hierachical manner. It can keep the module hier information and make a nested onnx graph. ✨
34
+ Hyper-ONNX can export pytorch models (`nn.Module`) in a hierarchical manner. It can keep the module hier information and make a nested onnx graph. ✨
32
35
 
33
36
 
34
37
  ## 📦 Install
@@ -76,7 +79,7 @@ export_hyper_onnx(
76
79
 
77
80
  ```python
78
81
  from hyperonnx import auto_trace_method
79
- from hyperonnx.patch import patch_transformers
82
+ from hyperonnx.transformers import patch_transformers
80
83
  from transformers import (
81
84
  GenerationConfig,
82
85
  Qwen2_5OmniThinkerForConditionalGeneration,
@@ -2,7 +2,7 @@
2
2
 
3
3
  [中文](./README_CN.md)|[EN](./README.md)
4
4
 
5
- Hyper-ONNX can export pytorch models (`nn.Module`) in a hierachical manner. It can keep the module hier information and make a nested onnx graph. ✨
5
+ Hyper-ONNX can export pytorch models (`nn.Module`) in a hierarchical manner. It can keep the module hier information and make a nested onnx graph. ✨
6
6
 
7
7
 
8
8
  ## 📦 Install
@@ -50,7 +50,7 @@ export_hyper_onnx(
50
50
 
51
51
  ```python
52
52
  from hyperonnx import auto_trace_method
53
- from hyperonnx.patch import patch_transformers
53
+ from hyperonnx.transformers import patch_transformers
54
54
  from transformers import (
55
55
  GenerationConfig,
56
56
  Qwen2_5OmniThinkerForConditionalGeneration,
@@ -50,7 +50,7 @@ export_hyper_onnx(
50
50
 
51
51
  ```python
52
52
  from hyperonnx import auto_trace_method
53
- from hyperonnx.patch import patch_transformers
53
+ from hyperonnx.transformers import patch_transformers
54
54
  from transformers import (
55
55
  GenerationConfig,
56
56
  Qwen2_5OmniThinkerForConditionalGeneration,
@@ -19,4 +19,4 @@ from .hyper_export import export_hyper_onnx
19
19
  from .utils import HYPER_DOMAIN
20
20
 
21
21
  __all__ = ["auto_trace_method", "export_hyper_onnx", "HYPER_DOMAIN"]
22
- __version__ = "1.0.0"
22
+ __version__ = "1.0.2"
@@ -15,13 +15,13 @@ limitations under the License.
15
15
  """
16
16
 
17
17
  import inspect
18
+ from collections.abc import Collection
18
19
  from contextlib import contextmanager
19
20
  from functools import wraps
20
21
  from io import BytesIO
21
22
  from os import PathLike
22
23
  from pathlib import Path
23
24
  from types import MethodType
24
- from typing import Collection, Dict, List, Optional, Tuple
25
25
 
26
26
  from torch import inference_mode
27
27
  from torch.nn import Module
@@ -60,8 +60,8 @@ class AutoTraceMethod(Module):
60
60
 
61
61
  def __init__(self, clsmethod: MethodType, expected_stages: int = 1):
62
62
  super().__init__()
63
- self.pos_args: List[Tuple[AnyTensor, ...]] = []
64
- self.kwargs: List[Dict[str, AnyTensor]] = []
63
+ self.pos_args: list[tuple[AnyTensor, ...]] = []
64
+ self.kwargs: list[dict[str, AnyTensor]] = []
65
65
  model = clsmethod.__self__
66
66
  if not isinstance(model, Module):
67
67
  for k, v in model.__dict__.items():
@@ -88,15 +88,15 @@ class AutoTraceMethod(Module):
88
88
  self,
89
89
  f: str | PathLike | BytesIO,
90
90
  *,
91
- input_names: Optional[List[str]] = None,
92
- output_names: Optional[List[str]] = None,
91
+ input_names: list[str] | None = None,
92
+ output_names: list[str] | None = None,
93
93
  opset_version: int = 19,
94
94
  dynamo: bool = False,
95
95
  external_data: bool = False,
96
- hiera: Optional[Collection[type[Module]]] = None,
97
- module_spec: Optional[Dict[Module, ModuleSpec]] = None,
96
+ hiera: Collection[type[Module]] | None = None,
97
+ module_spec: dict[Module, ModuleSpec] | None = None,
98
98
  do_optimization: bool = True,
99
- external_directory: Optional[str | PathLike] = None,
99
+ external_directory: str | PathLike | None = None,
100
100
  ):
101
101
  """Export onnx model according to the traced data."""
102
102
  if not self.pos_args and not self.kwargs:
@@ -15,7 +15,6 @@ limitations under the License.
15
15
  """
16
16
 
17
17
  from contextlib import contextmanager
18
- from typing import Dict
19
18
 
20
19
  from torch.nn import Module
21
20
 
@@ -26,7 +25,7 @@ from .torchscript import replace_duck_forward
26
25
 
27
26
  @contextmanager
28
27
  def replace_with_duck_module(
29
- model: Module, dynamo: bool, module_spec: Dict[Module, ModuleSpec]
28
+ model: Module, dynamo: bool, module_spec: dict[Module, ModuleSpec]
30
29
  ):
31
30
  """Replace the forward function of modules in `module_spec` with a duck type.
32
31
 
@@ -17,8 +17,8 @@ limitations under the License.
17
17
  import inspect
18
18
  from ast import AST
19
19
  from collections import OrderedDict
20
+ from collections.abc import Callable
20
21
  from contextlib import contextmanager
21
- from typing import Callable, Dict
22
22
 
23
23
  import onnxscript
24
24
  import onnxscript.ir._schemas as schemas
@@ -257,7 +257,7 @@ def make_custom_op(module: Module, spec: ModuleSpec):
257
257
 
258
258
 
259
259
  @contextmanager
260
- def replace_with_custom_op(model: Module, module_spec: Dict[Module, ModuleSpec]):
260
+ def replace_with_custom_op(model: Module, module_spec: dict[Module, ModuleSpec]):
261
261
  """Replace the forward function of modules in `module_spec` with a duck type.
262
262
 
263
263
  It's used to laterly replace the duck type with the embedded onnx functions.
@@ -16,7 +16,6 @@ limitations under the License.
16
16
 
17
17
  from contextlib import contextmanager
18
18
  from functools import update_wrapper
19
- from typing import Dict, List
20
19
 
21
20
  import torch
22
21
  from torch import Tensor
@@ -91,7 +90,7 @@ def make_duck_forward(module_spec: ModuleSpec):
91
90
 
92
91
 
93
92
  @contextmanager
94
- def replace_duck_forward(model: Module, module_spec: Dict[Module, ModuleSpec]):
93
+ def replace_duck_forward(model: Module, module_spec: dict[Module, ModuleSpec]):
95
94
  """Replace the forward function of modules in `module_spec` with a duck type.
96
95
 
97
96
  It's used to laterly replace the duck type with the embedded onnx functions.
@@ -111,7 +110,7 @@ def replace_duck_forward(model: Module, module_spec: Dict[Module, ModuleSpec]):
111
110
  output = spec.get("output")
112
111
  return output
113
112
 
114
- handles: List[RemovableHandle] = []
113
+ handles: list[RemovableHandle] = []
115
114
  try:
116
115
  for child in filter(lambda c: c in module_spec, model.modules()):
117
116
  if module_spec[child]["status"] == ExportStatus.EXPORTED:
@@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  """
16
16
 
17
+ from collections.abc import Sequence
17
18
  from itertools import chain
18
- from typing import Sequence, Tuple
19
19
 
20
20
  import torch
21
21
  from onnxifier.logger import warning
@@ -24,7 +24,7 @@ from torch import Tensor
24
24
  from ..typing import AnyTensor, ModuleSpec
25
25
 
26
26
 
27
- def plain_tensor_container(obj: AnyTensor) -> Tuple[Tensor, ...]:
27
+ def plain_tensor_container(obj: AnyTensor) -> tuple[Tensor, ...]:
28
28
  """Iteratively flatten an arbitrary output of Tensors into a tuple of Tensors.
29
29
 
30
30
  Args:
@@ -1,5 +1,5 @@
1
1
  """
2
- Copyright (C) 2025 The HYPERONNX Authors.
2
+ Copyright (C) 2026 The HYPERONNX Authors.
3
3
 
4
4
  Licensed under the Apache License, Version 2.0 (the "License");
5
5
  you may not use this file except in compliance with the License.
@@ -17,11 +17,12 @@ limitations under the License.
17
17
  # pylint: disable=arguments-differ
18
18
 
19
19
  from collections import defaultdict
20
+ from collections.abc import Sequence
20
21
  from contextlib import suppress
21
22
  from copy import deepcopy
22
23
  from hashlib import md5
23
24
  from itertools import chain
24
- from typing import Dict, List, Literal, Sequence, Set, Tuple, cast
25
+ from typing import Literal, cast
25
26
 
26
27
  import networkx as nx
27
28
  import onnx
@@ -51,7 +52,7 @@ class ComposeOnnxAsFunctionRewriter(Rewriter):
51
52
 
52
53
  def __init__(self, domain: str, module_spec: Sequence[ModuleSpec]):
53
54
  super().__init__(SingleNodePattern().with_domain(domain))
54
- self._specs: Dict[str, ModuleSpec] = {
55
+ self._specs: dict[str, ModuleSpec] = {
55
56
  spec["type_name"]: spec for spec in module_spec
56
57
  }
57
58
 
@@ -122,8 +123,8 @@ class ComposeOnnxAsFunctionRewriter(Rewriter):
122
123
  # find the actual input with edges in the graph
123
124
  # and remove dangled inputs
124
125
  debugable_input_names = spec["input_names"]
125
- dangled_input: List[str] = []
126
- dangled_or_constant_unsafe: List[str] = []
126
+ dangled_input: list[str] = []
127
+ dangled_or_constant_unsafe: list[str] = []
127
128
  if len(node.input) != len(debugable_input_names):
128
129
  warning(
129
130
  f"Number of inputs on {node.name} is different from spec. "
@@ -143,10 +144,7 @@ class ComposeOnnxAsFunctionRewriter(Rewriter):
143
144
  debug(f"input unconnected to graph node: {input_name}")
144
145
  dangled_or_constant_unsafe.append(input_name)
145
146
  if len(dangled_input) < unused:
146
- error(
147
- f"Expect {unused} unused inputs but "
148
- f"enumerated {len(dangled_input)}."
149
- )
147
+ error(f"Expect {unused} unused inputs but enumerated {len(dangled_input)}.")
150
148
  reminder = unused - len(dangled_input)
151
149
  dangled_input.extend(dangled_or_constant_unsafe[:reminder])
152
150
  for j in dangled_input:
@@ -159,8 +157,8 @@ class ComposeOnnxAsFunctionRewriter(Rewriter):
159
157
  def _remove_unused_outputs(
160
158
  self, graph: OnnxGraph, unused: int, node: NodeProto, spec: ModuleSpec
161
159
  ):
162
- dangled_output: List[str] = []
163
- dangled_output_unsafe: List[str] = []
160
+ dangled_output: list[str] = []
161
+ dangled_output_unsafe: list[str] = []
164
162
  for i, output_name in enumerate(node.output):
165
163
  if output_name in spec["unused_outputs"]:
166
164
  dangled_output.append(output_name)
@@ -170,8 +168,7 @@ class ComposeOnnxAsFunctionRewriter(Rewriter):
170
168
  dangled_output_unsafe.append(output_name)
171
169
  if len(dangled_output) < unused:
172
170
  error(
173
- f"Expect {unused} unused outputs but "
174
- f"enumerated {len(dangled_output)}."
171
+ f"Expect {unused} unused outputs but enumerated {len(dangled_output)}."
175
172
  )
176
173
  reminder = unused - len(dangled_output)
177
174
  # try to drop `reminder` outputs from the last one
@@ -182,7 +179,7 @@ class ComposeOnnxAsFunctionRewriter(Rewriter):
182
179
  if j in graph.outputs:
183
180
  graph.remove_output(j)
184
181
 
185
- def rewrite(self, graph: OnnxGraph, nodes: List[NodeProto]):
182
+ def rewrite(self, graph: OnnxGraph, nodes: list[NodeProto]):
186
183
  node = nodes[0]
187
184
  if node.op_type not in self._specs:
188
185
  raise KeyError(f"node spec is not found for {node.name}")
@@ -253,7 +250,7 @@ class ComposeNodesToFunctionsRewriter(Rewriter):
253
250
  self.register_pre_hook(self._mark_isolated_nodes)
254
251
  self._name = name
255
252
  self._max_level = 0
256
- self._level_processed: Set[int] = set()
253
+ self._level_processed: set[int] = set()
257
254
 
258
255
  def _mark_isolated_nodes(self, graph: OnnxGraph) -> OnnxGraph:
259
256
  # make a shallow copy of the graph
@@ -269,7 +266,7 @@ class ComposeNodesToFunctionsRewriter(Rewriter):
269
266
  self._max_level = max(self._max_level, k + 1)
270
267
  return graph
271
268
 
272
- def _detect_cycles_in_graph(self, graph: OnnxGraph) -> List[List[str]]:
269
+ def _detect_cycles_in_graph(self, graph: OnnxGraph) -> list[list[str]]:
273
270
  """Comprehensive cycle detection in the entire graph."""
274
271
  try:
275
272
  cycles = list(nx.simple_cycles(graph))
@@ -278,7 +275,7 @@ class ComposeNodesToFunctionsRewriter(Rewriter):
278
275
  return []
279
276
 
280
277
  def _would_create_cycle(
281
- self, graph: OnnxGraph, new_node: NodeProto, nodes_to_remove: List[NodeProto]
278
+ self, graph: OnnxGraph, new_node: NodeProto, nodes_to_remove: list[NodeProto]
282
279
  ) -> bool:
283
280
  """Check if adding a new node and removing old nodes would create a cycle."""
284
281
  # Create a temporary graph by copying the original and removing nodes
@@ -307,7 +304,7 @@ class ComposeNodesToFunctionsRewriter(Rewriter):
307
304
  return True # Assume cycle exists for safety
308
305
 
309
306
  def _compose_subgraph(
310
- self, graph: OnnxGraph, same_level_nodes: List[NodeProto], level: int
307
+ self, graph: OnnxGraph, same_level_nodes: list[NodeProto], level: int
311
308
  ) -> None:
312
309
  if len(same_level_nodes) == 0:
313
310
  return # skip empty subgraph
@@ -388,7 +385,7 @@ class ComposeNodesToFunctionsRewriter(Rewriter):
388
385
  if direction == "upstream" and i.op_type == "Constant":
389
386
  continue
390
387
 
391
- same_level_nodes: List[NodeProto] = [i]
388
+ same_level_nodes: list[NodeProto] = [i]
392
389
  # Use BFS to collect neighbors to avoid recursive dependency issues
393
390
  visited = {i.name}
394
391
  queue = [i.name]
@@ -419,7 +416,7 @@ class ComposeNodesToFunctionsRewriter(Rewriter):
419
416
  """Compose downstream nodes into functions."""
420
417
  self._compose_neighbors(graph, node, "downstream")
421
418
 
422
- def rewrite(self, graph: OnnxGraph, nodes: List[NodeProto]):
419
+ def rewrite(self, graph: OnnxGraph, nodes: list[NodeProto]):
423
420
  node = nodes[0]
424
421
 
425
422
  # Check for cycles before starting composition
@@ -474,10 +471,10 @@ class FuseConstantsToFunctionRewriter(Rewriter):
474
471
 
475
472
  def __init__(self):
476
473
  super().__init__(SingleNodePattern().with_domain(HYPER_DOMAIN))
477
- self.users: Dict[str, int] = defaultdict(int)
474
+ self.users: dict[str, int] = defaultdict(int)
478
475
  self.register_pre_hook(self._collect_users)
479
476
 
480
- def rewrite(self, graph: OnnxGraph, nodes: List[NodeProto]):
477
+ def rewrite(self, graph: OnnxGraph, nodes: list[NodeProto]):
481
478
  node = nodes[0]
482
479
  func = graph.functions.get(node.op_type)
483
480
  if func is None:
@@ -491,7 +488,7 @@ class FuseConstantsToFunctionRewriter(Rewriter):
491
488
  node.op_type = func.name
492
489
  self.users[func.name] += 1
493
490
 
494
- consts: List[Tuple[int, NodeProto]] = []
491
+ consts: list[tuple[int, NodeProto]] = []
495
492
  for i, cst in enumerate(self.get_input_nodes(node)):
496
493
  if cst is not None and cst.op_type == "Constant":
497
494
  consts.append((i, cst))
@@ -520,7 +517,7 @@ class EraseOutputTypesRewriter(Rewriter):
520
517
  super().__init__(pattern=SingleNodePattern().with_name("__NO_MATCH__"))
521
518
  self.register_pre_hook(self._clear_types)
522
519
  self.register_post_hook(self._infer_types)
523
- self.output_types: List[onnx.TypeProto] = []
520
+ self.output_types: list[onnx.TypeProto] = []
524
521
 
525
522
  def _clear_types(self, graph: OnnxGraph):
526
523
  for i in graph.output:
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  """
16
16
 
17
+ from collections.abc import Collection, Container
17
18
  from contextlib import suppress
18
19
  from inspect import signature
19
20
  from io import BytesIO
@@ -21,7 +22,7 @@ from logging import Logger
21
22
  from os import PathLike
22
23
  from pathlib import Path
23
24
  from tempfile import TemporaryDirectory
24
- from typing import Any, Collection, Container, Dict, List, Optional, Tuple
25
+ from typing import Any
25
26
 
26
27
  import onnx
27
28
  from onnxifier import ONNXIFIER_OPSET, OnnxGraph, PassManager
@@ -48,8 +49,8 @@ from .typing import (
48
49
  from .utils import HYPER_DOMAIN, OPTIMIZER_PASSES
49
50
 
50
51
 
51
- def _get_input_names(spec: ModuleSpec) -> List[str]:
52
- names: List[str] = []
52
+ def _get_input_names(spec: ModuleSpec) -> list[str]:
53
+ names: list[str] = []
53
54
  params = spec["signature"].parameters
54
55
 
55
56
  def _arg_to_name(name: str, args):
@@ -70,13 +71,13 @@ def _get_input_names(spec: ModuleSpec) -> List[str]:
70
71
  return names
71
72
 
72
73
 
73
- def _get_output_names(spec: ModuleSpec) -> None | List[str]:
74
+ def _get_output_names(spec: ModuleSpec) -> None | list[str]:
74
75
  output = spec.get("output")
75
76
  if output is None:
76
77
  return None
77
78
 
78
- def _extract_names_from_dict(out_dict: dict) -> List[str]:
79
- names: List[str] = []
79
+ def _extract_names_from_dict(out_dict: dict) -> list[str]:
80
+ names: list[str] = []
80
81
  for key, value in out_dict.items():
81
82
  if isinstance(value, dict):
82
83
  names.extend(_extract_names_from_dict(value))
@@ -99,7 +100,7 @@ def _get_output_names(spec: ModuleSpec) -> None | List[str]:
99
100
 
100
101
 
101
102
  def make_hierarchical_hook(
102
- hiera: Container[type[Module]], module_spec: Dict[Module, ModuleSpec], index: int
103
+ hiera: Container[type[Module]], module_spec: dict[Module, ModuleSpec], index: int
103
104
  ) -> HookCallback:
104
105
  """Make a forward hook to record spec of modules in `hiera`.
105
106
 
@@ -115,8 +116,8 @@ def make_hierarchical_hook(
115
116
 
116
117
  def _hook(
117
118
  module: Module,
118
- args: Tuple[Tensor],
119
- kwargs: Dict[str, AnyTensor],
119
+ args: tuple[Tensor],
120
+ kwargs: dict[str, AnyTensor],
120
121
  output: AnyTensor,
121
122
  ) -> None:
122
123
  spec = module_spec[module]
@@ -140,12 +141,12 @@ def make_hierarchical_hook(
140
141
  def trace_module_spec(
141
142
  model: Module,
142
143
  input_args: tuple,
143
- kwargs: Optional[Dict[str, AnyTensor]],
144
+ kwargs: dict[str, AnyTensor] | None,
144
145
  opset_version: int,
145
146
  hiera: Container[type[Module]],
146
- module_spec: Dict[Module, ModuleSpec],
147
+ module_spec: dict[Module, ModuleSpec],
147
148
  dynamo: bool = False,
148
- ) -> Dict[Module, ModuleSpec]:
149
+ ) -> dict[Module, ModuleSpec]:
149
150
  """Register forward hooks to modules in the `hiera` and record forward
150
151
  information to `module_spec`.
151
152
 
@@ -208,13 +209,13 @@ def _export_hiera(
208
209
  dynamo: bool,
209
210
  external_data: bool,
210
211
  do_optimization: bool,
211
- external_directory: Optional[str | PathLike],
212
- module_spec: Dict[Module, ModuleSpec],
212
+ external_directory: str | PathLike | None,
213
+ module_spec: dict[Module, ModuleSpec],
213
214
  hiera: Collection[type[Module]],
214
215
  logger: Logger,
215
216
  ):
216
- def _get_sub_spec(module: Module, spec: Dict[Module, ModuleSpec]):
217
- child_spec: Dict[Module, ModuleSpec] = default_module_spec()
217
+ def _get_sub_spec(module: Module, spec: dict[Module, ModuleSpec]):
218
+ child_spec: dict[Module, ModuleSpec] = default_module_spec()
218
219
  for child in module.modules():
219
220
  if child in spec:
220
221
  child_spec[child] = spec[child]
@@ -308,16 +309,16 @@ def export_hyper_onnx( # noqa: C901
308
309
  input_args: tuple,
309
310
  f: str | PathLike | BytesIO,
310
311
  *,
311
- kwargs: Optional[Dict[str, AnyTensor]] = None,
312
- input_names: Optional[List[str]] = None,
313
- output_names: Optional[List[str]] = None,
312
+ kwargs: dict[str, AnyTensor] | None = None,
313
+ input_names: list[str] | None = None,
314
+ output_names: list[str] | None = None,
314
315
  opset_version: int = ONNXIFIER_OPSET.version,
315
316
  dynamo: bool = False,
316
317
  external_data: bool = False,
317
- hiera: Optional[Collection[type[Module]]] = None,
318
- module_spec: Optional[Dict[Module, ModuleSpec]] = None,
318
+ hiera: Collection[type[Module]] | None = None,
319
+ module_spec: dict[Module, ModuleSpec] | None = None,
319
320
  do_optimization: bool = True,
320
- external_directory: Optional[str | PathLike] = None,
321
+ external_directory: str | PathLike | None = None,
321
322
  **_: Any, # ignored options
322
323
  ) -> Any | None:
323
324
  r"""Export a Pytorch module to ONNX format with hierarchical structure,
@@ -450,12 +451,12 @@ def export_hyper_onnx( # noqa: C901
450
451
  else:
451
452
  onnx_model = onnx.load_model_from_string(model_path.getvalue())
452
453
 
453
- typenames: List[str] = [module_spec[i]["type_name"] for i in module_spec]
454
+ typenames: list[str] = [module_spec[i]["type_name"] for i in module_spec]
454
455
  for node in onnx_model.graph.node:
455
456
  if node.op_type in typenames:
456
457
  node.domain = HYPER_DOMAIN # add domain tag to run rewriter
457
458
  graph = OnnxGraph(onnx_model)
458
- passes: List[Any]
459
+ passes: list[Any]
459
460
  passes = [ComposeOnnxAsFunctionRewriter(HYPER_DOMAIN, tuple(module_spec.values()))]
460
461
  if do_optimization:
461
462
  passes.extend(OPTIMIZER_PASSES)
@@ -15,10 +15,10 @@ limitations under the License.
15
15
  """
16
16
 
17
17
  import warnings
18
- from collections.abc import Callable
18
+ from collections.abc import Callable, Mapping, Sequence
19
19
  from inspect import signature
20
20
  from os import PathLike
21
- from typing import Any, Mapping, Sequence
21
+ from typing import Any
22
22
 
23
23
  import torch
24
24
  from torch.onnx import OperatorExportTypes
@@ -0,0 +1,10 @@
1
+ from .attention import attention_interface, register_attention_opsets
2
+ from .cache import StaticCache
3
+ from .patch import patch_transformers
4
+
5
+ __all__ = [
6
+ "attention_interface",
7
+ "register_attention_opsets",
8
+ "StaticCache",
9
+ "patch_transformers",
10
+ ]