nneditor 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. nneditor-1.0.0/.gitignore +42 -0
  2. nneditor-1.0.0/PKG-INFO +318 -0
  3. nneditor-1.0.0/README.md +293 -0
  4. nneditor-1.0.0/pyproject.toml +113 -0
  5. nneditor-1.0.0/src/nneditor/__init__.py +5 -0
  6. nneditor-1.0.0/src/nneditor/__main__.py +12 -0
  7. nneditor-1.0.0/src/nneditor/adapters/__init__.py +6 -0
  8. nneditor-1.0.0/src/nneditor/adapters/detect.py +91 -0
  9. nneditor-1.0.0/src/nneditor/adapters/jax/__init__.py +23 -0
  10. nneditor-1.0.0/src/nneditor/adapters/jax/checkpoint.py +158 -0
  11. nneditor-1.0.0/src/nneditor/adapters/jax/mlir_text.py +614 -0
  12. nneditor-1.0.0/src/nneditor/adapters/jax/stablehlo.py +309 -0
  13. nneditor-1.0.0/src/nneditor/adapters/onnx/__init__.py +56 -0
  14. nneditor-1.0.0/src/nneditor/adapters/onnx/dtypes.py +85 -0
  15. nneditor-1.0.0/src/nneditor/adapters/onnx/exporter.py +1081 -0
  16. nneditor-1.0.0/src/nneditor/adapters/onnx/index.py +280 -0
  17. nneditor-1.0.0/src/nneditor/adapters/onnx/indexer.py +1269 -0
  18. nneditor-1.0.0/src/nneditor/adapters/onnx/numerical.py +319 -0
  19. nneditor-1.0.0/src/nneditor/adapters/onnx/smoke_worker.py +118 -0
  20. nneditor-1.0.0/src/nneditor/adapters/onnx/splice.py +197 -0
  21. nneditor-1.0.0/src/nneditor/adapters/onnx/to_ir.py +411 -0
  22. nneditor-1.0.0/src/nneditor/adapters/onnx/typed_data.py +279 -0
  23. nneditor-1.0.0/src/nneditor/adapters/onnx/wire.py +297 -0
  24. nneditor-1.0.0/src/nneditor/adapters/pytorch/__init__.py +27 -0
  25. nneditor-1.0.0/src/nneditor/adapters/pytorch/checkpoint.py +292 -0
  26. nneditor-1.0.0/src/nneditor/adapters/pytorch/fx.py +296 -0
  27. nneditor-1.0.0/src/nneditor/adapters/pytorch/pickle_scan.py +413 -0
  28. nneditor-1.0.0/src/nneditor/adapters/pytorch/pt2.py +635 -0
  29. nneditor-1.0.0/src/nneditor/adapters/pytorch/safetensors.py +371 -0
  30. nneditor-1.0.0/src/nneditor/adapters/pytorch/scalar_types.py +103 -0
  31. nneditor-1.0.0/src/nneditor/adapters/pytorch/zip_store.py +148 -0
  32. nneditor-1.0.0/src/nneditor/adapters/registry.py +185 -0
  33. nneditor-1.0.0/src/nneditor/analysis/__init__.py +6 -0
  34. nneditor-1.0.0/src/nneditor/analysis/detectors.py +766 -0
  35. nneditor-1.0.0/src/nneditor/analysis/hierarchy.py +367 -0
  36. nneditor-1.0.0/src/nneditor/analysis/layout.py +306 -0
  37. nneditor-1.0.0/src/nneditor/analysis/lod.py +505 -0
  38. nneditor-1.0.0/src/nneditor/analysis/statistics.py +337 -0
  39. nneditor-1.0.0/src/nneditor/application/__init__.py +7 -0
  40. nneditor-1.0.0/src/nneditor/application/editing.py +318 -0
  41. nneditor-1.0.0/src/nneditor/application/edits_store.py +164 -0
  42. nneditor-1.0.0/src/nneditor/application/hierarchy.py +618 -0
  43. nneditor-1.0.0/src/nneditor/application/jobs.py +218 -0
  44. nneditor-1.0.0/src/nneditor/application/navigation.py +228 -0
  45. nneditor-1.0.0/src/nneditor/application/persistence.py +163 -0
  46. nneditor-1.0.0/src/nneditor/application/session.py +1253 -0
  47. nneditor-1.0.0/src/nneditor/application/slices.py +284 -0
  48. nneditor-1.0.0/src/nneditor/application/statistics_store.py +89 -0
  49. nneditor-1.0.0/src/nneditor/artifact_formats.py +35 -0
  50. nneditor-1.0.0/src/nneditor/assets/favicon.png +0 -0
  51. nneditor-1.0.0/src/nneditor/assets/icons/apple-touch-icon-192.png +0 -0
  52. nneditor-1.0.0/src/nneditor/assets/icons/icon-192.png +0 -0
  53. nneditor-1.0.0/src/nneditor/assets/icons/icon-512.png +0 -0
  54. nneditor-1.0.0/src/nneditor/assets/icons/icon-maskable-192.png +0 -0
  55. nneditor-1.0.0/src/nneditor/assets/icons/icon-maskable-512.png +0 -0
  56. nneditor-1.0.0/src/nneditor/assets/manifest.json +35 -0
  57. nneditor-1.0.0/src/nneditor/assets/nneditor.ico +0 -0
  58. nneditor-1.0.0/src/nneditor/assets/nneditor.png +0 -0
  59. nneditor-1.0.0/src/nneditor/cancellation.py +44 -0
  60. nneditor-1.0.0/src/nneditor/desktop/__init__.py +21 -0
  61. nneditor-1.0.0/src/nneditor/desktop/windows_associations.py +252 -0
  62. nneditor-1.0.0/src/nneditor/diagnostics.py +526 -0
  63. nneditor-1.0.0/src/nneditor/editing/__init__.py +12 -0
  64. nneditor-1.0.0/src/nneditor/editing/commands.py +1259 -0
  65. nneditor-1.0.0/src/nneditor/editing/cow.py +182 -0
  66. nneditor-1.0.0/src/nneditor/editing/diff.py +219 -0
  67. nneditor-1.0.0/src/nneditor/editing/revisions.py +572 -0
  68. nneditor-1.0.0/src/nneditor/editing/validation.py +868 -0
  69. nneditor-1.0.0/src/nneditor/input_generation.py +464 -0
  70. nneditor-1.0.0/src/nneditor/ir/__init__.py +6 -0
  71. nneditor-1.0.0/src/nneditor/ir/capabilities.py +595 -0
  72. nneditor-1.0.0/src/nneditor/ir/core.py +644 -0
  73. nneditor-1.0.0/src/nneditor/ir/identity.py +201 -0
  74. nneditor-1.0.0/src/nneditor/ir/schema.py +189 -0
  75. nneditor-1.0.0/src/nneditor/ir/serialize.py +518 -0
  76. nneditor-1.0.0/src/nneditor/py.typed +0 -0
  77. nneditor-1.0.0/src/nneditor/rendering/__init__.py +34 -0
  78. nneditor-1.0.0/src/nneditor/rendering/contract.py +121 -0
  79. nneditor-1.0.0/src/nneditor/rendering/flet_canvas.py +210 -0
  80. nneditor-1.0.0/src/nneditor/rendering/flet_canvas_managed.py +341 -0
  81. nneditor-1.0.0/src/nneditor/rendering/flet_shapes.py +278 -0
  82. nneditor-1.0.0/src/nneditor/rendering/hit_testing.py +63 -0
  83. nneditor-1.0.0/src/nneditor/rendering/scene.py +362 -0
  84. nneditor-1.0.0/src/nneditor/rendering/spatial.py +170 -0
  85. nneditor-1.0.0/src/nneditor/rendering/synthetic.py +202 -0
  86. nneditor-1.0.0/src/nneditor/storage/__init__.py +6 -0
  87. nneditor-1.0.0/src/nneditor/storage/cache.py +191 -0
  88. nneditor-1.0.0/src/nneditor/storage/paths.py +53 -0
  89. nneditor-1.0.0/src/nneditor/storage/reader.py +376 -0
  90. nneditor-1.0.0/src/nneditor/storage/store.py +451 -0
  91. nneditor-1.0.0/src/nneditor/tracing/__init__.py +117 -0
  92. nneditor-1.0.0/src/nneditor/tracing/comparison.py +244 -0
  93. nneditor-1.0.0/src/nneditor/tracing/contracts.py +453 -0
  94. nneditor-1.0.0/src/nneditor/tracing/inputs.py +433 -0
  95. nneditor-1.0.0/src/nneditor/tracing/runner.py +220 -0
  96. nneditor-1.0.0/src/nneditor/tracing/store.py +408 -0
  97. nneditor-1.0.0/src/nneditor/tracing/trace_worker.py +271 -0
  98. nneditor-1.0.0/src/nneditor/tracing/visualization.py +253 -0
  99. nneditor-1.0.0/src/nneditor/transformations/__init__.py +59 -0
  100. nneditor-1.0.0/src/nneditor/transformations/calibration.py +118 -0
  101. nneditor-1.0.0/src/nneditor/transformations/engine.py +942 -0
  102. nneditor-1.0.0/src/nneditor/transformations/schema.py +308 -0
  103. nneditor-1.0.0/src/nneditor/ui/__init__.py +1 -0
  104. nneditor-1.0.0/src/nneditor/ui/app.py +4982 -0
  105. nneditor-1.0.0/src/nneditor/ui/input_workspace.py +934 -0
  106. nneditor-1.0.0/src/nneditor/ui/overview.py +478 -0
  107. nneditor-1.0.0/src/nneditor/ui/shell_layout.py +353 -0
  108. nneditor-1.0.0/src/nneditor/ui/tensor_tools.py +130 -0
  109. nneditor-1.0.0/src/nneditor/ui/trace_graph.py +253 -0
  110. nneditor-1.0.0/src/nneditor/ui/viewmodel.py +437 -0
