NNx
Lightweight PyTorch training, evaluation, and visualization with first-class graph neural network support.
Transparent orchestration for durable experiments, with your models and step logic left in your hands.
NNx is a lightweight PyTorch toolkit for repeatable training, evaluation, and visualization. It owns the routine experiment infrastructure: frozen configuration objects, supervised train/eval/predict orchestration, callbacks, schedulers, metrics, and content-addressed checkpoints that support reliable resume and inspection. Models and per-step logic remain replaceable, so the same loop can serve standard networks, graph neural networks, transformers, diffusion, representation learning, fine-tuning, and multi-optimizer workflows. Focused modules add PEFT, quantization, pruning, model surgery, embeddings, export, and diagnostics without forcing those concerns into the core loop. NNx is aimed at researchers and engineers who want transparent PyTorch code and durable experiments without adopting a larger training platform.
1. Overview
NNx owns the boilerplate around supervised training so you can focus on the model: it builds the network from frozen-dataclass configs, runs the train / eval / predict loop, manages checkpoints under a content-addressed runs/<id>/ directory, dispatches a documented Callback lifecycle, and exposes pluggable extension points for fine-tuning, multi-optimizer training, diffusion, alternative training paradigms, and parameter-efficient fine-tuning.
1.1. Architecture
The architecture separates user-facing orchestration, per-batch extension hooks, callback lifecycle, and persisted run artifacts.
Reading the diagram top-to-bottom (summary):
- User code instantiates
NNModel(supervised) orTrainer(multi-optimizer for GAN / actor-critic). - The
train_step_fn/eval_step_fn/trainer_step_fnhooks are the training extension bus.diffusion,paradigms,quantize, andembeddingsprovide hook-compatible factories;_step_helperssupplies shared step finalization. The remaining specialization packages provide model transforms (finetune,peft,prune,surgery), exchange formats (interop), inference utilities (generation), and diagnostics (viz) that compose around the loop rather than injecting hooks. - The Training-loop internals run per-batch step hooks inside the data loop, then
_step_schedulerand_save_checkpointsonce per completed epoch; paradigm/diffusion step factories additionally route throughfinalize_step(NaN guard + grad-clip). - The Callback bus fires
on_train_begin / on_epoch_begin / on_epoch_end / on_train_endto every registered listener (EarlyStopping,LRMonitor,ModelCheckpoint,TensorBoardCallback,WandbCallback). - After
on_epoch_end,NNRunandNNCheckpointcommit durable state in order: history → LAST → phase/BEST → deferred callback checkpoints.
See docs/concepts.md §1 for the full 8-layer breakdown.
1.2. Capabilities at a glance
- Generic training loop — callbacks, early stopping, schedulers (
Schedulersenum:REDUCE_LR_ON_PLATEAU/STEP/COSINE_ANNEALING/ONE_CYCLE/LINEAR_WARMUP_DECAY), AMP, gradient clipping, gradient accumulation, seeded reproducibility, custom metrics. - Content-addressed persistence —
NNRunsavesrun.yaml+idps.csv+metadata.yamlunderruns/<id>/(whereidis the md5 ofstate()). LAST is the epoch commit marker: failed LAST writes roll history back, while failures in later ancillary tags retain the committed history/LAST pair.NNRun.load()truncates history newer than LAST after an interrupted process.NNCheckpointsaves FIRST / Q1 / Q2 / Q3 / LAST / BEST with generation-addressed training-state sidecars for warm resume. train_step_fnhook — swap the per-batch supervised step for any user-supplied function. Unblocks autoencoder / VAE / link-prediction / recommendation / diffusion / KD / SimCLR / Mixup / CutMix paradigms without modifying NNx internals.- Fine-tuning (transfer learning) —
nnx.finetune.{freeze, unfreeze, load_pretrained, NNParamGroupSpec, build_param_groups}plusNNModel.{freeze, unfreeze, export_state_dict}. Glob-pattern layer freezing, external state-dict loading with optional key remapping, per-layer-group learning rates viaNNOptimParams.param_groups. - Multi-optimizer
Trainer—nnx.trainer.TrainerparallelsNNModel.train()for scenarios that need disjoint optimizers (GAN G/D, actor-critic). Accepts a name-keyed dict ofNNOptimParams; each entry'sNNParamGroupSpecscopes the optimizer under strict-partition semantics. - Diffusion (DDPM) —
nnx.diffusion.{NoiseSchedulers, DiffusionMLP, diffusion_train_step_factory, sample}. LINEAR / COSINE noise schedules, a small conditional MLP denoiser, a DDPM-style training step factory that plugs into thetrain_step_fnhook, and a reverse-diffusion sampler. - Training paradigms —
nnx.paradigms.{kd, feature_kd, simclr, mixup, cutmix, moe, jepa, dpo}_train_step_factoryplusborn_again_train. Hinton-style knowledge distillation (teacher frozen, soft+hard loss mix), FitNets-style feature distillation (feature_kd_train_step_factoryadds an MSE term between named teacher/student intermediate activations via forward hooks, mixed in withbeta), SimCLR contrastive (NT-Xent loss exposed), Mixup and CutMix batch augmentation, sparse top-k Mixture-of-Experts (softmax-gated routing + Switch-style load-balancing aux loss + drop-innnx.MoELinear), I-JEPA self-supervised pretraining (masked patches → latent prediction against an EMA target encoder; ships withJEPAPredictor,build_target_encoder,update_ema,random_block_mask, and a smallViTNNencoder), Born-Again Networks (iterated self-distillation across G generations), and DPO (Rafailov et al. 2023 — preference-pair fine-tuning against a frozen reference policy via the chosen-vs-rejected log-ratio objective). All share an internal_step_helpers.finalize_stepfor grad-clip + NaN guard. - Parameter-efficient fine-tuning (PEFT) — LoRA + DoRA + IA3 + Prefix + Prompt + Adapters —
nnx.peft.{LoRALinear, apply_lora_to, save_lora_weights, load_lora_weights, AdapterLayer, DoRALinear, apply_dora_to, IA3Linear, apply_ia3_to, save_ia3_weights, load_ia3_weights, PrefixTuner, PromptTuner, save_prefix_weights, load_prefix_weights, save_prompt_weights, load_prompt_weights}. LoRA wrapsnn.Linearsubmodules in-place with a frozen base + trainable low-rank residual (B is zero-initialized so output at step 0 equals the pretrained behavior). DoRA (Liu et al., 2024) extends LoRA with a trainable per-output-row magnitude vector using onlyout_featuresextra parameters per layer. IA3 (NeurIPS 2022) is the smallest adapter in the family: a single learned per-output-dim scaling vector applied to a frozen Linear's output. PrefixTuner prepends a learned key/value prefix to every attention layer of a frozenTransformerNN; PromptTuner prepends learned soft-prompt embeddings ahead of the input tokens.save_*_weightspersist only the trainable delta for each method. - Quantization — torchao-based PTQ INT8 weight-only via
nnx.quantize.quantize_int8(model)(one call, no calibration data, no retraining; returns a newNNModelwhosenet.Linearweights are stored in int8 per-channel with FP32 activations; the quantized model still ONNX-exports) and QAT 8da4w viannx.quantize.{qat_train_step_factory, QATLifecycleCallback}(Int8DynActInt4WeightQATQuantizer fake-quant during training, real-quant on convert). Opt-in extra:pip install thekaveh-nnx[quantize]. - Pruning —
nnx.prune.magnitude_prune(mask-based unstructured, checkpoint-safe) andnnx.prune.semi_structured_24(2:4 semi-structured via torchao, Ampere+ hardware speedups). - Model surgery — Net2Net + drop + low-rank + embedding —
nnx.surgery.{widen, deepen, drop_layer, low_rank_factorize, expand_embedding}.widenanddeepenare function-preserving Net2Net edits (Chen/Goodfellow/Shlens, ICLR 2016) — the surged module's forward output matches the original's before refinement, soNNModel.train()can resume immediately without an accuracy cliff.low_rank_factorizeis SVD truncation on a Linear (exact at max rank, Eckart-Young-bounded below it).drop_layerreplaces a named layer withnn.Identity;expand_embeddinggrows an Embedding's row count and returns a frozen-mask for the original rows. Every primitive returns a freshnn.Moduleand composes withNNModel.train()for the "refine after surgery" loop. - Embeddings — contrastive trainer + FAISS export —
nnx.embeddings.{ContrastiveTextDataset, train_contrastive, embed_texts, text_contrastive_train_step_factory, export_to_faiss, export_to_safetensors}. Train a domain-specific text embedder from(anchor, positive)pairs via the existing NT-Xent machinery, then export to a FAISS index file that any RAG framework (LangChain / LlamaIndex / Haystack / raw FAISS) can consume. NNx's job ends at the FAISS index — chunking / reranking / prompt orchestration live downstream. Optional dep:pip install "thekaveh-nnx[embeddings]"forfaiss-cpu+sentence-transformers. - Networks —
FeedFwdNN,FeedFwdMoENN,ConvNN,GraphConvNN/GraphSageNN/GraphAttNN(all built on the sharedGraphNNBase),TransformerNN(decoder-only LM: RMSNorm + RoPE + SwiGLU + tied embeddings + KV-cache), andViTNN(small ViT encoder used as the I-JEPA backbone). - Language modeling (opt-in via
thekaveh-nnx[lm]) —TransformerNN+NNTransformerParams+NNTokenizerParams(HF Rust BPE wrapper) +GenerativeNNModel.generate(prompt, ...)with KV-cache acceleration for autoregressive decoding. A CPU regression test requires cached decoding to be at least 1.2× faster than full recomputation for its fixed 128-token workload; results on other hardware and workloads vary. Pastmax_seq_len, the cache rebuilds per step and converges to full-recompute cost. Greedy / top-k / top-p / repetition-penalty sampling is provided through aLogitsProcessorchain. See docs/lm.md for the full walkthrough;examples/11_tinystories_lm.pyships an end-to-end TinyStories-class training run. - Experimental GGUF export (opt-in via
thekaveh-nnx[gguf-write]) —nnx.interop.write_gguf(model, tokenizer, path)writes a structurally valid GGUF artifact with NNx tensor names andgeneral.architecture=nnx_transformer. Stock llama.cpp, Ollama, and LM Studio do not implement that architecture; use the output for inspection or a reader explicitly patched for NNx. See docs/gguf.md. - HuggingFace Hub (opt-in via
thekaveh-nnx[hub]) —NNModelmixes inPyTorchModelHubMixin:save_pretrained/push_to_hub/from_pretrained, with safetensors as an opt-in checkpoint format viaNNCheckpoint.to_file(format="safetensors"). See docs/hub.md. - Datasets —
NNDataset(torchvisionVisionDatasetwrapper),NNGraphDataset(PyG single-graph wrapper usingNeighborLoader),NNTabularDataset(pandas DataFrame → train/val/test loaders),NNPreferenceDataset(tokenized(prompt, chosen, rejected)preference triples for DPO). - Params — frozen, kw-only, slotted dataclasses for every config knob:
NNParams,NNModelParams,NNTrainParams,NNOptimParams,NNSchedulerParams,NNTrainerParams. Every params object round-trips throughstate()/from_state(). New fields omit themselves fromstate()when at their default so existingrun.idhashes are preserved. - Fluent params construction —
NNSchedulerParams.builder(),NNOptimParams.builder(),NNTransformerParams.builder(), andNNTrainerParams.builder()(the composite, wraps the prior two for the multi-optim Trainer) expose variant-gated.adam(...)/.sgd(...)/.one_cycle(...)/ etc. methods so the user can't construct an invalid kind/field combination.LogitsChain.builder()extends the pattern to the LM-decoding path — chain custom logit processors in any order; the Builder sorts them into NNx's canonical order (matchinggenerate()'s inline-kwargs chain) before decoding runs. All Builders are purely additive; the existing direct-kwarg ctors keep working. - Enums-as-factories —
Nets,Losses,Optims,Schedulers,Activations,Devices,Checkpoints,NoiseSchedulers. Each enum value's__call__constructs the underlying object; adding a new option is a single-place change. - Callbacks —
Callbackbase class withon_{train,epoch}_{begin,end}hooks. Stock:EarlyStopping,LRMonitor,ModelCheckpoint(custom-epoch tags),TensorBoardCallback(opt-in viathekaveh-nnx[tensorboard]),WandbCallback(opt-in viathekaveh-nnx[wandb]). LegacyCallable[[List[IDP]], None]is still accepted. - Visualization —
VisUtils(and module-level aliases) returns PlotlyFigureobjects:confusion_matrix,classification_report(returns a DataFrame),multi_line_plot,scatter_plot,two_dim_tsne_checkpoint_logits. - Model-internals viz —
nnx.viz.summary(Keras-style parameter table viatorchinfo),nnx.viz.weight_histogram(per-layer Plotly histogram grid),nnx.viz.activation_map(forward-hook activation heatmaps),nnx.viz.attribute(Captum-backed input attribution:integrated_gradients/gradient_shap/deep_lift/saliency/input_x_gradient/occlusion, returns the attribution tensor plus a Plotly heatmap),nnx.viz.gradient_flow(per-layer L2 gradient-norm bar chart for vanishing/exploding diagnostics, call afterloss.backward()), andnnx.viz.netron_export(write the underlying network to a.onnxartifact for Netron). Companion to the existingnnx.vis_utilsrun-output viz; opt-in viapip install thekaveh-nnx[viz](pullstorchinfo+captum; the Netron browser viewer isthekaveh-nnx[viz-interactive]). - Reproducibility + training diagnostics —
nnx.set_seed(seed, strict=False)pins every RNG + cuDNN;nnx.dataloader_worker_init_fnhandles per-worker seeds;NNTrainParams.seedrunsset_seedattrain()entry.nnx.lr_finder(model, train_loader, *, loss_fn, ...)runs a fastai-style exponential LR sweep and returns the Smith-2017 suggested one-cyclemax_lrplus a Plotly figure; the sweep restores model state, every module's train/eval mode, loader generators, and Python/NumPy/PyTorch RNG state on exit. - Type-checked downstream — NNx ships a PEP 561
py.typedmarker so consumers'pyright/mypyhonor the public-surface annotations onNNModel, the params dataclasses, callbacks, and enums (rather than seeing every symbol asAny). - ONNX export —
NNModel.to_onnx(path, example_input)exports the network via the legacytorch.onnx.export(noonnxscriptdep needed). Passdynamo=True(opt-in viathekaveh-nnx[onnx-dynamo]) to dispatch through PyTorch's newertorch.export-based exporter (default in torch>=2.9; supports >2 GB models via external data; generally faster).
2. Install
2.1. Runtime
pip install thekaveh-nnx # latest release from PyPI
Python 3.10+. Tested on 3.10 through 3.14. Examples in examples/ are runnable on CPU.
2.2. Optional extras
pip install "thekaveh-nnx[tensorboard]" # TensorBoardCallback
pip install "thekaveh-nnx[wandb]" # WandbCallback
pip install "thekaveh-nnx[onnx]" # NNModel.to_onnx validation tooling
pip install "thekaveh-nnx[onnx-dynamo]" # NNModel.to_onnx(dynamo=True) — torch.export-based exporter
pip install "thekaveh-nnx[quantize]" # nnx.quantize_int8 (torchao PTQ INT8)
pip install "thekaveh-nnx[hub]" # safetensors checkpoints + HuggingFace Hub publish/load
pip install "thekaveh-nnx[embeddings]" # nnx.embeddings: FAISS export + sentence-transformers
pip install "thekaveh-nnx[lm]" # TransformerNN + HF tokenizer + generate()
pip install "thekaveh-nnx[gguf-write]" # experimental NNx GGUF writer
pip install "thekaveh-nnx[viz]" # nnx.viz: summary + weight_histogram + activation_map + attribute + gradient_flow + netron_export
pip install "thekaveh-nnx[viz-interactive]" # adds Netron browser viewer for nnx.viz.netron_export(launch=True)
pip install "thekaveh-nnx[docs]" # local documentation build toolchain
For a reproducible contributor environment, install with the committed resolver state:
python -m pip install -r requirements-tools.txt
uv sync --all-extras --frozen
For local development (editable install from a git checkout, including the test/lint toolchain), see CONTRIBUTING.md §1.
3. Quickstart
End-to-end CPU example — a tiny random-tensor classification run:
import torch
from torch.utils.data import DataLoader, TensorDataset
from nnx import (
NNModel, NNParams, NNModelParams, NNTrainParams,
NNOptimParams, NNSchedulerParams,
Activations, Devices, Losses, Nets, Optims,
EarlyStopping,
)
# 1. Data
X_train, y_train = torch.randn(256, 8), torch.randint(0, 3, (256,))
X_val, y_val = torch.randn(64, 8), torch.randint(0, 3, (64,))
train_loader = DataLoader(TensorDataset(X_train, y_train), batch_size=32, shuffle=True)
val_loader = DataLoader(TensorDataset(X_val, y_val), batch_size=32)
# 2. Model
net_params = NNParams(input_dim=8, output_dim=3, hidden_dims=[32, 16],
dropout_prob=0.1, activation=Activations.RELU)
model_params = NNModelParams(net=Nets.FEED_FWD, device=Devices.CPU,
loss=Losses.CROSS_ENTROPY)
model = NNModel(net_params=net_params, params=model_params)
# 3. Train
train_params = NNTrainParams(
n_epochs=10,
train_loader=train_loader,
val_loader=val_loader,
optim=NNOptimParams(name=Optims.ADAM, max_lr=1e-2,
momentum=(0.9, 0.999), weight_decay=5e-5),
scheduler=NNSchedulerParams(min_lr=1e-7, factor=0.5,
patience=3, cooldown=1, threshold=1e-3),
)
run = model.train(params=train_params, callbacks=[EarlyStopping(patience=5)])
# 4. Use it
print(f"trained {len(run.idps)} iterations; saved under runs/{run.id}/")
logits, classes = model.predict(X=X_val.numpy()) # returns PredictResult(logits=..., classes=...)
4. Advanced patterns
4.1. Switching networks
Change the Nets enum value passed to NNModelParams; NNModel constructs the underlying network for you:
NNModelParams(net=Nets.GRAPH_CONV, device=Devices.CPU, loss=Losses.CROSS_ENTROPY)
NNModelParams(net=Nets.GRAPH_SAGE, device=Devices.CPU, loss=Losses.CROSS_ENTROPY)
NNModelParams(net=Nets.GRAPH_ATT, device=Devices.CPU, loss=Losses.CROSS_ENTROPY)
# Then pass NNParams(..., n_heads=4) for GRAPH_ATT.
# Use NNGraphDataset (PyG NeighborLoader-backed) to feed batches.
See examples/ for runnable end-to-end scripts.
4.2. Reproducibility
from nnx import set_seed, dataloader_worker_init_fn
set_seed(42) # pins torch / numpy / python / cudnn
DataLoader(..., worker_init_fn=dataloader_worker_init_fn)
NNTrainParams(seed=42, ...) # pins again at train() entry
4.3. Warm-resume training
run = model.train(params=NNTrainParams(n_epochs=10, ...))
# Build a fresh NNModel and continue from run's LAST checkpoint
# (optimizer topology/state, scheduler, scaler, epoch, loader generators,
# and Python/NumPy/PyTorch CPU/CUDA/MPS RNG state preserved):
NNModel(net_params=..., params=...).train(params=NNTrainParams(
n_epochs=10,
resume_from_run_id=run.id,
resume_from_checkpoint="last", # or "best" / "first" / "q1" / "q2" / "q3"
...
))
Scope: Loader and sampler generators are restored by stable seed identity. Exact continuation still requires
train_loader.num_workers=0, because worker-local RNG state cannot be reconstructed. Warm-resume is supported for the supervisedNNModel.train()path.nnx.trainer.Trainer(multi-optimizer) does not yet ship per-optimizer sidecars.
4.4. Custom metrics
NNTrainParams(
...,
extra_metrics={
"my_metric": lambda y, y_hat: float((y == y_hat).mean()),
},
)
# Available on idp.train_edp.extra / idp.val_edp.extra and survives NNRun.load.
4.5. Visualization
from nnx import VisUtils
fig = VisUtils.confusion_matrix(y_true, y_pred, class_names=["a","b","c"])
fig.show()
df = VisUtils.classification_report(y_true, y_pred) # DataFrame
4.6. Auto device detection
from nnx import Devices
NNModelParams(net=Nets.FEED_FWD, device=Devices.get(), loss=Losses.CROSS_ENTROPY)
# Devices.get() picks MPS (Apple) > CUDA > CPU.
4.7. Mixed precision (CUDA)
NNModelParams(..., mixed_precision=True) # silently no-op on CPU/MPS
4.8. Scheduler choices
By default the scheduler is ReduceLROnPlateau driven by the params dataclass. Pass kind= to switch:
from nnx import Schedulers
NNSchedulerParams(..., kind=Schedulers.COSINE_ANNEALING, T_max=100)
# Or: STEP, ONE_CYCLE, LINEAR_WARMUP_DECAY
4.9. Loading a run
from nnx import NNRun, NNCheckpoint, Checkpoints
run = NNRun.load(id="<md5>") # rehydrate idps + params
ckpt = NNCheckpoint.load(run=run.id, type=Checkpoints.BEST)
model = NNModel.from_checkpoint(checkpoint=ckpt)
from_checkpoint also replays persisted topology transforms before loading weights. In particular, QAT-produced LAST checkpoints record their torchao recipe and reload as converted quantized models without downstream prepare/convert code.
5. Documentation
The documentation below covers the public API, architecture, extension contracts, and runnable examples.
5.1. Conceptual + reference
- Concepts — architecture deep-dive, persistence layout, callback protocol, every specialization in detail. Read this when you want to understand how the pieces fit together (callbacks, params hashing, train_step_fn hook, multi-optim Trainer, paradigms, PEFT).
- Quickstart — paste-runnable example with variations. Read this when you want to copy a working snippet and iterate from there.
- Language modeling — the decoder-only Transformer path:
TransformerNN+ HF tokenizer +GenerativeNNModel.generate()with KV-cache. Read this when you want to train a tiny LM end-to-end on CPU. - Direct Preference Optimization —
dpo_train_step_factoryfor fine-tuning a TransformerNN against(prompt, chosen, rejected)preference pairs via the Rafailov et al. 2023 chosen-vs-rejected log-ratio objective against a frozen reference policy. Read this when you have preference data and want to steer LM behavior post-SFT without reward modeling or RL. - I-JEPA — Joint Embedding Predictive Architecture: masked-patch → latent-prediction self-supervised pretraining against an EMA target encoder. Read this when you want to pretrain a vision encoder without pixel-reconstruction or strong augmentations.
- Experimental GGUF export —
nnx.interop.write_gguffor producing and inspecting an NNx-tagged GGUF artifact; includes the official llama.cppllama-quantizebuild path and the current stock-runtime limitation. - HuggingFace Hub — safetensors checkpoints +
save_pretrained/push_to_hub/from_pretrainedonNNModel. Read this when you want to publish a trained model to the Hub, load from it, or write checkpoints in a format outside-of-Python tools (ComfyUI, vLLM, AutoGPTQ) can read. - Embeddings + FAISS export — walkthrough for training a domain-specific text embedder via contrastive learning and exporting it to a FAISS index for any RAG stack to consume.
- Model surgery — walkthrough of the
nnx.surgeryprimitives (widen/deepen/drop_layer/low_rank_factorize/expand_embedding), the function-preservation contract, before/after parameter-count tables, and the "load checkpoint → surgery → refine viaNNModel.train()→ save" pattern. - API reference — signatures and docstrings for public symbols.
- Comparison vs Lightning / HF / fastai / Composer — honest scope-explicit comparison: when to use NNx vs Lightning vs HF Transformers vs fastai vs MosaicML Composer, axis by axis. Read this when you're picking a PyTorch training toolkit and want a real decision matrix instead of a marketing page.
- Architecture — the system overview and exact training lifecycle, including callback, scheduler, history, and checkpoint ordering.
- External dependency contracts — ledger of optional integrations, version sources, verification coverage, and intentionally gated real-service checks. Read this before changing dependency ranges, external CLI commands, or publish workflows.
5.2. Workflow + history
- Examples catalog — ordered tour of the 26 runnable scripts under
examples/, grouped foundational to specialized (core loop, fine-tuning, paradigms, quantization, embeddings, language modeling, GGUF inspection, self-supervised learning, pruning, surgery, explainability, DPO, and distillation variants). - Test import boundaries — when tests should use the public facade and when a deep implementation import is intentional.
- Contributing — setup, back-compat invariants, test policy, the omit-when-default rule for params, what we will and won't merge.
- Security policy — supported versions, private vulnerability reporting, and the checkpoint trust boundary.
- Changelog — release history (Keep-a-Changelog format), back-compat migration notes, and on-disk run.id hash shifts when they occur.
6. Project
6.1. Status
Alpha. API is stable for the existing thekaveh/ml notebook consumer; pre-1.0 means we'll fix obvious bugs (see CHANGELOG) without renaming public APIs unless they're broken in ways notebooks can't work around.
6.2. Contributing
Bug reports and PRs are welcome via GitHub issues. See CONTRIBUTING.md for setup, verification, and the complete style guide.
6.3. License
Apache License 2.0. Copyright 2026 Kaveh Razavi. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file thekaveh_nnx-0.2.2.tar.gz.
File metadata
- Download URL: thekaveh_nnx-0.2.2.tar.gz
- Upload date:
- Size: 572.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d23a30367903109ebd2098f05c9a63fe3219ff157c905f62696c6479cefae70c
|
|
| MD5 |
f5392e812c53b1ccf37bf764e96d2e64
|
|
| BLAKE2b-256 |
caba007476996bd24beaf91c07b53aad9bf7a8abd8b53bebe23ae967f41a8f06
|
Provenance
The following attestation bundles were made for thekaveh_nnx-0.2.2.tar.gz:
Publisher:
release.yml on thekaveh/NNx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
thekaveh_nnx-0.2.2.tar.gz -
Subject digest:
d23a30367903109ebd2098f05c9a63fe3219ff157c905f62696c6479cefae70c - Sigstore transparency entry: 2387721782
- Sigstore integration time:
-
Permalink:
thekaveh/NNx@1f5483be6eadd5973dc80b41ecb9e018541a72eb -
Branch / Tag:
refs/heads/main - Owner: https://github.com/thekaveh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1f5483be6eadd5973dc80b41ecb9e018541a72eb -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file thekaveh_nnx-0.2.2-py3-none-any.whl.
File metadata
- Download URL: thekaveh_nnx-0.2.2-py3-none-any.whl
- Upload date:
- Size: 317.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee56474926fdfd5329721f067cf1b8ae31955627c6949844e09ee4a7bb2bb9d7
|
|
| MD5 |
4a58a39d20273f4a0a1268e6d352f0cb
|
|
| BLAKE2b-256 |
3389e35b6a6bd8df877a33d79c1265ee29461e92e962dd08eabf2c0f42ade65e
|
Provenance
The following attestation bundles were made for thekaveh_nnx-0.2.2-py3-none-any.whl:
Publisher:
release.yml on thekaveh/NNx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
thekaveh_nnx-0.2.2-py3-none-any.whl -
Subject digest:
ee56474926fdfd5329721f067cf1b8ae31955627c6949844e09ee4a7bb2bb9d7 - Sigstore transparency entry: 2387721790
- Sigstore integration time:
-
Permalink:
thekaveh/NNx@1f5483be6eadd5973dc80b41ecb9e018541a72eb -
Branch / Tag:
refs/heads/main - Owner: https://github.com/thekaveh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1f5483be6eadd5973dc80b41ecb9e018541a72eb -
Trigger Event:
workflow_dispatch
-
Statement type: