You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Trim ONNX attention heads + MLP slots per layer (not just sparsify)
The streaming ONNX exporter gated both head trimming (compile.py:1034)
and MLP-slot trimming (1079) behind `on_layer_compiled is None`, but the
ONNX path always installs a streaming callback — so every ONNX compile
skipped both trims and emitted full-width (128-head) layers, merely
zeroing the unused heads/slots. The KV cache and MatMuls stayed full.
Fix: trim each layer inside `_make_stream_layer_weights_cb` — the one
chokepoint all 3 callsites flow through — before reading `attn.n_heads`
and before the tensors are nulled. `used_heads` and the per-slot weights
are already populated by write_attn_sublayer/write_mlp_sublayer when the
callback fires, so both trims see final counts. Gated by a new
`trim_heads` param on the factory, threaded through both exporters;
`trim_heads=False` keeps today's full-width sparsified model.
Downstream is already per-layer-ready (per_layer_n_heads sizes every
emitted tensor + ValueInfo; OnnxTokenRuntime discovers heads from
past_K shapes), so no runtime change. Post-loop in-process trims and
their guards are unchanged (corrected the false comments that claimed
the streaming sparse export already dropped zeros). Added a verbose
"Head pruning (ONNX)" summary to both exporters.
Tests: rewrote test_streaming_trim docstring (the ordering regression
stays); added 4 tests to test_headless_onnx — KV cache shrinks per-layer
+ non-uniform, full width preserved under trim_heads=False, MLP W1 slots
shrink, and a trim-vs-no-trim numerical no-op (only all-zero
heads/slots removed). Full torchwright + torchwright_doom suites green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0 commit comments