hyperonnx 1.0.2__tar.gz → 1.0.4__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 (48) hide show
  1. hyperonnx-1.0.4/.claude/CLAUDE.md +27 -0
  2. hyperonnx-1.0.4/.claude/skills/torch-dynamo-onnx-export/SKILL.md +422 -0
  3. hyperonnx-1.0.4/.claude/skills/torch-legacy-onnx-export/SKILL.md +407 -0
  4. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/.github/workflows/lint.yml +8 -1
  5. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/.github/workflows/unittest.yml +9 -2
  6. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/.gitignore +7 -1
  7. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/.pre-commit-config.yaml +2 -2
  8. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/PKG-INFO +3 -3
  9. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/__init__.py +1 -1
  10. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/hyper_export.py +16 -1
  11. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/torch_export.py +3 -0
  12. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/transformers/__init__.py +6 -0
  13. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/transformers/cache.py +59 -6
  14. hyperonnx-1.0.4/hyperonnx/transformers/mamba.py +179 -0
  15. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/transformers/patch.py +30 -1
  16. hyperonnx-1.0.4/hyperonnx/transformers/recurrent.py +367 -0
  17. hyperonnx-1.0.4/hyperonnx/utils.py +58 -0
  18. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/pyproject.toml +6 -6
  19. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/test_export_hyper_onnx.py +7 -3
  20. hyperonnx-1.0.4/tests/transformers/test_mamba.py +206 -0
  21. hyperonnx-1.0.4/tests/transformers/test_recurrent.py +69 -0
  22. hyperonnx-1.0.2/hyperonnx/utils.py +0 -27
  23. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/.github/words_bag.txt +0 -0
  24. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/LICENSE +0 -0
  25. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/README.md +0 -0
  26. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/README_CN.md +0 -0
  27. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/docs/assets/qwen2_omni_vision.gif +0 -0
  28. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/docs/assets/r18-sample.gif +0 -0
  29. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/auto.py +0 -0
  30. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/exporter/__init__.py +0 -0
  31. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/exporter/dynamo.py +0 -0
  32. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/exporter/torchscript.py +0 -0
  33. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/exporter/utils.py +0 -0
  34. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/function_rewriter.py +0 -0
  35. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/transformers/attention.py +0 -0
  36. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/hyperonnx/typing.py +0 -0
  37. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/expoter/test_detach_module_outputs.py +0 -0
  38. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/expoter/test_dynamo_build_onnxscript.py +0 -0
  39. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/expoter/test_dynamo_make_custom_op.py +0 -0
  40. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/expoter/test_dynamo_replace_custom_op.py +0 -0
  41. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/expoter/test_non_pod_export.py +0 -0
  42. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/expoter/test_plain_output_tensors.py +0 -0
  43. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/test_auto_trace_method.py +0 -0
  44. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/test_compose_nodes_to_functions.py +0 -0
  45. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/test_export_functions.py +0 -0
  46. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/test_fuse_constants_to_function.py +0 -0
  47. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/transformers/test_attention.py +0 -0
  48. {hyperonnx-1.0.2 → hyperonnx-1.0.4}/tests/transformers/test_static_cache.py +0 -0
