Compact GraphBuilder authoring and runtime walkthroughs#
- Date:
2026-08
discussion
Objective#
The objective is to make small ONNX graphs concise to author, easy to inspect, and easy to execute from the regular documentation. The work has two connected parts:
add a compact Python facade over the existing
GraphBuilderprimitives, inspired by yet-another-onnx-builder;add non-gallery documentation that follows a model from construction or a backend-test case through compact display, optimization, and runtime execution.
The existing make_input, make_output, make_initializer, and
make_node methods remain the stable low-level API. The compact facade
delegates to them so opset resolution, schema validation, incremental shape
inference, naming, and serialization continue to have one implementation.
Compact authoring contract#
GraphBuilder.op exposes ONNX operators by their canonical CamelCase names:
x = g.inp("X", TensorProto.FLOAT, [None, 4])
bias = g.init(numpy.array([1, 2, 3, 4], dtype=numpy.float32), name="bias")
added = g.op.Add(x, bias)
result = g.op.Relu(added, outputs="Y")
custom = g.op.CustomNormalize(
result, domain="com.example", outputs="Z", epsilon=1e-5
)
g.out(custom, TensorProto.FLOAT, [None, 4])
The facade follows these rules:
g.op.<Operator>(*inputs, **kwargs)forwards canonical ONNX attributes fromkwargsand returns one output name or a tuple of output names;outputscontrols an explicit output name, a list of names, or an output count;domainandnameremain reserved node options;Nonerepresents an omitted optional ONNX input, variadic inputs remain positional, and NumPy arrays may be converted to named initializers;standard-domain operators use the builder’s configured opset and unknown standard operators fail explicitly;
custom operators use the same
g.op.<Operator>surface with an explicit non-emptydomain; the domain and version must already exist in the builder’s opset imports and are never registered silently;a custom operator does not require a locally registered schema. When no schema is available, attributes are preserved without schema inference and
outputsmust specify every output for operators that do not have exactly one output;g.inp(name, elem_type, shape)creates and returns an input name;g.out(name, elem_type=None, shape=None)declares a graph output and returns its name;g.init(value, name=None)adds an initializer, generates a name when necessary, and returns the final name.
Operator lookup should use one cached proxy and __getattr__ rather than
generating one Python method per schema. Reserved options must be separated
from ONNX attributes before calling the existing node builder. Multi-output,
optional-input, variadic-input, custom-domain, custom-operator,
unknown-standard-operator, duplicate-name, and invalid-attribute behavior
require direct tests.
The compact aliases are additive. Code generated by
onnx_light.tools.translate continues to use the explicit make_* API
until the compact facade is stable and can reproduce every generated construct.
GraphBuilder documentation#
Add docs/howto/graph_builder_basics.rst as a regular RST page, not a
Sphinx-Gallery example. It should be linked from the how-to index and from the
builder design section. The page covers:
creating a builder and selecting opsets;
declaring inputs, outputs, and initializers with the compact aliases;
adding standard, variadic, optional-input, multi-output, and custom-domain operators, including a custom operator without a local schema;
exporting and checking a model;
running the existing
GraphGraphpattern optimization;inspecting the optimization report and replaying its
LocalRewritingrecords.
Every snippet must execute during documentation testing or be covered by an
equivalent unit test. The page should show the compact API first and link to
the explicit make_* methods as the complete low-level contract.
LocalRewriting display#
Improve LocalRewriting presentation without changing the data consumed by
replay():
add a deterministic one-line summary containing the pattern, graph path, and matched/added node counts;
add a structured multiline representation grouping matched nodes, added nodes and positions, removed initializers, value renames, and timings;
display the root graph consistently as
<root>and nested graph paths in execution order;expose the short form through Python
repr()and the detailed form throughstr()or an explicitly named detail method;keep node ordering, field values, replay semantics, and serialization unchanged.
Tests compare stable structural lines rather than terminal width or color. Documentation output must remain readable without ANSI styling.
Runtime documentation walkthrough#
Add docs/howto/run_backend_test_case.rst outside Sphinx-Gallery. The page
uses public APIs to perform one reproducible end-to-end flow:
retrieve an exact backend-test case with
onnx_light.onnx.backend.get_test_case;display its model with an existing
onnx_light.toolsrepresentation, including theonnx-compactstyle;construct
onnx_light.onnx.reference.ReferenceEvaluator;execute the supplied test inputs and compare the outputs with the expected backend-test values;
repeat the run with representative
verbose,events_enabled, andrelease_intermediatesoptions, explaining the effect of each option.
The selected case must be small, deterministic, and identified by an exact
stable name. The example must not download data or depend on optional large
backend-test assets. If producing onnx-compact output currently requires a
private helper, first expose or reuse one stable public function under
onnx_light.tools rather than documenting internals.
The runtime design index should summarize the same execution path at the architecture level:
ReferenceEvaluatoras the Python entry point;RuntimeSessionpreparation, kernel resolution, and repeated execution;RuntimeContextvalues, allocators, events, and intermediate release;kernel registry dispatch and the session CPU executor;
the relationship between backend tests, the runtime how-to, and lower-level C++ APIs.
The design page remains conceptual and links to the runnable how-to for code.
Implementation sequence#
PR |
Scope |
Merge criterion |
Status |
|---|---|---|---|
Builder PR01 |
Compact |
Existing |
Planned |
Builder PR02 |
Deterministic short and detailed |
Reports are readable in Python and plain documentation while replay data and behavior remain unchanged. |
Planned |
Builder PR03 |
Non-gallery GraphBuilder basics and optimization how-to. |
The documented model builds, validates, optimizes, displays its rewrites, and round-trips in documentation tests. |
Planned |
Runtime PR01 |
Non-gallery backend-test runtime walkthrough and runtime design summary. |
One stable case is displayed in |
Planned |
Acceptance criteria#
The complete plan is accepted when:
compact authoring is additive and delegates to existing builder primitives;
generated models preserve opset imports, schema validation, names, shapes, and initializer ownership;
custom operators work through
g.opwith explicit domain/opset ownership, including when no local schema is registered;LocalRewritingis readable without losing any replay information;GraphBuilder construction and optimization have a runnable non-gallery how-to;
a backend-test model can be retrieved, rendered in compact form, executed, and validated from a second non-gallery how-to;
the runtime design section explains the architecture behind that example;
relevant Python/C++ tests, documentation builds, formatting, and linting pass.