Published July 17, 2026 | Version 2.6.5

Tools to convert ONNX files (NCHW) to TensorFlow format (NHWC)

Authors/Creators

Description

2.6.5

Summary

This pull request is the sixth staged checkpoint of the flatbuffer_direct refactor. It moves the remaining large groups of already-supported ModelIR compatibility logic out of the central ONNX lowerer and into focused, characterized pass and orchestration modules.

The central implementation in lower_from_onnx2tf.py is reduced from 25,647 lines on main to 5,585 lines. The branch adds 79 focused pass/orchestration modules and updates or adds 92 test files. The large net addition is primarily the extracted owners, synthetic characterization fixtures, architecture contracts, and the recorded Tier 0-4 regression evidence; it is not a second conversion pipeline.

The main goals of this checkpoint are:

  • make pass ownership explicit and local;
  • preserve the existing CLI, Python API, artifact formats, pass order, and conversion policy;
  • prevent partially applied rewrites when a late guard rejects a match;
  • reuse graph indexes, layout state, diagnostics, and pass state instead of reconstructing equivalent context in nested helpers;
  • keep direct TFLite conversion and -cotof outside the TensorFlow import boundary;
  • provide a reproducible, sequential Tier 0-4 regression result for both TFLite and native PyTorch output.

No dependency was added. Project and container metadata are synchronized at version 2.6.5.

Why this change is needed

The direct FlatBuffer backend accumulated shape repair, layout recovery, quantization compatibility, fusion, and late cleanup rules in one central module. Many rules were individually valid, but their implicit ordering and shared mutation made them difficult to understand or modify safely. A guard that failed after an early tensor/layout mutation could leave the graph in a partially rewritten state, and nested recovery helpers repeatedly assembled nearly identical ModelIR/LayoutState/diagnostic contexts.

This branch follows a deliberately conservative sequence for each family:

  1. characterize the existing match, guard, ordering, statistics, metadata, and no-op behavior;
  2. add rejection, fan-out, boundary, dynamic-shape, quantization, and idempotence fixtures;
  3. correct mutation atomicity where a rejected candidate could leak changes;
  4. extract the implementation into one focused owner while retaining the original private lowerer symbol as a thin compatibility wrapper;
  5. verify owner/wrapper ModelIR fingerprints and architecture boundaries.

This separates ownership without attempting a broad semantic rewrite at the same time.

Main improvements

1. Focused pass ownership

The branch extracts shape, layout, quantization, attention, binary, affine, Concat, and terminal recovery behavior into op-family-oriented modules under onnx2tf/tflite_builder/passes/.

Representative extracted families include:

  • static Squeeze and shape-signature sanitization;
  • dynamic boundary-signature realignment;
  • ExpandDims/Squeeze-to-Reshape compatibility;
  • exact and singleton rank-four binary layout adaptation;
  • channelwise broadcast-constant and stale binary-adapter repair;
  • Conv/Pool output passthrough and Conv/Mul/Add affine folding;
  • mixed-layout Concat input repair and legacy pre-Concat recovery;
  • Concat/Mul/Add, nested-Concat, Mean/Reshape, and StridedSlice/Pad/Concat bridge recovery;
  • Softmax/Transpose canonicalization and Reshape/Transpose collapse;
  • BatchMatMul affine input, SE, adjoint, and attention preprojection recovery;
  • attention Gather cleanup and QKV reshape compatibility;
  • elementwise round-trip, fan-out, residual affine, and terminal PReLU/FC recovery;
  • QLinear SiLU, QLinear Concat/Conv, QDQ bridge, quantized Swish, and other quantized recovery orchestration;
  • late and terminal recovery clusters for Slice/Concat, affine/Concat/Split, normalization/attention, channel shuffle, SPP, hard activations, and singleton reshape patterns.

The original call sites and their relative order remain visible in the lowerer. Existing private names remain available through compatibility wrappers, so downstream internal imports are not forced to change in this checkpoint.

2. Transactional rejection and deterministic rewrites