@@ -0,0 +1,42 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ .mypy_cache/
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ .coverage
8
+ htmlcov/
9
+
10
+ # Internal planning and assistant state
11
+ .claude/
12
+ .codex/
13
+ *.md
14
+ !/README.md
15
+
16
+ # Environments and builds
17
+ .venv/
18
+ .package-venv/
19
+ build/
20
+ dist/
21
+ *.egg-info/
22
+
23
+ # Flet
24
+ .flet/
25
+
26
+ # Editors and operating systems
27
+ .idea/
28
+ .vscode/
29
+ .DS_Store
30
+ Thumbs.db
31
+
32
+ # NNEditor local state and model artifacts
33
+ .nneditor/
34
+ *.onnx
35
+ *.onnx.data
36
+ *.safetensors
37
+
38
+ # Generated benchmark artifacts
39
+ benchmarks/results/
40
+
41
+ # Documentation generator is not part of the release source tree.
42
+ tools/render_docs.py
@@ -0,0 +1,318 @@
1
+ Metadata-Version: 2.4
2
+ Name: nneditor
3
+ Version: 1.0.0
4
+ Summary: A scalable, capability-aware neural-network viewer and editor.
5
+ Author-email: Imed Bouazizi <ibouazizi@gmail.com>
6
+ Keywords: flet,jax,machine-learning,model-editor,neural-network,onnx,pruning,pytorch,quantization,visualization
7
+ Classifier: Development Status :: 5 - Production/Stable
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Classifier: Topic :: Software Development :: User Interfaces
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: <3.15,>=3.12
20
+ Requires-Dist: flet[all]==0.86.4
21
+ Requires-Dist: numpy<3,>=1.26
22
+ Requires-Dist: onnx<2,>=1.22
23
+ Requires-Dist: pillow<13,>=10
24
+ Description-Content-Type: text/markdown
25
+
26
+ <p align="center">
27
+ <img src="assets/icons/nneditor.png" alt="NNEditor icon" width="128">
28
+ </p>
29
+
30
+ <h1 align="center">NNEditor</h1>
31
+
32
+ <p align="center">
33
+ Inspect, understand, edit, optimize, and trace neural-network artifacts
34
+ without loading an entire model into memory or executing artifact-provided
35
+ code.
36
+ </p>
37
+
38
+ NNEditor 1.0 is a capability-aware neural-network workspace for ONNX, PyTorch,
39
+ safetensors, and textual StableHLO artifacts. It combines semantic graph
40
+ navigation, lazy tensor access, reversible editing, validated export, and
41
+ desktop activation tracing in one application.
42
+
43
+ ## NNEditor in action
44
+
45
+ These screenshots come from a real desktop session with the 2,364-operator
46
+ `detr-resnet-50.onnx` model. The trace used the included fox image tensor and an
47
+ automatically generated all-valid pixel mask. It reached the approved 256 MiB
48
+ capture bound, so NNEditor reported an honest partial result while retaining
49
+ 2,364 readable activations.
50
+
51
+ ### Navigate a model by architecture
52
+
53
+ ![DETR ResNet-50 architecture overview in NNEditor](assets/screenshots/architecture-overview.jpg)
54
+
55
+ ### Run a bounded activation trace
56
+
57
+ ![Partial DETR ResNet-50 activation trace with 2,364 readable values](assets/screenshots/trace-results.jpg)
58
+
59
+ ### Open activation data in a large view
60
+
61
+ ![Large activation overlay for a traced DETR tensor](assets/screenshots/activation-overlay.jpg)
62
+
63
+ ## Highlights
64
+
65
+ - Navigate large graphs through architecture, block, layer, and operator views.
66
+ - Detect attention, feed-forward, convolutional, repeated, and structural
67
+ regions with retained evidence and explanations.
68
+ - Read embedded and external tensors lazily through bounded byte ranges.
69
+ - Inspect tensor metadata, decoded previews, heatmaps, streaming statistics,
70
+ and paged hexadecimal data.
71
+ - Apply reversible graph and tensor changes without modifying the source
72
+ artifact.
73
+ - Save only when needed through a dirty-aware top-bar action, or close the
74
+ current model without quitting the application.
75
+ - Generate safe `.npy` test inputs from images, masks, CSV data, synthetic
76
+ time series, or generic tensor patterns, then assign them to model inputs.
77
+ - Preview quantization and pruning before committing them.
78
+ - Export validated ONNX revisions or clearly labelled weights-only artifacts.
79
+ - Trace ONNX activations in an isolated desktop worker and inspect values by
80
+ clicking nodes, blocks, connections, inputs, or outputs.
81
+ - Explain every unavailable action through an explicit artifact capability
82
+ contract.
83
+
84
+ ## Supported artifacts
85
+
86
+ NNEditor identifies artifacts by their contents, not only by their extension.
87
+ The table describes the built-in readers and the strongest release-level
88
+ workflow available for each artifact.
89
+
90
+ | Artifact | Inspection | Editing | Export | Activation tracing |
91
+ |:--|:--|:--|:--|:--|
92
+ | ONNX model, including external data | Graphs, weights, metadata | Validated graph and tensor subset | ONNX with validation and provenance | Available on desktop |
93
+ | PyTorch exported program | Graph, parameters, buffers, constraints | Parameter and buffer bytes | Weights-only safetensors | Unavailable |
94
+ | PyTorch state dictionary | Weights and tensor metadata | Tensor-level changes | Weights-only artifact | Unavailable |
95
+ | PyTorch FX graph module | Partial topology and metadata | Unavailable | Unavailable | Unavailable |
96
+ | Safetensors | Weights and header metadata | Tensor-level changes | Safetensors | Unavailable |
97
+ | Flax or Orbax checkpoint | Weights and tensor metadata | Tensor-level changes | Weights-only artifact | Unavailable |
98
+ | Textual StableHLO | Functions, regions, operations, attributes | Inspection only | Unavailable | Unavailable |
99
+
100
+ Support is intentionally capability-specific. For example, opening a checkpoint
101
+ does not imply that NNEditor can reconstruct a model graph, and reading
102
+ StableHLO does not imply that NNEditor can write the dialect back. Unavailable
103
+ actions explain the format-specific reason directly in the interface.
104
+
105
+ ## Installation
106
+
107
+ NNEditor requires Python 3.12, 3.13, or 3.14.
108
+
109
+ ```bash
110
+ python -m pip install nneditor==1.0.0
111
+ ```
112
+
113
+ Start the desktop application with either command:
114
+
115
+ ```bash
116
+ nneditor
117
+ ```
118
+
119
+ ```bash
120
+ python -m nneditor
121
+ ```
122
+
123
+ Open a model directly from the command line:
124
+
125
+ ```bash
126
+ nneditor path/to/model.onnx
127
+ ```
128
+
129
+ On Windows, select **File types** in the top bar to register NNEditor for
130
+ `.onnx`, `.pb`, `.pt2`, `.pt`, `.pth`, `.ckpt`, `.bin`, `.safetensors`,
131
+ `.mlir`, and `.stablehlo` files. NNEditor then opens Windows Default apps,
132
+ where you choose which extensions should launch it. Registration is per-user
133
+ and never replaces a protected Windows default without that explicit choice.
134
+
135
+ ## First run
136
+
137
+ 1. Select **Open model** and choose a supported artifact. NNEditor detects its
138
+ format from the file contents.
139
+ 2. Start in the architecture view, then open a block or change the detail level
140
+ to move through blocks, layers, and operators.
141
+ 3. Select a node to inspect its ports, attributes, weights, and capability
142
+ information.
143
+ 4. Use search, breadcrumbs, the hierarchy explorer, keyboard navigation, and
144
+ the minimap to move around large models.
145
+ 5. Prepare edits or transformations in the left panel. NNEditor validates a
146
+ preview before enabling **Commit**.
147
+ 6. After a commit, **Save changes…** appears in the top bar. Select it to
148
+ export the current revision to a new destination; it disappears after a
149
+ successful save and returns after another change.
150
+ 7. Select **Close model** to release the current artifact and return to the
151
+ start screen without quitting NNEditor.
152
+
153
+ The opened source remains unchanged throughout this workflow. A recovered
154
+ sidecar revision is treated as unsaved and offers **Save changes…** immediately.
155
+
156
+ Large imports, statistics, exports, and traces run as cancellable background
157
+ jobs. The interface reports partial or unavailable data instead of presenting
158
+ it as complete.
159
+
160
+ ## Activation tracing
161
+
162
+ Desktop tracing is available for ONNX models:
163
+
164
+ 1. Open **Generate test input** to resize an image, create a mask, convert
165
+ numeric CSV/time-series data, synthesize a signal, or create a generic
166
+ tensor. Select a model input and use **Generate, save & assign** to return
167
+ directly to that input node. You can also click the tensor-picker button
168
+ inside an input node and choose an existing safe NumPy `.npy` tensor.
169
+ Required `*_mask` inputs left unchanged use an automatically generated
170
+ all-valid mask; other inputs use deterministic random data.
171
+ 2. Open **Trace activations**, review the input specification and the
172
+ wall-clock, memory, capture, and chunk limits.
173
+ 3. Select **Approve & run trace**. This click creates an approval bound to the
174
+ current model, inputs, and limits for that run only.
175
+ 4. Click any operator, semantic block, visible connection, model input, or model
176
+ output. NNEditor automatically builds the corresponding bounded activation
177
+ views and shows them in the inspector.
178
+ 5. Select **Open large view** on an activation card for a scrollable overlay
179
+ containing its histogram, line view, heatmap, feature-map grid, or attention
180
+ view, as applicable.
181
+
182
+ Ready-made image and time-series tensors are available in
183
+ [examples/trace-inputs](examples/trace-inputs).
184
+
185
+ Input tensors are checked against the model's declared dtype and shape.
186
+ Approval is created only when **Approve & run trace** is selected, so a changed
187
+ input or limit cannot reuse stale consent. The UI captures graph inputs and
188
+ operator outputs by default so inspection does not depend on the selection that
189
+ was active when the trace began.
190
+
191
+ Tracing uses the ONNX reference evaluator in a separate, resource-limited
192
+ process. A failed or cancelled run publishes no trace. Desktop subprocess
193
+ isolation is not a multi-tenant security boundary, so tracing is disabled in
194
+ the browser application until a dedicated worker service is available.
195
+
196
+ ## Editing and optimization
197
+
198
+ ### Validated ONNX editing
199
+
200
+ The 1.0 release supports a deliberately bounded entry-graph edit surface:
201
+
202
+ - rename nodes;
203
+ - edit supported scalar and list attributes;
204
+ - replace compatible operators;
205
+ - insert or remove validated unary operators;
206
+ - reconnect compatible inputs; and
207
+ - replace same-length tensor byte ranges.
208
+
209
+ Every change is prepared as a transaction, checked against the graph and ONNX
210
+ schema, and committed as a reversible revision. Undo, redo, recovery, diff
211
+ previews, and export provenance use the same revision chain.
212
+
213
+ ### Quantization and pruning
214
+
215
+ NNEditor can preview and commit:
216
+
217
+ - 8-bit signed or unsigned, symmetric or asymmetric weight conversion;
218
+ - per-tensor and per-channel quantization;
219
+ - portable ONNX QuantizeLinear/DequantizeLinear insertion;
220
+ - threshold, mask, and exact `N:M` logical pruning; and
221
+ - a shape-proven terminal `MatMul` channel-pruning pattern.
222
+
223
+ The UI distinguishes a mathematical conversion from storage reduction or
224
+ runtime acceleration. Logical sparsity alone is never advertised as a smaller
225
+ or faster model.
226
+
227
+ ## Safety and data integrity
228
+
229
+ NNEditor is safe-artifact-first:
230
+
231
+ - Import parses artifact bytes without importing or executing Python stored in
232
+ the artifact.
233
+ - Pickle-based PyTorch containers are inspected through a restricted,
234
+ non-executing reader.
235
+ - Source artifacts are immutable and identified by cryptographic content
236
+ hashes.
237
+ - External tensor files are verified before their bytes are used.
238
+ - Tensor reads, caches, statistics, capture storage, and writes are bounded.
239
+ - Unsupported or ambiguous edits are rejected rather than approximated.
240
+ - Exports are staged, validated, and published as new artifacts.
241
+ - Inference requires explicit per-run approval and enforced resource limits.
242
+
243
+ ## Large-model design
244
+
245
+ NNEditor avoids eager model materialization during normal inspection. Its ONNX
246
+ reader indexes protobuf wire ranges directly, tensor storage uses range reads
247
+ and bounded caches, and semantic graph levels keep the visible working set
248
+ manageable. The renderer is behind a toolkit-neutral contract and uses culling,
249
+ persistent shapes, and deterministic aggregation.
250
+
251
+ These choices make ordinary navigation responsive without pretending that an
252
+ unaggregated view containing tens of thousands of visible operators is cheap.
253
+
254
+ ## Platform support
255
+
256
+ The desktop application targets:
257
+
258
+ - 64-bit Windows 10 and 11;
259
+ - macOS 12 or newer; and
260
+ - Debian 10–12 and Ubuntu 20.04, 22.04, and 24.04 LTS.
261
+
262
+ CI exercises Python 3.12, 3.13, and 3.14 on Linux and Python 3.14 on Windows.
263
+ The dynamic Flet browser application supports model inspection and editing, but
264
+ desktop-only tracing and browser multi-file export packaging remain unavailable.
265
+ Mobile packaging is outside the 1.0 release.
266
+
267
+ ## Known boundaries
268
+
269
+ - Structural editing is limited to validated ONNX entry-graph cases.
270
+ - Custom or unknown operator schemas may be inspected but are not guessed
271
+ during editing or tracing.
272
+ - PyTorch graph re-serialization and ONNX conversion are not included.
273
+ - Textual StableHLO is inspection-only.
274
+ - Weights-only exports do not contain executable topology.
275
+ - Browser tracing is disabled pending multi-user worker isolation.
276
+ - The original Python, module definitions, and training code cannot be
277
+ reconstructed from serialized artifacts.
278
+
279
+ ## Development
280
+
281
+ The development environment is managed with
282
+ [uv](https://docs.astral.sh/uv/):
283
+
284
+ ```bash
285
+ uv sync --locked --group dev
286
+ ```
287
+
288
+ Run the desktop application:
289
+
290
+ ```bash
291
+ uv run flet run src/main.py
292
+ ```
293
+
294
+ Run the browser application:
295
+
296
+ ```bash
297
+ uv run flet run --web src/main.py
298
+ ```
299
+
300
+ Run the release quality gates:
301
+
302
+ ```bash
303
+ uv run ruff format --check .
304
+ uv run ruff check .
305
+ uv run mypy
306
+ uv run pytest -m "not performance" \
307
+ --cov=nneditor \
308
+ --cov-report=term-missing \
309
+ --cov-fail-under=90
310
+ uv run pytest -m performance tests/performance
311
+ ```
312
+
313
+ Build and validate the distributions:
314
+
315
+ ```bash
316
+ uv build --clear
317
+ uvx twine check --strict dist/*
318
+ ```
@@ -0,0 +1,293 @@
1
+ <p align="center">
2
+ <img src="assets/icons/nneditor.png" alt="NNEditor icon" width="128">
3
+ </p>
4
+
5
+ <h1 align="center">NNEditor</h1>
6
+
7
+ <p align="center">
8
+ Inspect, understand, edit, optimize, and trace neural-network artifacts
9
+ without loading an entire model into memory or executing artifact-provided
10
+ code.
11
+ </p>
12
+
13
+ NNEditor 1.0 is a capability-aware neural-network workspace for ONNX, PyTorch,
14
+ safetensors, and textual StableHLO artifacts. It combines semantic graph
15
+ navigation, lazy tensor access, reversible editing, validated export, and
16
+ desktop activation tracing in one application.
17
+
18
+ ## NNEditor in action
19
+
20
+ These screenshots come from a real desktop session with the 2,364-operator
21
+ `detr-resnet-50.onnx` model. The trace used the included fox image tensor and an
22
+ automatically generated all-valid pixel mask. It reached the approved 256 MiB
23
+ capture bound, so NNEditor reported an honest partial result while retaining
24
+ 2,364 readable activations.
25
+
26
+ ### Navigate a model by architecture
27
+
28
+ ![DETR ResNet-50 architecture overview in NNEditor](assets/screenshots/architecture-overview.jpg)
29
+
30
+ ### Run a bounded activation trace
31
+
32
+ ![Partial DETR ResNet-50 activation trace with 2,364 readable values](assets/screenshots/trace-results.jpg)
33
+
34
+ ### Open activation data in a large view
35
+
36
+ ![Large activation overlay for a traced DETR tensor](assets/screenshots/activation-overlay.jpg)
37
+
38
+ ## Highlights
39
+
40
+ - Navigate large graphs through architecture, block, layer, and operator views.
41
+ - Detect attention, feed-forward, convolutional, repeated, and structural
42
+ regions with retained evidence and explanations.
43
+ - Read embedded and external tensors lazily through bounded byte ranges.
44
+ - Inspect tensor metadata, decoded previews, heatmaps, streaming statistics,
45
+ and paged hexadecimal data.
46
+ - Apply reversible graph and tensor changes without modifying the source
47
+ artifact.
48
+ - Save only when needed through a dirty-aware top-bar action, or close the
49
+ current model without quitting the application.
50
+ - Generate safe `.npy` test inputs from images, masks, CSV data, synthetic
51
+ time series, or generic tensor patterns, then assign them to model inputs.
52
+ - Preview quantization and pruning before committing them.
53
+ - Export validated ONNX revisions or clearly labelled weights-only artifacts.
54
+ - Trace ONNX activations in an isolated desktop worker and inspect values by
55
+ clicking nodes, blocks, connections, inputs, or outputs.
56
+ - Explain every unavailable action through an explicit artifact capability
57
+ contract.
58
+
59
+ ## Supported artifacts
60
+
61
+ NNEditor identifies artifacts by their contents, not only by their extension.
62
+ The table describes the built-in readers and the strongest release-level
63
+ workflow available for each artifact.
64
+
65
+ | Artifact | Inspection | Editing | Export | Activation tracing |
66
+ |:--|:--|:--|:--|:--|
67
+ | ONNX model, including external data | Graphs, weights, metadata | Validated graph and tensor subset | ONNX with validation and provenance | Available on desktop |
68
+ | PyTorch exported program | Graph, parameters, buffers, constraints | Parameter and buffer bytes | Weights-only safetensors | Unavailable |
69
+ | PyTorch state dictionary | Weights and tensor metadata | Tensor-level changes | Weights-only artifact | Unavailable |
70
+ | PyTorch FX graph module | Partial topology and metadata | Unavailable | Unavailable | Unavailable |
71
+ | Safetensors | Weights and header metadata | Tensor-level changes | Safetensors | Unavailable |
72
+ | Flax or Orbax checkpoint | Weights and tensor metadata | Tensor-level changes | Weights-only artifact | Unavailable |
73
+ | Textual StableHLO | Functions, regions, operations, attributes | Inspection only | Unavailable | Unavailable |
74
+
75
+ Support is intentionally capability-specific. For example, opening a checkpoint
76
+ does not imply that NNEditor can reconstruct a model graph, and reading
77
+ StableHLO does not imply that NNEditor can write the dialect back. Unavailable
78
+ actions explain the format-specific reason directly in the interface.
79
+
80
+ ## Installation
81
+
82
+ NNEditor requires Python 3.12, 3.13, or 3.14.
83
+
84
+ ```bash
85
+ python -m pip install nneditor==1.0.0
86
+ ```
87
+
88
+ Start the desktop application with either command:
89
+
90
+ ```bash
91
+ nneditor
92
+ ```
93
+
94
+ ```bash
95
+ python -m nneditor
96
+ ```
97
+
98
+ Open a model directly from the command line:
99
+
100
+ ```bash
101
+ nneditor path/to/model.onnx
102
+ ```
103
+
104
+ On Windows, select **File types** in the top bar to register NNEditor for
105
+ `.onnx`, `.pb`, `.pt2`, `.pt`, `.pth`, `.ckpt`, `.bin`, `.safetensors`,
106
+ `.mlir`, and `.stablehlo` files. NNEditor then opens Windows Default apps,
107
+ where you choose which extensions should launch it. Registration is per-user
108
+ and never replaces a protected Windows default without that explicit choice.
109
+
110
+ ## First run
111
+
112
+ 1. Select **Open model** and choose a supported artifact. NNEditor detects its
113
+ format from the file contents.
114
+ 2. Start in the architecture view, then open a block or change the detail level
115
+ to move through blocks, layers, and operators.
116
+ 3. Select a node to inspect its ports, attributes, weights, and capability
117
+ information.
118
+ 4. Use search, breadcrumbs, the hierarchy explorer, keyboard navigation, and
119
+ the minimap to move around large models.
120
+ 5. Prepare edits or transformations in the left panel. NNEditor validates a
121
+ preview before enabling **Commit**.
122
+ 6. After a commit, **Save changes…** appears in the top bar. Select it to
123
+ export the current revision to a new destination; it disappears after a
124
+ successful save and returns after another change.
125
+ 7. Select **Close model** to release the current artifact and return to the
126
+ start screen without quitting NNEditor.
127
+
128
+ The opened source remains unchanged throughout this workflow. A recovered
129
+ sidecar revision is treated as unsaved and offers **Save changes…** immediately.
130
+
131
+ Large imports, statistics, exports, and traces run as cancellable background
132
+ jobs. The interface reports partial or unavailable data instead of presenting
133
+ it as complete.
134
+
135
+ ## Activation tracing
136
+
137
+ Desktop tracing is available for ONNX models:
138
+
139
+ 1. Open **Generate test input** to resize an image, create a mask, convert
140
+ numeric CSV/time-series data, synthesize a signal, or create a generic
141
+ tensor. Select a model input and use **Generate, save & assign** to return
142
+ directly to that input node. You can also click the tensor-picker button
143
+ inside an input node and choose an existing safe NumPy `.npy` tensor.
144
+ Required `*_mask` inputs left unchanged use an automatically generated
145
+ all-valid mask; other inputs use deterministic random data.
146
+ 2. Open **Trace activations**, review the input specification and the
147
+ wall-clock, memory, capture, and chunk limits.
148
+ 3. Select **Approve & run trace**. This click creates an approval bound to the
149
+ current model, inputs, and limits for that run only.
150
+ 4. Click any operator, semantic block, visible connection, model input, or model
151
+ output. NNEditor automatically builds the corresponding bounded activation
152
+ views and shows them in the inspector.
153
+ 5. Select **Open large view** on an activation card for a scrollable overlay
154
+ containing its histogram, line view, heatmap, feature-map grid, or attention
155
+ view, as applicable.
156
+
157
+ Ready-made image and time-series tensors are available in
158
+ [examples/trace-inputs](examples/trace-inputs).
159
+
160
+ Input tensors are checked against the model's declared dtype and shape.
161
+ Approval is created only when **Approve & run trace** is selected, so a changed
162
+ input or limit cannot reuse stale consent. The UI captures graph inputs and
163
+ operator outputs by default so inspection does not depend on the selection that
164
+ was active when the trace began.
165
+
166
+ Tracing uses the ONNX reference evaluator in a separate, resource-limited
167
+ process. A failed or cancelled run publishes no trace. Desktop subprocess
168
+ isolation is not a multi-tenant security boundary, so tracing is disabled in
169
+ the browser application until a dedicated worker service is available.
170
+
171
+ ## Editing and optimization
172
+
173
+ ### Validated ONNX editing
174
+
175
+ The 1.0 release supports a deliberately bounded entry-graph edit surface:
176
+
177
+ - rename nodes;
178
+ - edit supported scalar and list attributes;
179
+ - replace compatible operators;
180
+ - insert or remove validated unary operators;
181
+ - reconnect compatible inputs; and
182
+ - replace same-length tensor byte ranges.
183
+
184
+ Every change is prepared as a transaction, checked against the graph and ONNX
185
+ schema, and committed as a reversible revision. Undo, redo, recovery, diff
186
+ previews, and export provenance use the same revision chain.
187
+
188
+ ### Quantization and pruning
189
+
190
+ NNEditor can preview and commit:
191
+
192
+ - 8-bit signed or unsigned, symmetric or asymmetric weight conversion;
193
+ - per-tensor and per-channel quantization;
194
+ - portable ONNX QuantizeLinear/DequantizeLinear insertion;
195
+ - threshold, mask, and exact `N:M` logical pruning; and
196
+ - a shape-proven terminal `MatMul` channel-pruning pattern.
197
+
198
+ The UI distinguishes a mathematical conversion from storage reduction or
199
+ runtime acceleration. Logical sparsity alone is never advertised as a smaller
200
+ or faster model.
201
+
202
+ ## Safety and data integrity
203
+
204
+ NNEditor is safe-artifact-first:
205
+
206
+ - Import parses artifact bytes without importing or executing Python stored in
207
+ the artifact.
208
+ - Pickle-based PyTorch containers are inspected through a restricted,
209
+ non-executing reader.
210
+ - Source artifacts are immutable and identified by cryptographic content
211
+ hashes.
212
+ - External tensor files are verified before their bytes are used.
213
+ - Tensor reads, caches, statistics, capture storage, and writes are bounded.
214
+ - Unsupported or ambiguous edits are rejected rather than approximated.
215
+ - Exports are staged, validated, and published as new artifacts.
216
+ - Inference requires explicit per-run approval and enforced resource limits.
217
+
218
+ ## Large-model design
219
+
220
+ NNEditor avoids eager model materialization during normal inspection. Its ONNX
221
+ reader indexes protobuf wire ranges directly, tensor storage uses range reads
222
+ and bounded caches, and semantic graph levels keep the visible working set
223
+ manageable. The renderer is behind a toolkit-neutral contract and uses culling,
224
+ persistent shapes, and deterministic aggregation.
225
+
226
+ These choices make ordinary navigation responsive without pretending that an
227
+ unaggregated view containing tens of thousands of visible operators is cheap.
228
+
229
+ ## Platform support
230
+
231
+ The desktop application targets:
232
+
233
+ - 64-bit Windows 10 and 11;
234
+ - macOS 12 or newer; and
235
+ - Debian 10–12 and Ubuntu 20.04, 22.04, and 24.04 LTS.
236
+
237
+ CI exercises Python 3.12, 3.13, and 3.14 on Linux and Python 3.14 on Windows.
238
+ The dynamic Flet browser application supports model inspection and editing, but
239
+ desktop-only tracing and browser multi-file export packaging remain unavailable.
240
+ Mobile packaging is outside the 1.0 release.
241
+
242
+ ## Known boundaries
243
+
244
+ - Structural editing is limited to validated ONNX entry-graph cases.
245
+ - Custom or unknown operator schemas may be inspected but are not guessed
246
+ during editing or tracing.
247
+ - PyTorch graph re-serialization and ONNX conversion are not included.
248
+ - Textual StableHLO is inspection-only.
249
+ - Weights-only exports do not contain executable topology.
250
+ - Browser tracing is disabled pending multi-user worker isolation.
251
+ - The original Python, module definitions, and training code cannot be
252
+ reconstructed from serialized artifacts.
253
+
254
+ ## Development
255
+
256
+ The development environment is managed with
257
+ [uv](https://docs.astral.sh/uv/):
258
+
259
+ ```bash
260
+ uv sync --locked --group dev
261
+ ```
262
+
263
+ Run the desktop application:
264
+
265
+ ```bash
266
+ uv run flet run src/main.py
267
+ ```
268
+
269
+ Run the browser application:
270
+
271
+ ```bash
272
+ uv run flet run --web src/main.py
273
+ ```
274
+
275
+ Run the release quality gates:
276
+
277
+ ```bash
278
+ uv run ruff format --check .
279
+ uv run ruff check .
280
+ uv run mypy
281
+ uv run pytest -m "not performance" \
282
+ --cov=nneditor \
283
+ --cov-report=term-missing \
284
+ --cov-fail-under=90
285
+ uv run pytest -m performance tests/performance
286
+ ```
287
+
288
+ Build and validate the distributions:
289
+
290
+ ```bash
291
+ uv build --clear
292
+ uvx twine check --strict dist/*
293
+ ```