@@ -0,0 +1,27 @@
1
+ # HyperONNX Instructions
2
+
3
+ ## Workflow
4
+
5
+ - Check relevant skills in `.claude/skills/` before handling specialized tasks.
6
+ - Prefer minimal, targeted changes that preserve existing project structure and style.
7
+ - Validate the files you change with the smallest relevant command before finishing.
8
+
9
+ ## Python Changes
10
+
11
+ - Follow the existing Python style already used in `hyperonnx/`.
12
+ - When Python files are modified, use the lint skill workflow and prefer `uv run ruff check hyperonnx`.
13
+ - Format Python changes with `uv run ruff format hyperonnx` when formatting is needed.
14
+
15
+ ## Version Compatibility (Hard Constraints)
16
+
17
+ ⚠️ **Supported Versions**: This project is currently tested and working on:
18
+ - **torch < 2.11** (torch 2.5–2.10 verified)
19
+ - **onnxscript < 0.6.0**
20
+
21
+ Both torch >= 2.11 and onnxscript >= 0.6.0 introduce breaking changes to module structure, dtype handling, and ONNX IR that are not yet resolved. **Do not use these newer versions** without explicit future work to support them.
22
+
23
+ **When users ask about newer versions**: Acknowledge the constraint, suggest using compatible versions from `pyproject.toml` optional dependencies, and note that torch >= 2.11 support is a known gap requiring future implementation.
24
+
25
+ ## Commits
26
+
27
+ - If asked to create a commit, use a clear and concise commit message that describes the actual change.
@@ -0,0 +1,422 @@
1
+ ---
2
+ name: torch-dynamo-onnx-export
3
+ description: Use this skill when exporting PyTorch models to ONNX using the modern torch.export (dynamo) path in HyperONNX. Best for models with dynamic control flow, complex tensor operations, and hierarchical custom operators defined via onnxscript.
4
+ argument-hint: Describe the model, custom operations (if any), target opset, and whether you need hierarchical export or simple custom operator definitions.
5
+ ---
6
+
7
+ # Torch Dynamo ONNX Export
8
+
9
+ Use this skill when the task is about the modern Torch ONNX export path in HyperONNX, meaning the `torch.export`-based path with `dynamo=True`.
10
+
11
+ This skill is specific to this repository. It captures the actual workflow used by HyperONNX code and tests, rather than generic PyTorch ONNX advice.
12
+
13
+ ## Torch Behaviour
14
+
15
+ - PyTorch 2.6+ introduced `torch.export` for AOT (Ahead-of-Time) tracing, enabling more dynamic models than TorchScript.
16
+ - PyTorch 2.9+ made `dynamo=True` the default in `torch.onnx.export()`.
17
+ - The dynamo path is based on FX graphs and bytecode analysis, not static tracing.
18
+ - On PyTorch 2.5 and below, `dynamo` parameter may not exist; always check `torch.onnx.export` signature and use the wrapper `torch_export_handle_lower_version` from HyperONNX.
19
+ - In this repository, prefer being explicit: always pass `dynamo=True` to clarify intent when using the modern exporter.
20
+
21
+ ⚠️ **Version Constraint**: This skill is tested and supported on **torch < 2.11** with **onnxscript < 0.6.0**. These versions have breaking changes in ONNX/module structure that require future work to resolve.
22
+
23
+ ## What This Skill Produces
24
+
25
+ Produce one of these outcomes:
26
+
27
+ - A correct export snippet using the modern `torch.export` path with `dynamo=True`.
28
+ - A HyperONNX code change that leverages `torch.export` for better dynamic model support.
29
+ - A custom operator definition using onnxscript and custom_translation_table for the dynamo path.
30
+ - A debugging checklist for why a dynamo export is failing or behaving unexpectedly.
31
+ - A migration guide from legacy (dynamo=False) to modern (dynamo=True) export.
32
+
33
+ ## When To Use It
34
+
35
+ Use this skill when the user asks for any of the following:
36
+
37
+ - Use `torch.onnx.export` with the modern or dynamo path.
38
+ - Force torch.export instead of TorchScript tracing.
39
+ - Export a model with `dynamo=True`.
40
+ - Create custom ONNX operators using onnxscript for the dynamo path.
41
+ - Build a custom_translation_table for hierarchical export.
42
+ - Understand why dynamo export behaves differently from legacy export.
43
+ - Export models with dynamic shapes, loops, or data-dependent control flow.
44
+
45
+ Do not use this skill for generic ONNX export or torch.export advice unrelated to HyperONNX.
46
+
47
+ ## Repository Facts To Ground Decisions
48
+
49
+ - HyperONNX exposes `torch_export_handle_lower_version` in [hyperonnx/torch_export.py](../../../hyperonnx/torch_export.py) to bridge version differences.
50
+ - The main hierarchical export entrypoint is [hyperonnx/hyper_export.py](../../../hyperonnx/hyper_export.py).
51
+ - The dynamo-specific branch for hierarchical replacement lives in [hyperonnx/exporter/dynamo.py](../../../hyperonnx/exporter/dynamo.py).
52
+ - Custom operator definition using onnxscript is built dynamically in [hyperonnx/exporter/dynamo.py](../../../hyperonnx/exporter/dynamo.py) via `build_onnxscript` and IRBuilder.
53
+ - Transformer attention for the dynamo path is handled in [hyperonnx/transformers/attention.py](../../../hyperonnx/transformers/attention.py) via `attention_translation_table()`.
54
+ - Reference tests: [tests/expoter/test_dynamo_replace_custom_op.py](../../../tests/expoter/test_dynamo_replace_custom_op.py), [tests/expoter/test_dynamo_build_onnxscript.py](../../../tests/expoter/test_dynamo_build_onnxscript.py), [tests/expoter/test_dynamo_make_custom_op.py](../../../tests/expoter/test_dynamo_make_custom_op.py).
55
+
56
+ ## Dynamo Export Fundamentals
57
+
58
+ ### Core Concepts
59
+
60
+ **torch.export**: Produces an ExportedProgram (AOT traced graph) that preserves more semantics than TorchScript, including data-dependent control flow and dynamic shapes.
61
+
62
+ **custom_translation_table**: A dictionary mapping PyTorch callables (e.g., custom ops, modules) to their ONNX counterparts (via onnxscript). The dynamo exporter uses this table to translate FX nodes to ONNX operators.
63
+
64
+ **onnxscript**: A framework for defining ONNX functions programmatically. HyperONNX uses `onnxscript.OnnxFunction` and `irbuilder.IRFunction` to build custom operators dynamically.
65
+
66
+ **replace_with_custom_op**: Context manager in [hyperonnx/exporter/dynamo.py](../../../hyperonnx/exporter/dynamo.py) that builds a custom_translation_table from module_spec, yielding it for use in export.
67
+
68
+ **build_onnxscript**: Dynamically constructs an ONNX function from a module's spec (inputs, outputs, dtype info). Used to create custom operator definitions without writing onnxscript manually.
69
+
70
+ ### Key Differences from Legacy Export (TorchScript)
71
+
72
+ | Aspect | Legacy (dynamo=False) | Dynamo (dynamo=True) |
73
+ |--------|----------------------|---------------------|
74
+ | **Tracer** | TorchScript (static tracing) | torch.export (FX bytecode) |
75
+ | **Dynamic Shapes** | Limited | Better supported |
76
+ | **Control Flow** | Loops unrolled, if/else lost | Can be preserved (with torch.cond) |
77
+ | **Custom Op Registration** | torch.onnx.register_custom_op_symbolic | custom_translation_table + onnxscript |
78
+ | **Module Replacement** | DuckForward (torch.autograd.Function) | Direct FX node replacement |
79
+ | **Symbolic Gen** | Automatic from DuckForward.symbolic | Explicit via onnxscript |
80
+ | **Attention Registration** | register_attention_opsets() | attention_translation_table() |
81
+ | **Performance** | Often faster export | Slower export (bytecode analysis) |
82
+
83
+ ## Defining Custom Operators for Dynamo Export
84
+
85
+ ### Pattern 1: Direct onnxscript function (simple custom op)
86
+
87
+ For single custom operations without hierarchical wrapping:
88
+
89
+ ```python
90
+ import onnxscript
91
+ import torch
92
+
93
+ # Step 1: Define an onnxscript function
94
+ _MY_OPSET = onnxscript.values.Opset("custom_domain", 1)
95
+
96
+ @onnxscript.script(_MY_OPSET)
97
+ def my_custom_op(x: onnxscript.FLOAT) -> onnxscript.FLOAT:
98
+ return x * 2.0 + 1.0
99
+
100
+ # Step 2: Build custom_translation_table
101
+ custom_translation_table = {
102
+ torch.ops.custom_lib.my_op: my_custom_op,
103
+ }
104
+
105
+ # Step 3: Export with dynamo=True and the table
106
+ torch.onnx.export(
107
+ model,
108
+ example_inputs,
109
+ 'model.onnx',
110
+ dynamo=True,
111
+ custom_translation_table=custom_translation_table,
112
+ opset_version=18,
113
+ )
114
+ ```
115
+
116
+ Key rules:
117
+ - The onnxscript function signature must match the PyTorch operation signature.
118
+ - The dictionary key must be a callable (e.g., torch.ops, a custom op).
119
+ - Always pass opset_version to align with onnxscript opset expectations.
120
+
121
+ ### Pattern 2: HyperONNX hierarchical export with dynamic onnxscript
122
+
123
+ For complex modules that need hierarchical export, use `replace_with_custom_op` and `build_onnxscript`:
124
+
125
+ ```python
126
+ import torch
127
+ from hyperonnx import export_hyper_onnx
128
+
129
+ class MyCustomModule(torch.nn.Module):
130
+ """A complex module with loops or dynamic shapes."""
131
+ def forward(self, x):
132
+ for i in range(x.shape[0]):
133
+ x = x * 2
134
+ return x
135
+
136
+ model = torch.nn.Sequential(
137
+ torch.nn.Linear(10, 20),
138
+ MyCustomModule(),
139
+ torch.nn.Linear(20, 5),
140
+ )
141
+
142
+ export_hyper_onnx(
143
+ model,
144
+ (torch.randn(1, 10),),
145
+ 'model.onnx',
146
+ hiera=[MyCustomModule], # Export as hierarchical function
147
+ dynamo=True, # Use torch.export, not TorchScript
148
+ opset_version=18,
149
+ )
150
+ ```
151
+
152
+ How it works:
153
+ 1. HyperONNX traces the model and caches module specs (inputs, outputs, dtypes).
154
+ 2. `build_onnxscript` dynamically creates an ONNX function from the module spec.
155
+ 3. `replace_with_custom_op` builds the custom_translation_table.
156
+ 4. torch.onnx.export (with dynamo=True) translates the FX graph using the table.
157
+
158
+ Reference: [tests/expoter/test_dynamo_replace_custom_op.py](../../../tests/expoter/test_dynamo_replace_custom_op.py).
159
+
160
+ ### Pattern 3: Attention-specific translation for dynamo
161
+
162
+ For transformer attention layers:
163
+
164
+ ```python
165
+ import torch
166
+ from hyperonnx.transformers.attention import attention_translation_table
167
+
168
+ # Step 1: Get the translation table for dynamo path
169
+ translation_table = attention_translation_table()
170
+
171
+ # Step 2: Export with dynamo=True and the table
172
+ torch.onnx.export(
173
+ model,
174
+ example_inputs,
175
+ 'model.onnx',
176
+ opset_version=24,
177
+ dynamo=True,
178
+ custom_translation_table=translation_table,
179
+ )
180
+ ```
181
+
182
+ This uses the modern onnxscript-based Attention definition. See [hyperonnx/transformers/attention.py](../../../hyperonnx/transformers/attention.py) for implementation.
183
+
184
+ ## Building Custom Operators with onnxscript
185
+
186
+ ### Overview
187
+
188
+ HyperONNX's `build_onnxscript` function constructs ONNX operators automatically from module specs, eliminating the need to write onnxscript manually. However, you can also write custom onnxscript functions for fine-grained control.
189
+
190
+ ### Auto-generation via build_onnxscript
191
+
192
+ ```python
193
+ from hyperonnx.exporter.dynamo import build_onnxscript
194
+ from hyperonnx.typing import default_module_spec, ModuleSpec
195
+
196
+ # Assume module_spec is populated via trace_module_spec
197
+ spec: ModuleSpec = {...} # Contains: args, output, signature, etc.
198
+
199
+ # Auto-build onnxscript function
200
+ onnx_func = build_onnxscript(spec)
201
+
202
+ # Use in custom_translation_table
203
+ custom_translation_table = {
204
+ MyModule: onnx_func,
205
+ }
206
+ ```
207
+
208
+ ### Manual onnxscript Definition
209
+
210
+ For more control, write onnxscript directly:
211
+
212
+ ```python
213
+ import onnxscript
214
+
215
+ # Define a custom opset
216
+ CUSTOM_OPSET = onnxscript.values.Opset(domain="my_domain", version=1)
217
+
218
+ @onnxscript.script(CUSTOM_OPSET)
219
+ def my_complex_op(x: onnxscript.FLOAT, mask: onnxscript.BOOL) -> onnxscript.FLOAT:
220
+ """Custom operator that applies masking."""
221
+ return x * mask.cast(onnxscript.FLOAT)
222
+
223
+ # Use in translation table
224
+ custom_translation_table = {
225
+ my_pytorch_op: my_complex_op,
226
+ }
227
+ ```
228
+
229
+ Key considerations:
230
+ - onnxscript functions use ONNX IR types (FLOAT, INT32, BOOL, etc.), not PyTorch types.
231
+ - The function signature must match the number of inputs/outputs of the PyTorch operation.
232
+ - Use `.cast()` for type conversions when needed.
233
+
234
+ ## Workflow
235
+
236
+ ### 0. Decide between direct onnxscript and hierarchical export
237
+
238
+ Before writing code, ask:
239
+ - **Is this a single atomic custom operation?** → Use direct onnxscript (Pattern 1).
240
+ - **Is this a module hierarchy that needs reusable ONNX functions?** → Use hierarchical export (Pattern 2).
241
+ - **Is this transformer attention?** → Use the built-in pattern (Pattern 3).
242
+
243
+ If unsure, check:
244
+ - [tests/expoter/test_dynamo_make_custom_op.py](../../../tests/expoter/test_dynamo_make_custom_op.py) for simple custom ops.
245
+ - [tests/expoter/test_dynamo_replace_custom_op.py](../../../tests/expoter/test_dynamo_replace_custom_op.py) for hierarchical examples.
246
+ - [tests/expoter/test_dynamo_build_onnxscript.py](../../../tests/expoter/test_dynamo_build_onnxscript.py) for build_onnxscript usage.
247
+
248
+ ### 1. Check torch version and dynamo availability
249
+
250
+ ```python
251
+ import torch
252
+ from inspect import signature
253
+
254
+ # Verify dynamo parameter exists
255
+ sig = signature(torch.onnx.export)
256
+ if 'dynamo' not in sig.parameters:
257
+ # Use torch_export_handle_lower_version from HyperONNX
258
+ from hyperonnx.torch_export import torch_export_handle_lower_version
259
+ torch_export_handle_lower_version(model, args, f, dynamo=True, ...)
260
+ else:
261
+ torch.onnx.export(model, args, f, dynamo=True, ...)
262
+ ```
263
+
264
+ ### 2. Identify and define custom operators
265
+
266
+ For each custom operator:
267
+ - Determine its input/output signatures.
268
+ - Write an onnxscript function or use build_onnxscript.
269
+ - Add it to custom_translation_table.
270
+
271
+ Example:
272
+ ```python
273
+ custom_translation_table = {}
274
+
275
+ # Add manually-written onnxscript functions
276
+ custom_translation_table[torch.ops.custom_lib.op1] = onnxscript_op1
277
+
278
+ # Or add auto-generated ones from module specs
279
+ custom_translation_table[MyModule] = build_onnxscript(my_module_spec)
280
+ ```
281
+
282
+ ### 3. Build custom_translation_table
283
+
284
+ Use the context manager `replace_with_custom_op` for hierarchical export:
285
+
286
+ ```python
287
+ from hyperonnx.exporter.dynamo import replace_with_custom_op
288
+
289
+ with replace_with_custom_op(model, module_spec) as custom_translation_table:
290
+ torch.onnx.export(
291
+ model,
292
+ example_inputs,
293
+ 'model.onnx',
294
+ dynamo=True,
295
+ custom_translation_table=custom_translation_table,
296
+ opset_version=18,
297
+ )
298
+ ```
299
+
300
+ ### 4. Call torch.onnx.export with dynamo=True
301
+
302
+ ```python
303
+ torch.onnx.export(
304
+ model,
305
+ example_inputs,
306
+ 'model.onnx',
307
+ input_names=['input'],
308
+ output_names=['output'],
309
+ opset_version=18,
310
+ dynamo=True,
311
+ custom_translation_table=custom_translation_table,
312
+ dynamic_shapes={'input': {0: 'batch_size'}}, # Optional: specify dynamic shapes
313
+ )
314
+ ```
315
+
316
+ Key parameters:
317
+ - `dynamo=True`: Use torch.export instead of TorchScript.
318
+ - `custom_translation_table`: Dict mapping callables to onnxscript functions.
319
+ - `dynamic_shapes`: Preferred over dynamic_axes for dynamo path.
320
+ - `opset_version`: Must align with onnxscript opset.
321
+
322
+ ### 5. Handle export failures and fallback
323
+
324
+ The dynamo path may fail on complex models. HyperONNX provides fallback:
325
+
326
+ ```python
327
+ from hyperonnx.hyper_export import export_hyper_onnx
328
+
329
+ # export_hyper_onnx tries fallback automatically
330
+ export_hyper_onnx(
331
+ model,
332
+ args,
333
+ 'model.onnx',
334
+ dynamo=True,
335
+ # If dynamo export fails, HyperONNX may retry with dynamo=False
336
+ )
337
+ ```
338
+
339
+ To disable fallback and fail fast:
340
+ ```python
341
+ # Call torch_export_handle_lower_version directly without fallback
342
+ torch.onnx.export(
343
+ model,
344
+ args,
345
+ f,
346
+ dynamo=True,
347
+ # No fallback logic here
348
+ )
349
+ ```
350
+
351
+ ### 6. Validate the exported ONNX model
352
+
353
+ ```python
354
+ import onnx
355
+
356
+ # Load and check
357
+ onnx_model = onnx.load('model.onnx')
358
+ onnx.checker.check_model(onnx_model, full_check=True)
359
+
360
+ # Verify custom operators appear
361
+ for node in onnx_model.graph.node:
362
+ print(f"{node.op_type} in domain {node.domain}")
363
+ ```
364
+
365
+ ## Common Errors & Recovery
366
+
367
+ | Error | Cause | Fix |
368
+ |-------|-------|-----|
369
+ | `KeyError` in custom_translation_table | torch.ops key not in table | Verify the key exactly matches the PyTorch op reference |
370
+ | `TypeError: ... got an unexpected keyword argument 'dynamo'` | torch.onnx.export too old | Use `torch_export_handle_lower_version` wrapper |
371
+ | onnxscript function signature mismatch | ONNX function has wrong number of inputs/outputs | Verify spec['args'] and spec['output'] match onnxscript function |
372
+ | `UnflatteningError` in build_onnxscript | Output structure not flattened | Use `plain_tensor_container` to extract only tensors |
373
+ | Export succeeds but ONNX model is wrong | dynamic_shapes not specified | Add `dynamic_shapes` parameter for dynamic-shape models |
374
+ | torch.export fails on data-dependent branches | Model has unhandled control flow | Wrap loops/conditionals with `torch.cond` or fall back to dynamo=False |
375
+
376
+ ## Branching Guidance
377
+
378
+ If the request is about library implementation:
379
+ - Prefer HyperONNX abstractions (export_hyper_onnx, replace_with_custom_op).
380
+ - Preserve backward compatibility with older torch versions.
381
+ - Use torch_export_handle_lower_version wrapper for version bridging.
382
+
383
+ If the request is about custom operators:
384
+ - Start with simple onnxscript functions (Pattern 1) for atomic ops.
385
+ - Use build_onnxscript for auto-generation from module specs.
386
+ - Write manual onnxscript only when fine-grained control is needed.
387
+
388
+ If the request is about a failing export:
389
+ - Check if the model uses data-dependent control flow; consider torch.cond.
390
+ - Verify custom_translation_table keys match torch.ops exactly.
391
+ - Check onnxscript function signatures match specs.
392
+ - Try lowering torch version requirement (dynamo may not exist in older PyTorch).
393
+ - Consider falling back to dynamo=False if dynamo export is unreliable for this model.
394
+
395
+ ## Quality Bar
396
+
397
+ A good answer or code change using this skill should:
398
+ - Clearly distinguish between dynamo=True (modern) and dynamo=False (legacy).
399
+ - Use repository-native abstractions (export_hyper_onnx, replace_with_custom_op, build_onnxscript).
400
+ - Specify dynamic_shapes when exporting models with variable batch size or sequence length.
401
+ - Include custom_translation_table definitions with clear onnxscript signatures.
402
+ - Provide validation (onnx.checker.check_model) and explain expected ONNX structure.
403
+ - Mention torch version requirements and fallback behavior.
404
+
405
+ ## Example Prompts
406
+
407
+ - Export this model using dynamo=True and custom attention operators.
408
+ - Add dynamic shape support to this ONNX export.
409
+ - Create a custom_translation_table for my hierarchical model.
410
+ - Why does dynamo export fail on this model with torch.cond?
411
+ - Migrate this export from dynamo=False to dynamo=True.
412
+ - Build an onnxscript function for this custom module.
413
+
414
+ ## Weak Spots To Clarify Before Extending This Skill
415
+
416
+ If you evolve this skill later, clarify these points first:
417
+
418
+ - Which torch versions (2.5, 2.6, 2.8, 2.9+) should be officially supported for dynamo export examples?
419
+ - Should we recommend torch.cond for all data-dependent branches, or only certain patterns?
420
+ - Is build_onnxscript reliable enough to recommend for user-defined modules, or should we prefer manual onnxscript?
421
+ - How to handle dtype inference in build_onnxscript for models with mixed precision (float16, bfloat16)?
422
+ - Should fallback behavior be exposed as a user-facing option, or remain internal to HyperONNX?