Debugging transformations¶
ONNX IR provides readable object displays, ONNX text conversion, mutation journaling, and construction tapes for inspecting model transformations.
Print or display IR objects¶
Model, Graph, Node, Value, and tensor objects have compact string
representations:
print(model.graph)
print(node)
Call display() for syntax-highlighted terminal output when rich is installed:
pip install rich
model.display()
model.graph.display(page=True)
page=True opens a terminal pager, which is useful for large graphs.
Use ONNX text format¶
Convert a model to the standard ONNX textual syntax when comparing structure with other ONNX tools:
text = ir.to_onnx_text(model)
print(text)
round_tripped = ir.from_onnx_text(text)
Pass exclude_initializers=True to to_onnx_text when large constant values
would obscure the graph structure. Text conversion serializes through ONNX and is
best used for diagnostics or interchange rather than inside performance-sensitive
transformation loops.
Record mutations with a journal¶
The alpha onnx_ir.journaling API records supported IR operations,
including stack traces and object references:
from onnx_ir.journaling import Journal
with Journal() as journal:
transform(model)
journal.display()
Inspect journal.entries to filter by operation or class, call
entry.display() for full details, or attach a hook for real-time logging:
journal = Journal()
journal.add_hook(lambda entry: print(entry.operation, entry.class_name))
Keep the journal scope focused around the suspicious transformation. Recording a large pipeline creates substantial diagnostic output and stack-trace data.
Inspect graph relationships¶
Use object relationships rather than names when diagnosing connectivity:
print(value.producer())
print(list(value.uses()))
print(list(value.consumers()))
print(node.predecessors())
print(node.successors())
print(node.graph)
For nested graphs, use RecursiveGraphIterator and
analysis.analyze_implicit_usage to reveal control-flow bodies and outer-scope
captures.
Isolate a failing region¶
onnx_ir.convenience.extract() can clone a bounded region into a smaller
graph for inspection or reproduction:
region = ir.convenience.extract(
model.graph,
inputs=["x", "weight"],
outputs=["y"],
)
region.display()
Extraction reports undeclared frontier dependencies instead of silently creating an incomplete graph.
Validate between pipeline stages¶
When a long pass pipeline fails, insert focused checks to locate the first invalid stage:
import onnx_ir.passes.common as common_passes
checker = common_passes.CheckerPass()
for pass_ in passes:
result = pass_(model)
model = result.model
checker(model)
This per-stage checking is a diagnostic technique, not a recommended production pipeline: it serializes and checks the whole model after each pass.
Topological sorting, name fixing, shape inference, and ONNX checking test different properties. Apply the checks relevant to the invariant each stage promises.
Use Tape to reproduce construction bugs¶
onnx_ir.tape.Tape records nodes and initializers while constructing a
graph. It is useful for reducing a failing model to a short sequence of operations
that can be copied into a regression test.
See Constructing models for a complete example.