Skip to main content

NNSchemaParser

NNSchemaParser converts a PyTorch nn.Module into a serializable, inspectable graph representation — the ModelBlockSchema — that keeps the original variable names of the forward source and every sub-module (including MoE experts that a single trace would never visit). The schema can then be executed by a built-in schema interpreter that re-dispatches every recorded call to the real torch callables, so the graph runs exactly like the model — and can optionally capture the value of every intermediate tensor.

   nn.Module  ──parse──►  ModelBlockSchema  ──interpret──►  outputs / captured values
  (your code)              (names + graph)                   (identical to model(x))

Why not torch.fx?

torch.fx.symbolic_trace NNSchemaParser
Variable names lost (_0, _1, …) kept (hidden_states, query, …)
Untaken branches (MoE experts) missing all present
Control flow graph_module nodes only if / for / try as first-class instructions
*args / **kwargs limited supported in signatures and call sites
Comprehensions unsupported compiled to helper functions
Re-executable via the FX machinery via a small self-contained interpreter

Quick start

import torch
from torch import nn

from nnschemaparser import NNParser, SchemaInterpreter, TraceRecorder, dump_schema


class MLP(nn.Module):
    def __init__(self) -> None:
        super().__init__()
        self.fc1 = nn.Linear(784, 256)
        self.fc2 = nn.Linear(256, 10)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        hidden = self.fc1(x)
        activated = hidden.relu()
        return self.fc2(activated)


model = MLP().eval()
x = torch.randn(2, 784)

# 1. Parse the model into a schema (resolves shapes and dtypes)
schema = NNParser.parse_model(
    model=model,
    inputs_tensors_shapes={"x": (2, 784)},
    inputs_tensors_dtypes={"x": "torch.float32"},
    inputs_tensors_values={"x": x},
)

# 2. Dump a readable view of the whole block tree
dump_schema(schema=schema, path="schema.txt")

# 3. Execute it with a tracer and compare with the real forward
tracer = TraceRecorder()
outputs = SchemaInterpreter(capture_values=True, listeners=[tracer]).run(
    block=schema,
    scope={"x": x.clone()},
)
tracer.save("trace.txt")
reference = model(x)
assert torch.equal(outputs[0], reference)

The schema dump of MLP reads exactly like the source — original variable names, every sub-module, and the resolved shape of every step:

=== BLOCK MLP ===
inputs:
  - x = torch.float32[2, 784]
outputs:
  - torch.float32[2, 10]
weights:
  (none)
sub-blocks:
  - fc1(Linear)
  - fc2(Linear)
body:
  hidden = CALL fc1(x)  -> torch.float32[2, 256]
  $t1 = getattr(hidden, 'relu')  -> builtin_function_or_method
  activated = hidden.relu()  -> torch.float32[2, 256]
  $t2 = CALL fc2(activated)  -> torch.float32[2, 10]
  RETURN $t2

The tracer records the same execution chronologically, with the value of every intermediate tensor (one line per event, indented by the nesting depth) — this is what a WebUI consumes to display every intermediate value:

[00001] ENTER BLOCK MLP
[00002]   in x = torch.float32[2, 784] abs_sum=1241.4496 min=-3.0303 max=3.3046
[00003]   ENTER BLOCK Linear
[00004]     in input = torch.float32[2, 784] abs_sum=1241.4496 min=-3.0303 max=3.3046
[00005]     $t1 = F.linear(input, weight, bias)  [torch.float32[2, 256] abs_sum=215.3293 ...]
[00006]   EXIT BLOCK Linear -> (torch.float32[2, 256] abs_sum=215.3293 ...)
[00007]   hidden = CALL fc1 [Linear]  [torch.float32[2, 256] abs_sum=215.3293 ...]

Installation

pip install .            # or: pip install -e .[research] for the harness extras

Requires Python ≥ 3.12 and PyTorch ≥ 2.0. The model classes must be importable from a real file (the parser reads the forward source with inspect.getsource, which fails for classes defined in a REPL or stdin).

Validation

A robustness sweep of 58 models — 48 Hugging Face hub checkpoints (text, vision, audio, multimodal) plus 10 locally built architectures (MLP, RNN, CNN, autoencoder, GAN, GNN) — runs each model through parse → interpret → compare against the real forward. All 58 pass with maxdiff = 0.0 against the real forward. See docs/DOCUMENTATION.md for the full model matrix and the sweep CLI.

Documentation

  • docs/API.md — the public API: parsing, executing, tracing, dumping and walking schemas.
  • docs/DOCUMENTATION.md — full documentation: how the parser works, the schema and instruction reference, the interpreter, usage recipes, supported syntax, supported/unsupported models, and limitations.
  • CHANGELOG.md — the release history.
  • tests/hf_sweep.py — the validation harness CLI (58 HuggingFace models).
  • tests/test_new_syntax.py, tests/test_parser.py, tests/test_methods_and_scalars.py — the fixture test suite (pytest, no network needed), also runnable with python -m tests.test_new_syntax.
  • tests/test_speech_models.py — the espnet/torchaudio regression tests.

License

MIT — see LICENSE.

Metadata

Release files for nnschemaparser 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nnschemaparser 0.1.0
File Size Uploaded Provenance Actions
nnschemaparser-0.1.0.tar.gz 68.9 kB Without provenance Details for nnschemaparser-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for nnschemaparser 0.1.0
File Interpreter ABI Platform Actions
nnschemaparser-0.1.0-py3-none-any.whl Python 3 none any Details for nnschemaparser-0.1.0-py3-none-any.whl

Total release size: 145.5 kB

Release files / nnschemaparser-0.1.0.tar.gz

Download URL nnschemaparser-0.1.0.tar.gz
Size 68.9 kB
Tags Source
SHA-256 checksum
How to use checksums
c8c5eb7e6cae86df435ea886a081d59157b15957d2e49b95c247da22ad0c2744
BLAKE2b-256 checksum
How to use checksums
135f5ad86ba3d3f43d0d03eb3ecf2fad72527cbd72af53a11fd3562745a843ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.0

Release files / nnschemaparser-0.1.0-py3-none-any.whl

Download URL nnschemaparser-0.1.0-py3-none-any.whl
Size 76.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3895f2551553265358307e721833e281d4742216667e938caddffe0698ec4cb8
BLAKE2b-256 checksum
How to use checksums
59abedc33c907f38f9d6b526216db8671f4cd47993dac85d1098432125f00658
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.0

Security for nnschemaparser 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page