or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

backend-integration.mdindex.mdmodel-composition.mdmodel-construction.mdmodel-hub.mdmodel-io.mdmodel-validation.mdnumpy-integration.mdoperator-definitions.mdreference-implementation.mdshape-inference.mdtext-processing.mdversion-conversion.md

operator-definitions.mddocs/

0

# Operator Definitions

1

2

Access to ONNX operator schemas, type definitions, and version compatibility information for all supported operators across different domains. This module provides programmatic access to the complete ONNX operator specification.

3

4

## Capabilities

5

6

### Schema Access

7

8

Retrieve operator schemas and metadata for validation and code generation.

9

10

```python { .api }

11

def get_schema(op_type, max_inclusive_version=None, domain=""):

12

"""

13

Get operator schema for a specific operator.

14

15

Parameters:

16

- op_type: Name of the operator (e.g., 'Conv', 'Relu', 'Add')

17

- max_inclusive_version: Maximum opset version to consider

18

- domain: Operator domain (empty string for ONNX domain)

19

20

Returns:

21

OpSchema: Schema object with operator definition and constraints

22

23

Raises:

24

SchemaError: If operator is not found or version is invalid

25

"""

26

27

def has(op_type, domain=""):

28

"""

29

Check if an operator schema exists.

30

31

Parameters:

32

- op_type: Name of the operator to check

33

- domain: Operator domain (empty string for ONNX domain)

34

35

Returns:

36

bool: True if operator schema exists, False otherwise

37

"""

38

39

def get_all_schemas():

40

"""

41

Get all operator schemas for the current opset version.

42

43

Returns:

44

list[OpSchema]: List of all available operator schemas

45

"""

46

47

def get_all_schemas_with_history():

48

"""

49

Get all operator schemas including historical versions.

50

51

Returns:

52

list[OpSchema]: List of all schemas across all versions

53

"""

54

```

55

56

### Function Operations

57

58

Access to operators that are defined as functions rather than primitives.

59

60

```python { .api }

61

def get_function_ops():

62

"""

63

Get list of operators that are defined as functions.

64

65

Returns:

66

list[str]: Names of operators defined as functions

67

"""

68

```

69

70

### Version Information

71

72

Get current and supported opset versions.

73

74

```python { .api }

75

def onnx_opset_version():

76

"""

77

Get the current ONNX opset version.

78

79

Returns:

80

int: Current opset version number

81

"""

82

```

83

84

### Domain Constants

85

86

Standard domain identifiers for ONNX operators.

87

88

```python { .api }

89

ONNX_DOMAIN = "" # Standard ONNX domain (empty string)

90

ONNX_ML_DOMAIN = "ai.onnx.ml" # ONNX ML domain for traditional ML operators

91

AI_ONNX_PREVIEW_TRAINING_DOMAIN = "ai.onnx.preview.training" # Training operators domain

92

```

93

94

### Schema Classes

95

96

Classes for working with operator schemas and handling errors.

97

98

```python { .api }

99

class OpSchema:

100

"""

101

Operator schema containing definition, constraints, and metadata.

102

103

Key properties:

104

- name: Operator name

105

- domain: Operator domain

106

- since_version: Minimum opset version

107

- doc: Documentation string

108

- attributes: Dict of attribute schemas

109

- inputs: List of input specifications

110

- outputs: List of output specifications

111

- type_constraints: List of type constraints for inputs/outputs

112

"""

113

114

class SchemaError(Exception):

115

"""

116

Exception raised when operator schema operations fail.

117

118

Thrown when requesting schemas for unknown operators,

119

unsupported versions, or invalid operator definitions.

120

"""

121

122

# C++ implementation reference

123

C = ... # Module containing C++ operator definitions implementation

124

```

125

126

## Usage Examples

127

128

### Basic Schema Access

129

130

```python

131

import onnx

132

from onnx import defs

133

134

# Check if an operator exists

135

if defs.has('Conv'):

136

print("Conv operator is available")

137

138

# Get schema for a specific operator

139

conv_schema = defs.get_schema('Conv')

140

print(f"Conv operator documentation: {conv_schema.doc}")

141

print(f"Conv available since opset version: {conv_schema.since_version}")

142

143

# Get schema for a specific version

144

relu_schema = defs.get_schema('Relu', max_inclusive_version=6)

145

print(f"Relu schema for opset <= 6: {relu_schema.name}")

146

147

# Check ML domain operators

148

if defs.has('LinearRegressor', domain=defs.ONNX_ML_DOMAIN):

149

ml_schema = defs.get_schema('LinearRegressor', domain=defs.ONNX_ML_DOMAIN)

150

print(f"ML operator: {ml_schema.name}")

151

```

