Skip to content

How it works

The audit pipeline from model loading to verdict.

An audit is a controlled experiment. The only variable is the model. Everything else, inputs, dtype, device, decoding, and statistics, is held fixed.

flowchart LR
    A[Base model] --> P[Fingerprints and audit id]
    B[Derivative model] --> P
    P --> C[Identical inputs]
    C --> D[Capability scoring]
    C --> E[Over refusal generation]
    C --> F[Token level KL]
    D --> G[Paired bootstrap]
    E --> G
    F --> H[One sample bootstrap]
    G --> I[Verdict]
    H --> I
    I --> J[report.json and report.html]
    J --> K[Proof hashes]

Pipeline

0. Fingerprint, check and name the audit

Both models' weights, tokenizers and chat templates are hashed. Modeldiffr checks that the pair can be compared fairly, chooses how generation prompts are rendered, and computes the audit id from everything that defines the experiment. See Fingerprints and proof.

1. Load both models identically

Both models load through HFBackend with the same dtype and device. Revisions can be pinned with --base-revision and --derivative-revision. Models run in eval mode with gradients disabled.

2. Score capability by log likelihood

Each multiple choice question is formatted as Question: ...\nAnswer:. Every option is scored by the summed log probability of its tokens as a continuation. The highest scoring option is the prediction. Nothing is parsed from generated text, so formatting differences between models cannot affect the score.

3. Generate for over refusal

Each benign prompt is wrapped in a chat template, or User: ...\nAssistant: when no template exists. When the two models' templates differ but their tokenizers match, both receive the prompt rendered with one template, so the text is byte identical; the hash of every rendered prompt is stored. Decoding is greedy with max_new_tokens set by the suite (64 for quick), so results are deterministic. A keyword detector classifies each response as refused or answered.

4. Measure output divergence

When both tokenizers have the same vocabulary signature (a SHA256 hash of the sorted vocab), Modeldiffr computes KL divergence from base to derivative at every token position of each neutral text and averages it. When the tokenizers differ, the metric is skipped and the report records a note.

5. Resample for confidence

Paired bootstrap resampling turns per item results into a delta with a 95% confidence interval. See Statistics.

6. Write the reports and proof

The result dict is written as report.json and rendered as a self contained report.html.

Design principles

Fair

Same inputs, same dtype, same device, same decoding. Capability is scored without answer parsing so chat formatting cannot bias the result.

Statistical

Every number carries an interval. A change is reported only when the interval excludes zero, which keeps identical models clean.

Repeatable

The bootstrap is seeded, generation is greedy, and the report stores model commits, weight fingerprints, settings, environment, and the version of Modeldiffr that produced it.

Verifiable

Every input and result is hashed into the report. modeldiffr verify recomputes the hashes and metrics, so an edited report or a swapped model is caught.

Light core

The core package imports nothing heavy. PyTorch and Transformers load lazily only when HFBackend is constructed.