d0rj commited on
Commit
732ec0e
·
verified ·
1 Parent(s): c72635a

Publish trained base checkpoint, evaluation confidence intervals and TensorBoard logs

Browse files
README.md ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - en
4
+ library_name: transformers
5
+ pipeline_tag: text-generation
6
+ tags:
7
+ - pretrained
8
+ - from-scratch
9
+ - tiny-llm-ablation
10
+ - custom_code
11
+ - tensorboard
12
+ - causal-lm
13
+ datasets:
14
+ - HuggingFaceFW/fineweb-edu
15
+ model-index:
16
+ - name: q-51M-base
17
+ results:
18
+ - task:
19
+ type: text-generation
20
+ name: Zero-shot continuation likelihood
21
+ dataset:
22
+ type: Rowan/hellaswag
23
+ name: HellaSwag
24
+ config: default
25
+ split: validation
26
+ args:
27
+ num_few_shot: 0
28
+ metrics:
29
+ - type: acc_norm
30
+ name: acc_norm (fraction; lm-eval 0.4.12)
31
+ value: 0.29177454690300736
32
+ args:
33
+ ci95_low: 0.28296457902614003
34
+ ci95_high: 0.3007437626650362
35
+ ci_method: Wilson
36
+ - task:
37
+ type: text-generation
38
+ name: Zero-shot continuation likelihood
39
+ dataset:
40
+ type: allenai/ai2_arc
41
+ name: ARC-Easy
42
+ config: ARC-Easy
43
+ split: test
44
+ args:
45
+ num_few_shot: 0
46
+ metrics:
47
+ - type: acc_norm
48
+ name: acc_norm (fraction; lm-eval 0.4.12)
49
+ value: 0.43308080808080807
50
+ args:
51
+ ci95_low: 0.41328092357316454
52
+ ci95_high: 0.45309672993759426
53
+ ci_method: Wilson
54
+ - task:
55
+ type: text-generation
56
+ name: Zero-shot continuation likelihood
57
+ dataset:
58
+ type: allenai/ai2_arc
59
+ name: ARC-Challenge
60
+ config: ARC-Challenge
61
+ split: test
62
+ args:
63
+ num_few_shot: 0
64
+ metrics:
65
+ - type: acc_norm
66
+ name: acc_norm (fraction; lm-eval 0.4.12)
67
+ value: 0.24232081911262798
68
+ args:
69
+ ci95_low: 0.21865689491479706
70
+ ci95_high: 0.2676684124053075
71
+ ci_method: Wilson
72
+ - task:
73
+ type: text-generation
74
+ name: Zero-shot continuation likelihood
75
+ dataset:
76
+ type: baber/piqa
77
+ name: PIQA
78
+ config: default
79
+ split: validation
80
+ args:
81
+ num_few_shot: 0
82
+ metrics:
83
+ - type: acc_norm
84
+ name: acc_norm (fraction; lm-eval 0.4.12)
85
+ value: 0.5990206746463548
86
+ args:
87
+ ci95_low: 0.5764309418644076
88
+ ci95_high: 0.6211973601030507
89
+ ci_method: Wilson
90
+ - task:
91
+ type: text-generation
92
+ name: Zero-shot continuation likelihood
93
+ dataset:
94
+ type: allenai/winogrande
95
+ name: WinoGrande
96
+ config: winogrande_xl
97
+ split: validation
98
+ args:
99
+ num_few_shot: 0
100
+ metrics:
101
+ - type: acc
102
+ name: acc (fraction; lm-eval 0.4.12)
103
+ value: 0.500394632991318
104
+ args:
105
+ ci95_low: 0.47290359623559514
106
+ ci95_high: 0.5278832839791312
107
+ ci_method: Wilson
108
+ - task:
109
+ type: text-generation
110
+ name: Zero-shot continuation likelihood
111
+ dataset:
112
+ type: allenai/openbookqa
113
+ name: OpenBookQA
114
+ config: main
115
+ split: test
116
+ args:
117
+ num_few_shot: 0
118
+ metrics:
119
+ - type: acc_norm
120
+ name: acc_norm (fraction; lm-eval 0.4.12)
121
+ value: 0.282
122
+ args:
123
+ ci95_low: 0.2443364332272433
124
+ ci95_high: 0.32298777921399346
125
+ ci_method: Wilson
126
+ - task:
127
+ type: text-generation
128
+ name: Zero-shot continuation likelihood
129
+ dataset:
130
+ type: aps/super_glue
131
+ name: BoolQ
132
+ config: boolq
133
+ split: validation
134
+ args:
135
+ num_few_shot: 0
136
+ metrics:
137
+ - type: acc
138
+ name: acc (fraction; lm-eval 0.4.12)
139
+ value: 0.598776758409786
140
+ args:
141
+ ci95_low: 0.5818706845463824
142
+ ci95_high: 0.615451027004275
143
+ ci_method: Wilson
144
+ - task:
145
+ type: text-generation
146
+ name: Zero-shot continuation likelihood
147
+ dataset:
148
+ type: EleutherAI/lambada_openai
149
+ name: LAMBADA OpenAI
150
+ config: default
151
+ split: test
152
+ args:
153
+ num_few_shot: 0
154
+ metrics:
155
+ - type: acc
156
+ name: acc (fraction; lm-eval 0.4.12)
157
+ value: 0.20861633999611875
158
+ args:
159
+ ci95_low: 0.1977414700784266
160
+ ci95_high: 0.2199253277124155
161
+ ci_method: Wilson
162
+ ---
163
+
164
+ # Q-51M Base
165
+
166
+ A **50,878,208-parameter** English base model in the **Tiny llm ablation** experiment. Trained from scratch on exactly **3,932,160,000 source tokens** over **15,000 optimizer steps**. The token count measures processed input blocks, not unique text or supervised target tokens.
167
+
168
+ ## Architecture and references
169
+
170
+ 10 decoder layers, width 512, SwiGLU width 1792, 8 query / 2 KV heads, RoPE, per-head QK normalization, gated residual branches, tied embeddings; context 2048.
171
+
172
+ Architecture and unchanged 32,768-token tokenizer: [q-project/Q-50M-Base](https://huggingface.co/q-project/Q-50M-Base). This checkpoint was trained from random initialization; it is not a fine-tune of the reference weights.
173
+
174
+ ## Training
175
+
176
+ - Data: [FineWeb-Edu](https://huggingface.co/datasets/HuggingFaceFW/fineweb-edu), `sample-10BT`, streamed from local Parquet shards; shuffle buffer 100,000.
177
+ - Objective: Causal next-token cross-entropy.
178
+ - Batch: 32 sequences × 4 accumulation × 2048 tokens = 262,144 source tokens per step.
179
+ - Fused AdamW; peak LR 0.001, betas (0.9, 0.95), weight decay 0.1 (no decay for bias/norm/1D parameters), gradient clipping 1.0. Linear warmup for 150 steps, then cosine decay to 10% of peak LR.
180
+ - BF16 compute on one RTX 5070 Ti (16 GB), seed 2026; checkpoints retain FP32 weights. [Exact training configuration](training_config.json).
181
+
182
+ ## Evaluation
183
+
184
+ Full official task splits, **zero-shot**, **lm-eval 0.4.12**, no chat template, BF16 on RTX 5070 Ti, maximum context 2048. Accuracy is a percentage. **± is one standard error; the separate bracketed column is the 95% Wilson confidence interval.** Intervals describe finite evaluation-sample uncertainty, not variation across training seeds; no multiple-comparison correction is applied.
185
+
186
+ | Dataset | Split | Examples | Metric | Score ± SE (%) | 95% CI (%) |
187
+ |---|---|---:|---|---:|---:|
188
+ | [HellaSwag](https://huggingface.co/datasets/Rowan/hellaswag) | validation | 10,042 | `acc_norm` | 29.18 ± 0.45 | [28.30, 30.07] |
189
+ | [ARC-Easy](https://huggingface.co/datasets/allenai/ai2_arc) | test | 2,376 | `acc_norm` | 43.31 ± 1.02 | [41.33, 45.31] |
190
+ | [ARC-Challenge](https://huggingface.co/datasets/allenai/ai2_arc) | test | 1,172 | `acc_norm` | 24.23 ± 1.25 | [21.87, 26.77] |
191
+ | [PIQA](https://huggingface.co/datasets/baber/piqa) | validation | 1,838 | `acc_norm` | 59.90 ± 1.14 | [57.64, 62.12] |
192
+ | [WinoGrande](https://huggingface.co/datasets/allenai/winogrande) | validation | 1,267 | `acc` | 50.04 ± 1.41 | [47.29, 52.79] |
193
+ | [OpenBookQA](https://huggingface.co/datasets/allenai/openbookqa) | test | 500 | `acc_norm` | 28.20 ± 2.01 | [24.43, 32.30] |
194
+ | [BoolQ](https://huggingface.co/datasets/aps/super_glue) | validation | 3,270 | `acc` | 59.88 ± 0.86 | [58.19, 61.55] |
195
+ | [LAMBADA OpenAI](https://huggingface.co/datasets/EleutherAI/lambada_openai) | test | 5,153 | `acc` | 20.86 ± 0.57 | [19.77, 21.99] |
196
+
197
+ Q50M uses autoregressive continuation likelihood. LAMBADA accuracy requires the complete final-word token sequence. `acc_norm` is harness length-normalized option scoring; raw accuracy is also stored in [results.json](evaluation/results.json).
198
+
199
+ **[WikiText-2 raw test](https://huggingface.co/datasets/Salesforce/wikitext), conditional continuation:** CPU FP32 re-evaluation on 291 nonoverlapping blocks (512 prefix + 512 scored suffix tokens), 148,992 scored tokens; 335 tail tokens excluded. NLL **3.560862**, 95% CI **[3.521807, 3.599507]**; token PPL **35.194**, 95% CI **[33.846, 36.580]**. Percentile block bootstrap, 10,000 resamples, seed 2026; exponentiate NLL endpoints for PPL. Blocks are the resampling unit; this does not model all within-document dependence. This is not standard rolling AR or word PPL. The earlier BF16 point is retained separately in TensorBoard, with no borrowed FP32 interval.
200
+
201
+ The metadata contains author-reported `model-index` scores. The evaluated dataset repositories had no registered `eval.yaml` on 2026-09-20, so no `.eval_results` leaderboard entry or verified badge is claimed. [Machine-readable results and provenance](evaluation/results.json).
202
+
203
+ ## Usage
204
+
205
+ Install `requirements.txt` (tested with Transformers 5.17.0 / PyTorch 2.11.0). Custom model code is included; `trust_remote_code=True` is required. This example runs on CPU.
206
+
207
+ ```python
208
+ from transformers import AutoTokenizer, AutoModelForCausalLM
209
+ repo = "d0rj/q-51M-base"
210
+ tokenizer = AutoTokenizer.from_pretrained(repo)
211
+ model = AutoModelForCausalLM.from_pretrained(repo, trust_remote_code=True).eval()
212
+ inputs = tokenizer("The capital of France is", return_tensors="pt")
213
+ output = model.generate(**inputs, max_new_tokens=64, do_sample=False)
214
+ print(tokenizer.decode(output[0], skip_special_tokens=True))
215
+ ```
216
+
217
+ To reproduce the core evaluation from a downloaded repository, install `evaluation/requirements.txt` and run:
218
+
219
+ ```bash
220
+ python evaluation/run_core.py --device cuda:0 --dtype bfloat16 --batch-size 8 --output evaluation-rerun
221
+ ```
222
+
223
+ ## TensorBoard and limitations
224
+
225
+ [TensorBoard event files](tensorboard/) include training telemetry and `eval/<task>/<metric>` at step 15,000, plus separate CI bounds. Recovered text-log telemetry covers steps 12,020–15,000 only (150 points); earlier training telemetry is unavailable. `train/loss` was corrected for the historical gradient-accumulation logging scale; `recovery/loss_as_printed` preserves the printed values.
226
+
227
+ These are small English continuation models, not instruction-tuned assistants. Equal source-token budgets do not imply equal target-token supervision or FLOPs. Benchmark contamination was not audited; results are from one training seed. Reference-model scores from different prompts, tokenizers or corpora are not directly interchangeable.
config.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Q50MForCausalLM"
4
+ ],
5
+ "attention_dropout": 0.0,
6
+ "attention_scalar_gate": true,
7
+ "bos_token_id": 1,
8
+ "dtype": "float32",
9
+ "eos_token_id": 2,
10
+ "gate_multiplier": 2.0,
11
+ "head_dim": 64,
12
+ "hidden_size": 512,
13
+ "intermediate_size": 1792,
14
+ "max_position_embeddings": 2048,
15
+ "mlp_scalar_gate": true,
16
+ "model_type": "q50m",
17
+ "nope_every_n": null,
18
+ "nope_layers": [],
19
+ "num_attention_heads": 8,
20
+ "num_hidden_layers": 10,
21
+ "num_key_value_heads": 2,
22
+ "pad_token_id": 0,
23
+ "qk_norm": true,
24
+ "rms_norm_eps": 1e-05,
25
+ "rope_theta": 10000.0,
26
+ "tie_word_embeddings": true,
27
+ "transformers_version": "5.17.0",
28
+ "vocab_size": 32768,
29
+ "auto_map": {
30
+ "AutoConfig": "configuration_q50m.Q50MConfig",
31
+ "AutoModelForCausalLM": "modeling_q50m.Q50MForCausalLM"
32
+ },
33
+ "_name_or_path": "d0rj/q-51M-base"
34
+ }
configuration_q50m.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Configuration for the Q-50M architecture (replica of q-project/Q-50M-Base).
2
+
3
+ 512-wide, 10-layer decoder with GQA (8 q / 2 kv heads), per-head QK-Norm,
4
+ content-dependent scalar residual gates on both branches, tied embeddings.
5
+ """
6
+
7
+ from transformers import PretrainedConfig
8
+
9
+
10
+ class Q50MConfig(PretrainedConfig):
11
+ model_type = "q50m"
12
+
13
+ def __init__(
14
+ self,
15
+ vocab_size: int = 32768,
16
+ hidden_size: int = 512,
17
+ intermediate_size: int = 1792,
18
+ num_hidden_layers: int = 10,
19
+ num_attention_heads: int = 8,
20
+ num_key_value_heads: int = 2,
21
+ head_dim: int = 64,
22
+ max_position_embeddings: int = 2048,
23
+ rope_theta: float = 10000.0,
24
+ rms_norm_eps: float = 1e-5,
25
+ qk_norm: bool = True,
26
+ attention_scalar_gate: bool = True,
27
+ mlp_scalar_gate: bool = True,
28
+ gate_multiplier: float = 2.0,
29
+ nope_every_n: int | None = None,
30
+ nope_layers: list[int] | None = None,
31
+ attention_dropout: float = 0.0,
32
+ tie_word_embeddings: bool = True,
33
+ bos_token_id: int = 1,
34
+ eos_token_id: int = 2,
35
+ pad_token_id: int = 0,
36
+ **kwargs,
37
+ ):
38
+ super().__init__(
39
+ tie_word_embeddings=tie_word_embeddings,
40
+ bos_token_id=bos_token_id,
41
+ eos_token_id=eos_token_id,
42
+ pad_token_id=pad_token_id,
43
+ **kwargs,
44
+ )
45
+ self.vocab_size = vocab_size
46
+ self.hidden_size = hidden_size
47
+ self.intermediate_size = intermediate_size
48
+ self.num_hidden_layers = num_hidden_layers
49
+ self.num_attention_heads = num_attention_heads
50
+ self.num_key_value_heads = num_key_value_heads
51
+ self.head_dim = head_dim
52
+ self.max_position_embeddings = max_position_embeddings
53
+ self.rope_theta = rope_theta
54
+ self.rms_norm_eps = rms_norm_eps
55
+ self.qk_norm = qk_norm
56
+ self.attention_scalar_gate = attention_scalar_gate
57
+ self.mlp_scalar_gate = mlp_scalar_gate
58
+ self.gate_multiplier = gate_multiplier
59
+ self.nope_every_n = nope_every_n
60
+ if nope_layers is not None:
61
+ self.nope_layers = list(nope_layers)
62
+ elif nope_every_n:
63
+ self.nope_layers = [
64
+ i for i in range(num_hidden_layers) if (i + 1) % nope_every_n == 0
65
+ ]
66
+ else:
67
+ self.nope_layers = []
68
+ self.attention_dropout = attention_dropout
evaluation/adapters.py ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """HF loading and an explicitly experimental masked-model adapter.
2
+
3
+ Only imported for an actual evaluation, never for planning.
4
+ """
5
+
6
+ import torch
7
+ from lm_eval.models.huggingface import HFLM
8
+ from transformers import AutoTokenizer
9
+ from tqdm import tqdm
10
+
11
+
12
+ class UL2HFLM(HFLM):
13
+ """S-denoiser continuation scoring; only answer text contributes to NLL.
14
+
15
+ Source: S + context + sentinel_0 + EOS.
16
+ Decoder input: BOS + sentinel_0 + answer[:-1]. Controls are conditioned
17
+ on, never scored; the softmax still includes the complete vocabulary.
18
+ """
19
+
20
+ def _encode_pair(self, context, continuation):
21
+ # Match causal HFLM's text boundary, without tokenizer-added controls.
22
+ spaces = len(context) - len(context.rstrip())
23
+ if spaces:
24
+ continuation = context[-spaces:] + continuation
25
+ context = context[:-spaces]
26
+ whole = self.tok_encode(context + continuation, add_special_tokens=False)
27
+ prefix = self.tok_encode(context, add_special_tokens=False)
28
+ return prefix, whole[len(prefix):]
29
+
30
+ @torch.inference_mode()
31
+ def _loglikelihood_tokens(self, requests, disable_tqdm=False, override_bs=None):
32
+ contract = self.model.config.ul2
33
+ span = contract["sentinel_ids"][0]
34
+ bos = self.model.config.decoder_start_token_id
35
+ batch_size = override_bs or self.batch_size
36
+ results = [None] * len(requests)
37
+ ordered = sorted(enumerate(requests), key=lambda x: -(len(x[1][1]) + len(x[1][2])))
38
+ for start in tqdm(range(0, len(ordered), batch_size), disable=disable_tqdm, desc="UL2 likelihood"):
39
+ batch = ordered[start:start + batch_size]
40
+ sources, decoders = [], []
41
+ for _, (_, context, answer) in batch:
42
+ if not answer or len(answer) >= self.max_length:
43
+ raise ValueError("UL2 scoring requires a nonempty answer shorter than the context limit")
44
+ budget = min(self.max_length + 1 - len(answer), self.model.config.max_position_embeddings - 3)
45
+ context = context[-budget:]
46
+ sources.append([contract["mode_ids"]["S"], *context, span, contract["eos_id"]])
47
+ decoders.append([bos, span, *answer[:-1]])
48
+
49
+ def pad(rows):
50
+ ids = torch.full((len(rows), max(map(len, rows))), contract["pad_id"], dtype=torch.long, device=self.device)
51
+ mask = torch.zeros_like(ids)
52
+ for i, row in enumerate(rows):
53
+ ids[i, :len(row)] = torch.tensor(row, device=self.device)
54
+ mask[i, :len(row)] = 1
55
+ return ids, mask
56
+
57
+ source, source_mask = pad(sources)
58
+ decoder, decoder_mask = pad(decoders)
59
+ hidden = self.model.model(input_ids=source, attention_mask=source_mask,
60
+ decoder_input_ids=decoder, decoder_attention_mask=decoder_mask,
61
+ use_cache=False).last_hidden_state
62
+ # Project only scored positions and bound temporary vocabulary logits.
63
+ for row, (index, (key, _, answer)) in enumerate(batch):
64
+ score, greedy = 0.0, True
65
+ for offset in range(0, len(answer), 256):
66
+ target = torch.tensor(answer[offset:offset + 256], device=self.device)
67
+ logits = self.model.lm_head(hidden[row, 1 + offset:1 + offset + len(target)]).float()
68
+ score += torch.log_softmax(logits, -1).gather(1, target[:, None]).sum().item()
69
+ greedy = greedy and bool((logits.argmax(-1) == target).all())
70
+ results[index] = (score, greedy)
71
+ if key is not None:
72
+ self.cache_hook.add_partial("loglikelihood", key, results[index])
73
+ return results
74
+
75
+ def loglikelihood_rolling(self, requests, disable_tqdm=False):
76
+ raise NotImplementedError("UL2 continuation likelihood is not rolling autoregressive perplexity")
77
+
78
+ def generate_until(self, requests, disable_tqdm=False):
79
+ raise NotImplementedError("UL2 benchmark adapter currently supports likelihood tasks only")
80
+
81
+
82
+ class DiffusionHFLM(HFLM):
83
+ """Continuation PLL, with other answer tokens visible.
84
+
85
+ The bool is full-token reconstruction accuracy, NOT AR exact match.
86
+ Generation uses one masked next-token slot at a time, not the model's
87
+ unconditional parallel denoiser. Both are experimental protocols.
88
+ """
89
+
90
+ @torch.inference_mode()
91
+ def _loglikelihood_tokens(self, requests, disable_tqdm=False, override_bs=None):
92
+ results = []
93
+ for cache_key, context, continuation in requests:
94
+ if not continuation:
95
+ results.append((0.0, True))
96
+ continue
97
+ if len(continuation) >= self.max_length:
98
+ raise ValueError("Diffusion PLL needs room for context and the entire continuation")
99
+ context = context[-(self.max_length - len(continuation)):]
100
+ tokens = context + continuation
101
+ base = torch.tensor([tokens], dtype=torch.long, device=self.device)
102
+ timestep = torch.tensor([1 / len(tokens)], device=self.device)
103
+ score, greedy = 0.0, True
104
+ for pos in range(len(context), len(tokens)):
105
+ masked = base.clone()
106
+ masked[0, pos] = self.model.config.mask_token_id
107
+ logits = self.model(input_ids=masked, timesteps=timestep).logits[0, pos].float()
108
+ score += torch.log_softmax(logits, dim=-1)[tokens[pos]].item()
109
+ greedy = greedy and logits.argmax().item() == tokens[pos]
110
+ result = (score, greedy)
111
+ results.append(result)
112
+ if cache_key is not None:
113
+ self.cache_hook.add_partial("loglikelihood", cache_key, result)
114
+ return results
115
+
116
+ def loglikelihood_rolling(self, requests, disable_tqdm=False):
117
+ raise NotImplementedError("Diffusion PLL must not be reported as autoregressive perplexity")
118
+
119
+ @torch.inference_mode()
120
+ def _model_generate(self, context, max_length, stop, **generation_kwargs):
121
+ if context.shape[0] != 1:
122
+ raise ValueError("Diffusion generation requires batch size 1")
123
+ if generation_kwargs.get("do_sample", False):
124
+ raise ValueError("Diffusion adapter implements greedy generation only")
125
+ sequence = context
126
+ prompt_length = context.shape[1]
127
+ while sequence.shape[1] < min(max_length, self.max_length):
128
+ slot = torch.full((1, 1), self.model.config.mask_token_id,
129
+ dtype=torch.long, device=self.device)
130
+ masked = torch.cat((sequence, slot), dim=1)
131
+ timestep = torch.tensor([1 / masked.shape[1]], device=self.device)
132
+ logits = self.model(input_ids=masked, timesteps=timestep).logits[:, -1]
133
+ predicted = logits.argmax(dim=-1, keepdim=True)
134
+ sequence = torch.cat((sequence, predicted), dim=1)
135
+ text = self.tok_decode(sequence[0, prompt_length:].tolist())
136
+ if predicted.item() == self.eot_token_id or any(s and s in text for s in stop):
137
+ break
138
+ return sequence
139
+
140
+
141
+ def load_model(plan, args):
142
+ common = dict(batch_size=args.batch_size, device=args.device, dtype=args.dtype,
143
+ max_length=args.max_length, trust_remote_code=args.trust_remote_code,
144
+ revision=args.revision)
145
+ tokenizer = AutoTokenizer.from_pretrained(
146
+ plan["tokenizer"], trust_remote_code=args.trust_remote_code,
147
+ revision=args.tokenizer_revision or args.revision,
148
+ )
149
+ if plan["local_model"] is None:
150
+ return HFLM(pretrained=plan["checkpoint"], tokenizer=tokenizer, **common)
151
+
152
+ from tiny_llm.models import MODEL_REGISTRY
153
+
154
+ entry = MODEL_REGISTRY[plan["local_model"]]
155
+ dtype = args.dtype if args.dtype == "auto" else getattr(torch, args.dtype)
156
+ # Checkpoints have no auto_map or tokenizer. Never load train_state.pt.
157
+ config = entry["config_class"].from_pretrained(plan["checkpoint"])
158
+ model = entry["model_class"].from_pretrained(plan["checkpoint"], config=config, dtype=dtype)
159
+ model.to(args.device).eval()
160
+ backend = "seq2seq" if plan["kind"] == "seq2seq" else "causal"
161
+ adapter = DiffusionHFLM if plan["kind"] == "diffusion" else HFLM
162
+ if plan["kind"] == "seq2seq" and getattr(config, "ul2", None):
163
+ adapter = UL2HFLM
164
+ return adapter(pretrained=model, tokenizer=tokenizer, backend=backend, **common)
evaluation/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ lm_eval==0.4.12
2
+ tensorboard>=2.18
evaluation/results.json ADDED
@@ -0,0 +1,554 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "d0rj/q-51M-base",
3
+ "step": 15000,
4
+ "source_tokens": 3932160000,
5
+ "core_protocol": "autoregressive likelihood",
6
+ "core_device": "RTX 5070 Ti",
7
+ "core_dtype": "bfloat16",
8
+ "harness": "lm-eval 0.4.12",
9
+ "date": "2026-09-20",
10
+ "tasks": {
11
+ "hellaswag": {
12
+ "samples": 10042,
13
+ "shots": 0,
14
+ "dataset": "Rowan/hellaswag",
15
+ "config": "default",
16
+ "split": "validation",
17
+ "metrics": {
18
+ "acc": {
19
+ "value": 0.27633937462656843,
20
+ "stderr": 0.004462727543055927,
21
+ "ci95": [
22
+ 0.2676798053353836,
23
+ 0.28516999640463647
24
+ ],
25
+ "ci_method": "Wilson score, z=1.959963984540054"
26
+ },
27
+ "acc_norm": {
28
+ "value": 0.29177454690300736,
29
+ "stderr": 0.004536500714147901,
30
+ "ci95": [
31
+ 0.28296457902614003,
32
+ 0.3007437626650362
33
+ ],
34
+ "ci_method": "Wilson score, z=1.959963984540054"
35
+ }
36
+ }
37
+ },
38
+ "arc_easy": {
39
+ "samples": 2376,
40
+ "shots": 0,
41
+ "dataset": "allenai/ai2_arc",
42
+ "config": "ARC-Easy",
43
+ "split": "test",
44
+ "metrics": {
45
+ "acc": {
46
+ "value": 0.49074074074074076,
47
+ "stderr": 0.010258024147860667,
48
+ "ci95": [
49
+ 0.47067078447639055,
50
+ 0.5108405889653497
51
+ ],
52
+ "ci_method": "Wilson score, z=1.959963984540054"
53
+ },
54
+ "acc_norm": {
55
+ "value": 0.43308080808080807,
56
+ "stderr": 0.010167478013701743,
57
+ "ci95": [
58
+ 0.41328092357316454,
59
+ 0.45309672993759426
60
+ ],
61
+ "ci_method": "Wilson score, z=1.959963984540054"
62
+ }
63
+ }
64
+ },
65
+ "arc_challenge": {
66
+ "samples": 1172,
67
+ "shots": 0,
68
+ "dataset": "allenai/ai2_arc",
69
+ "config": "ARC-Challenge",
70
+ "split": "test",
71
+ "metrics": {
72
+ "acc": {
73
+ "value": 0.197098976109215,
74
+ "stderr": 0.011625047669880649,
75
+ "ci95": [
76
+ 0.17532930720089182,
77
+ 0.22084779246346944
78
+ ],
79
+ "ci_method": "Wilson score, z=1.959963984540054"
80
+ },
81
+ "acc_norm": {
82
+ "value": 0.24232081911262798,
83
+ "stderr": 0.012521593295800071,
84
+ "ci95": [
85
+ 0.21865689491479706,
86
+ 0.2676684124053075
87
+ ],
88
+ "ci_method": "Wilson score, z=1.959963984540054"
89
+ }
90
+ }
91
+ },
92
+ "piqa": {
93
+ "samples": 1838,
94
+ "shots": 0,
95
+ "dataset": "baber/piqa",
96
+ "config": "default",
97
+ "split": "validation",
98
+ "metrics": {
99
+ "acc": {
100
+ "value": 0.6115342763873776,
101
+ "stderr": 0.011371877593210428,
102
+ "ci95": [
103
+ 0.5890412805423275,
104
+ 0.6335620266188204
105
+ ],
106
+ "ci_method": "Wilson score, z=1.959963984540054"
107
+ },
108
+ "acc_norm": {
109
+ "value": 0.5990206746463548,
110
+ "stderr": 0.011434766962108364,
111
+ "ci95": [
112
+ 0.5764309418644076,
113
+ 0.6211973601030507
114
+ ],
115
+ "ci_method": "Wilson score, z=1.959963984540054"
116
+ }
117
+ }
118
+ },
119
+ "winogrande": {
120
+ "samples": 1267,
121
+ "shots": 0,
122
+ "dataset": "allenai/winogrande",
123
+ "config": "winogrande_xl",
124
+ "split": "validation",
125
+ "metrics": {
126
+ "acc": {
127
+ "value": 0.500394632991318,
128
+ "stderr": 0.01405248130604961,
129
+ "ci95": [
130
+ 0.47290359623559514,
131
+ 0.5278832839791312
132
+ ],
133
+ "ci_method": "Wilson score, z=1.959963984540054"
134
+ }
135
+ }
136
+ },
137
+ "openbookqa": {
138
+ "samples": 500,
139
+ "shots": 0,
140
+ "dataset": "allenai/openbookqa",
141
+ "config": "main",
142
+ "split": "test",
143
+ "metrics": {
144
+ "acc": {
145
+ "value": 0.152,
146
+ "stderr": 0.016071982367911835,
147
+ "ci95": [
148
+ 0.12319239267380164,
149
+ 0.18611414828743875
150
+ ],
151
+ "ci_method": "Wilson score, z=1.959963984540054"
152
+ },
153
+ "acc_norm": {
154
+ "value": 0.282,
155
+ "stderr": 0.020143572847290726,
156
+ "ci95": [
157
+ 0.2443364332272433,
158
+ 0.32298777921399346
159
+ ],
160
+ "ci_method": "Wilson score, z=1.959963984540054"
161
+ }
162
+ }
163
+ },
164
+ "boolq": {
165
+ "samples": 3270,
166
+ "shots": 0,
167
+ "dataset": "aps/super_glue",
168
+ "config": "boolq",
169
+ "split": "validation",
170
+ "metrics": {
171
+ "acc": {
172
+ "value": 0.598776758409786,
173
+ "stderr": 0.008572708337179049,
174
+ "ci95": [
175
+ 0.5818706845463824,
176
+ 0.615451027004275
177
+ ],
178
+ "ci_method": "Wilson score, z=1.959963984540054"
179
+ }
180
+ }
181
+ },
182
+ "lambada_openai": {
183
+ "samples": 5153,
184
+ "shots": 0,
185
+ "dataset": "EleutherAI/lambada_openai",
186
+ "config": "default",
187
+ "split": "test",
188
+ "metrics": {
189
+ "acc": {
190
+ "value": 0.20861633999611875,
191
+ "stderr": 0.005660825573438258,
192
+ "ci95": [
193
+ 0.1977414700784266,
194
+ 0.2199253277124155
195
+ ],
196
+ "ci_method": "Wilson score, z=1.959963984540054"
197
+ },
198
+ "perplexity": {
199
+ "value": 189.6865878818963,
200
+ "stderr": 8.94540405067453
201
+ }
202
+ }
203
+ }
204
+ },
205
+ "continuation_cpu_fp32": {
206
+ "nll": 3.560861705095088,
207
+ "nll_ci95": [
208
+ 3.521807046434314,
209
+ 3.599506885284411
210
+ ],
211
+ "ppl": 35.19351050996088,
212
+ "ppl_ci95": [
213
+ 33.84553368820155,
214
+ 36.580191764630115
215
+ ],
216
+ "blocks": 291,
217
+ "scored_tokens": 148992,
218
+ "block_nll": [
219
+ 2.8818949460983276,
220
+ 3.559372901916504,
221
+ 3.4997223615646362,
222
+ 3.5533182621002197,
223
+ 3.904844641685486,
224
+ 3.7352592945098877,
225
+ 4.410188436508179,
226
+ 3.7979665994644165,
227
+ 3.6401803493499756,
228
+ 3.706244707107544,
229
+ 3.3963332176208496,
230
+ 2.9677618741989136,
231
+ 2.9415470361709595,
232
+ 3.381311774253845,
233
+ 3.761952519416809,
234
+ 3.502508759498596,
235
+ 3.827163577079773,
236
+ 3.726546883583069,
237
+ 3.598921537399292,
238
+ 3.8391060829162598,
239
+ 3.615709662437439,
240
+ 3.3927921056747437,
241
+ 3.9658381938934326,
242
+ 2.9928760528564453,
243
+ 3.289688467979431,
244
+ 3.522820830345154,
245
+ 3.514780282974243,
246
+ 3.4957292079925537,
247
+ 3.4607547521591187,
248
+ 3.3068007230758667,
249
+ 3.829126238822937,
250
+ 4.061469554901123,
251
+ 3.32765793800354,
252
+ 3.3051648139953613,
253
+ 3.4504024982452393,
254
+ 3.987992525100708,
255
+ 3.617965340614319,
256
+ 3.45237398147583,
257
+ 3.2098472118377686,
258
+ 3.6943342685699463,
259
+ 3.2918165922164917,
260
+ 3.7236536741256714,
261
+ 3.3088908195495605,
262
+ 3.5559070110321045,
263
+ 3.3810545206069946,
264
+ 3.626940131187439,
265
+ 3.8755948543548584,
266
+ 3.4037437438964844,
267
+ 3.8654167652130127,
268
+ 3.5353585481643677,
269
+ 3.423677682876587,
270
+ 3.527420997619629,
271
+ 3.8018072843551636,
272
+ 4.020987868309021,
273
+ 3.4471275806427,
274
+ 4.067643642425537,
275
+ 3.1591018438339233,
276
+ 3.1642297506332397,
277
+ 3.5973926782608032,
278
+ 3.252170205116272,
279
+ 3.200021743774414,
280
+ 3.070353388786316,
281
+ 3.260322332382202,
282
+ 2.5585895776748657,
283
+ 3.14900541305542,
284
+ 3.241077184677124,
285
+ 3.1020973920822144,
286
+ 2.980721950531006,
287
+ 3.3583728075027466,
288
+ 3.282616138458252,
289
+ 3.4956382513046265,
290
+ 3.161021590232849,
291
+ 3.7117087841033936,
292
+ 3.4659478664398193,
293
+ 3.7045702934265137,
294
+ 3.560722827911377,
295
+ 3.566222310066223,
296
+ 3.6698633432388306,
297
+ 3.529252290725708,
298
+ 3.6588650941848755,
299
+ 3.5175918340682983,
300
+ 3.6442832946777344,
301
+ 3.546086549758911,
302
+ 3.9669642448425293,
303
+ 3.9136862754821777,
304
+ 4.107044577598572,
305
+ 3.8092015981674194,
306
+ 3.8360373973846436,
307
+ 3.784490466117859,
308
+ 3.9585541486740112,
309
+ 3.542818546295166,
310
+ 3.608612895011902,
311
+ 3.712354898452759,
312
+ 3.7949299812316895,
313
+ 3.5544456243515015,
314
+ 3.6868759393692017,
315
+ 3.4533783197402954,
316
+ 3.4440205097198486,
317
+ 3.385461211204529,
318
+ 4.006747007369995,
319
+ 3.7272919416427612,
320
+ 3.518463134765625,
321
+ 2.864761471748352,
322
+ 3.4449726343154907,
323
+ 3.4412227869033813,
324
+ 3.110851764678955,
325
+ 3.3665395975112915,
326
+ 3.103492498397827,
327
+ 3.2595232725143433,
328
+ 3.3449599742889404,
329
+ 3.251083731651306,
330
+ 3.348357915878296,
331
+ 2.8886704444885254,
332
+ 3.0338516235351562,
333
+ 3.6125348806381226,
334
+ 3.265676736831665,
335
+ 3.208403468132019,
336
+ 3.8483210802078247,
337
+ 3.346174716949463,
338
+ 3.436376690864563,
339
+ 3.76150643825531,
340
+ 3.8037009239196777,
341
+ 3.6503586769104004,
342
+ 3.6716541051864624,
343
+ 3.9631524085998535,
344
+ 3.73912513256073,
345
+ 3.523168683052063,
346
+ 3.6097822189331055,
347
+ 3.807469367980957,
348
+ 3.660905122756958,
349
+ 3.8983651399612427,
350
+ 3.7528629302978516,
351
+ 3.823133945465088,
352
+ 3.454434037208557,
353
+ 3.8696566820144653,
354
+ 3.581449508666992,
355
+ 3.627530574798584,
356
+ 3.8549742698669434,
357
+ 3.481117367744446,
358
+ 3.6938220262527466,
359
+ 3.5973401069641113,
360
+ 3.131093144416809,
361
+ 4.145915865898132,
362
+ 3.846521258354187,
363
+ 3.906494617462158,
364
+ 3.995554804801941,
365
+ 4.2677435874938965,
366
+ 4.066015124320984,
367
+ 3.2945024967193604,
368
+ 3.526572823524475,
369
+ 3.762774705886841,
370
+ 3.6110243797302246,
371
+ 3.0586884021759033,
372
+ 3.4789986610412598,
373
+ 3.098861813545227,
374
+ 3.476531982421875,
375
+ 3.6977832317352295,
376
+ 3.6894044876098633,
377
+ 4.153103709220886,
378
+ 3.3070541620254517,
379
+ 3.663380265235901,
380
+ 3.6190026998519897,
381
+ 2.991021156311035,
382
+ 2.888830542564392,
383
+ 2.809903621673584,
384
+ 3.1375738382339478,
385
+ 3.0203697681427,
386
+ 3.3764541149139404,
387
+ 3.0283684730529785,
388
+ 3.8419175148010254,
389
+ 3.703011989593506,
390
+ 3.9893038272857666,
391
+ 3.885919213294983,
392
+ 4.4654247760772705,
393
+ 4.350051641464233,
394
+ 3.898257851600647,
395
+ 4.068492889404297,
396
+ 3.401093602180481,
397
+ 3.329573631286621,
398
+ 4.586219072341919,
399
+ 3.7894513607025146,
400
+ 4.155319690704346,
401
+ 4.0569844245910645,
402
+ 4.123142957687378,
403
+ 4.2685511112213135,
404
+ 4.168790817260742,
405
+ 3.9254218339920044,
406
+ 4.219369173049927,
407
+ 4.145432949066162,
408
+ 4.055754661560059,
409
+ 4.449324369430542,
410
+ 4.017173767089844,
411
+ 3.2817542552948,
412
+ 4.302147626876831,
413
+ 4.085442543029785,
414
+ 3.6487646102905273,
415
+ 3.7623459100723267,
416
+ 3.4463300704956055,
417
+ 3.7141886949539185,
418
+ 3.693334460258484,
419
+ 3.477225184440613,
420
+ 3.063503861427307,
421
+ 3.466049075126648,
422
+ 3.2781829833984375,
423
+ 3.5349220037460327,
424
+ 3.6245510578155518,
425
+ 3.305224299430847,
426
+ 3.6646769046783447,
427
+ 3.295943021774292,
428
+ 3.564467668533325,
429
+ 3.447028160095215,
430
+ 3.268126368522644,
431
+ 3.388076663017273,
432
+ 3.4262938499450684,
433
+ 3.2643288373947144,
434
+ 3.563586711883545,
435
+ 3.6324812173843384,
436
+ 3.3838117122650146,
437
+ 2.9912376403808594,
438
+ 3.1752302646636963,
439
+ 3.2856974601745605,
440
+ 3.4931013584136963,
441
+ 3.2308322191238403,
442
+ 3.2233749628067017,
443
+ 3.502491593360901,
444
+ 3.303251266479492,
445
+ 3.0688891410827637,
446
+ 3.631072521209717,
447
+ 3.84873628616333,
448
+ 3.3207255601882935,
449
+ 3.7225327491760254,
450
+ 3.5921976566314697,
451
+ 3.480934739112854,
452
+ 3.669029474258423,
453
+ 3.7562562227249146,
454
+ 3.764595627784729,
455
+ 3.822733163833618,
456
+ 3.6460816860198975,
457
+ 3.160399556159973,
458
+ 3.726219892501831,
459
+ 3.462749719619751,
460
+ 3.500929832458496,
461
+ 3.1595499515533447,
462
+ 3.0313973426818848,
463
+ 3.2162559032440186,
464
+ 3.2418947219848633,
465
+ 3.2680046558380127,
466
+ 3.580800771713257,
467
+ 4.050579786300659,
468
+ 3.4574050903320312,
469
+ 3.9652373790740967,
470
+ 4.038872718811035,
471
+ 3.5344061851501465,
472
+ 3.4817302227020264,
473
+ 3.8452590703964233,
474
+ 3.525113582611084,
475
+ 3.5390002727508545,
476
+ 3.4374747276306152,
477
+ 3.7511621713638306,
478
+ 3.556244730949402,
479
+ 3.4953012466430664,
480
+ 3.5543426275253296,
481
+ 3.1843537092208862,
482
+ 3.2016040086746216,
483
+ 3.458970069885254,
484
+ 3.6360448598861694,
485
+ 3.3213725090026855,
486
+ 3.729948401451111,
487
+ 3.7068639993667603,
488
+ 2.9791568517684937,
489
+ 3.8019036054611206,
490
+ 3.64823317527771,
491
+ 2.9146808385849,
492
+ 3.088519811630249,
493
+ 3.0383111238479614,
494
+ 2.6207664012908936,
495
+ 3.47467839717865,
496
+ 3.4298750162124634,
497
+ 3.7091829776763916,
498
+ 3.6953502893447876,
499
+ 3.5971832275390625,
500
+ 3.733664035797119,
501
+ 3.306243062019348,
502
+ 3.5431629419326782,
503
+ 3.622551202774048,
504
+ 3.268967390060425,
505
+ 3.5540285110473633,
506
+ 3.8727654218673706,
507
+ 4.464851140975952,
508
+ 4.037501811981201,
509
+ 3.530550479888916
510
+ ]
511
+ },
512
+ "continuation_ci_method": "percentile bootstrap of nonoverlapping 1024-token blocks; conditional suffix NLL; exponentiate interval endpoints for PPL",
513
+ "continuation_bootstrap_samples": 10000,
514
+ "continuation_bootstrap_seed": 2026,
515
+ "corpus_sha256": "aca2f46735043bcfd0a44eca981d04627b9cdf74c4c9a04bf0856d04066f58fc",
516
+ "weights_sha256": "aeab3483f72ca0f9937730614c9cabbcbfa2bdcf8327936d7e6f9794d464c1cf",
517
+ "source_sha256": {
518
+ "src/tiny_llm/__init__.py": "8c7f075d51006a53fe1d645ef5a84d65db58ff4251e7544074fe29ee7549c14c",
519
+ "src/tiny_llm/benchmarks.py": "5d9f461366389bd1f926c6a6468192f3e2313c87caf5b1de27f407d563a858a4",
520
+ "src/tiny_llm/checkpoint.py": "ac9df5f8c981a47eb1f1e59d0687ff41a1f6c38ca74ced50f71ac446a58d6ef5",
521
+ "src/tiny_llm/continuation.py": "548b7e76401cd545af3e7ff1aedf041fc96a330c8c9cc80266e0e20830f0e95d",
522
+ "src/tiny_llm/data.py": "973e4ff3e7b6e80c74bd99173f89cb8ce94c6ef3a21ff54acf1a42eab9654d89",
523
+ "src/tiny_llm/evaluation/__init__.py": "e49e80f7be3ab6e200f0db14b028e465de9caa8f6f705430eabce0c41b8322ba",
524
+ "src/tiny_llm/evaluation/adapters.py": "5a881b82bf6938ca953be751de021889f2c51a559df88f537da1e6ce4dfc6e15",
525
+ "src/tiny_llm/evaluation/catalog.py": "5681c9433c67890644488f7f73280e18662f28a5de8c18374443bd7c84ba4be9",
526
+ "src/tiny_llm/evaluation/cli.py": "b4875211ed8390c72ee96e2cb5f0abc02eb9ea7c5e4828b7c3eea7d6ad682f11",
527
+ "src/tiny_llm/losses.py": "592a05287369f6e5077b3faca404a9392de4772cf06389fb8aa7e36924e74f86",
528
+ "src/tiny_llm/models/__init__.py": "55f88bbd8cf8bfd70e5e17c1d0050299412528385c3714bb712623f40b0a681d",
529
+ "src/tiny_llm/models/diffusion/__init__.py": "c92eaf5986d604d8aaf1894a862a217cefa32ab25359175b88110e45a71c1b25",
530
+ "src/tiny_llm/models/diffusion/configuration_diffusion_lm.py": "8f796fb3bb105dfedc5d14d939ffc1c0cb3a119904fe90ca0feb76ffee9fc9a2",
531
+ "src/tiny_llm/models/diffusion/modeling_diffusion_lm.py": "71162bf7fbe92cbf08cf3bf64f59fc11098c5c302787fc1c7fe9fcb14c9479e5",
532
+ "src/tiny_llm/models/looped/__init__.py": "4b46b426021c59ed313cb2f49afc1926ad2793d771ef90117e3fef0462957cff",
533
+ "src/tiny_llm/models/looped/configuration_looped_lm.py": "b8d99c52b98e0a97a4cae76ca4c20affd8f4d019ec38e0a9beefd5fad864dc25",
534
+ "src/tiny_llm/models/looped/modeling_looped_lm.py": "9bdb3c5e3aaae663d09e98055f95df1adbc42e0a4bf5dffb7f6c39242af41b9e",
535
+ "src/tiny_llm/models/moe_t5/__init__.py": "18e33fe38b2049521f573512ac8796afa209e1b25c2052784e1c927a7160d66c",
536
+ "src/tiny_llm/models/moe_t5/configuration_alicet5_moe.py": "4647b1e9ab9ce07887bffc1abc3beb3e691962a380b4cc237aae376490bb56b7",
537
+ "src/tiny_llm/models/moe_t5/modeling_alicet5_moe.py": "c7bbba2f01dc889cc604c7bc161354397239b28503d05f7e00665658be84751d",
538
+ "src/tiny_llm/models/prefixlm/__init__.py": "c94c3c861acba8d2147a3a6c46bccfc71ac8adc8d70757bede009598029d31ea",
539
+ "src/tiny_llm/models/prefixlm/configuration_prefix_lm.py": "20b3a62ae3628b5a64566ef19d2947c90f10c6159daad00dd13d18fc5910c42c",
540
+ "src/tiny_llm/models/prefixlm/modeling_prefix_lm.py": "f62a38211df175696f64945173d1e41d9f7fcf6152a7648020da8c91788e98fd",
541
+ "src/tiny_llm/models/q50m/__init__.py": "9d0dfec6fa0cfa6967e2f17a73d8fbeca69ba93b4a93651eda4d95626d5f5eb5",
542
+ "src/tiny_llm/models/q50m/configuration_q50m.py": "796806b2d5d982b633796bc7de53c3073b1b6e52d259f44ef798b63f55eaea92",
543
+ "src/tiny_llm/models/q50m/modeling_q50m.py": "b7a712050167fad24471193b0ca7baf4ca7e5ebdf8036c91b506d3fff5b49c8b",
544
+ "src/tiny_llm/telemetry.py": "f5a35de68da1a2304159fd3613fa3773bc368982ed18712791c847285b895c09",
545
+ "src/tiny_llm/ul2.py": "f4d948d89d5e106965612971dd473a54b57719f811761f18457c6221d763b876"
546
+ },
547
+ "packages": {
548
+ "lm_eval": "0.4.12",
549
+ "torch": "2.11.0+cu128",
550
+ "transformers": "5.17.0",
551
+ "datasets": "5.0.1",
552
+ "accelerate": "1.15.0"
553
+ }
554
+ }
evaluation/run_core.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Reproduce the released model's eight-task likelihood evaluation."""
2
+ import argparse
3
+ import json
4
+ import importlib.metadata
5
+ from pathlib import Path
6
+ import torch
7
+ from transformers import AutoTokenizer,AutoModelForCausalLM,AutoModelForSeq2SeqLM
8
+ from lm_eval import evaluator,tasks
9
+ from lm_eval.models.huggingface import HFLM
10
+ from adapters import UL2HFLM
11
+
12
+ def main():
13
+ if importlib.metadata.version('lm_eval') != '0.4.12':
14
+ raise RuntimeError('This reproduction protocol requires lm_eval==0.4.12')
15
+ p=argparse.ArgumentParser(description=__doc__)
16
+ p.add_argument('--device',default='cpu')
17
+ p.add_argument('--dtype',default='float32',choices=['float32','bfloat16'])
18
+ p.add_argument('--batch-size',type=int,default=1)
19
+ p.add_argument('--output',type=Path,required=True)
20
+ p.add_argument('--limit',type=int,help='Smoke only; not a full benchmark')
21
+ a=p.parse_args(); a.output.mkdir(parents=True,exist_ok=False)
22
+ torch.set_num_threads(4)
23
+ root=Path(__file__).resolve().parents[1]
24
+ config=json.loads((root/'config.json').read_text()); ul2=bool(config.get('ul2'))
25
+ cls=AutoModelForSeq2SeqLM if ul2 else AutoModelForCausalLM
26
+ model=cls.from_pretrained(root,trust_remote_code=True,dtype=getattr(torch,a.dtype)).to(a.device).eval()
27
+ tok=AutoTokenizer.from_pretrained(root)
28
+ adapter=(UL2HFLM if ul2 else HFLM)(pretrained=model,tokenizer=tok,backend='seq2seq' if ul2 else 'causal',device=a.device,batch_size=a.batch_size,max_length=2048)
29
+ mapping={'hellaswag':'hellaswag','arc_easy':'arc','arc_challenge':'arc','piqa':'piqa','winogrande':'winogrande','openbookqa':'openbookqa','boolq':'super_glue/boolq','lambada_openai':'lambada'}
30
+ manager=tasks.TaskManager(include_defaults=False,include_path=sorted({Path(tasks.__file__).parent/v for v in mapping.values()}))
31
+ for name in mapping:
32
+ result=evaluator.simple_evaluate(model=adapter,tasks=[name],num_fewshot=0,limit=a.limit,bootstrap_iters=1000,log_samples=False,task_manager=manager,random_seed=1234,numpy_random_seed=1234,torch_random_seed=1234,fewshot_random_seed=1234,apply_chat_template=False)
33
+ def fallback(x): return x.item() if hasattr(x,'item') else str(x)
34
+ (a.output/(name+'.json')).write_text(json.dumps(result,indent=2,default=fallback))
35
+
36
+ if __name__=='__main__': main()
generation_config.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token_id": 1,
3
+ "eos_token_id": 2,
4
+ "pad_token_id": 0,
5
+ "do_sample": false
6
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:aeab3483f72ca0f9937730614c9cabbcbfa2bdcf8327936d7e6f9794d464c1cf
3
+ size 203527808
modeling_q50m.py ADDED
@@ -0,0 +1,445 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Modeling for the Q-50M architecture (replica of q-project/Q-50M-Base).
2
+
3
+ Self-contained implementation of the exact architecture described in the
4
+ model card: Mistral-shaped 512-wide 10-layer decoder, GQA 8q/2kv, per-head
5
+ QK-Norm, RoPE in every layer (configurable NoPE), scalar content-dependent
6
+ gates (gate = multiplier * sigmoid(Wx)) on attention and MLP residual
7
+ branches, SwiGLU MLP, tied input/output embeddings, final RMSNorm.
8
+
9
+ Follows the transformers v5 modeling pattern (DynamicCache, create_causal_mask,
10
+ GradientCheckpointingLayer, GenerationMixin).
11
+ """
12
+
13
+ from collections.abc import Callable
14
+
15
+ import torch
16
+ import torch.nn as nn
17
+ import torch.nn.functional as F
18
+ from transformers.cache_utils import Cache, DynamicCache
19
+ from transformers.generation import GenerationMixin
20
+ from transformers.masking_utils import create_causal_mask
21
+ from transformers.modeling_layers import GradientCheckpointingLayer
22
+ from transformers.modeling_outputs import BaseModelOutputWithPast, CausalLMOutputWithPast
23
+ from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
24
+ from transformers.processing_utils import Unpack
25
+ from transformers.utils import TransformersKwargs
26
+
27
+ from .configuration_q50m import Q50MConfig
28
+
29
+
30
+ def _rotate_half(x: torch.Tensor) -> torch.Tensor:
31
+ x1 = x[..., : x.shape[-1] // 2]
32
+ x2 = x[..., x.shape[-1] // 2 :]
33
+ return torch.cat((-x2, x1), dim=-1)
34
+
35
+
36
+ def _apply_rotary_pos_emb(q, k, cos, sin):
37
+ # cos/sin: (batch, seq, head_dim)
38
+ cos = cos.unsqueeze(1)
39
+ sin = sin.unsqueeze(1)
40
+ return q * cos + _rotate_half(q) * sin, k * cos + _rotate_half(k) * sin
41
+
42
+
43
+ class Q50MRMSNorm(nn.Module):
44
+ def __init__(self, hidden_size: int, eps: float = 1e-6) -> None:
45
+ super().__init__()
46
+ self.weight = nn.Parameter(torch.ones(hidden_size))
47
+ self.variance_epsilon = eps
48
+
49
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
50
+ input_dtype = hidden_states.dtype
51
+ hidden_states = hidden_states.to(torch.float32)
52
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
53
+ hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
54
+ return (self.weight * hidden_states.to(input_dtype)).to(input_dtype)
55
+
56
+ def extra_repr(self):
57
+ return f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}"
58
+
59
+
60
+ class Q50MRotaryEmbedding(nn.Module):
61
+ def __init__(self, config: Q50MConfig, device=None):
62
+ super().__init__()
63
+ self.config = config
64
+ inv_freq = 1.0 / (
65
+ config.rope_theta
66
+ ** (torch.arange(0, config.head_dim, 2, dtype=torch.float32, device=device) / config.head_dim)
67
+ )
68
+ self.inv_freq = nn.Buffer(inv_freq, persistent=True)
69
+
70
+ @torch.no_grad()
71
+ def forward(self, x, position_ids):
72
+ inv_freq_expanded = (
73
+ self.inv_freq[None, :, None].expand(position_ids.shape[0], -1, 1)
74
+ .to(dtype=torch.float32, device=x.device)
75
+ )
76
+ position_ids_expanded = position_ids[:, None, :].float()
77
+ freqs = (inv_freq_expanded @ position_ids_expanded).transpose(1, 2)
78
+ emb = torch.cat((freqs, freqs), dim=-1)
79
+ return emb.cos().to(dtype=x.dtype), emb.sin().to(dtype=x.dtype)
80
+
81
+
82
+ class Q50MScalarGate(nn.Module):
83
+ """Content-dependent scalar gate: output = branch * multiplier * sigmoid(W x)."""
84
+
85
+ def __init__(self, hidden_size: int, multiplier: float = 2.0):
86
+ super().__init__()
87
+ self.projection = nn.Linear(hidden_size, 1, bias=False)
88
+ self.multiplier = multiplier
89
+
90
+ def forward(self, branch: torch.Tensor, residual_input: torch.Tensor) -> torch.Tensor:
91
+ return branch * self.multiplier * torch.sigmoid(self.projection(residual_input))
92
+
93
+ def reset_parameters(self):
94
+ nn.init.zeros_(self.projection.weight)
95
+
96
+
97
+ def _repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
98
+ batch, num_key_value_heads, slen, head_dim = hidden_states.shape
99
+ if n_rep == 1:
100
+ return hidden_states
101
+ hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
102
+ return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
103
+
104
+
105
+ def _eager_attention_forward(
106
+ module: nn.Module,
107
+ query: torch.Tensor,
108
+ key: torch.Tensor,
109
+ value: torch.Tensor,
110
+ attention_mask: torch.Tensor | None,
111
+ scaling: float,
112
+ dropout: float = 0.0,
113
+ **kwargs: Unpack[TransformersKwargs],
114
+ ):
115
+ key_states = _repeat_kv(key, module.num_key_value_groups)
116
+ value_states = _repeat_kv(value, module.num_key_value_groups)
117
+ attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
118
+ if attention_mask is not None:
119
+ attn_weights = attn_weights + attention_mask
120
+ attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
121
+ attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
122
+ attn_output = torch.matmul(attn_weights, value_states)
123
+ attn_output = attn_output.transpose(1, 2).contiguous()
124
+ return attn_output, attn_weights
125
+
126
+
127
+ def _sdpa_attention_forward(
128
+ module: nn.Module,
129
+ query: torch.Tensor,
130
+ key: torch.Tensor,
131
+ value: torch.Tensor,
132
+ attention_mask: torch.Tensor | None,
133
+ scaling: float,
134
+ dropout: float = 0.0,
135
+ **kwargs: Unpack[TransformersKwargs],
136
+ ):
137
+ """Local SDPA wrapper. HF's generic SDPA interface falls back to the math
138
+ backend for GQA shapes (q heads != kv heads), which materializes
139
+ (batch, heads, seq, seq) fp32 attention scores. Expanding kv first keeps
140
+ the fused flash / memory-efficient kernels eligible."""
141
+ n_rep = getattr(module, "num_key_value_groups", 1)
142
+ if n_rep > 1:
143
+ key = _repeat_kv(key, n_rep)
144
+ value = _repeat_kv(value, n_rep)
145
+ is_causal = (
146
+ attention_mask is None
147
+ and getattr(module, "is_causal", False)
148
+ and query.shape[2] > 1
149
+ )
150
+ attn_output = nn.functional.scaled_dot_product_attention(
151
+ query,
152
+ key,
153
+ value,
154
+ attn_mask=attention_mask,
155
+ dropout_p=dropout,
156
+ is_causal=is_causal,
157
+ scale=scaling,
158
+ )
159
+ return attn_output.transpose(1, 2).contiguous(), None
160
+
161
+
162
+ class Q50MAttention(nn.Module):
163
+ def __init__(self, config: Q50MConfig, layer_idx: int):
164
+ super().__init__()
165
+ self.config = config
166
+ self.layer_idx = layer_idx
167
+ self.head_dim = config.head_dim
168
+ self.num_heads = config.num_attention_heads
169
+ self.num_kv_heads = config.num_key_value_heads
170
+ self.num_key_value_groups = self.num_heads // self.num_kv_heads
171
+ self.scaling = self.head_dim**-0.5
172
+ self.attention_dropout = config.attention_dropout
173
+ self.is_causal = True
174
+ self.use_rope = layer_idx not in config.nope_layers
175
+
176
+ inner = self.num_heads * self.head_dim
177
+ kv_inner = self.num_kv_heads * self.head_dim
178
+ self.q_proj = nn.Linear(config.hidden_size, inner, bias=False)
179
+ self.k_proj = nn.Linear(config.hidden_size, kv_inner, bias=False)
180
+ self.v_proj = nn.Linear(config.hidden_size, kv_inner, bias=False)
181
+ self.o_proj = nn.Linear(inner, config.hidden_size, bias=False)
182
+ self.q_norm = Q50MRMSNorm(self.head_dim, config.rms_norm_eps) if config.qk_norm else None
183
+ self.k_norm = Q50MRMSNorm(self.head_dim, config.rms_norm_eps) if config.qk_norm else None
184
+ self.output_gate = (
185
+ Q50MScalarGate(config.hidden_size, config.gate_multiplier)
186
+ if config.attention_scalar_gate
187
+ else None
188
+ )
189
+
190
+ def forward(
191
+ self,
192
+ hidden_states: torch.Tensor,
193
+ position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
194
+ attention_mask: torch.Tensor | None = None,
195
+ past_key_values: Cache | None = None,
196
+ **kwargs: Unpack[TransformersKwargs],
197
+ ) -> tuple[torch.Tensor, torch.Tensor]:
198
+ input_shape = hidden_states.shape[:-1]
199
+ hidden_shape = (*input_shape, -1, self.head_dim)
200
+ q = self.q_proj(hidden_states).view(hidden_shape).transpose(1, 2)
201
+ k = self.k_proj(hidden_states).view(hidden_shape).transpose(1, 2)
202
+ v = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
203
+
204
+ if self.q_norm is not None:
205
+ q = self.q_norm(q)
206
+ k = self.k_norm(k)
207
+ if self.use_rope:
208
+ cos, sin = position_embeddings
209
+ q, k = _apply_rotary_pos_emb(q, k, cos, sin)
210
+
211
+ if past_key_values is not None:
212
+ k, v = past_key_values.update(k, v, self.layer_idx)
213
+
214
+ if self.config._attn_implementation == "sdpa":
215
+ attention_interface: Callable = _sdpa_attention_forward
216
+ else:
217
+ attention_interface = ALL_ATTENTION_FUNCTIONS.get_interface(
218
+ self.config._attn_implementation, _eager_attention_forward
219
+ )
220
+ attn_output, attn_weights = attention_interface(
221
+ self,
222
+ q, k, v,
223
+ attention_mask,
224
+ dropout=0.0 if not self.training else self.attention_dropout,
225
+ scaling=self.scaling,
226
+ **kwargs,
227
+ )
228
+ attn_output = attn_output.reshape(*input_shape, -1).contiguous()
229
+ attn_output = self.o_proj(attn_output)
230
+ if self.output_gate is not None:
231
+ attn_output = self.output_gate(attn_output, hidden_states)
232
+ return attn_output, attn_weights
233
+
234
+
235
+ class Q50MMLP(nn.Module):
236
+ def __init__(self, config: Q50MConfig):
237
+ super().__init__()
238
+ self.gate_proj = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
239
+ self.up_proj = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
240
+ self.down_proj = nn.Linear(config.intermediate_size, config.hidden_size, bias=False)
241
+ self.output_gate = (
242
+ Q50MScalarGate(config.hidden_size, config.gate_multiplier)
243
+ if config.mlp_scalar_gate
244
+ else None
245
+ )
246
+
247
+ def forward(self, hidden_states):
248
+ output = self.down_proj(F.silu(self.gate_proj(hidden_states)) * self.up_proj(hidden_states))
249
+ if self.output_gate is not None:
250
+ output = self.output_gate(output, hidden_states)
251
+ return output
252
+
253
+
254
+ class Q50MDecoderLayer(GradientCheckpointingLayer):
255
+ def __init__(self, config: Q50MConfig, layer_idx: int):
256
+ super().__init__()
257
+ self.hidden_size = config.hidden_size
258
+ self.self_attn = Q50MAttention(config, layer_idx)
259
+ self.mlp = Q50MMLP(config)
260
+ self.input_layernorm = Q50MRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
261
+ self.post_attention_layernorm = Q50MRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
262
+
263
+ def forward(
264
+ self,
265
+ hidden_states: torch.Tensor,
266
+ attention_mask: torch.Tensor | None = None,
267
+ position_ids: torch.LongTensor | None = None,
268
+ past_key_values: Cache | None = None,
269
+ use_cache: bool | None = False,
270
+ position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
271
+ **kwargs: Unpack[TransformersKwargs],
272
+ ) -> torch.Tensor:
273
+ residual = hidden_states
274
+ hidden_states = self.input_layernorm(hidden_states)
275
+ hidden_states, _ = self.self_attn(
276
+ hidden_states=hidden_states,
277
+ attention_mask=attention_mask,
278
+ position_ids=position_ids,
279
+ past_key_values=past_key_values,
280
+ use_cache=use_cache,
281
+ position_embeddings=position_embeddings,
282
+ **kwargs,
283
+ )
284
+ hidden_states = residual + hidden_states
285
+
286
+ residual = hidden_states
287
+ hidden_states = self.post_attention_layernorm(hidden_states)
288
+ hidden_states = self.mlp(hidden_states)
289
+ hidden_states = residual + hidden_states
290
+ return hidden_states
291
+
292
+
293
+ class Q50MPreTrainedModel(PreTrainedModel):
294
+ config_class = Q50MConfig
295
+ base_model_prefix = "model"
296
+ supports_gradient_checkpointing = True
297
+ _no_split_modules = ["Q50MDecoderLayer"]
298
+ _skip_keys_device_placement = ["past_key_values"]
299
+ _supports_sdpa = True
300
+ _supports_flash_attn = False
301
+ _supports_flex_attn = False
302
+
303
+
304
+ class Q50MModel(Q50MPreTrainedModel):
305
+ def __init__(self, config: Q50MConfig):
306
+ super().__init__(config)
307
+ self.padding_idx = config.pad_token_id
308
+ self.vocab_size = config.vocab_size
309
+ self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
310
+ self.layers = nn.ModuleList(
311
+ [Q50MDecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
312
+ )
313
+ self.norm = Q50MRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
314
+ self.rotary_emb = Q50MRotaryEmbedding(config=config)
315
+ self.gradient_checkpointing = False
316
+ self.post_init()
317
+
318
+ def forward(
319
+ self,
320
+ input_ids: torch.LongTensor | None = None,
321
+ attention_mask: torch.Tensor | None = None,
322
+ position_ids: torch.LongTensor | None = None,
323
+ past_key_values: Cache | None = None,
324
+ inputs_embeds: torch.FloatTensor | None = None,
325
+ use_cache: bool | None = None,
326
+ **kwargs: Unpack[TransformersKwargs],
327
+ ) -> BaseModelOutputWithPast:
328
+ if (input_ids is None) ^ (inputs_embeds is not None):
329
+ raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
330
+
331
+ if inputs_embeds is None:
332
+ inputs_embeds = self.embed_tokens(input_ids)
333
+
334
+ if use_cache and past_key_values is None:
335
+ past_key_values = DynamicCache(config=self.config)
336
+
337
+ standard_positions = position_ids is None
338
+ if position_ids is None:
339
+ past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
340
+ position_ids = torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device) + past_seen_tokens
341
+ position_ids = position_ids.unsqueeze(0)
342
+
343
+ # Unpadded, uncached SDPA can use its native causal flag, including
344
+ # under torch.compile where HF otherwise materializes a dense mask.
345
+ causal_mask = None if (
346
+ attention_mask is None and past_key_values is None and standard_positions
347
+ and self.config._attn_implementation == "sdpa"
348
+ ) else create_causal_mask(
349
+ config=self.config,
350
+ inputs_embeds=inputs_embeds,
351
+ attention_mask=attention_mask,
352
+ past_key_values=past_key_values,
353
+ position_ids=position_ids,
354
+ )
355
+
356
+ hidden_states = inputs_embeds
357
+ position_embeddings = self.rotary_emb(hidden_states, position_ids=position_ids)
358
+
359
+ for decoder_layer in self.layers[: self.config.num_hidden_layers]:
360
+ if self.gradient_checkpointing and self.training:
361
+ hidden_states = self._gradient_checkpointing_func(
362
+ decoder_layer.forward,
363
+ hidden_states,
364
+ causal_mask,
365
+ position_ids,
366
+ past_key_values,
367
+ use_cache,
368
+ position_embeddings,
369
+ )
370
+ else:
371
+ hidden_states = decoder_layer(
372
+ hidden_states,
373
+ attention_mask=causal_mask,
374
+ position_embeddings=position_embeddings,
375
+ position_ids=position_ids,
376
+ past_key_values=past_key_values,
377
+ use_cache=use_cache,
378
+ **kwargs,
379
+ )
380
+
381
+ hidden_states = self.norm(hidden_states)
382
+ return BaseModelOutputWithPast(
383
+ last_hidden_state=hidden_states,
384
+ past_key_values=past_key_values,
385
+ )
386
+
387
+
388
+ class Q50MForCausalLM(Q50MPreTrainedModel, GenerationMixin):
389
+ _tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
390
+
391
+ def __init__(self, config: Q50MConfig):
392
+ super().__init__(config)
393
+ self.model = Q50MModel(config)
394
+ self.vocab_size = config.vocab_size
395
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
396
+ self.post_init()
397
+
398
+ def get_input_embeddings(self):
399
+ return self.model.embed_tokens
400
+
401
+ def set_input_embeddings(self, value):
402
+ self.model.embed_tokens = value
403
+
404
+ def get_output_embeddings(self):
405
+ return self.lm_head
406
+
407
+ def forward(
408
+ self,
409
+ input_ids: torch.LongTensor | None = None,
410
+ attention_mask: torch.Tensor | None = None,
411
+ position_ids: torch.LongTensor | None = None,
412
+ past_key_values: Cache | None = None,
413
+ inputs_embeds: torch.FloatTensor | None = None,
414
+ labels: torch.LongTensor | None = None,
415
+ use_cache: bool | None = None,
416
+ logits_to_keep: int | torch.Tensor = 0,
417
+ **kwargs: Unpack[TransformersKwargs],
418
+ ) -> CausalLMOutputWithPast:
419
+ outputs = self.model(
420
+ input_ids=input_ids,
421
+ attention_mask=attention_mask,
422
+ position_ids=position_ids,
423
+ past_key_values=past_key_values,
424
+ inputs_embeds=inputs_embeds,
425
+ use_cache=use_cache,
426
+ **kwargs,
427
+ )
428
+ hidden_states = outputs.last_hidden_state
429
+ slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
430
+ logits = self.lm_head(hidden_states[:, slice_indices, :])
431
+
432
+ loss = None
433
+ if labels is not None:
434
+ shift_logits = logits[..., :-1, :].contiguous()
435
+ shift_labels = labels[..., 1:].contiguous()
436
+ loss = F.cross_entropy(
437
+ shift_logits.view(-1, shift_logits.size(-1)),
438
+ shift_labels.view(-1),
439
+ ignore_index=-100,
440
+ )
441
+ return CausalLMOutputWithPast(
442
+ loss=loss,
443
+ logits=logits,
444
+ past_key_values=outputs.past_key_values,
445
+ )
release-manifest.json ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "repo": "d0rj/q-51M-base",
3
+ "files_sha256": {
4
+ "README.md": "70275eaece2a4b14b996e9e53fdfad2ac6045c24f2bca89f4891ba240ec76cc6",
5
+ "config.json": "c5c22bdc342dc8ba2dfadfad98733a697892ff696bc4a6a49fe07efc0096f9ad",
6
+ "configuration_q50m.py": "e1fcd06df2efb41474bb18d3954f54c04dc7733350c600afced9ab9dcf61d5c7",
7
+ "evaluation/adapters.py": "5a881b82bf6938ca953be751de021889f2c51a559df88f537da1e6ce4dfc6e15",
8
+ "evaluation/requirements.txt": "953e2117755df78f80177d62b34ff1d7a297efb5edc87a442864385424f416d3",
9
+ "evaluation/results.json": "662314441ea584474f234bf20ad0c37100291ab4fb6ba80176b8da0a71159799",
10
+ "evaluation/run_core.py": "217376c792abb0cbd4729580c78725388b83e5df0d126dcfe7e198568f6ed28f",
11
+ "generation_config.json": "baaf419957543384a7ed26a4d70753267fa60aea90bac2c55bb2232d70f9602a",
12
+ "model.safetensors": "aeab3483f72ca0f9937730614c9cabbcbfa2bdcf8327936d7e6f9794d464c1cf",
13
+ "modeling_q50m.py": "d8f48321584187276d991a8ef5792d3048029af5a319e16c3fb6800587546431",
14
+ "requirements.txt": "ac09bc9a52f1464d18f19032046f29b2faefc89c5716deca900ead1ee8aa572e",
15
+ "tensorboard/events.out.tfevents.1789820315.DESKTOP-OU3A33R.3028.0": "d65557d13fbf25ec08e48f2d845ea6c4cb38129c738cd0b64208019b7223cfca",
16
+ "tensorboard/events.out.tfevents.1789905190.DESKTOP-OU3A33R.12878.0.eval-core-20260920": "9f517d66584b507239662826fc95fe04d18f6ced59d3c7359d08968b6dfb7a3f",
17
+ "tokenizer.json": "6155a4212832ddd656acd1cd45ab4acb327dbb080e3acdbec84f086adf17414e",
18
+ "tokenizer_config.json": "cccfc292e0846e8ab8aa04dafae32483a831bcf1df6f15100f82d306b4a9f4c6",
19
+ "training_config.json": "39a3b2780f731260fe969aa0c458477f2aede7552bac925f69398fcaa7e405b1"
20
+ },
21
+ "validation": {
22
+ "logits_bitwise_equal": true,
23
+ "cached_generation_matches_uncached": true,
24
+ "parameters": 50878208,
25
+ "generated_ids": [
26
+ [
27
+ 463,
28
+ 2934,
29
+ 283,
30
+ 4226,
31
+ 314,
32
+ 265,
33
+ 2046,
34
+ 283,
35
+ 6270,
36
+ 15,
37
+ 493,
38
+ 314,
39
+ 265
40
+ ]
41
+ ]
42
+ }
43
+ }
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ torch>=2.11.0
2
+ transformers==5.17.0
3
+ tokenizers>=0.22
4
+ safetensors>=0.4
tensorboard/events.out.tfevents.1789820315.DESKTOP-OU3A33R.3028.0 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d65557d13fbf25ec08e48f2d845ea6c4cb38129c738cd0b64208019b7223cfca
3
+ size 81330
tensorboard/events.out.tfevents.1789905190.DESKTOP-OU3A33R.12878.0.eval-core-20260920 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9f517d66584b507239662826fc95fe04d18f6ced59d3c7359d08968b6dfb7a3f
3
+ size 3571
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "bos_token": "<s>",
4
+ "eos_token": "</s>",
5
+ "is_local": true,
6
+ "model_max_length": 2048,
7
+ "pad_token": "<pad>",
8
+ "tokenizer_class": "TokenizersBackend",
9
+ "unk_token": "<unk>"
10
+ }
training_config.json ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "step": 15000,
3
+ "source_tokens": 3932160000,
4
+ "args": {
5
+ "model": "q50m",
6
+ "max_steps": 15000,
7
+ "batch_size": 32,
8
+ "grad_accum": 4,
9
+ "seq_len": 2048,
10
+ "lr": 0.001,
11
+ "min_lr_frac": 0.1,
12
+ "weight_decay": 0.1,
13
+ "warmup_frac": 0.01,
14
+ "betas": [
15
+ 0.9,
16
+ 0.95
17
+ ],
18
+ "grad_clip": 1.0,
19
+ "dtype": "bf16",
20
+ "device": "auto",
21
+ "seed": 2026,
22
+ "text_file": null,
23
+ "dataset_name": "parquet",
24
+ "log_every": 20,
25
+ "save_steps": 100,
26
+ "max_host_memory_gib": 12.0,
27
+ "shuffle_buffer": 100000,
28
+ "compile": true,
29
+ "ce_chunk": 8192,
30
+ "grad_ckpt": true,
31
+ "resume": true,
32
+ "dataset": "HuggingFaceFW/fineweb-edu",
33
+ "dataset_subset": "sample-10BT"
34
+ }
35
+ }