Several rule families previously performed metadata or graph mutations before all rejection conditions had been evaluated. The branch adds preflight planning or snapshot-based rollback behavior before extracting those owners.

The corrected families include Conv input adapters, Conv/Pool passthrough, mixed-layout Concat, stale binary adapters, QLinear output propagation, QLinear SiLU prefix recovery, Mean/MaxPool/Concat recovery, Softmax transpose canonicalization, Concat bridge families, Reshape/Transpose collapse, and attention cleanup/rank-lift patterns.

The tests explicitly verify that rejected candidates leave operator lists, tensor metadata, quantization records, LayoutState, graph outputs, and diagnostics unchanged. Successful rewrites retain deterministic candidate priority, fixed-point restart behavior, unique naming, pruning order, and the historical statistics keys.

3. Indexed graph access and shared pass state

Extracted owners use ModelIRGraphIndex for producer/consumer lookup and differential updates where the family contract permits it. Nested pass groups share one pass-state scope so graph indexes can be reused across compatible owners instead of being rebuilt for each helper.

Architecture and efficiency tests cover:

  • one graph-index build across multi-owner orchestration fixtures;
  • stable pass IDs and diagnostic ordering;
  • deterministic owner selection for all policy combinations;
  • no import cycle from pass modules back into the central lowerer;
  • preservation of target-specific contexts and child-model boundaries.

4. Consolidated ModelIR pass contexts

Repeated frozen context dataclasses are consolidated around ModelIRPassContext, owned by ConversionSession. Twenty-five historical context names remain compatible internal aliases, while main-model consumers reuse the Session-owned ModelIR, LayoutState, and diagnostics identities.

Callback-bearing recovery contexts now compose the shared context while retaining their exact callback objects and argument contracts. Target-specific and child-model conversions still receive fresh context where isolation is required. No orchestration dataclass now duplicates the common core identity fields.

5. Typed NodeView tensor references

NodeView.inputs and NodeView.outputs previously created a new dynamic class for every tensor reference. Runtime attribute access worked, but static analysis could not prove that .name, .onnx_name, .shape, and .dtype existed. They now use lightweight typed instances with the same mutable metadata and remapping behavior. This removes the Pylance attribute-access error without suppressing diagnostics.

6. More reliable sequential corpus runner

The bulk runner now publishes its increasingly large state JSON through a same-directory temporary file followed by os.replace(). Concurrent readers therefore observe either the previous complete state or the new complete state, never the truncated interval created by direct open(..., "w") output.

The change preserves filenames, JSON schema, indentation, file mode, resume behavior, and classification. Serialization or replacement failure removes the unpublished temporary file and leaves the previous state intact. No per-update fsync was added, avoiding unnecessary I/O cost for state files that reached approximately 17 MiB.

The pre-correction evidence was committed before changing the writer, so the observed failure and the correction remain independently reviewable.

Compatibility guarantees

  • Public CLI and Python APIs are unchanged.
  • flatbuffer_direct remains the default backend.
  • Artifact names, formats, return behavior, and report schemas are unchanged.
  • Existing pass order, private compatibility entry points, statistics keys, and requested-artifact behavior are preserved.
  • Direct TFLite conversion and -cotof do not import or execute TensorFlow.
  • Optional TensorFlow artifacts remain behind their explicit optional-extra boundary.
  • No package was added or removed.
  • All validation commands used the repository uv environment.
  • Model inference was strictly sequential: no ProcessPool and no concurrent model-inference workers were used.
  • The 2,000 threshold is only the ONNX operation-count boundary between corpus tiers; this change does not impose a 2,000-line source-file requirement.

Tier 0-4 full regression validation

The final managed run covered every active Tier 0-4 model that was below the ten-minute policy boundary, did not trigger SWAP, and had not been explicitly excluded by prior validation policy.

| Metric | Result | | --- | ---: | | Active models completed | 379 / 379 | | Timeout | 0 | | Nonzero process-tree SWAP | 0 | | Median per-model time | 8.746 s | | Maximum per-model time | 191.394 s | | Sum of per-model time | 7,542.595 s |

