ConceptStablesince v0.4.0

Fingerprinting

Deterministic, portable identity for models, datasets, prompts, and environments. Fingerprints are the primitive every other NeuronScope guarantee is built on.

Audience: All usersRead: 10 minEdit on GitHub Source

A fingerprint is a short, content-addressed identifier for a NeuronScope object. Two fingerprints are equal if and only if the two objects would produce byte-identical recorded artifacts under the same runtime contract. Every model, dataset, prompt, environment, and experiment carries a fingerprint, and every artifact stores the fingerprints of its inputs.

Why fingerprints exist

Interpretability workflows re-run the same computation many times: across seeds, across commits, across machines, across weeks. The single most common failure mode is silent drift — the input looks identical but is not, and the resulting comparison is meaningless. Fingerprints turn "looks identical" into a checkable property.

  • Comparability. A layer-wise diff between two experiments is only defined when their model, dataset, and prompt fingerprints match.
  • Caching. The recorder skips work whose inputs are already fingerprinted into a cached artifact.
  • Provenance. Every .nsz artifact carries the fingerprints of its inputs, so a downstream reader can verify what was recorded without re-executing the original code.

The shape of a fingerprint

A fingerprint is a 32-byte BLAKE3 digest, rendered as a 64-character lowercase hex string with a two-character namespace prefix. The namespace tells the reader which canonicalizer produced the digest.

·text
fp:model:b3c2f0a1e8d7a2c6b91af4d0e5c7a1b0f3d2c9e8a1b4c5d6e7f8091a2b3c4d5e

Computing a fingerprint

Every fingerprintable object exposes a .fingerprint() method that returns the string above. The library also exposes a top-level helper for the common case of fingerprinting an arbitrary Python object that implements the protocol.

fingerprint_example.py·
·python
import neuronscope as ns
from transformers import AutoModel

model = AutoModel.from_pretrained("google-bert/bert-base-uncased")

fp_model  = ns.fingerprint(model)
fp_prompt = ns.fingerprint(ns.Prompt("The quick brown fox"))
fp_env    = ns.fingerprint(ns.Environment.current())

print(fp_model)
# fp:model:b3c2f0a1e8d7a2c6b91af4d0e5c7a1b0f3d2c9e8a1b4c5d6e7f8091a2b3c4d5e

Canonicalization rules

Every namespace has its own canonicalizer. The rules are deliberately narrow so that unrelated changes to a model or dataset do not change its fingerprint.

Model canonicalization

  • Parameter tensors are hashed in parameter-name order, not module traversal order.
  • Tensor bytes are hashed in row-major, native-dtype form after a fixed endianness cast.
  • Buffer tensors (running means, RNG state) are included. Optimizer state is not.
  • Non-persistent modules and hooks are excluded.

Dataset canonicalization

  • Row order is normalised via a stable sort on the row's canonical bytes.
  • Streaming datasets are fingerprinted over their schema and generator identity, not their materialised rows — see the ADR for the trade-off.

Environment canonicalization

  • Only fields that materially affect numeric output are hashed: Python version, framework versions, BLAS provider, CUDA/ROCm version, and hardware family.
  • The wall-clock, hostname, and user are not in the digest.

Stability contract

Comparing fingerprints

Fingerprints are opaque strings; compare them with ==. Higher-level helpers exist for the common case of asserting a match at the top of a script.

compare.py·
·python
import neuronscope as ns

ns.assert_matches(model_a, model_b, kind="model")
# raises FingerprintMismatch with a diff summary when they differ

Pitfalls

  1. In-place mutation. If you fingerprint a model, then callmodel.eval(), then fingerprint it again, the digest may change ifeval() flips a persistent buffer.
  2. Non-deterministic dataset order. A dataset built from a Python setwill have a different fingerprint on every process. Use an ordered container.
  3. Framework upgrades. Upgrading PyTorch across a minor version can change the environment fingerprint even if your code is identical. This is intentional — the numeric results may differ.
Related