0
# Model Construction
1
2
Helper functions for programmatically creating ONNX models, graphs, nodes, tensors, and type definitions. These functions provide the building blocks for constructing valid ONNX models with proper protocol buffer structure.
3
4
## Capabilities
5
6
### Model and Graph Creation
7
8
Create complete ONNX models and computation graphs with proper metadata and structure.
9
10
```python { .api }
11
def make_model(graph: GraphProto, **kwargs: Any) -> ModelProto:
12
"""
13
Construct a ModelProto
14
15
Parameters:
16
- graph: *make_graph* returns
17
- **kwargs: any attribute to add to the returned instance
18
19
Returns:
20
ModelProto
21
"""
22
23
def make_model_gen_version(graph: GraphProto, **kwargs: Any) -> ModelProto:
24
"""
25
An extension of make_model that infers an IR_VERSION for the model,
26
if not specified, using a best-effort-basis.
27
28
Parameters:
29
- graph: GraphProto representing the computation graph
30
- **kwargs: Additional model metadata
31
32
Returns:
33
ModelProto: ONNX model with generated version info
34
"""
35
36
def make_graph(
37
nodes: Sequence[NodeProto],
38
name: str,
39
inputs: Sequence[ValueInfoProto],
40
outputs: Sequence[ValueInfoProto],
41
initializer: Optional[Sequence[TensorProto]] = None,
42
doc_string: Optional[str] = None,
43
value_info: Optional[Sequence[ValueInfoProto]] = None,
44
sparse_initializer: Optional[Sequence[SparseTensorProto]] = None,
45
) -> GraphProto:
46
"""
47
Construct a GraphProto
48
49
Parameters:
50
- nodes: list of NodeProto
51
- name: graph name
52
- inputs: list of ValueInfoProto
53
- outputs: list of ValueInfoProto
54
- initializer: list of TensorProto
55
- doc_string: graph documentation
56
- value_info: list of ValueInfoProto
57
- sparse_initializer: list of SparseTensorProto
58
59
Returns:
60
GraphProto
61
"""
62
def make_operatorsetid(domain: str, version: int) -> OperatorSetIdProto:
63
"""
64
Construct an OperatorSetIdProto.
65
66
Parameters:
67
- domain: The domain of the operator set id
68
- version: Version of operator set id
69
70
Returns:
71
OperatorSetIdProto
72
"""
73
74
def make_opsetid(domain: str, version: int) -> OperatorSetIdProto:
75
"""
76
Alias for make_operatorsetid. Construct an OperatorSetIdProto.
77
78
Parameters:
79
- domain: The domain of the operator set id
80
- version: Version of operator set id
81
82
Returns:
83
OperatorSetIdProto
84
"""
85
86
def make_function(
87
domain: str,
88
fname: str,
89
inputs: List[str],
90
outputs: List[str],
91
nodes: List[NodeProto],
92
opset_imports: List[OperatorSetIdProto],
93
attributes: Optional[List[str]] = None,
94
**kwargs: Any,
95
) -> FunctionProto:
96
"""
97
Construct a FunctionProto for user-defined functions.
98
99
Parameters:
100
- domain: Function domain
101
- fname: Function name
102
- inputs: List of input names
103
- outputs: List of output names
104
- nodes: List of nodes in function body
105
- opset_imports: List of required opset imports
106
- attributes: Optional list of function attributes
107
- **kwargs: Additional function metadata
108
109
Returns:
110
FunctionProto: User-defined function representation
111
"""
112
113
def set_model_props(model: ModelProto, dict_value: Dict[str, str]) -> None:
114
"""
115
Set model properties from a dictionary.
116
117
Parameters:
118
- model: ModelProto to modify
119
- dict_value: Dictionary of property key-value pairs
120
"""
121
```
122
123
### Version Constants
124
125
Important constants for version handling and model construction:
126
127
```python { .api }
128
VERSION_TABLE # List of ONNX version mapping tuples (release, IR, ai.onnx, ai.onnx.ml)
129
OP_SET_ID_VERSION_MAP # Map from (domain, version) to IR version requirements
130
131
def find_min_ir_version_for(
132
opsetidlist: List[OperatorSetIdProto],
133
ignore_unknown: bool = False
134
) -> int:
135
"""
136
Given list of opset ids, determine minimum IR version required.
137
138
Parameters:
139
- opsetidlist: List of OperatorSetIdProto
140
- ignore_unknown: If True, ignore unknown domains
141
142
Returns:
143
int: Minimum required IR version
144
"""
145
```
146
147
### Node Creation
148
149
Create computation nodes representing operations in the ONNX graph.
150
151
```python { .api }
152
def make_node(
153
op_type: str,
154
inputs: Sequence[str],
155
outputs: Sequence[str],
156
name: Optional[str] = None,
157
doc_string: Optional[str] = None,
158
domain: Optional[str] = None,
159
**kwargs: Any,
160
) -> NodeProto:
161
"""
162
Construct a NodeProto.
163
164
Parameters:
165
- op_type: The name of the operator to construct
166
- inputs: list of input names
167
- outputs: list of output names
168
- name: optional unique identifier for NodeProto
169
- doc_string: optional documentation string for NodeProto
170
- domain: optional domain for NodeProto.
171
If it's None, we will just use default domain (which is empty)
172
- **kwargs: the attributes of the node. The acceptable values
173
are documented in :func:`make_attribute`.
174
175
Returns:
176
NodeProto
177
"""
178
```
179
180
### Tensor Creation
181
182
Create tensor representations for model weights, constants, and data.
183
184
```python { .api }
185
def make_tensor(
186
name: str, data_type: int, dims: Sequence[int], vals: Any, raw: bool = False
187
) -> TensorProto:
188
"""
189
Make a TensorProto with specified arguments. If raw is False, this
190
function will choose the corresponding proto field to store the
191
values based on data_type. If raw is True, use "raw_data" proto
192
field to store the values, and values should be of type bytes in
193
this case.
194
195
Parameters:
196
- name: tensor name
197
- data_type: a value such as onnx.TensorProto.FLOAT
198
- dims: shape
199
- vals: values
200
- raw: if True, vals contains the serialized content of the tensor,
201
otherwise, vals should be a list of values of the type defined by *data_type*
202
203
Returns:
204
TensorProto
205
"""
206
207
def make_sparse_tensor(values, indices, dims, name=None):
208
"""
209
Create a SparseTensorProto from sparse data.
210
211
Parameters:
212
- values: TensorProto containing non-zero values
213
- indices: TensorProto containing indices of non-zero values
214
- dims: List of integers representing tensor shape
215
- name: Optional name for the sparse tensor
216
217
Returns:
218
SparseTensorProto: Sparse tensor representation
219
"""
220
221
def make_sequence(name: str, elem_type: int, values: List[Any]) -> SequenceProto:
222
"""
223
Create a SequenceProto from a list of values.
224
225
Parameters:
226
- name: Sequence name
227
- elem_type: Element data type
228
- values: List of values to include in sequence
229
230
Returns:
231
SequenceProto: Sequence representation
232
"""
233
234
def make_map(name: str, key_type: int, keys: List[Any], values: List[Any]) -> MapProto:
235
"""
236
Create a MapProto from keys and values.
237
238
Parameters:
239
- name: Map name
240
- key_type: Key data type
241
- keys: List of keys
242
- values: List of corresponding values
243
244
Returns:
245
MapProto: Map representation
246
"""
247
248
def make_optional(name: str, elem_type: Optional[TypeProto], value: Any = None) -> OptionalProto:
249
"""
250
Create an OptionalProto that may contain a value.
251
252
Parameters:
253
- name: Optional name
254
- elem_type: Element type (None for empty optional)
255
- value: Optional value to store
256
257
Returns:
258
OptionalProto: Optional representation
259
"""
260
```
261
262
### Type System
263
264
Create type definitions for tensor, sequence, map, and optional types.
265
266
```python { .api }
267
def make_tensor_type_proto(elem_type, shape, elem_type_name=""):
268
"""
269
Create a TypeProto for tensor types.
270
271
Parameters:
272
- elem_type: Element data type (e.g., TensorProto.FLOAT)
273
- shape: List of dimensions (use None for unknown dimensions)
274
- elem_type_name: Optional name for custom element types
275
276
Returns:
277
TypeProto: Tensor type specification
278
"""
279
280
def make_sparse_tensor_type_proto(elem_type, shape, elem_type_name=""):
281
"""
282
Create a TypeProto for sparse tensor types.
283
284
Parameters:
285
- elem_type: Element data type
286
- shape: List of dimensions
287
- elem_type_name: Optional name for custom element types
288
289
Returns:
290
TypeProto: Sparse tensor type specification
291
"""
292
293
def make_sequence_type_proto(inner_type_proto):
294
"""
295
Create a TypeProto for sequence types.
296
297
Parameters:
298
- inner_type_proto: TypeProto for sequence elements
299
300
Returns:
301
TypeProto: Sequence type specification
302
"""
303
304
def make_map_type_proto(key_type, value_type):
305
"""
306
Create a TypeProto for map types.
307
308
Parameters:
309
- key_type: Key data type (must be string or integral type)
310
- value_type: TypeProto for map values
311
312
Returns:
313
TypeProto: Map type specification
314
"""
315
316
def make_optional_type_proto(inner_type_proto):
317
"""
318
Create a TypeProto for optional types.
319
320
Parameters:
321
- inner_type_proto: TypeProto for optional value
322
323
Returns:
324
TypeProto: Optional type specification
325
"""
326
```
327
328
### Value Info Creation
329
330
Create value information for graph inputs, outputs, and intermediate values.
331
332
```python { .api }
333
def make_tensor_value_info(
334
name: str,
335
elem_type: int,
336
shape: Optional[Sequence[Union[str, int, None]]],
337
doc_string: str = "",
338
shape_denotation: Optional[List[str]] = None,
339
) -> ValueInfoProto:
340
"""
341
Makes a ValueInfoProto based on the data type and shape.
342
343
Parameters:
344
- name: Name of the value
345
- elem_type: Element data type
346
- shape: List of dimensions (use None for unknown dimensions)
347
- doc_string: Human-readable documentation
348
- shape_denotation: Optional shape denotation
349
350
Returns:
351
ValueInfoProto: Value information for tensors
352
"""
353
354
def make_sparse_tensor_value_info(name, elem_type, shape, doc_string="", elem_type_name=""):
355
"""
356
Create a ValueInfoProto for sparse tensor values.
357
358
Parameters:
359
- name: Name of the value
360
- elem_type: Element data type
361
- shape: List of dimensions
362
- doc_string: Human-readable documentation
363
- elem_type_name: Optional name for custom element types
364
365
Returns:
366
ValueInfoProto: Value information for sparse tensors
367
"""
368
369
def make_tensor_sequence_value_info(name, elem_type, shape, doc_string="", elem_type_name=""):
370
"""
371
Create a ValueInfoProto for tensor sequence values.
372
373
Parameters:
374
- name: Name of the value
375
- elem_type: Element data type for sequence elements
376
- shape: Shape of individual tensors in sequence
377
- doc_string: Human-readable documentation
378
- elem_type_name: Optional name for custom element types
379
380
Returns:
381
ValueInfoProto: Value information for tensor sequences
382
"""
383
384
def make_empty_tensor_value_info(name):
385
"""
386
Create an empty ValueInfoProto for tensors with unknown type/shape.
387
388
Parameters:
389
- name: Name of the value
390
391
Returns:
392
ValueInfoProto: Empty value information
393
"""
394
395
def make_value_info(name, type_proto, doc_string=""):
396
"""
397
Create a ValueInfoProto from a TypeProto.
398
399
Parameters:
400
- name: Name of the value
401
- type_proto: TypeProto specifying the type
402
- doc_string: Human-readable documentation
403
404
Returns:
405
ValueInfoProto: Value information
406
"""
407
```
408
409
### Attribute Creation
410
411
Create node attributes for operator parameters and configuration.
412
413
```python { .api }
414
def make_attribute(key, value, doc_string=""):
415
"""
416
Create an AttributeProto from a value.
417
418
Parameters:
419
- key: Attribute name
420
- value: Attribute value (int, float, string, list, or tensor)
421
- doc_string: Human-readable documentation
422
423
Returns:
424
AttributeProto: Node attribute
425
"""
426
427
def make_attribute_ref(key, ref_attr_name, doc_string=""):
428
"""
429
Create an AttributeProto that references another attribute.
430
431
Parameters:
432
- key: Attribute name
433
- ref_attr_name: Name of referenced attribute
434
- doc_string: Human-readable documentation
435
436
Returns:
437
AttributeProto: Attribute reference
438
"""
439
440
def get_attribute_value(attr):
441
"""
442
Extract the actual value from an AttributeProto.
443
444
Parameters:
445
- attr: AttributeProto to extract value from
446
447
Returns:
448
Any: The attribute value in appropriate Python type
449
"""
450
451
def get_node_attr_value(node, attr_name):
452
"""
453
Get attribute value from a node by name.
454
455
Parameters:
456
- node: NodeProto to get attribute from
457
- attr_name: Name of the attribute to retrieve
458
459
Returns:
460
Any: The attribute value, or None if not found
461
"""
462
```
463
464
465
### Function Creation
466
467
Create user-defined functions for custom operations.
468
469
```python { .api }
470
def make_function(domain, fname, inputs, outputs, nodes, opset_imports=None,
471
attributes=None, doc_string=""):
472
"""
473
Create a FunctionProto representing a user-defined function.
474
475
Parameters:
476
- domain: Function domain namespace
477
- fname: Function name
478
- inputs: List of input parameter names
479
- outputs: List of output parameter names
480
- nodes: List of NodeProto representing function body
481
- opset_imports: List of operator set imports
482
- attributes: List of function attributes
483
- doc_string: Human-readable documentation
484
485
Returns:
486
FunctionProto: User-defined function
487
"""
488
```
489
490
491
### Data Type Utilities
492
493
Utilities for working with tensor data types and conversions.
494
495
```python { .api }
496
def tensor_dtype_to_np_dtype(tensor_dtype):
497
"""
498
Convert ONNX tensor data type to NumPy dtype.
499
500
Parameters:
501
- tensor_dtype: ONNX tensor data type (e.g., TensorProto.FLOAT)
502
503
Returns:
504
numpy.dtype: Corresponding NumPy data type
505
"""
506
507
def np_dtype_to_tensor_dtype(np_dtype):
508
"""
509
Convert NumPy dtype to ONNX tensor data type.
510
511
Parameters:
512
- np_dtype: NumPy data type
513
514
Returns:
515
int: ONNX tensor data type constant
516
"""
517
518
def tensor_dtype_to_string(tensor_dtype):
519
"""
520
Convert tensor data type to string representation.
521
522
Parameters:
523
- tensor_dtype: ONNX tensor data type
524
525
Returns:
526
str: String representation of the data type
527
"""
528
529
def get_all_tensor_dtypes():
530
"""
531
Get all supported ONNX tensor data types.
532
533
Returns:
534
list: List of all supported tensor data type constants
535
"""
536
```
537
538
### Training Information
539
540
Create training-specific information for models that support training workflows.
541
542
```python { .api }
543
def make_training_info(
544
algorithm: GraphProto,
545
algorithm_bindings: AssignmentBindingType,
546
initialization: Optional[GraphProto],
547
initialization_bindings: Optional[AssignmentBindingType],
548
) -> TrainingInfoProto:
549
"""
550
Construct a TrainingInfoProto for training-enabled models.
551
552
Parameters:
553
- algorithm: GraphProto representing the training algorithm
554
- algorithm_bindings: Binding assignments for algorithm parameters
555
- initialization: Optional initialization graph
556
- initialization_bindings: Optional binding assignments for initialization
557
558
Returns:
559
TrainingInfoProto: Training information protocol buffer
560
"""
561
```
562
563
### Float Conversion Utilities
564
565
Specialized functions for converting between float32 and various reduced-precision formats.
566
567
```python { .api }
568
def float32_to_bfloat16(fval: float, truncate: bool = False) -> int:
569
"""
570
Convert a float32 value to bfloat16 format (as int).
571
572
Parameters:
573
- fval: Float32 value to convert
574
- truncate: If True, use simple truncation; if False, use round-to-nearest-even
575
576
Returns:
577
int: Bfloat16 value as integer representation
578
"""
579
580
def float32_to_float8e4m3(
581
fval: float,
582
scale: float = 1.0,
583
fn: bool = True,
584
uz: bool = False,
585
saturate: bool = True,
586
) -> int:
587
"""
588
Convert a float32 value to float8 e4m3 format (as int).
589
590
Parameters:
591
- fval: Float32 value to convert
592
- scale: Scale factor to divide fval before conversion
593
- fn: No infinite values (must be True)
594
- uz: No negative zero
595
- saturate: Convert out-of-range values to max instead of NaN
596
597
Returns:
598
int: Float8 e4m3 value as integer representation
599
"""
600
601
def float32_to_float8e5m2(
602
fval: float,
603
scale: float = 1.0,
604
fn: bool = False,
605
uz: bool = False,
606
saturate: bool = True,
607
) -> int:
608
"""
609
Convert a float32 value to float8 e5m2 format (as int).
610
611
Parameters:
612
- fval: Float32 value to convert
613
- scale: Scale factor to divide fval before conversion
614
- fn: No infinite values
615
- uz: No negative zero
616
- saturate: Convert out-of-range values to max instead of NaN
617
618
Returns:
619
int: Float8 e5m2 value as integer representation
620
"""
621
```
622
623
### Version Management
624
625
Utilities for managing ONNX version compatibility and operator sets.
626
627
```python { .api }
628
VERSION_TABLE = ... # List of version compatibility information
629
630
def create_op_set_id_version_map(table):
631
"""
632
Create operator set version mapping from compatibility table.
633
634
Parameters:
635
- table: Version compatibility table
636
637
Returns:
638
dict: Mapping of operator set domains to versions
639
"""
640
641
def find_min_ir_version_for(**kwargs):
642
"""
643
Find minimum IR version required for given operators or features.
644
645
Parameters:
646
- **kwargs: Features or operators to check version requirements for
647
648
Returns:
649
int: Minimum required IR version
650
"""
651
```
652
653
### Printing and Inspection Utilities
654
655
Functions for creating human-readable representations of ONNX objects.
656
657
```python { .api }
658
def printable_attribute(attr):
659
"""
660
Create human-readable string representation of an attribute.
661
662
Parameters:
663
- attr: AttributeProto to represent
664
665
Returns:
666
str: Human-readable attribute representation
667
"""
668
669
def printable_type(t):
670
"""
671
Create human-readable string representation of a type.
672
673
Parameters:
674
- t: TypeProto to represent
675
676
Returns:
677
str: Human-readable type representation
678
"""
679
680
def printable_value_info(v):
681
"""
682
Create human-readable string representation of value info.
683
684
Parameters:
685
- v: ValueInfoProto to represent
686
687
Returns:
688
str: Human-readable value info representation
689
"""
690
691
def printable_tensor_proto(t):
692
"""
693
Create human-readable string representation of a tensor.
694
695
Parameters:
696
- t: TensorProto to represent
697
698
Returns:
699
str: Human-readable tensor representation
700
"""
701
702
def printable_node(node, **kwargs):
703
"""
704
Create human-readable string representation of a node.
705
706
Parameters:
707
- node: NodeProto to represent
708
- **kwargs: Additional formatting options
709
710
Returns:
711
str: Human-readable node representation
712
"""
713
714
def printable_graph(graph, prefix=""):
715
"""
716
Create human-readable string representation of a graph.
717
718
Parameters:
719
- graph: GraphProto to represent
720
- prefix: Prefix for indentation
721
722
Returns:
723
str: Human-readable graph representation
724
"""
725
```
726
727
## Usage Examples
728
729
### Building a Simple Neural Network
730
731
```python
732
import onnx
733
from onnx import helper, TensorProto
734
import numpy as np
735
736
# Define input and output
737
X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [1, 3, 224, 224])
738
Y = helper.make_tensor_value_info('Y', TensorProto.FLOAT, [1, 1000])
739
740
# Create weight tensor
741
weight_data = np.random.randn(64, 3, 7, 7).astype(np.float32)
742
weight = helper.make_tensor('conv_weight', TensorProto.FLOAT,
743
weight_data.shape, weight_data.flatten())
744
745
# Create convolution node
746
conv_node = helper.make_node(
747
'Conv',
748
inputs=['X', 'conv_weight'],
749
outputs=['conv_out'],
750
kernel_shape=[7, 7],
751
strides=[2, 2],
752
pads=[3, 3, 3, 3]
753
)
754
755
# Create ReLU activation
756
relu_node = helper.make_node('Relu', ['conv_out'], ['relu_out'])
757
758
# Create global average pooling
759
pool_node = helper.make_node('GlobalAveragePool', ['relu_out'], ['pool_out'])
760
761
# Create fully connected layer
762
fc_weight = np.random.randn(1000, 64).astype(np.float32)
763
fc_weight_tensor = helper.make_tensor('fc_weight', TensorProto.FLOAT,
764
fc_weight.shape, fc_weight.flatten())
765
766
fc_node = helper.make_node('MatMul', ['pool_out', 'fc_weight'], ['Y'])
767
768
# Create graph
769
graph_def = helper.make_graph(
770
[conv_node, relu_node, pool_node, fc_node],
771
'simple_cnn',
772
[X],
773
[Y],
774
[weight, fc_weight_tensor]
775
)
776
777
# Create model
778
model_def = helper.make_model(graph_def, producer_name='onnx-example')
779
780
# Save model
781
onnx.save_model(model_def, 'simple_cnn.onnx')
782
```
783
784
### Creating Custom Types and Attributes
785
786
```python
787
import onnx
788
from onnx import helper, TensorProto
789
790
# Create a node with various attribute types
791
node = helper.make_node(
792
'CustomOp',
793
inputs=['input'],
794
outputs=['output'],
795
# Various attribute types
796
int_attr=42,
797
float_attr=3.14,
798
string_attr="hello",
799
ints_attr=[1, 2, 3],
800
floats_attr=[1.0, 2.0, 3.0],
801
strings_attr=["a", "b", "c"]
802
)
803
804
# Create complex type information
805
sequence_type = helper.make_sequence_type_proto(
806
helper.make_tensor_type_proto(TensorProto.FLOAT, [None, 128])
807
)
808
809
map_type = helper.make_map_type_proto(
810
TensorProto.STRING,
811
helper.make_tensor_type_proto(TensorProto.FLOAT, [None])
812
)
813
814
optional_type = helper.make_optional_type_proto(
815
helper.make_tensor_type_proto(TensorProto.INT64, [None])
816
)
817
```