jfrick commited on
Commit
4719692
·
verified ·
1 Parent(s): 5c0d3ed

python-124m-muon-5b-20261021-v1: 50065393 training targets

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ training-curves.png filter=lfs diff=lfs merge=lfs -text
37
+ validation-curves.png filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language: en
3
+ library_name: pytorch
4
+ tags:
5
+ - causal-lm
6
+ - python
7
+ - from-scratch
8
+ - muon
9
+ - experimental
10
+ ---
11
+ # Simple LLM Python 124M / 5B
12
+
13
+ Run: `python-124m-muon-5b-20261021-v1`. This is an **intermediate** base-model checkpoint, freshly initialized.
14
+ Processed **50,065,393 nonpadding training targets** in **549 optimizer updates**.
15
+ The exact target is 5,000,000,000. This model is not instruction-tuned.
16
+
17
+ 124,389,632 parameters; 14 layers, width 768, 12 attention heads, RMSNorm,
18
+ RoPE, SwiGLU, tied embeddings and the existing frozen 32K tokenizer. Training
19
+ uses eight H100s, 8K context, cropped padding, cached RoPE, torch.compile,
20
+ microbatch 2 and global batch 32 document-local windows. Hidden matrices use
21
+ the previously tested five-step Muon (LR .02, momentum .95); tied embeddings,
22
+ norms and biases use auxiliary AdamW (LR .0003, betas .9/.95). Weight decay .1,
23
+ gradient clipping 1, 20M-target warmup and cosine decay to 10%.
24
+
25
+ ## Data
26
+ Target proportions: 65% Python implementation, 15% Python tests/examples,
27
+ 10% Python programming documentation (including explanatory technical Q&A),
28
+ 5% CS/math, 3% general educational prose, 2% licensed/public-domain books.
29
+ Complete recent collected repository snapshots are preferred. Supplemental
30
+ sources include pinned CodeParrot pools, Common Pile StackExchange, FineWeb-Edu,
31
+ FineMath and public-domain Gutenberg material. All code allocations are Python.
32
+ The capacity table and exact per-category targets are in `capacity.json` and
33
+ `data-manifest.json`; one pass is preferred and two is the maximum. Public source
34
+ pins, aggregate collected-source capacity and filtering limitations are recorded
35
+ in `data-provenance.json`.
36
+
37
+ Repository/thread splits precede windows. Exact held-out hashes and repositories
38
+ are excluded across sources. Exact deduplication and repository caps are applied;
39
+ near clones can remain. Path/content filtering and license metadata are imperfect.
40
+ Some supplements are older and may contain outdated practices or errors.
41
+ Private documents and sensitive source-level provenance are not published.
42
+ StackExchange sources carry per-document CC-BY-SA attribution in the private
43
+ provenance ledger; Common Pile source revision is
44
+ `5ec3aa2e65b7c61b7c18f1ff18ccbc4d3279a23c`.
45
+
46
+ ## Evaluation
47
+ Held-out category losses, all fixed greedy/sampled Python generations, syntax,
48
+ repetition, length/EOS metrics and hidden-test execution results are included.
49
+ Function evaluation uses 32 reproducibly selected MBPP sanitized test tasks
50
+ (CC-BY-4.0, Google Research), revision
51
+ `4bb6404fdc6cacfda99d4ac4205087b89d32030c`. Tests are omitted from model prompts.
52
+ Exact reference hashes are excluded from training; no exhaustive benchmark
53
+ contamination audit or benchmark-clean claim is made. Generated code executes
54
+ in isolated network-blocked, credential-free sandboxes with resource limits.
55
+ Low early accuracy alone does not stop training.
56
+
57
+ ![Training curves](training-curves.png)
58
+ ![Validation curves](validation-curves.png)
59
+
60
+ All fixed-suite generations are retained without selection in `evaluations/`.
61
+ Each Hub commit preserves an inference checkpoint. Optimizer, RNG and data cursors
62
+ remain in private Modal training checkpoints for exact continuation.
63
+ Weight hashes are in `provenance.json`; runtime/cost figures are explicitly estimates.
64
+ Use the bundled custom PyTorch model, not Transformers AutoModel:
65
+
66
+ ```bash
67
+ pip install -r requirements.txt
68
+ python generate.py --prompt 'def add(a, b):' --tokens 128
69
+ ```
70
+
71
+ Code and execution evidence: https://github.com/koogle/lm-exploration/pull/30 .
capacity.json ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "stage": "ready_to_freeze",
3
+ "updated_unix": 1792550906.6174269,
4
+ "tokenizer_sha256": "add5b2c7542e4efded329735825ecdcb94df1432617c3d3e4b7508aa459432f9",
5
+ "categories": {
6
+ "python_implementation": {
7
+ "target": 3250000000,
8
+ "unique_train_targets": 3344840434,
9
+ "validation_targets": 202402128,
10
+ "required_passes": 0.9716457523545949,
11
+ "two_pass_shortfall": 0,
12
+ "one_pass_shortfall": 0
13
+ },
14
+ "python_tests_examples": {
15
+ "target": 750000000,
16
+ "unique_train_targets": 1455959517,
17
+ "validation_targets": 88631252,
18
+ "required_passes": 0.5151242127565282,
19
+ "two_pass_shortfall": 0,
20
+ "one_pass_shortfall": 0
21
+ },
22
+ "python_documentation": {
23
+ "target": 500000000,
24
+ "unique_train_targets": 638756689,
25
+ "validation_targets": 32309371,
26
+ "required_passes": 0.782770667783958,
27
+ "two_pass_shortfall": 0,
28
+ "one_pass_shortfall": 0
29
+ },
30
+ "cs_math": {
31
+ "target": 250000000,
32
+ "unique_train_targets": 255001393,
33
+ "validation_targets": 31729746,
34
+ "required_passes": 0.9803868012595524,
35
+ "two_pass_shortfall": 0,
36
+ "one_pass_shortfall": 0
37
+ },
38
+ "general_education": {
39
+ "target": 150000000,
40
+ "unique_train_targets": 153000047,
41
+ "validation_targets": 59391033,
42
+ "required_passes": 0.9803918556966195,
43
+ "two_pass_shortfall": 0,
44
+ "one_pass_shortfall": 0
45
+ },
46
+ "books": {
47
+ "target": 100000000,
48
+ "unique_train_targets": 102061503,
49
+ "validation_targets": 14413928,
50
+ "required_passes": 0.9798013654570618,
51
+ "two_pass_shortfall": 0,
52
+ "one_pass_shortfall": 0
53
+ }
54
+ },
55
+ "capacity_sufficient": true,
56
+ "rejections": {
57
+ "repository_license_unresolved": 5,
58
+ "generated": 37974,
59
+ "not_python_material": 15299,
60
+ "size": 1236,
61
+ "notice_or_changelog": 121,
62
+ "minified_or_long_line": 171,
63
+ "exact_duplicate": 910960,
64
+ "malformed_or_size": 19,
65
+ "boilerplate": 566,
66
+ "excluded_path": 76203,
67
+ "repository_one_percent_cap": 1372,
68
+ "reserved_or_empty_encoding": 4,
69
+ "invalid_python3": 175412,
70
+ "non_utf8": 17,
71
+ "reserved_test_record": 203318,
72
+ "heldout_hash_exclusion": 273597,
73
+ "older_collected_repository_version": 1440,
74
+ "heldout_repository_exclusion": 287838,
75
+ "placeholder_test_scaffold": 23,
76
+ "documentation_references_heldout_repository": 2926,
77
+ "python2_specific_documentation": 5529
78
+ },
79
+ "repository_count": 58,
80
+ "by_origin": [
81
+ {
82
+ "category": "books",
83
+ "origin": "existing_pinned_pool",
84
+ "documents": 923,
85
+ "unique_train_targets": 102061503
86
+ },
87
+ {
88
+ "category": "cs_math",
89
+ "origin": "existing_pinned_pool",
90
+ "documents": 153044,
91
+ "unique_train_targets": 255001393
92
+ },
93
+ {
94
+ "category": "general_education",
95
+ "origin": "existing_pinned_pool",
96
+ "documents": 113805,
97
+ "unique_train_targets": 153000047
98
+ },
99
+ {
100
+ "category": "python_documentation",
101
+ "origin": "collected_git",
102
+ "documents": 8796,
103
+ "unique_train_targets": 27901636
104
+ },
105
+ {
106
+ "category": "python_documentation",
107
+ "origin": "existing_pinned_pool",
108
+ "documents": 55,
109
+ "unique_train_targets": 1975348
110
+ },
111
+ {
112
+ "category": "python_documentation",
113
+ "origin": "python_explanatory_qa",
114
+ "documents": 620563,
115
+ "unique_train_targets": 608879705
116
+ },
117
+ {
118
+ "category": "python_implementation",
119
+ "origin": "collected_git",
120
+ "documents": 10392,
121
+ "unique_train_targets": 41406577
122
+ },
123
+ {
124
+ "category": "python_implementation",
125
+ "origin": "existing_pinned_pool",
126
+ "documents": 708699,
127
+ "unique_train_targets": 1422349105
128
+ },
129
+ {
130
+ "category": "python_implementation",
131
+ "origin": "supplemental_python_file",
132
+ "documents": 870723,
133
+ "unique_train_targets": 1881084752
134
+ },
135
+ {
136
+ "category": "python_tests_examples",
137
+ "origin": "collected_git",
138
+ "documents": 11828,
139
+ "unique_train_targets": 38755717
140
+ },
141
+ {
142
+ "category": "python_tests_examples",
143
+ "origin": "existing_pinned_pool",
144
+ "documents": 274648,
145
+ "unique_train_targets": 680803158
146
+ },
147
+ {
148
+ "category": "python_tests_examples",
149
+ "origin": "supplemental_python_file",
150
+ "documents": 281242,
151
+ "unique_train_targets": 736400642
152
+ }
153
+ ]
154
+ }
capacity.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ | Category | Target | Unique train targets | Validation targets | Required passes | Two-pass shortfall |
2
+ |---|---:|---:|---:|---:|---:|
3
+ | python_implementation | 3,250,000,000 | 3,344,840,434 | 202,402,128 | 0.972 | 0 |
4
+ | python_tests_examples | 750,000,000 | 1,455,959,517 | 88,631,252 | 0.515 | 0 |
5
+ | python_documentation | 500,000,000 | 638,756,689 | 32,309,371 | 0.783 | 0 |
6
+ | cs_math | 250,000,000 | 255,001,393 | 31,729,746 | 0.980 | 0 |
7
+ | general_education | 150,000,000 | 153,000,047 | 59,391,033 | 0.980 | 0 |
8
+ | books | 100,000,000 | 102,061,503 | 14,413,928 | 0.980 | 0 |
config.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "n_layer": 14,
3
+ "n_head": 12,
4
+ "n_embd": 768,
5
+ "vocab_size": 32768,
6
+ "block_size": 8192,
7
+ "architecture_version": 2
8
+ }
data-manifest.json ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "format": "scholarly-raw-v1",
3
+ "training_ready": true,
4
+ "max_passes": 2,
5
+ "experiment": "python-124m-muon-5b",
6
+ "prefer_collected": true,
7
+ "target_tokens": 5000000000,
8
+ "tokenizer_sha256": "add5b2c7542e4efded329735825ecdcb94df1432617c3d3e4b7508aa459432f9",
9
+ "database": {
10
+ "path": "raw.sqlite",
11
+ "sha256": "3942c0e7edccc426cbf7f0c3b9d69144f0511960a36e6615151645c38da41565"
12
+ },
13
+ "sources": {
14
+ "python_implementation": {
15
+ "weight_percent": 65,
16
+ "target_tokens": 3250000000,
17
+ "max_passes": 1,
18
+ "splits": {
19
+ "train": {
20
+ "loss_tokens": 3344840434
21
+ },
22
+ "validation": {
23
+ "loss_tokens": 202402128
24
+ }
25
+ }
26
+ },
27
+ "python_tests_examples": {
28
+ "weight_percent": 15,
29
+ "target_tokens": 750000000,
30
+ "max_passes": 1,
31
+ "splits": {
32
+ "train": {
33
+ "loss_tokens": 1455959517
34
+ },
35
+ "validation": {
36
+ "loss_tokens": 88631252
37
+ }
38
+ }
39
+ },
40
+ "python_documentation": {
41
+ "weight_percent": 10,
42
+ "target_tokens": 500000000,
43
+ "max_passes": 1,
44
+ "splits": {
45
+ "train": {
46
+ "loss_tokens": 638756689
47
+ },
48
+ "validation": {
49
+ "loss_tokens": 32309371
50
+ }
51
+ }
52
+ },
53
+ "cs_math": {
54
+ "weight_percent": 5,
55
+ "target_tokens": 250000000,
56
+ "max_passes": 1,
57
+ "splits": {
58
+ "train": {
59
+ "loss_tokens": 255001393
60
+ },
61
+ "validation": {
62
+ "loss_tokens": 31729746
63
+ }
64
+ }
65
+ },
66
+ "general_education": {
67
+ "weight_percent": 3,
68
+ "target_tokens": 150000000,
69
+ "max_passes": 1,
70
+ "splits": {
71
+ "train": {
72
+ "loss_tokens": 153000047
73
+ },
74
+ "validation": {
75
+ "loss_tokens": 59391033
76
+ }
77
+ }
78
+ },
79
+ "books": {
80
+ "weight_percent": 2,
81
+ "target_tokens": 100000000,
82
+ "max_passes": 1,
83
+ "splits": {
84
+ "train": {
85
+ "loss_tokens": 102061503
86
+ },
87
+ "validation": {
88
+ "loss_tokens": 14413928
89
+ }
90
+ }
91
+ }
92
+ },
93
+ "heldout": {
94
+ "path": "heldout.jsonl.gz",
95
+ "sha256": "58ed450084b99893f1e1b09d8f7556653ab36a66db1eb41644e8f92029490325",
96
+ "windows": 192,
97
+ "tokenizer_sha256": "add5b2c7542e4efded329735825ecdcb94df1432617c3d3e4b7508aa459432f9"
98
+ },
99
+ "limitations": [
100
+ "Exact file/document deduplication; near clones can remain",
101
+ "Path and content heuristics are imperfect",
102
+ "Documentation includes explanatory Python technical Q&A",
103
+ "Collected recent repositories preferred; supplements include older material",
104
+ "No benchmark-contamination claim; detailed source provenance remains private"
105
+ ]
106
+ }
data-provenance.json ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "experiment": "python-124m-muon-5b",
3
+ "public_source_snapshots": [
4
+ {
5
+ "dataset": "codeparrot/codeparrot-clean-train",
6
+ "revision": "3e6ab65f2864931e041f6a82db9b5a6ec2b71ab4",
7
+ "representation": "complete Python files; dataset snapshot is pinned, individual upstream Git commits are not supplied"
8
+ },
9
+ {
10
+ "dataset": "common-pile/stackexchange",
11
+ "revision": "5ec3aa2e65b7c61b7c18f1ff18ccbc4d3279a23c",
12
+ "representation": "complete explanatory Python Stack Overflow threads with per-record CC-BY-SA attribution"
13
+ }
14
+ ],
15
+ "collected_repositories": "Complete pinned Git blobs from the user's collected snapshots; prefer recent snapshots and consume retained collected files first within each category. Repository identities, commits and notices remain in the private ledger.",
16
+ "existing_source_pools": "Pinned prepared CodeParrot, FineWeb-Edu, FineMath, Gutenberg and programming-documentation pools. Original database hashes, upstream record metadata and license evidence remain in the private ledger.",
17
+ "filters": [
18
+ "Exclusive implementation, tests/examples, Python documentation and supporting-text categories",
19
+ "Exclude vendored, generated, minified, boilerplate-heavy and malformed files; preserve accepted text unchanged",
20
+ "Python 3.12 AST validation; newer syntax can be conservatively excluded",
21
+ "Exact file/document deduplication across sources; near clones can remain",
22
+ "Per-repository/category cap of 1 percent of that category's training budget",
23
+ "Repository/thread holdouts before window construction; cross-source heldout repository and exact document-hash exclusions",
24
+ "Exclude exact MBPP reference hashes; no exhaustive benchmark-contamination claim"
25
+ ],
26
+ "token_accounting": "Nonpadding next-token labels, including each document's EOS target. Existing frozen tokenizer; exact six-category budgets; prefer one pass, never exceed two.",
27
+ "limitations": "Supplemental code and technical Q&A include older material. Heuristic filters and upstream licensing metadata are imperfect. Detailed provenance is retained privately; this file contains only aggregate and public-source information.",
28
+ "corpus_database_sha256": "3942c0e7edccc426cbf7f0c3b9d69144f0511960a36e6615151645c38da41565",
29
+ "tokenizer_sha256": "add5b2c7542e4efded329735825ecdcb94df1432617c3d3e4b7508aa459432f9",
30
+ "capacity_by_origin": [
31
+ {
32
+ "category": "books",
33
+ "origin": "existing_pinned_pool",
34
+ "documents": 923,
35
+ "unique_train_targets": 102061503
36
+ },
37
+ {
38
+ "category": "cs_math",
39
+ "origin": "existing_pinned_pool",
40
+ "documents": 153044,
41
+ "unique_train_targets": 255001393
42
+ },
43
+ {
44
+ "category": "general_education",
45
+ "origin": "existing_pinned_pool",
46
+ "documents": 113805,
47
+ "unique_train_targets": 153000047
48
+ },
49
+ {
50
+ "category": "python_documentation",
51
+ "origin": "collected_git",
52
+ "documents": 8796,
53
+ "unique_train_targets": 27901636
54
+ },
55
+ {
56
+ "category": "python_documentation",
57
+ "origin": "existing_pinned_pool",
58
+ "documents": 55,
59
+ "unique_train_targets": 1975348
60
+ },
61
+ {
62
+ "category": "python_documentation",
63
+ "origin": "python_explanatory_qa",
64
+ "documents": 620563,
65
+ "unique_train_targets": 608879705
66
+ },
67
+ {
68
+ "category": "python_implementation",
69
+ "origin": "collected_git",
70
+ "documents": 10392,
71
+ "unique_train_targets": 41406577
72
+ },
73
+ {
74
+ "category": "python_implementation",
75
+ "origin": "existing_pinned_pool",
76
+ "documents": 708699,
77
+ "unique_train_targets": 1422349105
78
+ },
79
+ {
80
+ "category": "python_implementation",
81
+ "origin": "supplemental_python_file",
82
+ "documents": 870723,
83
+ "unique_train_targets": 1881084752
84
+ },
85
+ {
86
+ "category": "python_tests_examples",
87
+ "origin": "collected_git",
88
+ "documents": 11828,
89
+ "unique_train_targets": 38755717
90
+ },
91
+ {
92
+ "category": "python_tests_examples",
93
+ "origin": "existing_pinned_pool",
94
+ "documents": 274648,
95
+ "unique_train_targets": 680803158
96
+ },
97
+ {
98
+ "category": "python_tests_examples",
99
+ "origin": "supplemental_python_file",
100
+ "documents": 281242,
101
+ "unique_train_targets": 736400642
102
+ }
103
+ ]
104
+ }
evaluation.json ADDED
The diff for this file is too large to render. See raw diff
 