152

153

### Exploring Available Operators

154

155

```python

156

import onnx

157

from onnx import defs

158

159

# Get current opset version

160

current_opset = defs.onnx_opset_version()

161

print(f"Current ONNX opset version: {current_opset}")

162

163

# List all available operators

164

all_schemas = defs.get_all_schemas()

165

print(f"Total operators available: {len(all_schemas)}")

166

167

# Group operators by domain

168

operators_by_domain = {}

169

for schema in all_schemas:

170

domain = schema.domain or "ONNX"

171

if domain not in operators_by_domain:

172

operators_by_domain[domain] = []

173

operators_by_domain[domain].append(schema.name)

174

175

for domain, ops in operators_by_domain.items():

176

print(f"{domain} domain: {len(ops)} operators")

177

print(f" Examples: {', '.join(sorted(ops)[:5])}")

178

179

# Find function-based operators

180

function_ops = defs.get_function_ops()

181

print(f"Function-based operators: {function_ops}")

182

```

183

184

### Operator Schema Analysis

185

186

```python

187

import onnx

188

from onnx import defs

189

190

def analyze_operator(op_name, domain=""):

191

"""Analyze an operator's schema in detail."""

192

193

try:

194

schema = defs.get_schema(op_name, domain=domain)

195

196

print(f"Operator: {schema.name}")

197

print(f"Domain: {schema.domain or 'ONNX'}")

198

print(f"Since version: {schema.since_version}")

199

print(f"Documentation: {schema.doc[:200]}...")

200

201

# Analyze inputs

202

print(f"\nInputs ({len(schema.inputs)}):")

203

for i, input_spec in enumerate(schema.inputs):

204

print(f" {i}: {input_spec.name} - {input_spec.description}")

205

print(f" Type constraints: {input_spec.type_str}")

206

207

# Analyze outputs

208

print(f"\nOutputs ({len(schema.outputs)}):")

209

for i, output_spec in enumerate(schema.outputs):

210

print(f" {i}: {output_spec.name} - {output_spec.description}")

211

print(f" Type constraints: {output_spec.type_str}")

212

213

# Analyze attributes

214

print(f"\nAttributes ({len(schema.attributes)}):")

215

for attr_name, attr_spec in schema.attributes.items():

216

required = "required" if attr_spec.required else "optional"

217

print(f" {attr_name} ({required}): {attr_spec.description}")

218

print(f" Type: {attr_spec.type}")

219

if hasattr(attr_spec, 'default_value') and attr_spec.default_value:

220

print(f" Default: {attr_spec.default_value}")

221

222

# Check if it's a function

223

if hasattr(schema, 'function_body') and schema.function_body:

224

print(f"\nFunction-based operator with {len(schema.function_body.node)} nodes")

225

226

except defs.SchemaError as e:

227

print(f"Schema error for {op_name}: {e}")

228

229

# Analyze some common operators

230

analyze_operator('Conv')

231

print("\n" + "="*50 + "\n")

232

analyze_operator('BatchNormalization')

233

print("\n" + "="*50 + "\n")

234

analyze_operator('LinearRegressor', domain=defs.ONNX_ML_DOMAIN)

235

```

236

237

### Version Compatibility Checking

238

239

