Metadata-Version: 2.4
Name: checkpoint-lens
Version: 0.1.0
Summary: Understand what's inside a PyTorch .pt checkpoint: terminal inspection + a local, interactive 3D viewer. Local-first -- your weights never leave your machine.
Author-email: Viraj Mhadgut <virajmhadgut77@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/virajm7/checkpoint-lens
Project-URL: Repository, https://github.com/virajm7/checkpoint-lens
Project-URL: Issues, https://github.com/virajm7/checkpoint-lens/issues
Keywords: pytorch,neural-network,checkpoint,visualization,3d,inspection,interpretability
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: torch>=2.2
Requires-Dist: fastapi>=0.110
Requires-Dist: uvicorn[standard]>=0.27
Requires-Dist: pydantic>=2.6
Requires-Dist: websockets>=12.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Dynamic: license-file

# Checkpoint Lens

Give it a PyTorch `.pt` checkpoint. It tells you what's actually inside —
in your terminal, and in an interactive 3D viewer in your browser.

```bash
pip install checkpoint-lens

checkpoint-lens inspect model.pt   # terminal report
checkpoint-lens view model.pt      # local 3D viewer, opens in your browser
```

Everything runs on your machine. Your checkpoint and its weights are
never uploaded anywhere.

## Why

Loading a `.pt` file you didn't train — someone else's checkpoint, an old
one of yours without the original training code, a bare `state_dict` with
no docs — usually means writing a one-off script to poke at tensor shapes.
Checkpoint Lens does that inspection for you: it detects the architecture
from the tensors themselves (no source code required), and is explicit
about what it actually knows versus what it's guessing versus what simply
isn't recoverable from a checkpoint at all.

## What it tells you

Every fact in the report is labeled with how certain it is:

```
CONFIRMED
✓ LSTM input=11 hidden=64 num_layers=1  [rnn.rnn]
✓ Linear 64 → 128  [mlp.0]
✓ Linear 128 → 128  [mlp.2]
✓ Linear 128 → 8  [mlp.4]
✓ Parameter count: 45,618

INFERRED
~ Role: Actor/Policy (inferred from checkpoint key naming, not guaranteed)

UNKNOWN
? Original activation function (not recoverable from weights -- has no parameters)
```

- **CONFIRMED** — directly backed by a tensor shape or a key in the file.
- **INFERRED** — a reasonable deduction from naming or structure (e.g. a
  network keyed `"actor"` probably plays an actor/policy role — but that's
  a naming convention, not something the file states outright).
- **UNKNOWN** — genuinely not recoverable. Activation functions carry no
  parameters, so no checkpoint can ever confirm which one was used; live
  inference lets you pick an assumption (ELU by default), but it is always
  labeled as an assumption, never presented as fact.

Nothing is ever silently invented. If a tensor doesn't match a known
layer pattern, it's reported as unclassified rather than guessed at.

## The 3D viewer

`checkpoint-lens view model.pt` starts a local server and opens a
cinematic, interactive 3D scene built from your checkpoint's *real*
layers, neuron counts, and weights — not a generic diagram. Rotate, zoom,
click a neuron or connection for its real values, switch between networks
(Actor/Critic, or `network_0`/`network_1` if there's no naming evidence to
go on), and — when the checkpoint can be safely reconstructed into a
runnable model — feed it an observation and watch real activations light
up the scene.

## Python API

```python
from checkpoint_lens import inspect

result = inspect("model.pt")

print(result)              # the same CONFIRMED/INFERRED/UNKNOWN report as the CLI
result.networks             # per-network detail (architecture, role, param count, ...)
result.confirmed             # flat list of confirmed facts
result.inferred               # flat list of inferred facts
result.unknown                 # flat list of things that cannot be recovered
```

## What v0.1 supports

- PyTorch `.pt` files containing a `state_dict`, or a checkpoint dict
  containing one or more `state_dict`s (e.g. a PPO-style `{"actor": ...,
  "critic": ..., "optimizer_state_dict": ...}` checkpoint). Optimizer
  state is always recognized and excluded from the architecture — it's
  training data, never shown as a network layer.
- Layer detection: **Linear**, **LSTM**, **GRU**, **RNN**, plus running
  normalizer buffers (mean/var-style preprocessing stats).
- Multiple networks per checkpoint, with Actor/Critic role detection —
  **only** when the checkpoint's own key names say so (`actor`, `policy`,
  `critic`, `value`). No naming evidence means no guessed role: networks
  are exposed generically as `network_0`, `network_1`, etc.
- Optional live inference, by reconstructing a runnable model directly
  from the inferred architecture and verifying it against the checkpoint
  with a strict `load_state_dict` (if a single tensor name or shape
  doesn't match exactly, reconstruction fails loudly instead of silently
  producing a network that doesn't match the file).

**Out of scope for v0.1** (reported honestly as unclassified rather than
silently mishandled, not silently misidentified as something else):
CNNs/Conv layers beyond shape detection, ONNX, TensorFlow/Keras,
Transformers/attention, safetensors, TorchScript modules, and any
checkpoint that isn't a `state_dict` or dict-of-`state_dict`s. Also out of
scope: a Linear layer saved under a descriptive, non-indexed name (e.g. a
lone `nn.Linear` not part of a numbered `nn.Sequential`) currently has no
home in live-inference reconstruction — it's correctly detected and shown
in the architecture/weight viewer, but reconstruction fails loudly for
that network rather than guessing where it belongs. These are natural
directions for future contributions — see below.

## Contributing

The architecture-detection logic (`architecture.py`) is a sequence of
independent, shape-based pattern-matching passes (normalizer buffers →
recurrent layers → Linear → Conv → leftover affine params). Adding
support for a new layer type is a matter of adding another pass that only
claims tensors it's confident about and leaves everything else for the
next pass — the "honest by construction" design this project is built on
extends the same way to new architectures.

Local dev setup:

```bash
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest

# in one terminal: the API, on a fixed port
checkpoint-lens view path/to/model.pt --port 8010

# in another: the frontend dev server with hot reload, pointed at that API
cd frontend
echo "VITE_API_BASE_URL=http://127.0.0.1:8010" > .env.local
npm install && npm run dev
```

To rebuild the bundled viewer after a frontend change:

```bash
cd frontend && npm run build
rm -rf ../src/checkpoint_lens/web/*
cp -r dist/. ../src/checkpoint_lens/web/
```

## License

MIT