The component observations were:

| Result | TFLite | Native PyTorch | | --- | ---: | ---: | | Accuracy pass | 347 | 138 | | Accuracy fail | 20 | 46 | | Missing report | 10 | 195 | | Pre-report conversion error | 2 | 2 |

These are raw observations, not regression counts. The existing PyTorch failures and missing reports remain visible and are not classified as successful conversions.

Compared with the finalized fb-refactor5 baseline:

  • the TFLite problem set is unchanged;
  • all known baseline failures retain their prior classification/signature;
  • yolox_nano.onnx and rtdetrv4_s.onnx remain improved passes;
  • the user-approved DEIM near-tied TopK index cases remain accepted;
  • no combined classification regressed;
  • combined pass count improved from 136 to 137;
  • PyTorch failure count improved from 32 to 31;
  • no fb-refactor6-specific TFLite or native-PyTorch regression was confirmed.

The full model-level result, timing, normalized signatures, exclusions, and baseline comparison are recorded in:

  • docs/flatbuffer_direct_tier0_4_full_regression_2026-07-17.md;
  • docs/baselines/flatbuffer_direct_tier0_4_tflite_native_pytorch_fb6_13fcf7ce.json.

Automated verification

The refactor was developed as many small characterization/correction/extraction checkpoints. Focused owner/wrapper, architecture, efficiency, core lowering, and TensorFlow-import-blocked gates were run at each boundary. The detailed command history and checkpoint results are retained in docs/fb_refactor6_pull_request_description.md and docs/flatbuffer_direct_handoff_2026-07-14.md.

Latest relevant gates include:

  • bulk runner, active corpus manifest, and architecture: 292 passed;
  • typed NodeView plus architecture: 250 passed;
  • representative core lowering, error reporting, QLinear, and rank inference: 43 passed;
  • atomic state writer focused suite: 42 passed;
  • non-inference atomic writer stress test: 40 successive 8,000-entry states, 1,742 successful reads, zero partial JSON reads, and no leaked temporary file;
  • repeated TensorFlow-import-blocked direct-backend gate: 11 passed at the relevant extraction checkpoints;
  • focused Ruff checks, Python compilation checks, uv lock --check, version consistency, and git diff --check: passed.

The authoritative 379-model conversion run is tied to converter checkpoint 13fcf7ce. The later atomic-writer and NodeView typing commits do not alter lowering, export policy, scheduling, or model inference and were covered by their focused gates rather than another multi-hour corpus run.

Known limitations and deliberate scope

  • Tier 5 models (2,000 or more ONNX operations) are outside this final corpus gate.
  • Models already classified as timeout, SWAP-risk, or explicitly excluded are outside the 379-model regression conclusion.
  • Native PyTorch still has substantial inherited accuracy failures and missing reports. This PR preserves and records them; it does not claim to solve the PyTorch exporter backlog.
  • Several inherited TFLite limitations remain, including the documented DPT Softmax/rank error, Conv-TasNet layout failures, MIRNet missing tensor data, and known numeric mismatches.
  • The extraction intentionally preserves many legacy compatibility policies. Further semantic simplification should be proposed only after the new local owners have equivalent corpus evidence.
  • The atomic state replacement guarantees complete visibility to concurrent readers, not durability across sudden power loss.

What's Changed

  • Refactor flatbuffer-direct pass ownership and shared ModelIR contexts by @PINTO0309 in https://github.com/PINTO0309/onnx2tf/pull/953

Full Changelog: https://github.com/PINTO0309/onnx2tf/compare/2.6.4...2.6.5

Notes

If you use onnx2tf in your research, please cite it using these metadata.

Files

PINTO0309/onnx2tf-2.6.5.zip

Files (5.7 MB)

Name Size Download all
md5:880f79b3cf05c62c7a95416c7ee6c223
5.7 MB Preview Download

Additional details

Related works

Is supplement to
Software: https://github.com/PINTO0309/onnx2tf/tree/2.6.5 (URL)

Software