```python

240

import onnx

241

from onnx import defs

242

243

def check_opset_compatibility(model_path):

244

"""Check if a model's operators are compatible with current opset."""

245

246

model = onnx.load_model(model_path)

247

current_opset = defs.onnx_opset_version()

248

249

# Get model's opset imports

250

model_opsets = {}

251

for opset_import in model.opset_import:

252

model_opsets[opset_import.domain] = opset_import.version

253

254

print(f"Model opset versions: {model_opsets}")

255

print(f"Current ONNX opset: {current_opset}")

256

257

# Check each node's operator

258

incompatible_nodes = []

259

for node in model.graph.node:

260

op_type = node.op_type

261

domain = node.domain or ""

262

263

try:

264

# Get schema for model's opset version

265

model_opset_version = model_opsets.get(domain, model_opsets.get("", 1))

266

schema = defs.get_schema(op_type,

267

max_inclusive_version=model_opset_version,

268

domain=domain)

269

270

# Check if operator exists in current version

271

if not defs.has(op_type, domain=domain):

272

incompatible_nodes.append((node.name or f"node_{node.op_type}",

273

op_type, domain, "not available"))

274

elif schema.since_version > current_opset:

275

incompatible_nodes.append((node.name or f"node_{node.op_type}",

276

op_type, domain, "version too high"))

277

278

except defs.SchemaError:

279

incompatible_nodes.append((node.name or f"node_{node.op_type}",

280

op_type, domain, "schema not found"))

281

282

if incompatible_nodes:

283

print(f"\nFound {len(incompatible_nodes)} incompatible nodes:")

284

for node_name, op_type, domain, reason in incompatible_nodes:

285

print(f" {node_name}: {op_type}@{domain} - {reason}")

286

else:

287

print("\nAll operators are compatible with current opset!")

288

289

# Example usage (commented out)

290

# check_opset_compatibility("model.onnx")

291

```

292

293

### Custom Operator Detection

294

295

```python

296

import onnx

297

from onnx import defs

298

299

def find_custom_operators(model_path):

300

"""Find custom (non-standard) operators in a model."""

301

302

model = onnx.load_model(model_path)

303

304

standard_domains = {"", defs.ONNX_ML_DOMAIN, defs.AI_ONNX_PREVIEW_TRAINING_DOMAIN}

305

custom_operators = []

306

307

for node in model.graph.node:

308

op_type = node.op_type

309

domain = node.domain or ""

310

311

# Check if it's a custom domain

312

if domain not in standard_domains:

313

custom_operators.append((op_type, domain, "custom domain"))

314

continue

315

316

# Check if operator exists in standard domains

317

if not defs.has(op_type, domain=domain):

318

custom_operators.append((op_type, domain, "unknown operator"))

319

320

if custom_operators:

321

print(f"Found {len(custom_operators)} custom operators:")

322

for op_type, domain, reason in custom_operators:

323

print(f" {op_type}@{domain} - {reason}")

324

325

# Group by domain

326

domains = set(domain for _, domain, _ in custom_operators)

327

print(f"\nCustom domains used: {domains}")

328

else:

329

print("No custom operators found - model uses only standard ONNX operators")

330

331

# Example usage (commented out)

332

# find_custom_operators("model_with_custom_ops.onnx")

333

```

334

335

### Operator Evolution Analysis

336

337

```python

338

import onnx

339

from onnx import defs

340

341

def analyze_operator_evolution(op_name, domain=""):

342

"""Analyze how an operator has evolved across opset versions."""

343

344

# Get all schemas with history

345

all_schemas = defs.get_all_schemas_with_history()

346

347

# Find all versions of the specified operator

348

op_versions = []

349

for schema in all_schemas:

350

if schema.name == op_name and schema.domain == domain:

351

op_versions.append(schema)

352

353

if not op_versions:

354

print(f"Operator {op_name}@{domain} not found")

355

return

356

357

# Sort by version

358

op_versions.sort(key=lambda s: s.since_version)

359

360

print(f"Evolution of {op_name}@{domain or 'ONNX'}:")

361

362

for schema in op_versions:

363

print(f"\nVersion {schema.since_version}:")

364

print(f" Inputs: {len(schema.inputs)}")

365

print(f" Outputs: {len(schema.outputs)}")

366

print(f" Attributes: {len(schema.attributes)}")

367

368

# Show what changed

369

if len(op_versions) > 1 and schema != op_versions[0]:

370

prev_schema = op_versions[op_versions.index(schema) - 1]

371

372

# Check for new attributes

373

new_attrs = set(schema.attributes.keys()) - set(prev_schema.attributes.keys())

374

if new_attrs:

375

print(f" New attributes: {list(new_attrs)}")

376

377

# Check for removed attributes

378

removed_attrs = set(prev_schema.attributes.keys()) - set(schema.attributes.keys())

379

if removed_attrs:

380

print(f" Removed attributes: {list(removed_attrs)}")

381

382

# Analyze evolution of some operators

383

analyze_operator_evolution('Conv')

384

print("\n" + "="*50 + "\n")

385

analyze_operator_evolution('BatchNormalization')

386

```