evaluations/000050065393-evaluated.json ADDED
The diff for this file is too large to render. See raw diff
 
execution-harness.json ADDED
@@ -0,0 +1,369 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "reference_harness": true,
3
+ "execution": [
4
+ {
5
+ "task_id": 20,
6
+ "passed": true,
7
+ "sandbox_id": "sb-01M5DZ71RN4QV6MRSND68C55PG",
8
+ "returncode": 0,
9
+ "network": "blocked",
10
+ "credentials": "none",
11
+ "cpu_seconds_limit": 2,
12
+ "wall_seconds_limit": 10,
13
+ "address_space_bytes_limit": 268435456
14
+ },
15
+ {
16
+ "task_id": 307,
17
+ "passed": true,
18
+ "sandbox_id": "sb-01M5DZ71JXJBAF4EAD0B8BJMWM",
19
+ "returncode": 0,
20
+ "network": "blocked",
21
+ "credentials": "none",
22
+ "cpu_seconds_limit": 2,
23
+ "wall_seconds_limit": 10,
24
+ "address_space_bytes_limit": 268435456
25
+ },
26
+ {
27
+ "task_id": 226,
28
+ "passed": true,
29
+ "sandbox_id": "sb-01M5DZ71NFAA1WFH8JJGBQ61C3",
30
+ "returncode": 0,
31
+ "network": "blocked",
32
+ "credentials": "none",
33
+ "cpu_seconds_limit": 2,
34
+ "wall_seconds_limit": 10,
35
+ "address_space_bytes_limit": 268435456
36
+ },
37
+ {
38
+ "task_id": 415,
39
+ "passed": true,
40
+ "sandbox_id": "sb-01M5DZ729EHQR68Y3WDS52A7KH",
41
+ "returncode": 0,
42
+ "network": "blocked",
43
+ "credentials": "none",
44
+ "cpu_seconds_limit": 2,
45
+ "wall_seconds_limit": 10,
46
+ "address_space_bytes_limit": 268435456
47
+ },
48
+ {
49
+ "task_id": 230,
50
+ "passed": true,
51
+ "sandbox_id": "sb-01M5DZ7250MQ00RRXR689TA84J",
52
+ "returncode": 0,
53
+ "network": "blocked",
54
+ "credentials": "none",
55
+ "cpu_seconds_limit": 2,
56
+ "wall_seconds_limit": 10,
57
+ "address_space_bytes_limit": 268435456
58
+ },
59
+ {
60
+ "task_id": 394,
61
+ "passed": true,
62
+ "sandbox_id": "sb-01M5DZ72EK9NNG5HD1DYJ0K8CW",
63
+ "returncode": 0,
64
+ "network": "blocked",
65
+ "credentials": "none",
66
+ "cpu_seconds_limit": 2,
67
+ "wall_seconds_limit": 10,
68
+ "address_space_bytes_limit": 268435456
69
+ },
70
+ {
71
+ "task_id": 429,
72
+ "passed": true,
73
+ "sandbox_id": "sb-01M5DZ72BKY2A8RNRRW0WF9A7C",
74
+ "returncode": 0,
75
+ "network": "blocked",
76
+ "credentials": "none",
77
+ "cpu_seconds_limit": 2,
78
+ "wall_seconds_limit": 10,
79
+ "address_space_bytes_limit": 268435456
80
+ },
81
+ {
82
+ "task_id": 108,
83
+ "passed": true,
84
+ "sandbox_id": "sb-01M5DZ72PYNRXBZ0EG7Z19JZZQ",
85
+ "returncode": 0,
86
+ "network": "blocked",
87
+ "credentials": "none",
88
+ "cpu_seconds_limit": 2,
89
+ "wall_seconds_limit": 10,
90
+ "address_space_bytes_limit": 268435456
91
+ },
92
+ {
93
+ "task_id": 397,
94
+ "passed": true,
95
+ "sandbox_id": "sb-01M5DZ72T6DF5PMGJJ57EJ26XE",
96
+ "returncode": 0,
97
+ "network": "blocked",
98
+ "credentials": "none",
99
+ "cpu_seconds_limit": 2,
100
+ "wall_seconds_limit": 10,
101
+ "address_space_bytes_limit": 268435456
102
+ },
103
+ {
104
+ "task_id": 120,
105
+ "passed": true,
106
+ "sandbox_id": "sb-01M5DZ72WH6H92HH0G68VB39JW",
107
+ "returncode": 0,
108
+ "network": "blocked",
109
+ "credentials": "none",
110
+ "cpu_seconds_limit": 2,
111
+ "wall_seconds_limit": 10,
112
+ "address_space_bytes_limit": 268435456
113
+ },
114
+ {
115
+ "task_id": 451,
116
+ "passed": true,
117
+ "sandbox_id": "sb-01M5DZ732M07ZYWK6EVT0FVQ6V",
118
+ "returncode": 0,
119
+ "network": "blocked",
120
+ "credentials": "none",
121
+ "cpu_seconds_limit": 2,
122
+ "wall_seconds_limit": 10,
123
+ "address_space_bytes_limit": 268435456
124
+ },
125
+ {
126
+ "task_id": 454,
127
+ "passed": true,
128
+ "sandbox_id": "sb-01M5DZ73E6PDK4BF7DD4W2VFAA",
129
+ "returncode": 0,
130
+ "network": "blocked",
131
+ "credentials": "none",
132
+ "cpu_seconds_limit": 2,
133
+ "wall_seconds_limit": 10,
134
+ "address_space_bytes_limit": 268435456
135
+ },
136
+ {
137
+ "task_id": 472,
138
+ "passed": true,
139
+ "sandbox_id": "sb-01M5DZ73B7TKG8K0ZSG5H4QJRB",
140
+ "returncode": 0,
141
+ "network": "blocked",
142
+ "credentials": "none",
143
+ "cpu_seconds_limit": 2,
144
+ "wall_seconds_limit": 10,
145
+ "address_space_bytes_limit": 268435456
146
+ },
147
+ {
148
+ "task_id": 431,
149
+ "passed": true,
150
+ "sandbox_id": "sb-01M5DZ73G81G4JTH1M768BCA2J",
151
+ "returncode": 0,
152
+ "network": "blocked",
153
+ "credentials": "none",
154
+ "cpu_seconds_limit": 2,
155
+ "wall_seconds_limit": 10,
156
+ "address_space_bytes_limit": 268435456
157
+ },
158
+ {
159
+ "task_id": 257,
160
+ "passed": true,
161
+ "sandbox_id": "sb-01M5DZ73TQ9EWGKAS7KXSV2C77",
162
+ "returncode": 0,
163
+ "network": "blocked",
164
+ "credentials": "none",
165
+ "cpu_seconds_limit": 2,
166
+ "wall_seconds_limit": 10,
167
+ "address_space_bytes_limit": 268435456
168
+ },
169
+ {
170
+ "task_id": 290,
171
+ "passed": true,
172
+ "sandbox_id": "sb-01M5DZ73MQEE4BTZN58ESSB0P6",
173
+ "returncode": 0,
174
+ "network": "blocked",
175
+ "credentials": "none",
176
+ "cpu_seconds_limit": 2,
177
+ "wall_seconds_limit": 10,
178
+ "address_space_bytes_limit": 268435456
179
+ },
180
+ {
181
+ "task_id": 237,
182
+ "passed": true,
183
+ "sandbox_id": "sb-01M5DZ7402RZ6P5Z249KA42WY2",
184
+ "returncode": 0,
185
+ "network": "blocked",
186
+ "credentials": "none",
187
+ "cpu_seconds_limit": 2,
188
+ "wall_seconds_limit": 10,
189
+ "address_space_bytes_limit": 268435456
190
+ },
191
+ {
192
+ "task_id": 297,
193
+ "passed": true,
194
+ "sandbox_id": "sb-01M5DZ741ZHWYDB45BPHT5R46M",
195
+ "returncode": 0,
196
+ "network": "blocked",
197
+ "credentials": "none",
198
+ "cpu_seconds_limit": 2,
199
+ "wall_seconds_limit": 10,
200
+ "address_space_bytes_limit": 268435456
201
+ },
202
+ {
203
+ "task_id": 247,
204
+ "passed": true,
205
+ "sandbox_id": "sb-01M5DZ740MSG2GXGNDDG4KBWXK",
206
+ "returncode": 0,
207
+ "network": "blocked",
208
+ "credentials": "none",
209
+ "cpu_seconds_limit": 2,
210
+ "wall_seconds_limit": 10,
211
+ "address_space_bytes_limit": 268435456
212
+ },
213
+ {
214
+ "task_id": 401,
215
+ "passed": true,
216
+ "sandbox_id": "sb-01M5DZ746PRGKM95006RTJ7KYY",
217
+ "returncode": 0,
218
+ "network": "blocked",
219
+ "credentials": "none",
220
+ "cpu_seconds_limit": 2,
221
+ "wall_seconds_limit": 10,
222
+ "address_space_bytes_limit": 268435456
223
+ },
224
+ {
225
+ "task_id": 283,
226
+ "passed": true,
227
+ "sandbox_id": "sb-01M5DZ74F032TWXAAMS4Y9FXYG",
228
+ "returncode": 0,
229
+ "network": "blocked",
230
+ "credentials": "none",
231
+ "cpu_seconds_limit": 2,
232
+ "wall_seconds_limit": 10,
233
+ "address_space_bytes_limit": 268435456
234
+ },
235
+ {
236
+ "task_id": 391,
237
+ "passed": true,
238
+ "sandbox_id": "sb-01M5DZ74GMQ2RNYNTBAY7MHSK1",
239
+ "returncode": 0,
240
+ "network": "blocked",
241
+ "credentials": "none",
242
+ "cpu_seconds_limit": 2,
243
+ "wall_seconds_limit": 10,
244
+ "address_space_bytes_limit": 268435456
245
+ },
246
+ {
247
+ "task_id": 305,
248
+ "passed": true,
249
+ "sandbox_id": "sb-01M5DZ74QKAVTNDMRPVDK6QEPR",
250
+ "returncode": 0,
251
+ "network": "blocked",
252
+ "credentials": "none",
253
+ "cpu_seconds_limit": 2,
254
+ "wall_seconds_limit": 10,
255
+ "address_space_bytes_limit": 268435456
256
+ },
257
+ {
258
+ "task_id": 67,
259
+ "passed": true,
260
+ "sandbox_id": "sb-01M5DZ74SH9J7WV1PVCTGYW6K2",
261
+ "returncode": 0,
262
+ "network": "blocked",
263
+ "credentials": "none",
264
+ "cpu_seconds_limit": 2,
265
+ "wall_seconds_limit": 10,
266
+ "address_space_bytes_limit": 268435456
267
+ },
268
+ {
269
+ "task_id": 460,
270
+ "passed": true,
271
+ "sandbox_id": "sb-01M5DZ751FXJ1VV5YZCNQR91Y8",
272
+ "returncode": 0,
273
+ "network": "blocked",
274
+ "credentials": "none",
275
+ "cpu_seconds_limit": 2,
276
+ "wall_seconds_limit": 10,
277
+ "address_space_bytes_limit": 268435456
278
+ },
279
+ {
280
+ "task_id": 12,
281
+ "passed": true,
282
+ "sandbox_id": "sb-01M5DZ750Z83GFKT90W0GP13HM",
283
+ "returncode": 0,
284
+ "network": "blocked",
285
+ "credentials": "none",
286
+ "cpu_seconds_limit": 2,
287
+ "wall_seconds_limit": 10,
288
+ "address_space_bytes_limit": 268435456
289
+ },
290
+ {
291
+ "task_id": 70,
292
+ "passed": true,
293
+ "sandbox_id": "sb-01M5DZ7599NFB6B31RF04NVE4F",
294
+ "returncode": 0,
295
+ "network": "blocked",
296
+ "credentials": "none",
297
+ "cpu_seconds_limit": 2,
298
+ "wall_seconds_limit": 10,
299
+ "address_space_bytes_limit": 268435456
300
+ },
301
+ {
302
+ "task_id": 277,
303
+ "passed": true,
304
+ "sandbox_id": "sb-01M5DZ75ENPGS36Z3J4GYZ428F",
305
+ "returncode": 0,
306
+ "network": "blocked",
307
+ "credentials": "none",
308
+ "cpu_seconds_limit": 2,
309
+ "wall_seconds_limit": 10,
310
+ "address_space_bytes_limit": 268435456
311
+ },
312
+ {
313
+ "task_id": 244,
314
+ "passed": true,
315
+ "sandbox_id": "sb-01M5DZ75F80K8KH4A48JVWFY87",
316
+ "returncode": 0,
317
+ "network": "blocked",
318
+ "credentials": "none",
319
+ "cpu_seconds_limit": 2,
320
+ "wall_seconds_limit": 10,
321
+ "address_space_bytes_limit": 268435456
322
+ },
323
+ {
324
+ "task_id": 19,
325
+ "passed": true,
326
+ "sandbox_id": "sb-01M5DZ75K6QYA0KWK4GG0CBTES",
327
+ "returncode": 0,
328
+ "network": "blocked",
329
+ "credentials": "none",
330
+ "cpu_seconds_limit": 2,
331
+ "wall_seconds_limit": 10,
332
+ "address_space_bytes_limit": 268435456
333
+ },
334
+ {
335
+ "task_id": 72,
336
+ "passed": true,
337
+ "sandbox_id": "sb-01M5DZ75FEKS3JTBMK17280T9Y",
338
+ "returncode": 0,
339
+ "network": "blocked",
340
+ "credentials": "none",
341
+ "cpu_seconds_limit": 2,
342
+ "wall_seconds_limit": 10,
343
+ "address_space_bytes_limit": 268435456
344
+ },
345
+ {
346
+ "task_id": 457,
347
+ "passed": true,
348
+ "sandbox_id": "sb-01M5DZ75V55YCBXKGE9K1KQC1M",
349
+ "returncode": 0,
350
+ "network": "blocked",
351
+ "credentials": "none",
352
+ "cpu_seconds_limit": 2,
353
+ "wall_seconds_limit": 10,
354
+ "address_space_bytes_limit": 268435456
355
+ },
356
+ {
357
+ "task_id": "isolation_probe",
358
+ "passed": true,
359
+ "sandbox_id": "sb-01M5DZ75SSWDD1CEAWE4X9RN4Y",
360
+ "returncode": 0,
361
+ "network": "blocked",
362
+ "credentials": "none",
363
+ "cpu_seconds_limit": 2,
364
+ "wall_seconds_limit": 10,
365
+ "address_space_bytes_limit": 268435456
366
+ }
367
+ ],
368
+ "execution_pass_rate": 1.0
369
+ }
generate.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Generate text with the standalone Python model with the fixed evaluation sampling policy."""
2
+
3
+ import argparse
4
+ import json
5
+ from pathlib import Path
6
+
7
+ import torch
8
+ from model_100m.model import GPT, ModelConfig
9
+ from safetensors.torch import load_file
10
+ from tokenizers import Tokenizer
11
+
12
+ p = argparse.ArgumentParser(description=__doc__)
13
+ p.add_argument("--prompt", default="The solar system consists of")
14
+ p.add_argument("--tokens", type=int, default=128)
15
+ p.add_argument("--seed", type=int, default=42)
16
+ p.add_argument("--temperature", type=float, default=0.8, help="0 selects greedy decoding")
17
+ p.add_argument("--top-k", type=int, default=50, help="0 samples the full vocabulary")
18
+ p.add_argument("--device", default="cpu", choices=["cpu", "cuda"])
19
+ a = p.parse_args()
20
+ if a.tokens < 0 or a.temperature < 0 or a.top_k < 0:
21
+ p.error("Generation settings must be nonnegative")
22
+ root = Path(__file__).resolve().parent
23
+ torch.set_num_threads(2)
24
+ torch.manual_seed(a.seed)
25
+ model = GPT(ModelConfig(**json.loads((root / "config.json").read_text()))).to(a.device).eval()
26
+ model.load_state_dict(load_file(str(root / "model.safetensors")), strict=True)
27
+ tokenizer = Tokenizer.from_file(str(root / "tokenizer/tokenizer.json"))
28
+ ids = [1] + tokenizer.encode(a.prompt, add_special_tokens=False).ids
29
+ generator = torch.Generator(device=a.device).manual_seed(a.seed)
30
+ torch.backends.cuda.matmul.allow_tf32 = False
31
+ torch.backends.cudnn.allow_tf32 = False
32
+ with torch.inference_mode():
33
+ for _ in range(a.tokens):
34
+ logits = model(torch.tensor([ids[-model.config.block_size :]], device=a.device))[
35
+ 0, -1
36
+ ].float()
37
+ if not torch.isfinite(logits).all():
38
+ raise ValueError("Non-finite generation logits")
39
+ logits[[0, 1, 3]] = -torch.inf # PAD/BOS/UNK; EOS remains eligible.
40
+ if a.temperature == 0:
41
+ token = int(logits.argmax())
42
+ elif a.top_k:
43
+ values, indices = torch.topk(logits / a.temperature, min(a.top_k, logits.numel()))
44
+ token = int(indices[torch.multinomial(values.softmax(-1), 1, generator=generator)])
45
+ else:
46
+ token = int(
47
+ torch.multinomial((logits / a.temperature).softmax(-1), 1, generator=generator)
48
+ )
49
+ ids.append(token)
50
+ if token == 2:
51
+ break
52
+ print(tokenizer.decode(ids, skip_special_tokens=True))
metrics.jsonl ADDED
The diff for this file is too large to render. See raw diff
 
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8e5e55c0beaac47b09427c261d7dc7a9b94240758b6e0f3724d419ed43d8c1f5
3
+ size 598238584
model_100m/PILOT.md ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Scholarly/code subword pilot
2
+
3
+ `modal_scholarly_pilot.py` connects the merged modern 100M-family model to the
4
+ frozen 32K tokenizer and `TokenMixture`. It preserves the merged 14×768 shape
5
+ (124,389,632 unique parameters), with context increased to 1,024. This is a
6
+ bounded execution/learning pilot, not the planned 20B-token run.
7
+
8
+ From `training/`, first prepare a fresh snapshot with `modal_prepare_scholarly.py`.
9
+ Then:
10
+
11
+ ```sh
12
+ modal run --detach modal_scholarly_pilot.py \
13
+ --run-id scholarly-124m-pilot-20261016-01 \
14
+ --snapshot scholarly-124m-20261016/snapshots/pilot-001
15
+ ```
16
+
17
+ One L40S worker, four CPUs, 16 GiB host RAM, no retries, and a 30-minute hard
18
+ worker timeout. Training stops at 600 optimizer updates, 5M loss-bearing tokens,
19
+ 20 minutes including intermediate checkpoint overhead, or source exhaustion.
20
+ The existing loader enforces at most two passes per source. No full pretraining
21
+ or automatic continuation is launched. The pilot deliberately permits snapshots
22
+ with pending corpus audits; this override must not be used for substantial runs.
23
+
24
+ Optimization: FP32 parameters, BF16 autocast, AdamW (betas 0.9/0.95, weight decay
25
+ 0.1), gradient norm clipping at 1, linear 30-update warmup to 3e-4 then constant
26
+ learning rate. Batch size 2 with four accumulated microbatches; gradients are
27
+ normalized by actual nonpadding targets across the complete optimizer batch.
28
+ This short pilot does not select a production learning-rate schedule.
29
+
30
+ The CPU qualification runs modern-model, tied-embedding and corpus-loader tests.
31
+ The GPU worker verifies tiny-set fitting, then reloads the actual step-10
32
+ checkpoint and checks identical next-batch IDs, labels and logits. Checkpoints
33
+ include optimizer/RNG/data state, source hashes, model settings, token counts and
34
+ manifest/tokenizer identities. Checkpoints and logs use fresh paths on
35
+ `lm-exploration-training/<run-id>/`; the final report is also copied to `results/`.
36
+ This pilot checkpoint format is separate from the character-only `lm-generate`
37
+ format. Cross-job resume and generation CLI integration remain future work.
38
+
39
+ Validation uses one fixed document-local window per source, reporting each source
40
+ and the token-mixture-weighted mean. This small provisional validation sample is
41
+ for detecting learning/failures, not capability claims or production checkpoint
42
+ selection. Samples use three fixed prompts, seed 42, full-softmax temperature 1,
43
+ and up to 64 new tokens. PAD/BOS/UNK are excluded from sampled outputs.
44
+
45
+ The full corpus still needs split reconciliation, global near deduplication,
46
+ provenance/eligibility and contamination audits, and capacity evidence. Measure
47
+ throughput before selecting the substantial-run hardware and budget. The current
48
+ model retains explicit attention; a supported SDPA kernel is a possible separately
49
+ verified optimization.
50
+
51
+ In the managed cloud environment, Modal's client needs the system CA trust:
52
+ install `modal[api-proxy-support]==1.6.2` and `truststore`, call
53
+ `truststore.inject_into_ssl()` before running the Modal CLI module. Keep inherited
54
+ proxy settings and TLS verification enabled.
55
+
56
+ ## First measured run
57
+
58
+ [The 2026-10-16 report](../results/scholarly-124m-pilot-20261016-01.md) records
59
+ 600 updates / 4,078,340 tokens, weighted pilot validation loss 10.5811 → 6.0272,
60
+ 23 passing qualification tests, and a successful checkpoint/data reload.
61
+ The final checkpoint is `lm-exploration-training/scholarly-124m-pilot-20261016-01/step-000600.pt`.
62
+ Samples remain incoherent; full corpus audits and substantial training are pending.
model_100m/README.md ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Updated 100M-family architecture
2
+
3
+ A subsequent [bounded subword pilot](PILOT.md) trained this architecture for
4
+ 4.08M tokens on Modal. See its [measured report](../results/scholarly-124m-pilot-20261016-01.md);
5
+ the architecture-merge verification described below remains separate.
6
+
7
+ `model.py` uses **RMSNorm, RoPE, SwiGLU and tied input/output embeddings** by
8
+ default. There is one `100m` model choice, keeping 14 layers, width 768, 12 ordinary
9
+ attention heads (head dimension 64) and context 256. The original vanilla 10M
10
+ model and its individual ablation PRs are unchanged.
11
+
12
+ | Component | Current default |
13
+ | --- | --- |
14
+ | Normalization | Pre-RMSNorm and final RMSNorm, epsilon 1e-5 |
15
+ | Positions | RoPE on Q/K in every layer, theta 10,000 |
16
+ | Feedforward | SwiGLU, hidden width 2,048 |
17
+ | Projection biases | Present |
18
+ | Attention kernel | PyTorch causal scaled-dot-product attention (SDPA) |
19
+ | Initialization | Normal std 0.02 |
20
+ | Input/output weights | One shared Parameter |
21
+
22
+ ## Mechanisms and references
23
+
24
+ - **RMSNorm:** `gamma * x / sqrt(mean(x**2) + epsilon)` omits mean centering and
25
+ normalization offsets. Epsilon matches historical LayerNorm; low-precision
26
+ statistics accumulate in FP32. [Zhang & Sennrich (2019)](https://arxiv.org/abs/1910.07467)
27
+ motivate simpler normalization. Actual speed depends on kernels.
28
+ - **RoPE:** rotates adjacent query/key feature pairs; values stay unchanged.
29
+ The positional dependence of Q/K dot products is relative.
30
+ [RoFormer, Su et al. (2021)](https://arxiv.org/abs/2104.09864) gives the construction.
31
+ Context remains capped by `block_size`: no GQA, KV cache or long-context scaling.
32
+ - **SwiGLU:** `down(SiLU(gate(x)) * up(x))` provides input-dependent feature
33
+ modulation. Hidden width `ceil(8 * width / 3)` exactly matches the old MLP's
34
+ matrix-parameter budget at width 768. Projections keep biases.
35
+ [Shazeer (2020)](https://arxiv.org/abs/2002.05202) reports matched-budget T5 gains;
36
+ that motivates a causal-GPT experiment, not a claimed improvement here.
37
+ - **Tied embeddings:** `self.lm_head.weight = self.token_embedding.weight`.
38
+ The shared table `E[vocabulary, width]` supplies input rows and output logits
39
+ `hidden @ E.T`. Gradients from both uses accumulate into the same Parameter,
40
+ which appears once in the optimizer's parameter list.
41
+ [Press & Wolf (2017)](https://arxiv.org/abs/1608.05859) study the parameter/quality
42
+ tradeoff. Sharing saves parameters but constrains the representations.
43
+
44
+ [LLaMA §2.2](https://arxiv.org/abs/2302.13971) adopts RMSNorm, RoPE and SwiGLU.
45
+ This update combines the requested choices; it cannot establish each component's
46
+ quality contribution. The individual 10M ablations serve that purpose. No quality
47
+ gain has been measured for this combined model.
48
+
49
+ ## Frozen tokenizer and parameter count
50
+
51
+ Use merged `structured-code-v1`: **32,768 entries**, unchanged tokenizer hash
52
+ `add5b2c7542e4efded329735825ecdcb94df1432617c3d3e4b7508aa459432f9`.
53
+ At context 256 and the unchanged 14×768 shape, the model has **124,389,632 unique
54
+ parameters**. Tying saves **25,165,824** (`32,768 × 768`) versus separate matrices
55
+ on the same modern backbone. There is no maintained untied modern variant,
56
+ separate package or recipe key for tying.
57
+
58
+ The historical vanilla 100M had 149,760,000 parameters at this vocabulary.
59
+ Besides tying, the modern blocks remove 196,608 position parameters and 22,272
60
+ normalization offsets, and add 14,336 FFN bias parameters. FFN matrix parameters
61
+ match. The `100m` label is historical: a 32K vocabulary changes the total relative
62
+ to the character model. No saving is reinvested in extra layers.
63
+
64
+ ## Usage and compatibility
65
+
66
+ ```python
67
+ from model_100m.model import GPT, ModelConfig
68
+
69
+ model = GPT(ModelConfig(vocab_size=32768))
70
+ assert model.lm_head.weight is model.token_embedding.weight
71
+ ```
72
+
73
+ Recipes continue to select `model="100m"`; no tying flag is needed. New checkpoints
74
+ record `architecture_version=2`. A small version-1 compatibility path reuses the
75
+ original vanilla implementation to load historical 100M checkpoints, preserving
76
+ their original untied weights and exact logits. Missing version metadata means
77
+ legacy; the loader does not silently tie or modernize old weights. Resume across
78
+ architecture versions is rejected. This is not a second modern model variant.
79
+
80
+ The general recipe trainer and generation CLI remain character-only. The separate
81
+ [subword pilot](PILOT.md) integrates the frozen BPE tokenizer and mixture loader.
82
+ The [GPU comparison](../results/scholarly-124m-gpu-comparison-20261017.md) measures
83
+ SDPA and fused AdamW on the full model, including two- and three-H100 DDP.
84
+ The historical pilot used explicit attention; its original source is archived
85
+ with its run. SDPA preserves the model shape and checkpoint keys, with output
86
+ and gradient agreement checked against the explicit implementation.
87
+
88
+ ## Verification
89
+
90
+ From `training/`:
91
+
92
+ ```sh
93
+ uv sync --locked --extra corpus --extra research
94
+ uv run --extra corpus --extra research python -m unittest discover -s tests -v
95
+ ```
96
+
97
+ Checks cover independent block output/gradient references, causality, finite
98
+ gradients, counts, config bounds and old checkpoint loading/resume. Tying checks
99
+ cover shared identity, summed gradients against a test-only reference, optimizer
100
+ deduplication, dtype conversion, checkpoint roundtrip and tokenizer ID bounds.
model_100m/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """The architecture-only 100M model, installed by uv as model_100m."""
model_100m/model.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """100M-family decoder: RMSNorm, RoPE, SwiGLU and tied embeddings by default.
2
+
3
+ Keep 14 layers, width 768, 12 MHA heads, context 256, projection biases and
4
+ vanilla weight initialization. architecture_version=1 reproduces the historical
5
+ LayerNorm/learned-position/GELU model only for legacy checkpoint compatibility.
6
+ """
7
+
8
+ from dataclasses import dataclass
9
+
10
+ import torch
11
+ from model_10m import model as vanilla
12
+ from torch import nn
13
+ from torch.nn import functional as F
14
+
15
+ __all__ = ["GPT", "Attention", "Block", "ModelConfig", "RMSNorm", "SwiGLU", "causal_attention"]
16
+ MODEL_DEPENDENCIES = {"model_10m_definition": vanilla.__file__}
17
+
18
+
19
+ @dataclass(frozen=True)
20
+ class ModelConfig(vanilla.ModelConfig):
21
+ n_layer: int = 14
22
+ n_head: int = 12
23
+ n_embd: int = 768
24
+ architecture_version: int = 2
25
+
26
+ def __post_init__(self):
27
+ if type(self.architecture_version) is not int or self.architecture_version not in (1, 2):
28
+ raise ValueError("architecture_version must be 1 (legacy) or 2 (RMSNorm/RoPE/SwiGLU)")
29
+ super().__post_init__()
30
+ if self.architecture_version == 2 and (self.n_embd // self.n_head) % 2:
31
+ raise ValueError("RoPE requires an even head dimension")
32
+
33
+
34
+ def causal_attention(query, key, value):
35
+ """Standard causal SDPA; CUDA selects FlashAttention where supported.
36
+
37
+ Same scale, mask and zero dropout as the explicit 10M reference. The legacy
38
+ architecture retains its original implementation in model_10m.
39
+ """
40
+ return F.scaled_dot_product_attention(query, key, value, is_causal=True, dropout_p=0.0)
41
+
42
+
43
+ class RMSNorm(nn.Module):
44
+ def __init__(self, width, eps=1e-5):
45
+ super().__init__()
46
+ self.weight = nn.Parameter(torch.ones(width))
47
+ self.eps = eps # Match the historical LayerNorm epsilon.
48
+
49
+ def forward(self, x):
50
+ values = x.float() if x.dtype in (torch.float16, torch.bfloat16) else x
51
+ normalized = values * torch.rsqrt(values.square().mean(-1, keepdim=True) + self.eps)
52
+ return normalized.to(x.dtype) * self.weight.to(x.dtype)
53
+
54
+
55
+ def rotary(x, offset=0):
56
+ """Rotate adjacent query/key feature pairs using position and theta 10,000."""
57
+ dtype = torch.float64 if x.dtype == torch.float64 else torch.float32
58
+ frequencies = 10000.0 ** (
59
+ -torch.arange(0, x.size(-1), 2, device=x.device, dtype=dtype) / x.size(-1)
60
+ )
61
+ positions = torch.arange(offset, offset + x.size(-2), device=x.device, dtype=dtype)
62
+ angles = torch.outer(positions, frequencies)
63
+ cos, sin = angles.cos().to(x.dtype), angles.sin().to(x.dtype)
64
+ even, odd = x[..., ::2], x[..., 1::2]
65
+ return torch.stack((even * cos - odd * sin, even * sin + odd * cos), -1).flatten(-2)
66
+
67
+
68
+ class Attention(vanilla.Attention):
69
+ def cache_rotary(self, length):
70
+ width = self.qkv.in_features // self.n_head
71
+ frequencies = 10000.0 ** (
72
+ -torch.arange(0, width, 2, device=self.qkv.weight.device).float() / width
73
+ )
74
+ angles = torch.outer(torch.arange(length, device=frequencies.device).float(), frequencies)
75
+ self.register_buffer("rope_cos", angles.cos(), persistent=False)
76
+ self.register_buffer("rope_sin", angles.sin(), persistent=False)
77
+
78
+ def rotate(self, x):
79
+ if not hasattr(self, "rope_cos"):
80
+ return rotary(x)
81
+ cos = self.rope_cos[: x.size(-2)].to(x.dtype)
82
+ sin = self.rope_sin[: x.size(-2)].to(x.dtype)
83
+ even, odd = x[..., ::2], x[..., 1::2]
84
+ return torch.stack((even * cos - odd * sin, even * sin + odd * cos), -1).flatten(-2)
85
+
86
+ def forward(self, x):
87
+ batch, length, width = x.shape
88
+ query, key, value = self.qkv(x).chunk(3, -1)
89
+ query, key, value = [
90
+ tensor.view(batch, length, self.n_head, width // self.n_head).transpose(1, 2)
91
+ for tensor in (query, key, value)
92
+ ]
93
+ attended = causal_attention(self.rotate(query), self.rotate(key), value)
94
+ return self.projection(attended.transpose(1, 2).contiguous().view(batch, length, width))
95
+
96
+
97
+ class SwiGLU(nn.Module):
98
+ def __init__(self, width):
99
+ super().__init__()
100
+ self.hidden_width = (8 * width + 2) // 3
101
+ self.gate = nn.Linear(width, self.hidden_width)
102
+ self.up = nn.Linear(width, self.hidden_width)
103
+ self.down = nn.Linear(self.hidden_width, width)
104
+
105
+ def forward(self, x):
106
+ return self.down(F.silu(self.gate(x)) * self.up(x))
107
+
108
+
109
+ class Block(vanilla.Block):
110
+ def __init__(self, config):
111
+ super().__init__(config)
112
+ self.attention_norm = RMSNorm(config.n_embd)
113
+ self.attention = Attention(config)
114
+ self.mlp_norm = RMSNorm(config.n_embd)
115
+ self.mlp = SwiGLU(config.n_embd)
116
+
117
+
118
+ class GPT(vanilla.GPT):
119
+ def __init__(self, config):
120
+ if config.architecture_version == 1:
121
+ super().__init__(config)
122
+ return
123
+ nn.Module.__init__(self)
124
+ self.config = config
125
+ self.token_embedding = nn.Embedding(config.vocab_size, config.n_embd)
126
+ self.blocks = nn.Sequential(*(Block(config) for _ in range(config.n_layer)))
127
+ self.final_norm = RMSNorm(config.n_embd)
128
+ self.lm_head = nn.Linear(config.n_embd, config.vocab_size, bias=False)
129
+ self.apply(self.initialize)
130
+ self.lm_head.weight = self.token_embedding.weight
131
+
132
+ def forward(self, tokens, labels=None, loss_chunk_size=0):
133
+ if self.config.architecture_version == 1:
134
+ return super().forward(tokens)
135
+ if not 0 < tokens.size(1) <= self.config.block_size:
136
+ raise ValueError("sequence length must be within the model's block_size")
137
+ hidden = self.final_norm(self.blocks(self.token_embedding(tokens)))
138
+ if labels is None:
139
+ return self.lm_head(hidden)
140
+ if not loss_chunk_size:
141
+ return F.cross_entropy(
142
+ self.lm_head(hidden).flatten(0, 1),
143
+ labels.flatten(),
144
+ ignore_index=-100,
145
+ reduction="sum",
146
+ )
147
+ # Recompute each projection during backward, bounding vocabulary-logit memory.
148
+ from torch.utils.checkpoint import checkpoint
149
+
150
+ def chunk_loss(features, targets):
151
+ return F.cross_entropy(
152
+ self.lm_head(features), targets, ignore_index=-100, reduction="sum"
153
+ )
154
+
155
+ return sum(
156
+ checkpoint(chunk_loss, features, targets, use_reentrant=False)
157
+ for features, targets in zip(
158
+ hidden.flatten(0, 1).split(loss_chunk_size), labels.flatten().split(loss_chunk_size)
159
+ )
160
+ )
model_10m/README.md ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Vanilla Shakespeare GPT, approximately 10M parameters
2
+
3
+ The complete, readable architecture is in [model.py](model.py): six pre-LayerNorm
4
+ causal decoder blocks, width 384, six attention heads, learned positions, GELU
5
+ MLPs, and a separate output projection. With 65 characters and context 256 it has
6
+ **10,795,776 parameters**. The [100M architecture](../100m/README.md) now defaults
7
+ to RMSNorm, RoPE and SwiGLU; its explicit version-1 mode preserves this vanilla
8
+ block design at larger dimensions. This published 10M definition is unchanged.
9
+
10
+ The model starts from random weights and learns next-character prediction from
11
+ Tiny Shakespeare. This is a learning benchmark, not an instruction-following
12
+ assistant. A contiguous 90/10 train/validation split prevents windows crossing
13
+ the boundary; vocabulary is drawn from the whole corpus. There is no sealed test.
14
+
15
+ ## Bounded Modal training
16
+
17
+ Run from `training/`, using a Python environment with Modal's API proxy support.
18
+ The Modal image explicitly pins PyTorch 2.6.0, safetensors 0.8.0 and tqdm 4.70.1,
19
+ independently of the newer version selected by the local training project's lock.
20
+ The executed versions and source hashes are saved in every run's config.
21
+
22
+ The published runs used the former `modal_shakespeare.py` (commit `ec5ebd1`). The
23
+ same settings are now the [`shakespeare-10m` recipe](../recipes/shakespeare-10m.json),
24
+ launched with the generic [recipe launcher](../recipes/README.md) (use a new run ID):
25
+
26
+ ```bash
27
+ uv run --with 'modal[api-proxy-support]==1.6.1' modal run modal_train.py \
28
+ --recipe recipes/shakespeare-10m.json --run-id shakespeare-10m-smoke-02 --smoke
29
+ ```
30
+
31
+ The original runs used app `lm-exploration-shakespeare-10m` and volume
32
+ `lm-exploration-training`. The smoke worker has a 120-second hard timeout; the
33
+ training worker a 1,500-second hard timeout and a cooperative 1,200-second training
34
+ limit. Both use one L4, no retries, and persist artifacts on exit. A separate
35
+ ignored `runs/shakespeare-budget.json` (now `runs/modal-budget.json`) reserved the full worker time at a
36
+ conservative $5/hour, with a $3 allocation ceiling. This is reservation accounting,
37
+ not an actual bill or an account-wide spending limit. No latent-workspace ledger
38
+ or research volume is used.
39
+
40
+ Training targets 4,000 updates with batch 32, context 256, FP32 AdamW,
41
+ learning rate 0.0003, betas (0.9, 0.95), weight decay 0.1, clipping norm 1 and seed
42
+ 1337. Every 200 updates, evaluate 20 fixed-seed validation batches and save a
43
+ checkpoint. Select the saved checkpoint with the lowest validation loss.
44
+ Cooperative stopping logs/evaluates/saves the final completed update. Each run
45
+ writes a report, metrics, source/runtime/dataset provenance and a sample.
46
+
47
+ ## Export and publication
48
+
49
+ The published model was exported with `publish_shakespeare.py`, removed after
50
+ publication (see commit `ec5ebd1`). It exported the validation-selected checkpoint
51
+ to safetensors without optimizer or RNG state, checked the parameter count,
52
+ selected update and architecture hash, and uploaded only inference files.
53
+ The public bundle includes `model.py`, `generate.py`, safetensors weights, exact
54
+ configuration/tokenizer, provenance, requirements and the measured training report.
55
+ From the downloaded bundle run `python generate.py --prompt 'ROMEO:' --tokens 300`.
56
+ The model uses custom PyTorch code, not Transformers AutoModel loading.
57
+
58
+ ## Completed training and public model
59
+
60
+ [Public Hugging Face model](https://huggingface.co/jfrick/shakespeare-vanilla-gpt-10m). The bounded L4 run completed 4,000 updates
61
+ in 503.3 worker seconds, with 32,768,000 training-character
62
+ exposures. Validation selected **update 1,800**, after 14,745,600 exposures:
63
+ **1.54483 nats/character**, character perplexity **4.687**.
64
+ The final update scored 2.10690 on validation; later training overfit this small
65
+ corpus, so the public weights come from the earlier checkpoint.
66
+
67
+ [Full training report](../results/shakespeare-10m-train-01.json),
68
+ [loss history](../results/shakespeare-10m-metrics.jsonl),
69
+ [smoke report](../results/shakespeare-10m-smoke-01.json),
70
+ and [publication receipt](../results/shakespeare-10m-publication.json).
71
+ One seed, validation used for checkpoint selection, no untouched test result.
72
+
73
+ Local verification covered the 10M parameter count, causal attention and gradients
74
+ against SDPA, safe stopping/checkpoint saving, reproducible CPU resume, and exact
75
+ exported logits/seeded generation against the selected training checkpoint.
76
+ Ruff lint/format, lock consistency and Git diff checks passed.
77
+
78
+ Pinned public release: `48b3eb9b56fd03056943bb905b8cd7637009588c`. Anonymous
79
+ Hub download verified the weights and definition checksums, strict model loading
80
+ and exact seeded generation from the downloaded standalone package.
model_10m/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """Vanilla character GPT, approximately 10M parameters."""
model_10m/generate.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Standalone sampling from a downloaded Hugging Face Shakespeare model folder."""
2
+
3
+ import argparse
4
+ import json
5
+ from pathlib import Path
6
+
7
+ import torch
8
+ from model import GPT, ModelConfig
9
+ from safetensors.torch import load_file
10
+
11
+
12
+ def load_model(folder, device="cpu"):
13
+ folder = Path(folder)
14
+ config = json.loads((folder / "config.json").read_text())
15
+ tokenizer = json.loads((folder / "tokenizer.json").read_text())
16
+ model = GPT(ModelConfig(**config)).to(device).eval()
17
+ model.load_state_dict(load_file(str(folder / "model.safetensors")), strict=True)
18
+ return model, tokenizer["characters"]
19
+
20
+
21
+ @torch.no_grad()
22
+ def generate(model, characters, prompt, tokens=300, seed=1339):
23
+ indices = {character: index for index, character in enumerate(characters)}
24
+ if set(prompt) - indices.keys():
25
+ raise ValueError("prompt contains characters absent from the training vocabulary")
26
+ context = [indices[c] for c in prompt] or [0]
27
+ random = torch.Generator().manual_seed(seed)
28
+ device = next(model.parameters()).device
29
+ output = []
30
+ for _ in range(tokens):
31
+ logits = model(torch.tensor([context[-model.config.block_size :]], device=device))
32
+ probabilities = logits[0, -1].softmax(-1).cpu()
33
+ token = torch.multinomial(probabilities, 1, generator=random).item()
34
+ context.append(token)
35
+ output.append(characters[token])
36
+ return prompt + "".join(output)
37
+
38
+
39
+ if __name__ == "__main__":
40
+ parser = argparse.ArgumentParser(description=__doc__)
41
+ parser.add_argument("--folder", default=".")
42
+ parser.add_argument("--prompt", default="ROMEO:\n")
43
+ parser.add_argument("--tokens", type=int, default=300)
44
+ parser.add_argument("--seed", type=int, default=1339)
45
+ parser.add_argument("--device", default="cpu", choices=("cpu", "cuda", "mps"))
46
+ args = parser.parse_args()
47
+ if args.tokens < 0:
48
+ parser.error("tokens must be nonnegative")
49
+ model, characters = load_model(args.folder, args.device)
50
+ print(generate(model, characters, args.prompt, args.tokens, args.seed))
model_10m/model.py ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Architecture only: a roughly 10M-parameter, decoder-only character GPT.
2
+
3
+ 6 layers, width 384, 6 heads, learned positions, pre-LayerNorm and GELU MLPs.
4
+ The exact count depends on context length and vocabulary; trainer/loop.py records it.
5
+ Training, data loading, checkpoints and CLI code deliberately live elsewhere.
6
+ """
7
+
8
+ import math
9
+ from dataclasses import asdict, dataclass
10
+
11
+ import torch
12
+ from torch import nn
13
+
14
+
15
+ # Model: B = batch, T = sequence length, C = embedding width, H = heads.
16
+ @dataclass(frozen=True)
17
+ class ModelConfig:
18
+ vocab_size: int
19
+ block_size: int = 256
20
+ n_layer: int = 6
21
+ n_head: int = 6
22
+ n_embd: int = 384
23
+
24
+ def __post_init__(self):
25
+ if any(value <= 0 for value in asdict(self).values()):
26
+ raise ValueError("all model dimensions must be positive")
27
+ if self.n_embd % self.n_head:
28
+ raise ValueError("n_embd must be divisible by n_head")
29
+
30
+
31
+ def causal_attention(query, key, value):
32
+ # Q, K, V: [B, H, T, C/H]. A row may see itself and earlier columns only.
33
+ # For each query position, compare its feature vector with every key vector.
34
+ # Q and K are [B, H, T, D], so transpose K's last two axes to [B, H, D, T].
35
+ # This makes the matrix product [B, H, T, D] @ [B, H, D, T] yield
36
+ # [B, H, T, T]: one score for each query/key position pair. K itself is
37
+ # unchanged; transpose only changes the view of its axes for this product.
38
+ scores = query @ key.transpose(-2, -1) / math.sqrt(query.size(-1))
39
+ # Example causal mask for T = 4 (rows are queries; columns are keys):
40
+ # [[1, 0, 0, 0],
41
+ # [1, 1, 0, 0],
42
+ # [1, 1, 1, 0],
43
+ # [1, 1, 1, 1]]
44
+ mask = torch.ones(query.size(-2), key.size(-2), device=query.device, dtype=torch.bool).tril()
45
+ weights = scores.masked_fill(~mask, float("-inf")).softmax(dim=-1)
46
+ return weights @ value
47
+
48
+
49
+ class Attention(nn.Module):
50
+ def __init__(self, config):
51
+ super().__init__()
52
+ self.n_head = config.n_head
53
+ self.qkv = nn.Linear(config.n_embd, 3 * config.n_embd)
54
+ self.projection = nn.Linear(config.n_embd, config.n_embd)
55
+
56
+ def forward(self, x):
57
+ batch, length, width = x.shape
58
+ query, key, value = self.qkv(x).chunk(
59
+ 3, dim=-1
60
+ ) # Split the combined projection into its three equal parts: query, key, and value.
61
+ # Split the embedding width evenly across heads; each head processes width / n_head features.
62
+ query, key, value = [
63
+ tensor.view(batch, length, self.n_head, width // self.n_head).transpose(1, 2)
64
+ for tensor in (query, key, value)
65
+ ]
66
+ attended = causal_attention(query, key, value)
67
+ attended = attended.transpose(1, 2).contiguous().view(batch, length, width)
68
+ return self.projection(attended)
69
+
70
+
71
+ class Block(nn.Module):
72
+ def __init__(self, config):
73
+ super().__init__()
74
+ self.attention_norm = nn.LayerNorm(
75
+ config.n_embd
76
+ ) # n_embd is the embedding width (number of features per token).
77
+ self.attention = Attention(config)
78
+ self.mlp_norm = nn.LayerNorm(config.n_embd)
79
+ self.mlp = nn.Sequential(
80
+ nn.Linear(config.n_embd, 4 * config.n_embd),
81
+ nn.GELU(),
82
+ nn.Linear(4 * config.n_embd, config.n_embd),
83
+ )
84
+
85
+ def forward(self, x):
86
+ x = x + self.attention(self.attention_norm(x))
87
+ return x + self.mlp(self.mlp_norm(x))
88
+
89
+
90
+ class GPT(nn.Module):
91
+ def __init__(self, config):
92
+ super().__init__()
93
+ self.config = config
94
+ self.token_embedding = nn.Embedding(config.vocab_size, config.n_embd)
95
+ self.position_embedding = nn.Embedding(config.block_size, config.n_embd)
96
+ self.blocks = nn.Sequential(*(Block(config) for _ in range(config.n_layer)))
97
+ self.final_norm = nn.LayerNorm(config.n_embd)
98
+ self.lm_head = nn.Linear(config.n_embd, config.vocab_size, bias=False)
99
+ self.apply(self.initialize)
100
+
101
+ @staticmethod
102
+ def initialize(module):
103
+ if isinstance(module, (nn.Linear, nn.Embedding)):
104
+ nn.init.normal_(module.weight, std=0.02)
105
+ if isinstance(module, nn.Linear) and module.bias is not None:
106
+ nn.init.zeros_(module.bias)
107
+
108
+ def forward(self, tokens):
109
+ if not 0 < tokens.size(1) <= self.config.block_size:
110
+ raise ValueError("sequence length must be within the model's block_size")
111
+ positions = torch.arange(tokens.size(1), device=tokens.device)
112
+ x = self.token_embedding(tokens) + self.position_embedding(positions)
113
+ logits = self.lm_head(
114
+ self.final_norm(self.blocks(x))
115
+ ) # [B, T, vocabulary]; normalize the final hidden states before projecting them to token scores.
116
+
117
+ return logits
provenance.json ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "format": "scholarly-ddp-v1",
3
+ "config": {
4
+ "world_size": 8,
5
+ "global_windows": 32,
6
+ "microbatch": 2,
7
+ "crop_padding": true,
8
+ "loss_chunk_size": 0,
9
+ "compile_model": true,
10
+ "cache_rope": true,
11
+ "context": 8192,
12
+ "target_tokens": 5000000000,
13
+ "warmup_tokens": 20000000,
14
+ "optimizer": "muon",
15
+ "muon_lr": 0.02,
16
+ "muon_momentum": 0.95,
17
+ "peak_lr": 0.0003,
18
+ "min_lr_ratio": 0.1,
19
+ "weight_decay": 0.1,
20
+ "seed": 42,
21
+ "checkpoint_every": 1000,
22
+ "evaluate_every": 500,
23
+ "pilot": false,
24
+ "experimental_data": true,
25
+ "prefetch_batches": 4,
26
+ "n_layer": 14,
27
+ "n_head": 12,
28
+ "n_embd": 768
29
+ },
30
+ "data_identity": {
31
+ "manifest_sha256": "70f63fa22fe19807bace17499f53a25c46145ad2c4e4966f61bef7e310528146",
32
+ "context": 8192,
33
+ "split": "train",
34
+ "tokenizer_sha256": "add5b2c7542e4efded329735825ecdcb94df1432617c3d3e4b7508aa459432f9"
35
+ },
36
+ "source_sha256": {
37
+ "trainer": "e90356e9f0e7740c4aae2fbc257d7facef2afb4152731aeacfd8143a28c204a3",
38
+ "heldout_loader": "afa53c739b8c6b81540e4b9b6d85f90d5353802537ab564d97f1c29df196cda4",
39
+ "config": "b3a9a2438b5fac9f383d138bdc0bd9987d88497162e5260c2b96b2f9b7572a7b",
40
+ "optimizer": "de43032f664ab20a1471ffa9d5be987c8fa4634d7aafb43fa7f16a7ca4fe9759",
41
+ "model": "2c978432e84cad6b2f661c63e7e62bccfc393a2aeb9f0519f7ca3db6775ed326",
42
+ "loader": "7821e13e765a9f2c0e0a94744bc7f2df8eea647f26d7aa0069f62556618a0ef2",
43
+ "raw_loader": "4312f800170e51f0a1d2be2b978c55fe9951f6df681c2bb225d83ecc0f33a6e7",
44
+ "prepared_loader": "c485580bd27298502a9ab4e9950f50e5680001bfe0e40cbb515906928ff76755",
45
+ "prefetch": "1786b1423f5881b23223ff0db47284a522020237d77e3d7fa28d542deea5c218",
46
+ "live_loader": "64457d0e60f1f1b664d3b174183c6e6f3d0c618973fe56712f9e72cd2a118a75",
47
+ "tokenizer": "00e32adc13dab74f5a029c63304b4591bd48f7cd6b086b22d4624d244667b4da"
48
+ },
49
+ "torch_version": "2.6.0+cu124",
50
+ "gpu": "NVIDIA H100 80GB HBM3",
51
+ "parameters": 124389632,
52
+ "resume_from": "/runs/python-124m-muon-5b-20261021-v1-s001/step-000000004.pt",
53
+ "step": 549,
54
+ "tokens": 50065393,
55
+ "run_id": "python-124m-muon-5b-20261021-v1",
56
+ "checkpoint": "/runs/python-124m-muon-5b-20261021-v1-s002/step-000000549.pt",
57
+ "weights_sha256": "8e5e55c0beaac47b09427c261d7dc7a9b94240758b6e0f3724d419ed43d8c1f5",
58
+ "weight_roundtrip_exact": true,
59
+ "cpu_logits_roundtrip_exact": true,
60
+ "loss_token_exposures": {
61
+ "python_implementation": 32533334,
62
+ "python_tests_examples": 7508444,
63
+ "python_documentation": 5009437,
64
+ "cs_math": 2506747,
65
+ "general_education": 1502082,
66
+ "books": 1005349
67
+ }
68
+ }
qualification.json ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "passed": true,
3
+ "parameters": 124389632,
4
+ "initial_loss": 10.464919090270996,
5
+ "final_loss": 0.0014346196549013257,
6
+ "updates": 21,
7
+ "losses": [
8
+ 10.461538314819336,
9
+ 7.20192289352417,
10
+ 4.79567289352417,
11
+ 2.724158763885498,
12
+ 1.326021671295166,
13
+ 0.6623347401618958,
14
+ 0.11782602220773697,
15
+ 0.10554386675357819,
16
+ 0.023414025083184242,
17
+ 0.010023850947618484,
18
+ 0.0060213529504835606,
19
+ 0.004254854749888182,
20
+ 0.003371018683537841,
21
+ 0.002859849249944091,
22
+ 0.0025118314661085606,
23
+ 0.0022271962370723486,
24
+ 0.002055828459560871,
25
+ 0.0018862211145460606,
26
+ 0.0017189612844958901,
27
+ 0.0016150841256603599,
28
+ 0.0014346196549013257
29
+ ],
30
+ "completion": {
31
+ "prompt": "def add(a, b):\n ",
32
+ "completion": " return a + b\n",
33
+ "token_ids": [
34
+ 262,
35
+ 401,
36
+ 277,
37
+ 361,
38
+ 305,
39
+ 202
40
+ ],
41
+ "temperature": 0.0,
42
+ "top_k": 0,
43
+ "seed": 42,
44
+ "new_tokens": 6,
45
+ "stop_reason": "eos",
46
+ "syntax_valid": true,
47
+ "repeated_token_4gram_fraction": 0.0,
48
+ "longest_tandem_repeat_tokens": 0,
49
+ "long_loop": false
50
+ },
51
+ "logit_alignment": "passed",
52
+ "causality": "passed",
53
+ "cached_rope": "passed",
54
+ "optimizer_partition": "passed",
55
+ "note": "Separate diagnostic model; its weights are discarded"
56
+ }
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ torch==2.6.0
2
+ safetensors>=0.4
3
+ tokenizers==0.22.2
runtime-cost-estimate.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "kind": "GPU compute estimate, not measured invoice",
3
+ "training_worker_reported_seconds": 842.245771547,
4
+ "h100_usd_per_second": 0.001097,
5
+ "excludes": [
6
+ "GPU work outside recorded training segments",
7
+ "CPU preparation and evaluation",
8
+ "storage and transfer"
9
+ ],
10
+ "training_gpu_usd_estimate": 7.391548891096472
11
+ }
tokenizer/config.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "format": "huggingface-tokenizers-json",
3
+ "vocab_size": 32768,
4
+ "special_tokens": {
5
+ "<|pad|>": 0,
6
+ "<|bos|>": 1,
7
+ "<|eos|>": 2,
8
+ "<|unk|>": 3
9
+ },
10
+ "normalization": null,
11
+ "pretokenization_regex": "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+",
12
+ "add_prefix_space": false,
13
+ "automatic_bos_eos": false,
14
+ "padding": null,
15
+ "truncation": null,
16
+ "decode_skip_special_tokens_default_for_roundtrips": false,
17
+ "all_valid_UTF8_supported": true
18
+ }
tokenizer/evaluation.json ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "focused-64mib-32768",
3
+ "vocab": 32768,
4
+ "execution": "modal-cpu",
5
+ "tokenizer_sha256": "add5b2c7542e4efded329735825ecdcb94df1432617c3d3e4b7508aa459432f9",
6
+ "evaluation_sha256": "a9a82723c1e78b46ec52b33b81551a61a5498e46ac73a6f09e4c0da9e27775a0",
7
+ "metrics": {
8
+ "python": {
9
+ "bytes": 2513044,
10
+ "tokens": 615688,
11
+ "examples": 512,
12
+ "roundtrip_failures": 0,
13
+ "unk_tokens": 0,
14
+ "bytes_per_token": 4.08168422967477,
15
+ "mean_tokens_per_example": 1202.515625,
16
+ "p95_tokens_per_example": 2184
17
+ },
18
+ "json": {
19
+ "bytes": 2782302,
20
+ "tokens": 722785,
21
+ "examples": 512,
22
+ "roundtrip_failures": 0,
23
+ "unk_tokens": 0,
24
+ "bytes_per_token": 3.849418568453966,
25
+ "mean_tokens_per_example": 1411.689453125,
26
+ "p95_tokens_per_example": 2514
27
+ },
28
+ "git_diff": {
29
+ "bytes": 187152,
30
+ "tokens": 52862,
31
+ "examples": 512,
32
+ "roundtrip_failures": 0,
33
+ "unk_tokens": 0,
34
+ "bytes_per_token": 3.5403881805455715,
35
+ "mean_tokens_per_example": 103.24609375,
36
+ "p95_tokens_per_example": 249
37
+ },
38
+ "tool_call": {
39
+ "bytes": 965682,
40
+ "tokens": 251703,
41
+ "examples": 512,
42
+ "roundtrip_failures": 0,
43
+ "unk_tokens": 0,
44
+ "bytes_per_token": 3.8365931276146887,
45
+ "mean_tokens_per_example": 491.607421875,
46
+ "p95_tokens_per_example": 2304
47
+ }
48
+ },
49
+ "fragmentation": {
50
+ "{\"name\":\"read_file\",\"arguments\":{\"path\":\"src/main.py\"}}": 14,
51
+ "diff --git a/main.py b/main.py\n@@ -1,2 +1,2 @@\n-old\n+new\n": 25,
52
+ "get_user_configuration": 3,
53
+ "\"additionalProperties\":false": 4,
54
+ "\"tool_call_id\":\"call_0123456789\"": 12
55
+ },
56
+ "correctness_passed": true,
57
+ "family": "focused",
58
+ "size_mib": 64
59
+ }
tokenizer/freeze-manifest.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "id": "structured-code-bpe-v1",
3
+ "status": "frozen",
4
+ "vocab_size": 32768,
5
+ "files": {
6
+ "recipe.json": "a4328e99a51bee64daaee66efe25e80ce01a263d568a69a130b94f687edef407",
7
+ "config.json": "2a4fa59b0a93ebd0995f3ea308c01484647e9ede935e128b4dba163b384224aa",
8
+ "tokenizer.json": "add5b2c7542e4efded329735825ecdcb94df1432617c3d3e4b7508aa459432f9",
9
+ "evaluation.json": "922b0fc33a0c38f06eaedbf3497a50723f4c66ac4dd8f96267038ad64764d80f"
10
+ },
11
+ "contract": "Immutable. Record tokenizer SHA256 in shards and checkpoints. Prior tokenizer data must be retokenized in a new version."
12
+ }
tokenizer/publication-verification.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "location": "jfrick/scholarly-code-tokenizer",
3
+ "revision": "0ebdb4fe4c8d21ccc06cfe6f5b464eac74773a80",
4
+ "status": "passed",
5
+ "default_and_variants_checked": 20,
6
+ "probes_per_variant": 6,
7
+ "checks": [
8
+ "artifact_hashes",
9
+ "special_ids",
10
+ "vocabulary_size",
11
+ "token_id_equivalence",
12
+ "exact_roundtrips",
13
+ "no_automatic_boundaries"
14
+ ],
15
+ "transformers_version": "4.57.6",
16
+ "tokenizers_version": "0.22.2"
17
+ }
tokenizer/publication.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "repo_id": "jfrick/scholarly-code-tokenizer",
3
+ "revision": "0ebdb4fe4c8d21ccc06cfe6f5b464eac74773a80",
4
+ "url": "https://huggingface.co/jfrick/scholarly-code-tokenizer",
5
+ "variant": "structured-code-v1-32768",
6
+ "tokenizer_sha256": "add5b2c7542e4efded329735825ecdcb94df1432617c3d3e4b7508aa459432f9",
7
+ "vocab_size": 32768,
8
+ "selection": "User explicitly selected code-focused 32K as repository and Hub default."
9
+ }
tokenizer/recipe.json ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "seed": 20261016,
3
+ "target_bytes": 67108864,
4
+ "weights_percent": {
5
+ "python": 40,
6
+ "json": 20,
7
+ "git_diff": 20,
8
+ "tool_call": 20
9
+ },
10
+ "actual_bytes": {
11
+ "python": 26847131,
12
+ "json": 13424847,
13
+ "git_diff": 13421882,
14
+ "tool_call": 13422435
15
+ },
16
+ "training_examples": {
17
+ "python": 5059,
18
+ "json": 2290,
19
+ "git_diff": 33758,
20
+ "tool_call": 6555
21
+ },
22
+ "fitting_parents": 14911,
23
+ "evaluation_parents_per_category": 512,
24
+ "train_sha256": "cdc34355495f1c21bba4742ac11e9bcc0a0d0df836ab49eed9a1e01f97ab9a09",
25
+ "evaluation_sha256": "a9a82723c1e78b46ec52b33b81551a61a5498e46ac73a6f09e4c0da9e27775a0",
26
+ "source_train_sha256": "5e1c04e310375d9922e008142e7d9813f56e541918b729dd7764eaec3ffbadea",
27
+ "source_validation_sha256": "611010954c9c48ccad9b9a28f7377d56ab180373b5e7eb76fe87ab723b2b8040",
28
+ "implementation_sha256": "cd1f6e5351aad5acce1a1021af649c4dd8a099c2b0d506e7cc67cd5aee230163",
29
+ "limitations": [
30
+ "Python excerpts from the existing pinned codeparrot corpus, not necessarily complete parseable files",
31
+ "JSON, tool calls and patches are generated controlled fixtures, not independent production traces",
32
+ "Fitting/evaluation parents are disjoint; generator templates are shared",
33
+ "Each category quota includes its final whole example, so 64 MiB is approximate",
34
+ "Unified diffs cover insertions, deletions and identifier replacements, but not binary patches or renames",
35
+ "One fitting seed; no model-level tool-call or code-generation correctness measured"
36
+ ]
37
+ }
tokenizer/tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
training-curves.png ADDED

Git LFS Details

  • SHA256: 56c19c3bc0449836be98ce7b76cf4be13e80ba9e6aae03c882be15dfff4a3eb0
  • Pointer size: 131 Bytes
  • Size of remote file: 293 kB
validation-curves.png ADDED

Git LFS Details

  • SHA256: cf5511aedc895d458a2b8a856575828066b4c7e4f0fb77e4c3044d3ff0d18882
  • Pointer size: 131 Bytes
  • Size of remote file: 133 kB
validation.jsonl ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {"step": 0, "tokens": 0, "target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "per_stratum": {"python_implementation": 10.52420629872608, "python_tests_examples": 10.49302304090685, "python_documentation": 10.538044416813456, "cs_math": 10.498617869293456, "general_education": 10.580692296640718, "books": 10.552069240456483}, "stratum_target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "windows": 192, "per_source": {"python_implementation": 10.52420629872608, "python_tests_examples": 10.49302304090685, "python_documentation": 10.538044416813456, "cs_math": 10.498617869293456, "general_education": 10.580692296640718, "books": 10.552069240456483}, "weighted_loss": 10.521885039162349}
2
+ {"step": 2, "tokens": 198806, "target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "per_stratum": {"python_implementation": 10.511782852054447, "python_tests_examples": 10.480197937202234, "python_documentation": 10.53078480641039, "cs_math": 10.490445001582403, "general_education": 10.573435295961549, "books": 10.54268923281465}, "stratum_target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "windows": 192, "per_source": {"python_implementation": 10.511782852054447, "python_tests_examples": 10.480197937202234, "python_documentation": 10.53078480641039, "cs_math": 10.490445001582403, "general_education": 10.573435295961549, "books": 10.54268923281465}, "weighted_loss": 10.510346118671023}
3
+ {"step": 2, "tokens": 198806, "target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "per_stratum": {"python_implementation": 10.511782852054447, "python_tests_examples": 10.480197937202234, "python_documentation": 10.53078480641039, "cs_math": 10.490445001582403, "general_education": 10.573435295961549, "books": 10.54268923281465}, "stratum_target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "windows": 192, "per_source": {"python_implementation": 10.511782852054447, "python_tests_examples": 10.480197937202234, "python_documentation": 10.53078480641039, "cs_math": 10.490445001582403, "general_education": 10.573435295961549, "books": 10.54268923281465}, "weighted_loss": 10.510346118671023}
4
+ {"step": 4, "tokens": 387014, "target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "per_stratum": {"python_implementation": 10.479941665000817, "python_tests_examples": 10.448600116025958, "python_documentation": 10.512487911442683, "cs_math": 10.469178979745234, "general_education": 10.556407058147432, "books": 10.516637554925667}, "stratum_target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "windows": 192, "per_source": {"python_implementation": 10.479941665000817, "python_tests_examples": 10.448600116025958, "python_documentation": 10.512487911442683, "cs_math": 10.469178979745234, "general_education": 10.556407058147432, "books": 10.516637554925667}, "weighted_loss": 10.480984802628893}
5
+ {"step": 4, "tokens": 387014, "target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "per_stratum": {"python_implementation": 10.479941665000817, "python_tests_examples": 10.448600116025958, "python_documentation": 10.512487911442683, "cs_math": 10.469178979745234, "general_education": 10.556407058147432, "books": 10.516637554925667}, "stratum_target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "windows": 192, "per_source": {"python_implementation": 10.479941665000817, "python_tests_examples": 10.448600116025958, "python_documentation": 10.512487911442683, "cs_math": 10.469178979745234, "general_education": 10.556407058147432, "books": 10.516637554925667}, "weighted_loss": 10.480984802628893}
6
+ {"step": 500, "tokens": 45650831, "target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "per_stratum": {"python_implementation": 4.162418328667418, "python_tests_examples": 3.918841802409977, "python_documentation": 5.080653659561132, "cs_math": 4.339001730203496, "general_education": 5.349691602343097, "books": 5.309149448988822}, "stratum_target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "windows": 192, "per_source": {"python_implementation": 4.162418328667418, "python_tests_examples": 3.918841802409977, "python_documentation": 5.080653659561132, "cs_math": 4.339001730203496, "general_education": 5.349691602343097, "books": 5.309149448988822}, "weighted_loss": 4.285087373511676}
7
+ {"step": 549, "tokens": 50065393, "target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "per_stratum": {"python_implementation": 3.89459791981912, "python_tests_examples": 3.5985489956984402, "python_documentation": 4.833967628435524, "cs_math": 4.094523666119857, "general_education": 5.163108580551279, "books": 5.183435151830238}, "stratum_target_counts": {"python_implementation": 55027, "python_tests_examples": 97392, "python_documentation": 28953, "cs_math": 50556, "general_education": 38282, "books": 256483}, "windows": 192, "per_source": {"python_implementation": 3.89459791981912, "python_tests_examples": 3.5985489956984402, "python_documentation": 4.833967628435524, "cs_math": 4.094523666119857, "general_education": 5.163108580551279, "books": 5.183435151830238}, "weighted_loss": 4.017955903839883}