NagaYu commited on
Commit
23f4eab
·
verified ·
1 Parent(s): 406065c

Seeded M/M' fixture and the gpt2 calibration band for Assay

Browse files
README.md ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ library_name: transformers
4
+ pipeline_tag: text-generation
5
+ tags:
6
+ - trustworthy-ml
7
+ - model-verification
8
+ - model-substitution
9
+ - research-fixture
10
+ - gpt2
11
+ ---
12
+
13
+ # Assay reproducibility bundle — the seeded M / M' pair and a calibrated band
14
+
15
+ This is **not a model you should generate text with.** It is the fixture that makes
16
+ [Assay](https://github.com/NagaYu/assay)'s model-substitution experiments reproducible
17
+ offline, in seconds, with no training and no downloads of anything large.
18
+
19
+ - **Code**: [github.com/NagaYu/assay](https://github.com/NagaYu/assay)
20
+ - **Demo**: [NagaYu/assay-demo](https://huggingface.co/spaces/NagaYu/assay-demo)
21
+ - **Receipt corpus**: [NagaYu/assay-receipts](https://huggingface.co/datasets/NagaYu/assay-receipts)
22
+
23
+ ## Contents
24
+
25
+ | Path | What it is |
26
+ |---|---|
27
+ | `tiny_pair/M/` | The "real" model **M**: a seeded, randomly-initialized GPT-2, 4 layers, hidden 64, vocab 256 |
28
+ | `tiny_pair/Mp/` | The "cheap" substitute **M'**: 2 layers, same hidden size and vocab, with an untied and permuted output head |
29
+ | `calibration.json` | The sketch protocol, the tolerance band calibrated on **gpt2**, and the demo HMAC key |
30
+
31
+ ## Why M' has a permuted head
32
+
33
+ This detail matters more than it looks. A randomly-initialized GPT-2 is dominated by the
34
+ residual copy of the last prompt token, so two independently seeded models both greedily echo
35
+ that token — they are *behaviourally identical*, and a "substitution" between them is one
36
+ nobody could notice in the output. Permuting the tied embedding does not help either: the
37
+ echo circuit reads and writes through the same matrix, so the permutation cancels.
38
+
39
+ So M' here has its output head **untied and permuted**. It stays a well-formed model, it
40
+ produces genuinely different text, and the substitution becomes something worth detecting.
41
+ Anything that reads the emitted tokens — including Assay's generation-consistency check and
42
+ the forgery it defends against — is meaningless without this.
43
+
44
+ ## Using it
45
+
46
+ ```python
47
+ from transformers import GPT2LMHeadModel
48
+ from huggingface_hub import snapshot_download
49
+
50
+ path = snapshot_download("NagaYu/assay-tiny-pair")
51
+ M = GPT2LMHeadModel.from_pretrained(f"{path}/tiny_pair/M").eval()
52
+ Mp = GPT2LMHeadModel.from_pretrained(f"{path}/tiny_pair/Mp").eval()
53
+ ```
54
+
55
+ The identical pair is also constructed on the fly by the library, with no download at all:
56
+
57
+ ```python
58
+ from assay.hooks import tiny_random_pair
59
+ M, Mp = tiny_random_pair(seed=0) # bit-identical to the weights published here
60
+ ```
61
+
62
+ Both are published because the copy here pins the fixture: if the constructor ever changes,
63
+ these weights still reproduce the numbers in the paper-style README and the receipt corpus.
64
+
65
+ ## `calibration.json`
66
+
67
+ The tolerance band Assay's verifier compares against, measured on honest **gpt2** traffic
68
+ with injected numerical jitter, plus the sketch protocol parameters:
69
+
70
+ ```json
71
+ {
72
+ "sketch": {"seed": ..., "layers": [3, 6, 8, 11], "n_positions": 6, "sketch_dim": 32},
73
+ "calibration": {"mu": {...}, "sigma": {...}, "gen_mismatch_rate": ...},
74
+ "verifier": {"deep_check_rate": 0.25, "alpha": 0.01}
75
+ }
76
+ ```
77
+
78
+ `gen_mismatch_rate` is the rate at which an honest greedy provider's emitted token differs
79
+ from M's own argmax at an inspected position — the null rate of the check that catches a
80
+ forged receipt. It is calibrated rather than assumed to be zero, because numerical jitter can
81
+ flip a near-tie.
82
+
83
+ The HMAC key in that file is published deliberately: without it the signatures in the receipt
84
+ corpus cannot be checked. It is a demo key for a research prototype, not a secret, and not a
85
+ TEE attestation key.
86
+
87
+ ## Intended use and limits
88
+
89
+ Intended for reproducing and probing substitution-detection experiments. These weights are
90
+ random — M and M' have never been trained and their text is meaningless. Do not use them for
91
+ anything other than the verification experiments they exist for.
92
+
93
+ ## Citation
94
+
95
+ ```bibtex
96
+ @software{assay2026,
97
+ title = {Assay: per-request internal receipts for model-substitution detection},
98
+ author = {Nagao, Yuta},
99
+ year = {2026},
100
+ url = {https://github.com/NagaYu/assay},
101
+ note = {Research prototype}
102
+ }
103
+ ```
calibration.json ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "sketch": {
3
+ "seed": 20260718,
4
+ "layers": [
5
+ 3,
6
+ 6,
7
+ 8,
8
+ 11
9
+ ],
10
+ "n_positions": 6,
11
+ "sketch_dim": 32,
12
+ "rank_top_m": 8
13
+ },
14
+ "calibration": {
15
+ "mu": {
16
+ "3": -7.309343497798924,
17
+ "6": -5.587953915026016,
18
+ "8": -5.450299438360374,
19
+ "11": -5.6453210104866685
20
+ },
21
+ "sigma": {
22
+ "3": 0.212757760417348,
23
+ "6": 0.1316980161516204,
24
+ "8": 0.0888338944598564,
25
+ "11": 0.11255746540264383
26
+ },
27
+ "n_samples": 48,
28
+ "gen_mismatch_rate": 0.01
29
+ },
30
+ "verifier": {
31
+ "deep_check_rate": 0.25,
32
+ "alpha": 0.01
33
+ },
34
+ "generation": {
35
+ "gen_len": 12,
36
+ "decoding": "greedy",
37
+ "jitter_sigma_rel": 0.0003
38
+ },
39
+ "model_m": "gpt2",
40
+ "hmac_demo_key": "assay-demo-key-0123456789abcdef!",
41
+ "signature_note": "HMAC-SHA256 over Receipt.canonical_bytes(); simulates a TEE attestation"
42
+ }
tiny_pair/M/config.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "activation_function": "gelu_new",
3
+ "add_cross_attention": false,
4
+ "architectures": [
5
+ "GPT2LMHeadModel"
6
+ ],
7
+ "attn_pdrop": 0.0,
8
+ "bos_token_id": 50256,
9
+ "dtype": "float32",
10
+ "embd_pdrop": 0.0,
11
+ "eos_token_id": 50256,
12
+ "initializer_range": 0.02,
13
+ "layer_norm_epsilon": 1e-05,
14
+ "model_type": "gpt2",
15
+ "n_embd": 64,
16
+ "n_head": 4,
17
+ "n_inner": null,
18
+ "n_layer": 4,
19
+ "n_positions": 128,
20
+ "pad_token_id": null,
21
+ "reorder_and_upcast_attn": false,
22
+ "resid_pdrop": 0.0,
23
+ "scale_attn_by_inverse_layer_idx": false,
24
+ "scale_attn_weights": true,
25
+ "summary_activation": null,
26
+ "summary_first_dropout": 0.1,
27
+ "summary_proj_to_labels": true,
28
+ "summary_type": "cls_index",
29
+ "summary_use_proj": true,
30
+ "tie_word_embeddings": true,
31
+ "transformers_version": "5.16.1",
32
+ "use_cache": true,
33
+ "vocab_size": 256
34
+ }
tiny_pair/M/generation_config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "bos_token_id": 50256,
4
+ "eos_token_id": 50256,
5
+ "output_attentions": false,
6
+ "output_hidden_states": false,
7
+ "transformers_version": "5.16.1",
8
+ "use_cache": true
9
+ }
tiny_pair/M/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e7e968601697cc5f0931a660abbb2680912e8a88cac6844b01a93eacaafac6fd
3
+ size 903456
tiny_pair/Mp/config.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "activation_function": "gelu_new",
3
+ "add_cross_attention": false,
4
+ "architectures": [
5
+ "GPT2LMHeadModel"
6
+ ],
7
+ "attn_pdrop": 0.0,
8
+ "bos_token_id": 50256,
9
+ "dtype": "float32",
10
+ "embd_pdrop": 0.0,
11
+ "eos_token_id": 50256,
12
+ "initializer_range": 0.02,
13
+ "layer_norm_epsilon": 1e-05,
14
+ "model_type": "gpt2",
15
+ "n_embd": 64,
16
+ "n_head": 4,
17
+ "n_inner": null,
18
+ "n_layer": 2,
19
+ "n_positions": 128,
20
+ "pad_token_id": null,
21
+ "reorder_and_upcast_attn": false,
22
+ "resid_pdrop": 0.0,
23
+ "scale_attn_by_inverse_layer_idx": false,
24
+ "scale_attn_weights": true,
25
+ "summary_activation": null,
26
+ "summary_first_dropout": 0.1,
27
+ "summary_proj_to_labels": true,
28
+ "summary_type": "cls_index",
29
+ "summary_use_proj": true,
30
+ "tie_word_embeddings": false,
31
+ "transformers_version": "5.16.1",
32
+ "use_cache": true,
33
+ "vocab_size": 256
34
+ }
tiny_pair/Mp/generation_config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "bos_token_id": 50256,
4
+ "eos_token_id": 50256,
5
+ "output_attentions": false,
6
+ "output_hidden_states": false,
7
+ "transformers_version": "5.16.1",
8
+ "use_cache": true
9
+ }
tiny_pair/Mp/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fd537928301388ee870cca1ebcdf400f2646972747eba57798de9b529c2d10d2
3
+ size 566952