fffoivos commited on
Commit
9c9ceec
·
verified ·
1 Parent(s): e58e61a

Reorganize Apertus tokenizer extension release

Browse files

Add curated tokenizer/checkpoint/dataset/results layout, manifests, code links, and provenance pointers. No legacy paths deleted.

This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +9 -0
  2. ARTIFACT_GRAPH.md +51 -0
  3. MANIFEST.json +150 -0
  4. README.md +77 -66
  5. SHA256SUMS +59 -23
  6. archive/legacy-hf-layout-index.md +27 -0
  7. archive/legacy_SHA256SUMS_20260525 +23 -0
  8. checkpoints/baselines/retok-3p5b-iter834/README.md +12 -0
  9. checkpoints/baselines/retok-3p5b-iter834/hydration.md +8 -0
  10. checkpoints/baselines/retok-3p5b-iter834/manifest.json +8 -0
  11. checkpoints/baselines/vanilla-3p5b-iter834/README.md +13 -0
  12. checkpoints/baselines/vanilla-3p5b-iter834/hydration.md +8 -0
  13. checkpoints/baselines/vanilla-3p5b-iter834/manifest.json +8 -0
  14. checkpoints/td-layer11-cpt-3p5b-iter834/README.md +30 -0
  15. checkpoints/td-layer11-cpt-3p5b-iter834/hydration.md +15 -0
  16. checkpoints/td-layer11-cpt-3p5b-iter834/manifest.json +11 -0
  17. checkpoints/td-layer11-init-r17-tp2/README.md +13 -0
  18. checkpoints/td-layer11-init-r17-tp2/hydration.md +14 -0
  19. checkpoints/td-layer11-init-r17-tp2/manifest.json +9 -0
  20. code-links/README.md +17 -0
  21. code-links/github_subproject_manifest.json +73 -0
  22. provenance/conversion-roundtrip/td_layer11_r17_roundtrip_verification.json +43 -0
  23. provenance/conversion-roundtrip/vanilla_r17_roundtrip_verification.json +43 -0
  24. provenance/dataset-build/CPT_DATASET_BUILD_RUNBOOK.md +108 -0
  25. provenance/dataset-build/MIX_RECIPE.md +173 -0
  26. provenance/dataset-build/bulk_mix_text_document.manifest.json +19 -0
  27. provenance/evals/CONTINUATION_3P5B_RESULTS_20260525.md +91 -0
  28. provenance/evals/EVAL_RECIPE.md +321 -0
  29. provenance/evals/V4_BENCHMARK_COMPARISON.md +77 -0
  30. provenance/token-distillation/RUN_LOG_20260523.md +2299 -0
  31. provenance/token-distillation/TOKEN_DISTILLATION_PLAN.md +773 -0
  32. provenance/tokenizer-selection/CHOSEN_CUTOFF.md +220 -0
  33. provenance/tokenizer-selection/CUTOFF_SWEEP_REPORT.md +441 -0
  34. provenance/tokenizer-selection/curated_padded_at_17408_manifest.json +15 -0
  35. provenance/tokenizer-selection/firing_count_20260518_run_summary_augmented.json +0 -0
  36. results/SUMMARY.md +91 -0
  37. results/benchmark_table.csv +5 -0
  38. results/continuation_3p5b_summary.json +364 -0
  39. results/plots/global_mmlu_full_el_subcategories_van_td.png +3 -0
  40. results/plots/include_base_44_greek_subjects_van_td.png +3 -0
  41. results/plots/intrinsic_trajectories.png +3 -0
  42. results/plots/intrinsic_van_td.png +3 -0
  43. results/plots/trajectories.png +3 -0
  44. results/plots/trajectories_per_task.png +3 -0
  45. results/plots/trajectories_per_task_van_td.png +3 -0
  46. results/plots/trajectories_van_td.png +3 -0
  47. results/plots/trajectories_van_td_gap.png +3 -0
  48. tokenizer/modern-greek-17408/README.md +22 -0
  49. tokenizer/modern-greek-17408/manifest.json +33 -0
  50. tokenizer/modern-greek-17408/special_tokens_map.json +30 -0
.gitattributes CHANGED
@@ -39,3 +39,12 @@ subprojects/03_apertus_extension_and_embedding_adaptation/03_4_implementation_ex
39
  subprojects/03_apertus_extension_and_embedding_adaptation/03_4_implementation_experiments/init_bakeoff/eval/trajectory_analysis_20260524/plots/trajectories_per_task_van_td.png filter=lfs diff=lfs merge=lfs -text
40
  subprojects/03_apertus_extension_and_embedding_adaptation/03_4_implementation_experiments/init_bakeoff/eval/trajectory_analysis_20260524/plots/trajectories_van_td.png filter=lfs diff=lfs merge=lfs -text
41
  subprojects/03_apertus_extension_and_embedding_adaptation/03_4_implementation_experiments/init_bakeoff/eval/trajectory_analysis_20260524/plots/trajectories_van_td_gap.png filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
39
  subprojects/03_apertus_extension_and_embedding_adaptation/03_4_implementation_experiments/init_bakeoff/eval/trajectory_analysis_20260524/plots/trajectories_per_task_van_td.png filter=lfs diff=lfs merge=lfs -text
40
  subprojects/03_apertus_extension_and_embedding_adaptation/03_4_implementation_experiments/init_bakeoff/eval/trajectory_analysis_20260524/plots/trajectories_van_td.png filter=lfs diff=lfs merge=lfs -text
41
  subprojects/03_apertus_extension_and_embedding_adaptation/03_4_implementation_experiments/init_bakeoff/eval/trajectory_analysis_20260524/plots/trajectories_van_td_gap.png filter=lfs diff=lfs merge=lfs -text
42
+ results/plots/global_mmlu_full_el_subcategories_van_td.png filter=lfs diff=lfs merge=lfs -text
43
+ results/plots/include_base_44_greek_subjects_van_td.png filter=lfs diff=lfs merge=lfs -text
44
+ results/plots/intrinsic_trajectories.png filter=lfs diff=lfs merge=lfs -text
45
+ results/plots/intrinsic_van_td.png filter=lfs diff=lfs merge=lfs -text
46
+ results/plots/trajectories.png filter=lfs diff=lfs merge=lfs -text
47
+ results/plots/trajectories_per_task.png filter=lfs diff=lfs merge=lfs -text
48
+ results/plots/trajectories_per_task_van_td.png filter=lfs diff=lfs merge=lfs -text
49
+ results/plots/trajectories_van_td.png filter=lfs diff=lfs merge=lfs -text
50
+ results/plots/trajectories_van_td_gap.png filter=lfs diff=lfs merge=lfs -text
ARTIFACT_GRAPH.md ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Artifact Graph
2
+
3
+ ```text
4
+ swiss-ai/Apertus-8B-2509
5
+ |
6
+ | continuous BPE on GlossAPI + HPLT 50/50
7
+ v
8
+ C3 full candidate
9
+ base 131072 + 25600 = 156672
10
+ |
11
+ | cutoff sweep, curation, backfill, alignment
12
+ v
13
+ tokenizer/modern-greek-17408
14
+ base 131072 + 17408 = 148480
15
+ |
16
+ | optional polytonic stack
17
+ v
18
+ tokenizer/polytonic-plus-5120
19
+ base 131072 + modern 17408 + polytonic 5120 = 153600
20
+
21
+ fffoivos/glossapi-greek-nanochat-pretraining-dataset
22
+ + nanochat internal dedup metadata
23
+ + Apertus overlap drop overlay
24
+ |
25
+ v
26
+ selected_after_apertus_and_internal_dedup.parquet
27
+ |
28
+ | 70/24/4/2 Greek/replay/code/math mix
29
+ v
30
+ bulk_mix.nfc.jsonl
31
+ |
32
+ | Megatron indexed dataset preprocessing
33
+ v
34
+ bulk_mix_base_nfc_megatron/bulk_mix_text_document.{bin,idx}
35
+
36
+ modern tokenizer + CPT mix
37
+ |
38
+ | Vanilla, ReTok, Centroid, Token Distillation layer 11
39
+ v
40
+ 2B bakeoff and 3.5B continuation
41
+ |
42
+ v
43
+ checkpoints/td-layer11-cpt-3p5b-iter834
44
+ |
45
+ v
46
+ results/
47
+ ```
48
+
49
+ The large checkpoint and dataset payloads are represented by hydration pointers
50
+ unless explicitly uploaded as model weights.
51
+
MANIFEST.json ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "release_name": "apertus-tokenizer-extension",
3
+ "generated_date": "2026-05-25",
4
+ "source_repo": "https://github.com/fffoivos/glossapi-tokenizer-extension",
5
+ "source_subproject": "subprojects/03_apertus_extension_and_embedding_adaptation",
6
+ "source_commit_for_code_refs": "7c67cf11eb3d31f0ddd006f7d709709037db93a1",
7
+ "artifacts": [
8
+ {
9
+ "artifact_id": "tokenizer.modern-greek-17408",
10
+ "type": "tokenizer",
11
+ "status": "payload-present",
12
+ "public_path": "tokenizer/modern-greek-17408",
13
+ "base_model": "swiss-ai/Apertus-8B-2509",
14
+ "vocab_size": 148480,
15
+ "base_vocab_size": 131072,
16
+ "added_modern_greek_tokens": 17408,
17
+ "sha256_tokenizer_json": "358ae3f29ac17c99769d6d437339e28657d5fcaed3486f8550feed3d6adfc394",
18
+ "review_docs": [
19
+ "provenance/tokenizer-selection/CHOSEN_CUTOFF.md"
20
+ ],
21
+ "github_code_refs": [
22
+ "code-links/github_subproject_manifest.json"
23
+ ]
24
+ },
25
+ {
26
+ "artifact_id": "tokenizer.polytonic-plus-5120",
27
+ "type": "tokenizer",
28
+ "status": "payload-present",
29
+ "public_path": "tokenizer/polytonic-plus-5120",
30
+ "base_model": "swiss-ai/Apertus-8B-2509",
31
+ "vocab_size": 153600,
32
+ "base_vocab_size": 131072,
33
+ "added_modern_greek_tokens": 17408,
34
+ "added_polytonic_greek_tokens": 5120,
35
+ "sha256_tokenizer_json": "b1eeb739a564b3abd33c1b85a16162b8284d98f9ab5d67528d3cbe8a82e9cbad",
36
+ "review_docs": [
37
+ "provenance/tokenizer-selection/CHOSEN_CUTOFF.md"
38
+ ],
39
+ "github_code_refs": [
40
+ "code-links/github_subproject_manifest.json"
41
+ ]
42
+ },
43
+ {
44
+ "artifact_id": "dataset.cpt-7b-mix",
45
+ "type": "dataset",
46
+ "status": "hydration-pointer",
47
+ "public_path": "training-data/cpt-7b-mix",
48
+ "clariden_jsonl": "/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix.nfc.jsonl",
49
+ "clariden_megatron_prefix": "/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix_base_nfc_megatron/bulk_mix_text_document",
50
+ "rows": 5754172,
51
+ "base_tokenized_tokens": 9831704774,
52
+ "mix_builder_target_tokens": 7000141612,
53
+ "review_docs": [
54
+ "provenance/dataset-build/CPT_DATASET_BUILD_RUNBOOK.md",
55
+ "provenance/dataset-build/MIX_RECIPE.md"
56
+ ],
57
+ "github_code_refs": [
58
+ "code-links/github_subproject_manifest.json"
59
+ ]
60
+ },
61
+ {
62
+ "artifact_id": "checkpoint.td-layer11-init-r17-tp2",
63
+ "type": "checkpoint",
64
+ "status": "hydration-pointer",
65
+ "public_path": "checkpoints/td-layer11-init-r17-tp2",
66
+ "format": "Megatron torch_dist TP=2, R17 patched",
67
+ "clariden_path": "/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/megatron_tp2_r17patched/release",
68
+ "depends_on": [
69
+ "tokenizer.modern-greek-17408"
70
+ ],
71
+ "review_docs": [
72
+ "provenance/token-distillation/RUN_LOG_20260523.md",
73
+ "provenance/conversion-roundtrip/td_layer11_r17_roundtrip_verification.json"
74
+ ],
75
+ "github_code_refs": [
76
+ "code-links/github_subproject_manifest.json"
77
+ ]
78
+ },
79
+ {
80
+ "artifact_id": "checkpoint.td-layer11-cpt-3p5b-iter834",
81
+ "type": "checkpoint",
82
+ "status": "hydration-pointer",
83
+ "public_path": "checkpoints/td-layer11-cpt-3p5b-iter834",
84
+ "format": "Megatron torch_dist TP=2 checkpoint plus HF eval conversion",
85
+ "clariden_checkpoint": "/capstor/scratch/cscs/fffoivos/runs/bakeoff/continuation_3p5b_20260524T143012Z_td_layer11/checkpoints/iter_0000834",
86
+ "clariden_hf_eval_copy": "/capstor/scratch/cscs/fffoivos/runs/eval/continuation_3p5b_20260524T143012Z_td_layer11/iter_0000834_hf",
87
+ "depends_on": [
88
+ "tokenizer.modern-greek-17408",
89
+ "dataset.cpt-7b-mix",
90
+ "checkpoint.td-layer11-init-r17-tp2"
91
+ ],
92
+ "review_docs": [
93
+ "results/SUMMARY.md",
94
+ "provenance/evals/CONTINUATION_3P5B_RESULTS_20260525.md"
95
+ ],
96
+ "github_code_refs": [
97
+ "code-links/github_subproject_manifest.json"
98
+ ]
99
+ },
100
+ {
101
+ "artifact_id": "checkpoint.baseline-vanilla-3p5b-iter834",
102
+ "type": "checkpoint",
103
+ "status": "hydration-pointer",
104
+ "public_path": "checkpoints/baselines/vanilla-3p5b-iter834",
105
+ "format": "Megatron torch_dist TP=2 checkpoint plus HF eval conversion",
106
+ "clariden_checkpoint": "/capstor/scratch/cscs/fffoivos/runs/bakeoff/continuation_3p5b_20260524T143012Z_vanilla/checkpoints/iter_0000834",
107
+ "depends_on": [
108
+ "dataset.cpt-7b-mix"
109
+ ],
110
+ "review_docs": [
111
+ "results/SUMMARY.md"
112
+ ],
113
+ "github_code_refs": [
114
+ "code-links/github_subproject_manifest.json"
115
+ ]
116
+ },
117
+ {
118
+ "artifact_id": "checkpoint.baseline-retok-3p5b-iter834",
119
+ "type": "checkpoint",
120
+ "status": "hydration-pointer",
121
+ "public_path": "checkpoints/baselines/retok-3p5b-iter834",
122
+ "format": "Megatron torch_dist TP=2 checkpoint plus HF eval conversion",
123
+ "clariden_checkpoint": "/capstor/scratch/cscs/fffoivos/runs/bakeoff/continuation_3p5b_20260524T143012Z_retok/checkpoints/iter_0000834",
124
+ "depends_on": [
125
+ "tokenizer.modern-greek-17408",
126
+ "dataset.cpt-7b-mix"
127
+ ],
128
+ "review_docs": [
129
+ "results/SUMMARY.md"
130
+ ],
131
+ "github_code_refs": [
132
+ "code-links/github_subproject_manifest.json"
133
+ ]
134
+ },
135
+ {
136
+ "artifact_id": "results.continuation-3p5b",
137
+ "type": "evaluation-summary",
138
+ "status": "compact-evidence",
139
+ "public_path": "results",
140
+ "review_docs": [
141
+ "results/SUMMARY.md",
142
+ "results/benchmark_table.csv"
143
+ ],
144
+ "github_code_refs": [
145
+ "code-links/github_subproject_manifest.json"
146
+ ]
147
+ }
148
+ ]
149
+ }
150
+
README.md CHANGED
@@ -1,88 +1,99 @@
1
- ---
2
- language:
3
- - el
4
- tags:
5
- - tokenizer
6
- - bpe
7
- - greek
8
- - apertus
9
- - tokenizer-extension
10
- - byte-level-bpe
11
- datasets:
12
- - fffoivos/glossapi-greek-nanochat-pretraining-dataset
13
- base_model:
14
- - swiss-ai/Apertus-8B-2509
15
- ---
16
-
17
- # Apertus Tokenizer Extension
18
-
19
- Current canonical artifact: **C3 + 17,408 curated/backfilled added units**.
20
-
21
- The active ship tokenizer is:
22
 
23
  ```text
24
- tokenizers/c3_added_17408_curated_padded/
25
  ```
26
 
27
- It starts from `swiss-ai/Apertus-8B-2509`, preserves the Apertus base ids
28
- `0..131071` verbatim, adds `17,408` C3 Greek-extension BPE units, and keeps
29
- the final vocab aligned at `148,480 = 128 * 1160 = 256 * 580`.
30
 
31
- ## Canonical Tokenizer
 
 
 
 
 
 
 
 
 
 
32
 
33
- | Path | Vocab | Added units | Curation | SHA-256 tokenizer.json |
34
- | --- | ---: | ---: | --- | --- |
35
- | `tokenizers/c3_added_17408_curated_padded/` | 148,480 | 17,408 | 69 noisy raw-cutoff tokens structurally skipped and backfilled | `358ae3f29ac17c99769d6d437339e28657d5fcaed3486f8550feed3d6adfc394` |
36
 
37
- The cutoff can be revisited after downstream embedding adaptation and CPT,
38
- but this is the current handoff artifact for the Apertus Greek tokenizer
39
- extension line.
40
 
41
- ## Cutoff Evidence
 
 
 
 
42
 
43
- The compact evidence bundle is under:
44
 
45
- ```text
46
- experiments/02_1_7_intrinsic_eval_sweep_20260518/
47
- ```
 
 
 
48
 
49
- Important files:
 
50
 
51
- - `CHOSEN_CUTOFF.md` — pinned decision and downstream contract.
52
- - `REPORT.md` — intrinsic/fertility/MorphScore evidence base.
53
- - `artifacts/plots/` — report plots for the cutoff decision.
54
- - `manifests/curated_padded_at_17408_manifest.json` — exact backfilled construction.
55
- - `manifests/removal_mask_at_17408.jsonl` — the 69 in-cutoff tokens filtered out.
56
- - `firing_counts_c3_added_17408_curated_padded/` — compact token firing-count attribution artifacts for the exact C3 BPE training corpus, split by GlossAPI-nanochat, HPLT, combined C3, and exact `source_dataset`.
57
 
58
- The full sweep zoo is intentionally not mirrored here. This repo keeps the
59
- canonical tokenizer and just enough evidence to explain why it is current.
60
- Raw local variants, TokEval vendor caches, parquet outputs, and large geometry
61
- arrays remain outside the Hub artifact set.
62
 
63
- ## Historical Artifacts
 
 
 
 
64
 
65
- Older C1/C2/C3 full-tokenizer candidates and language-attribution artifacts are
66
- still present in their historical paths, including:
67
 
68
- - `continuous/`
69
- - `fresh/`
70
- - `analysis/`
71
- - `artifacts/language_attribution_20260515/`
72
 
73
- Those are retained for provenance, but the current tokenizer handoff is the
74
- 17,408 curated/backfilled artifact above.
 
75
 
76
- ## Source Code
77
 
78
- Process docs and scripts live in GitHub:
79
 
80
- ```text
81
- https://github.com/fffoivos/glossapi-tokenizer-extension
82
- ```
83
 
84
- Relevant commit for this upload:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
- ```text
87
- 9a6b039 Add firing count attribution workflow
88
- ```
 
1
+ # Apertus Greek Tokenizer Extension
2
+
3
+ This release packages the Greek tokenizer-extension work around its main
4
+ artifacts:
5
+
6
+ 1. a modern Greek merge-rule tokenizer extension for `swiss-ai/Apertus-8B-2509`;
7
+ 2. an optional polytonic/ancient Greek stacked tokenizer;
8
+ 3. the CPT dataset recipe and hydration pointers used for the bakeoff;
9
+ 4. the init and Token Distillation checkpoint pointers;
10
+ 5. compact benchmark evidence from the 2B bakeoff and 3.5B continuation.
11
+
12
+ The runnable scripts live in GitHub, not in this Hugging Face artifact repo:
 
 
 
 
 
 
 
 
 
13
 
14
  ```text
15
+ https://github.com/fffoivos/glossapi-tokenizer-extension/tree/main/subprojects/03_apertus_extension_and_embedding_adaptation
16
  ```
17
 
18
+ ## Main Artifacts
 
 
19
 
20
+ | Artifact | Status | Path |
21
+ |---|---|---|
22
+ | Modern Greek tokenizer, 148,480 vocab | payload included | `tokenizer/modern-greek-17408/` |
23
+ | Polytonic-stacked tokenizer, 153,600 vocab | payload included | `tokenizer/polytonic-plus-5120/` |
24
+ | TD layer 11 CPT checkpoint at 3.5B | hydration pointer | `checkpoints/td-layer11-cpt-3p5b-iter834/` |
25
+ | TD layer 11 R17-patched init | hydration pointer | `checkpoints/td-layer11-init-r17-tp2/` |
26
+ | Vanilla/ReTok 3.5B baselines | hydration pointers | `checkpoints/baselines/` |
27
+ | CPT 7B text mix recipe | manifest and pointer | `training-data/cpt-7b-mix/` |
28
+ | 3.5B benchmark summary | compact evidence | `results/` |
29
+ | Source-code links | GitHub pointers | `code-links/` |
30
+ | Audit trail | compact provenance | `provenance/` |
31
 
32
+ ## Tokenizers
 
 
33
 
34
+ Modern-only tokenizer:
 
 
35
 
36
+ - base Apertus vocab: `131072`;
37
+ - added modern Greek C3 tokens: `17408`;
38
+ - total vocab: `148480`;
39
+ - SHA-256 for `tokenizer.json`:
40
+ `358ae3f29ac17c99769d6d437339e28657d5fcaed3486f8550feed3d6adfc394`.
41
 
42
+ Polytonic-stacked tokenizer:
43
 
44
+ - base Apertus vocab: `131072`;
45
+ - modern Greek extension: `17408`;
46
+ - polytonic/ancient Greek extension: `5120`;
47
+ - total vocab: `153600`;
48
+ - SHA-256 for `tokenizer.json`:
49
+ `b1eeb739a564b3abd33c1b85a16162b8284d98f9ab5d67528d3cbe8a82e9cbad`.
50
 
51
+ Both tokenizers preserve Apertus base ids and the first 1000 special/reserved
52
+ ids.
53
 
54
+ ## Dataset
 
 
 
 
 
55
 
56
+ The CPT text mix is built from:
 
 
 
57
 
58
+ - `fffoivos/glossapi-greek-nanochat-pretraining-dataset`;
59
+ - nanochat internal dedup metadata;
60
+ - Apertus-overlap drop overlay from
61
+ `fffoivos/apertus-c3-dedup-audit-dedup-20260519t010924z`;
62
+ - non-Greek replay, code, and math.
63
 
64
+ Bulk recipe:
 
65
 
66
+ - Greek: `70%`;
67
+ - non-Greek replay: `24%`;
68
+ - code: `4%`;
69
+ - math: `2%`.
70
 
71
+ The final text stream is about `7.0B` extended-tokenizer-budget tokens. The
72
+ same NFC JSONL stream contains `9,831,704,774` base-tokenized Megatron tokens
73
+ after preprocessing.
74
 
75
+ ## Current Result Anchor
76
 
77
+ The latest compact result is the 3.5B continuation summary in `results/`.
78
 
79
+ At iter 834:
 
 
80
 
81
+ | Arm | Greek aggregate | English retention | Multilingual | Heldout BPC, lower better |
82
+ |---|---:|---:|---:|---:|
83
+ | Vanilla | 0.4339 | 0.6782 | 0.4923 | 0.4724 |
84
+ | ReTok | 0.4246 | 0.6786 | 0.4864 | 0.5390 |
85
+ | TD layer 11 | 0.4344 | 0.6865 | 0.4967 | 0.5054 |
86
+
87
+ Reading: TD layer 11 is the strongest final benchmark arm overall after the
88
+ 3.5B continuation. Vanilla remains the heldout-BPC reference.
89
+
90
+ ## Source And Provenance
91
+
92
+ - `MANIFEST.json`: machine-readable artifact inventory.
93
+ - `ARTIFACT_GRAPH.md`: dependency graph.
94
+ - `code-links/github_subproject_manifest.json`: source-code pointers.
95
+ - `provenance/`: compact documents and verification outputs for tokenizer
96
+ selection, dataset build, TD, conversion, and eval.
97
+ - `archive/legacy-hf-layout-index.md`: index of older HF folders retained for
98
+ traceability.
99
 
 
 
 
SHA256SUMS CHANGED
@@ -1,23 +1,59 @@
1
- e6e321ad419e32ce43427bba05a02a23133f05500a3486f98c5de232830c1844 ./README.md
2
- 5c2140f0d646a2f5eaf7ea07c033fade7e28b37468eeb8595f61f6044f6cf109 ./SHA256SUMS
3
- f6742a090b39f1f576d18481bb1e284720275b0ab417393f219650821e83a72a ./experiments/02_1_7_intrinsic_eval_sweep_20260518/CHOSEN_CUTOFF.md
4
- 3d68bbd6e6c9e25df597f46819cbe57e336b62b8a9b5b441aadeae5346e70eb7 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/README.md
5
- 9b350211cf4f0bd964feec9504a093c1062425fb12f22534a947112f357e5c25 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/REPORT.md
6
- 60a57f77e13d8204c7728e6e5a117cb947c156c97e2c57db7de587965ada58bf ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/morphscore_greek_results.json
7
- 7dd2ae959af9504d522cf4b606c573e6cefdd71c009fe8a7269eb051382351f0 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/our_suite_raw_gcloud/curated_metrics_by_slice.csv
8
- 76ad56410ada9ef2d7649d3babb757287993982e03fc98057e7289ec837c990c ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/our_suite_raw_gcloud/extended_metrics_by_slice.csv
9
- 190c58ce62f8878c92499ef7da9bceb26f27a1b5f25927e6681d80df59359c79 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/our_suite_raw_gcloud/metrics_by_slice.csv
10
- f823dcc20f7cc2d7435fda6c5c09e65d704de10d37330f9ed930fdcf7f75506b ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/our_suite_raw_gcloud/padded_17408_metrics.csv
11
- 9e94927189811f9c5df2e6f75c3e4ffc4738d4305a35eef2b8499c6bf15c5acf ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/our_suite_raw_gcloud/summary.json
12
- 7bbfd6c76cc88190a2334ab45af03f77e8389830e46e8dcc4ef896f7e2e3b8fc ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/plots/extended_4metric_to_25k.png
13
- 0f472db11e1f6809b2369727de9d78e224d1c5916701141eae0c5207149d0681 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/plots/fertility_per_in_domain_slice.png
14
- 7b90ed2c76344942c48fbb445386e16fde9e0a9af0fdbd03e96054aee1ec38d3 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/plots/headline_4metric_in_domain.png
15
- f72541da46b7539acca2c0fc9d641d751f0461528598e9d82651e3722681c226 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/plots/knee_analysis.png
16
- 4f0148ff0c94a8b67e329517ab260963daa027c0ab64ac992cffe4e95c073665 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/plots/morphscore_greek.png
17
- 763f330459d536e1ca7832dddc755e7d5f43c69605f8f8ca6c688f24c7cdf895 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/manifests/curated_padded_at_17408_manifest.json
18
- 7874469554d319addc7f113e6b5d4b7f8984e3bd4db9b3dcaa3e4e476cf392f0 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/manifests/removal_mask_at_17408.jsonl
19
- 0b3c2f295d1f14c9409b39ca2e6fc98346037a7d11a7cd931b59fcff7824b2e9 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/manifests/tokeval_commit.txt
20
- 7147abc0dd32b702a399e02f47cea5576594ee6ec0d089a4e1fb6d822797aad3 ./tokenizers/c3_added_17408_curated_padded/README.md
21
- 358c249e2fb29060c6b73157d428853b0c48710deffc8ee670ab1013880946c9 ./tokenizers/c3_added_17408_curated_padded/special_tokens_map.json
22
- 358ae3f29ac17c99769d6d437339e28657d5fcaed3486f8550feed3d6adfc394 ./tokenizers/c3_added_17408_curated_padded/tokenizer.json
23
- 737b93393573376f6b4707ebfbb17688d0c358cba0daa3be12b4f9f57f9cb2ae ./tokenizers/c3_added_17408_curated_padded/tokenizer_config.json
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ d528c230d2d3e151776332036669794eaacc5962a1dd3b3805a64c56e2f539ff ./ARTIFACT_GRAPH.md
2
+ 6c8fe007c045e4be44f2825d16724be5cc80d53956b1aba3d64b8843f42f2c9c ./MANIFEST.json
3
+ e055076dd9f8fc307d2056f5c46c9f6cd99463dfe610758a45796e98200bf3cc ./README.md
4
+ dc2f59def39f4d46b645608e789ebca000b3f3257336c393b234da9b9c26f607 ./archive/legacy-hf-layout-index.md
5
+ 620d1591179643c31aca8c3ba98492204fc2dd3388afff5764726d632b28fd09 ./archive/legacy_SHA256SUMS_20260525
6
+ 2eee70665c1fd320ebc5d664d5fe3b526be32adf33be71f63a0edd3b52545076 ./checkpoints/baselines/retok-3p5b-iter834/README.md
7
+ be50de74fda67fb79a2d4ae616f3eaa0800e46b641b1ae3bd5a5d12e1fd6aeb2 ./checkpoints/baselines/retok-3p5b-iter834/hydration.md
8
+ 1a4aff5d2d4dec2424a50fb7921d3bb92fc9a92d3e6b539a4bc2b542dfefa9a5 ./checkpoints/baselines/retok-3p5b-iter834/manifest.json
9
+ ea3e33007aa0ddfff2f88039b9f7d6a16c1317b14bee999ab762fc6867000649 ./checkpoints/baselines/vanilla-3p5b-iter834/README.md
10
+ 1531171806fc72e45ba4467a1872a40ed1360ae5b6926cd7e313f818d924e4cd ./checkpoints/baselines/vanilla-3p5b-iter834/hydration.md
11
+ c7203eaed58b9b9a23d21e7b25ac37dbf9ee07538707626181f06795b1ae26c1 ./checkpoints/baselines/vanilla-3p5b-iter834/manifest.json
12
+ 553be4bd24ccfc8bef210913c5e6ff7a26ca909b782bbd266ad927db07709581 ./checkpoints/td-layer11-cpt-3p5b-iter834/README.md
13
+ 6d0724888604be70abae50448eb120160710b875b42dec21ce7419a82fa60c01 ./checkpoints/td-layer11-cpt-3p5b-iter834/hydration.md
14
+ 69b48c1c95a4c79cfdbab0ec12a669e0bc74549294e3c38dfde57d547dd2d2f6 ./checkpoints/td-layer11-cpt-3p5b-iter834/manifest.json
15
+ 4bcb2a3a6316ee1373a170d0d4bb9e32ec25dafb942c10fb781188216faceafd ./checkpoints/td-layer11-init-r17-tp2/README.md
16
+ da19cd1247b0401eb6d6e25d8c0fc496ee5d93b2e745b05ce8ff59b6b9fd8c57 ./checkpoints/td-layer11-init-r17-tp2/hydration.md
17
+ 98d6a3fa9b342949b4972514925bff2952de06a202bcfcc56b449741ea4530c6 ./checkpoints/td-layer11-init-r17-tp2/manifest.json
18
+ 44a71b0a1730bf13f3387ccf15967bf036f519f002b775cd4e7a671a44c9830a ./code-links/README.md
19
+ 44705bc53f80deba2ac02336a29a77a6fa1b83431ec10fe9b100b5493903956f ./code-links/github_subproject_manifest.json
20
+ 06ddc69f4787f470b85d4be55992f898b98d8ab4fd8ab34a89a4d3bb96eb7e33 ./provenance/conversion-roundtrip/td_layer11_r17_roundtrip_verification.json
21
+ 496fa7d6f5622d6038aa2e333adbbd142ac83341e834acedc697892d66031c44 ./provenance/conversion-roundtrip/vanilla_r17_roundtrip_verification.json
22
+ 61c13b8d63a692fad24e7cdf5fe5b5d6e2fb82bc4cf61981ea7c8b62b42569a6 ./provenance/dataset-build/CPT_DATASET_BUILD_RUNBOOK.md
23
+ 6ab3047ac06c925073ca06c1a91e91bf1c1ce4e4a1336f41f6ef35769228ebd1 ./provenance/dataset-build/MIX_RECIPE.md
24
+ 2dafea9a789b717e1f8b6fb931d8b47483e3b8433ceb1fe4b8064afa3bf5489a ./provenance/dataset-build/bulk_mix_text_document.manifest.json
25
+ 8fbed782f3250003ef427d56ff27ae4379311da5a6263e078466ce06d6078bd2 ./provenance/evals/CONTINUATION_3P5B_RESULTS_20260525.md
26
+ d336b0f9fa29db6ce9052ae5fcac15e55acf8f4dc0e1385c820076c43c1e4a42 ./provenance/evals/EVAL_RECIPE.md
27
+ c10f3693691c657945530ee70bfcca8ad85bd3b42939f1ff321c9aa27b085112 ./provenance/evals/V4_BENCHMARK_COMPARISON.md
28
+ 80e2fda4e1c0ce1e2e066986add6c9e76db592f9d9b20b0b0f6857209c101d7d ./provenance/token-distillation/RUN_LOG_20260523.md
29
+ acda2215c1443fdd3ad25ced78085c121139640adf6d4f3037f776ec6e13f47d ./provenance/token-distillation/TOKEN_DISTILLATION_PLAN.md
30
+ fada1d3fa64b8060b17a65bc8b4fa8739e560454fcfe172d681ce055a51a38ba ./provenance/tokenizer-selection/CHOSEN_CUTOFF.md
31
+ 9b350211cf4f0bd964feec9504a093c1062425fb12f22534a947112f357e5c25 ./provenance/tokenizer-selection/CUTOFF_SWEEP_REPORT.md
32
+ 763f330459d536e1ca7832dddc755e7d5f43c69605f8f8ca6c688f24c7cdf895 ./provenance/tokenizer-selection/curated_padded_at_17408_manifest.json
33
+ 6046eb8f4cabda22fddf8cf5ed1581267b854221d03253e2994d304572b4f320 ./provenance/tokenizer-selection/firing_count_20260518_run_summary_augmented.json
34
+ 8fbed782f3250003ef427d56ff27ae4379311da5a6263e078466ce06d6078bd2 ./results/SUMMARY.md
35
+ 712a3c96216fe3159433b9b9d886a8cb22b51001a35a3778a7e5d6ba99909772 ./results/benchmark_table.csv
36
+ 669dc4a1c3252f994495d2fb1459145222443bcfa6f6ca1221e8ee92b602c56b ./results/continuation_3p5b_summary.json
37
+ 13337a7976d4ca46c6c3db03014a2207ba81a42796c285410dc3f4ad26007cd9 ./results/plots/global_mmlu_full_el_subcategories_van_td.png
38
+ 6375661e9c50fd4b9f32db79a9c77375aaadbb878fab8a61019802978af3ac0e ./results/plots/include_base_44_greek_subjects_van_td.png
39
+ a44571c0aca767ace369a89534632a9b4618bc01391c0b20bb0f04f1c34a8830 ./results/plots/intrinsic_trajectories.png
40
+ 975e0c58604e6189f45182e07cf178bb94bead39130385aae36ed95c065ed2ad ./results/plots/intrinsic_van_td.png
41
+ ab072600c16be4aab4fe36ebd5b7fe3a216f1bf5ac391687733667f6231ff486 ./results/plots/trajectories.png
42
+ 375efc4b55341c0a1060fb9d7ccaa8774db66c8ca554683100449e15b1541a44 ./results/plots/trajectories_per_task.png
43
+ ea2a02ecd33210ada4c9a5d1f7832246de07205cc4bbc5679aedb6959f93bfbe ./results/plots/trajectories_per_task_van_td.png
44
+ a54f94603549ddaf022297a2f691a688fb6283d793394f482531211b42dfa3a3 ./results/plots/trajectories_van_td.png
45
+ d49ee1c80666418e6f36b649b63c9a80fb2808bb365d31e481a6c58c97053d11 ./results/plots/trajectories_van_td_gap.png
46
+ 55ce65390b6fbdc16a81f22e3d78c3a452e72192011b72289c0180a656052273 ./tokenizer/modern-greek-17408/README.md
47
+ 09c84b4086e9f800174942dcba688d8eefa8e40f3b60c20341699a6a7a11e2bf ./tokenizer/modern-greek-17408/manifest.json
48
+ 816ec96e37c6d15e3cbc535dc146c898a7218f209fc154384f31fc1e6ad31ba5 ./tokenizer/modern-greek-17408/special_tokens_map.json
49
+ 358ae3f29ac17c99769d6d437339e28657d5fcaed3486f8550feed3d6adfc394 ./tokenizer/modern-greek-17408/tokenizer.json
50
+ ea64a17b41e1deaa7469212f413676129f33977ca3a48767f0ca68dc346df502 ./tokenizer/modern-greek-17408/tokenizer_config.json
51
+ 208ae8ea5f95c9182dc669c150aaf0c720e5937a402c72062fd83e1960978d6a ./tokenizer/polytonic-plus-5120/README.md
52
+ 3881e1940ca013e9ec040fac3fb3a08a8f9b871e5105a0fec8165e0c6759acae ./tokenizer/polytonic-plus-5120/manifest.json
53
+ 816ec96e37c6d15e3cbc535dc146c898a7218f209fc154384f31fc1e6ad31ba5 ./tokenizer/polytonic-plus-5120/special_tokens_map.json
54
+ b1eeb739a564b3abd33c1b85a16162b8284d98f9ab5d67528d3cbe8a82e9cbad ./tokenizer/polytonic-plus-5120/tokenizer.json
55
+ ea64a17b41e1deaa7469212f413676129f33977ca3a48767f0ca68dc346df502 ./tokenizer/polytonic-plus-5120/tokenizer_config.json
56
+ d2f04aa396cf6558502b919b4503d248aef0ccfe08251625d75f8a9314272787 ./training-data/cpt-7b-mix/README.md
57
+ f16d35ba906d5439709f189b1dc1253ba6e3d8518a828aac71c04fd42fefd0cf ./training-data/cpt-7b-mix/hydration.md
58
+ cafd9e0b15ab1d9f4f0eb7bc2939ccab29e9b6ab86ccc1f20e9a42a86b5760c0 ./training-data/cpt-7b-mix/manifest.json
59
+ 4918a44fd6c0643c984b6cba3914c53c9a3a656f313ec904e9ba7e5ed1303279 ./training-data/cpt-7b-mix/source_graph.json
archive/legacy-hf-layout-index.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Legacy Hugging Face Layout Index
2
+
3
+ The previous Hugging Face repo layout included useful but noisy top-level
4
+ folders:
5
+
6
+ - `analysis/`;
7
+ - `artifacts/`;
8
+ - `continuous/`;
9
+ - `experiments/`;
10
+ - `fresh/`;
11
+ - `metadata/`;
12
+ - `subprojects/`;
13
+ - `tokenizers/`.
14
+
15
+ Those paths are retained for traceability. The release entrypoints are now the
16
+ curated folders at the repo root:
17
+
18
+ - `tokenizer/`;
19
+ - `checkpoints/`;
20
+ - `training-data/`;
21
+ - `results/`;
22
+ - `provenance/`;
23
+ - `code-links/`.
24
+
25
+ Do not treat this file as a deletion plan. It is an index explaining the old
26
+ layout while the new additive structure is reviewed.
27
+
archive/legacy_SHA256SUMS_20260525 ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ e6e321ad419e32ce43427bba05a02a23133f05500a3486f98c5de232830c1844 ./README.md
2
+ 5c2140f0d646a2f5eaf7ea07c033fade7e28b37468eeb8595f61f6044f6cf109 ./SHA256SUMS
3
+ f6742a090b39f1f576d18481bb1e284720275b0ab417393f219650821e83a72a ./experiments/02_1_7_intrinsic_eval_sweep_20260518/CHOSEN_CUTOFF.md
4
+ 3d68bbd6e6c9e25df597f46819cbe57e336b62b8a9b5b441aadeae5346e70eb7 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/README.md
5
+ 9b350211cf4f0bd964feec9504a093c1062425fb12f22534a947112f357e5c25 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/REPORT.md
6
+ 60a57f77e13d8204c7728e6e5a117cb947c156c97e2c57db7de587965ada58bf ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/morphscore_greek_results.json
7
+ 7dd2ae959af9504d522cf4b606c573e6cefdd71c009fe8a7269eb051382351f0 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/our_suite_raw_gcloud/curated_metrics_by_slice.csv
8
+ 76ad56410ada9ef2d7649d3babb757287993982e03fc98057e7289ec837c990c ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/our_suite_raw_gcloud/extended_metrics_by_slice.csv
9
+ 190c58ce62f8878c92499ef7da9bceb26f27a1b5f25927e6681d80df59359c79 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/our_suite_raw_gcloud/metrics_by_slice.csv
10
+ f823dcc20f7cc2d7435fda6c5c09e65d704de10d37330f9ed930fdcf7f75506b ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/our_suite_raw_gcloud/padded_17408_metrics.csv
11
+ 9e94927189811f9c5df2e6f75c3e4ffc4738d4305a35eef2b8499c6bf15c5acf ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/our_suite_raw_gcloud/summary.json
12
+ 7bbfd6c76cc88190a2334ab45af03f77e8389830e46e8dcc4ef896f7e2e3b8fc ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/plots/extended_4metric_to_25k.png
13
+ 0f472db11e1f6809b2369727de9d78e224d1c5916701141eae0c5207149d0681 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/plots/fertility_per_in_domain_slice.png
14
+ 7b90ed2c76344942c48fbb445386e16fde9e0a9af0fdbd03e96054aee1ec38d3 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/plots/headline_4metric_in_domain.png
15
+ f72541da46b7539acca2c0fc9d641d751f0461528598e9d82651e3722681c226 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/plots/knee_analysis.png
16
+ 4f0148ff0c94a8b67e329517ab260963daa027c0ab64ac992cffe4e95c073665 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/artifacts/plots/morphscore_greek.png
17
+ 763f330459d536e1ca7832dddc755e7d5f43c69605f8f8ca6c688f24c7cdf895 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/manifests/curated_padded_at_17408_manifest.json
18
+ 7874469554d319addc7f113e6b5d4b7f8984e3bd4db9b3dcaa3e4e476cf392f0 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/manifests/removal_mask_at_17408.jsonl
19
+ 0b3c2f295d1f14c9409b39ca2e6fc98346037a7d11a7cd931b59fcff7824b2e9 ./experiments/02_1_7_intrinsic_eval_sweep_20260518/manifests/tokeval_commit.txt
20
+ 7147abc0dd32b702a399e02f47cea5576594ee6ec0d089a4e1fb6d822797aad3 ./tokenizers/c3_added_17408_curated_padded/README.md
21
+ 358c249e2fb29060c6b73157d428853b0c48710deffc8ee670ab1013880946c9 ./tokenizers/c3_added_17408_curated_padded/special_tokens_map.json
22
+ 358ae3f29ac17c99769d6d437339e28657d5fcaed3486f8550feed3d6adfc394 ./tokenizers/c3_added_17408_curated_padded/tokenizer.json
23
+ 737b93393573376f6b4707ebfbb17688d0c358cba0daa3be12b4f9f57f9cb2ae ./tokenizers/c3_added_17408_curated_padded/tokenizer_config.json
checkpoints/baselines/retok-3p5b-iter834/README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ReTok Baseline, 3.5B Iter 834
2
+
3
+ Status: hydration pointer.
4
+
5
+ Clariden checkpoint:
6
+
7
+ ```text
8
+ /capstor/scratch/cscs/fffoivos/runs/bakeoff/continuation_3p5b_20260524T143012Z_retok/checkpoints/iter_0000834
9
+ ```
10
+
11
+ This is the ReTok baseline for the modern-only 148480-vocab tokenizer.
12
+
checkpoints/baselines/retok-3p5b-iter834/hydration.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # Hydration
2
+
3
+ On Clariden:
4
+
5
+ ```bash
6
+ ls -lh /capstor/scratch/cscs/fffoivos/runs/bakeoff/continuation_3p5b_20260524T143012Z_retok/checkpoints/iter_0000834
7
+ ```
8
+
checkpoints/baselines/retok-3p5b-iter834/manifest.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "artifact_id": "checkpoint.baseline-retok-3p5b-iter834",
3
+ "status": "hydration-pointer",
4
+ "tokenizer": "tokenizer.modern-greek-17408",
5
+ "source_checkpoint": "/capstor/scratch/cscs/fffoivos/runs/bakeoff/continuation_3p5b_20260524T143012Z_retok/checkpoints/iter_0000834",
6
+ "iteration": 834
7
+ }
8
+
checkpoints/baselines/vanilla-3p5b-iter834/README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Vanilla Baseline, 3.5B Iter 834
2
+
3
+ Status: hydration pointer.
4
+
5
+ Clariden checkpoint:
6
+
7
+ ```text
8
+ /capstor/scratch/cscs/fffoivos/runs/bakeoff/continuation_3p5b_20260524T143012Z_vanilla/checkpoints/iter_0000834
9
+ ```
10
+
11
+ This baseline keeps the original Apertus tokenizer and remains the heldout-BPC
12
+ reference in the 3.5B continuation.
13
+
checkpoints/baselines/vanilla-3p5b-iter834/hydration.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # Hydration
2
+
3
+ On Clariden:
4
+
5
+ ```bash
6
+ ls -lh /capstor/scratch/cscs/fffoivos/runs/bakeoff/continuation_3p5b_20260524T143012Z_vanilla/checkpoints/iter_0000834
7
+ ```
8
+
checkpoints/baselines/vanilla-3p5b-iter834/manifest.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "artifact_id": "checkpoint.baseline-vanilla-3p5b-iter834",
3
+ "status": "hydration-pointer",
4
+ "tokenizer": "swiss-ai/Apertus-8B-2509 base tokenizer",
5
+ "source_checkpoint": "/capstor/scratch/cscs/fffoivos/runs/bakeoff/continuation_3p5b_20260524T143012Z_vanilla/checkpoints/iter_0000834",
6
+ "iteration": 834
7
+ }
8
+
checkpoints/td-layer11-cpt-3p5b-iter834/README.md ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # TD Layer 11 CPT Checkpoint, 3.5B Iter 834
2
+
3
+ Status: hydration pointer.
4
+
5
+ This is the leading extended-tokenizer checkpoint after the 3.5B continuation.
6
+
7
+ Clariden checkpoint:
8
+
9
+ ```text
10
+ /capstor/scratch/cscs/fffoivos/runs/bakeoff/continuation_3p5b_20260524T143012Z_td_layer11/checkpoints/iter_0000834
11
+ ```
12
+
13
+ HF-format eval copy:
14
+
15
+ ```text
16
+ /capstor/scratch/cscs/fffoivos/runs/eval/continuation_3p5b_20260524T143012Z_td_layer11/iter_0000834_hf
17
+ ```
18
+
19
+ Tokenizer:
20
+
21
+ ```text
22
+ ../../tokenizer/modern-greek-17408/
23
+ ```
24
+
25
+ Result summary:
26
+
27
+ ```text
28
+ ../../results/SUMMARY.md
29
+ ```
30
+
checkpoints/td-layer11-cpt-3p5b-iter834/hydration.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hydration
2
+
3
+ This release entry is a pointer, not a checkpoint payload.
4
+
5
+ On Clariden, use:
6
+
7
+ ```bash
8
+ ls -lh /capstor/scratch/cscs/fffoivos/runs/bakeoff/continuation_3p5b_20260524T143012Z_td_layer11/checkpoints/iter_0000834
9
+ ls -lh /capstor/scratch/cscs/fffoivos/runs/eval/continuation_3p5b_20260524T143012Z_td_layer11/iter_0000834_hf
10
+ ```
11
+
12
+ Before publishing this as loadable HF weights, verify the HF eval copy contains
13
+ the expected config, tokenizer, and safetensor shards, then upload only that
14
+ inference-ready payload.
15
+
checkpoints/td-layer11-cpt-3p5b-iter834/manifest.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "artifact_id": "checkpoint.td-layer11-cpt-3p5b-iter834",
3
+ "status": "hydration-pointer",
4
+ "tokenizer": "tokenizer.modern-greek-17408",
5
+ "source_checkpoint": "/capstor/scratch/cscs/fffoivos/runs/bakeoff/continuation_3p5b_20260524T143012Z_td_layer11/checkpoints/iter_0000834",
6
+ "hf_eval_copy": "/capstor/scratch/cscs/fffoivos/runs/eval/continuation_3p5b_20260524T143012Z_td_layer11/iter_0000834_hf",
7
+ "training_stage": "3.5B continuation",
8
+ "iteration": 834,
9
+ "source_code": "https://github.com/fffoivos/glossapi-tokenizer-extension/tree/main/subprojects/03_apertus_extension_and_embedding_adaptation"
10
+ }
11
+
checkpoints/td-layer11-init-r17-tp2/README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # TD Layer 11 Init, R17-Patched TP=2
2
+
3
+ Status: hydration pointer.
4
+
5
+ Clariden checkpoint:
6
+
7
+ ```text
8
+ /iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/megatron_tp2_r17patched/release
9
+ ```
10
+
11
+ This is the Token Distillation layer-11 initialization in Megatron TP=2 format,
12
+ after the R17/xIELU/QK-Norm preservation patch and roundtrip verification.
13
+
checkpoints/td-layer11-init-r17-tp2/hydration.md ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hydration
2
+
3
+ On Clariden:
4
+
5
+ ```bash
6
+ ls -lh /iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/megatron_tp2_r17patched/release
7
+ ```
8
+
9
+ Verification evidence:
10
+
11
+ ```text
12
+ ../../provenance/conversion-roundtrip/td_layer11_r17_roundtrip_verification.json
13
+ ```
14
+
checkpoints/td-layer11-init-r17-tp2/manifest.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "artifact_id": "checkpoint.td-layer11-init-r17-tp2",
3
+ "status": "hydration-pointer",
4
+ "tokenizer": "tokenizer.modern-greek-17408",
5
+ "source_checkpoint": "/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/megatron_tp2_r17patched/release",
6
+ "format": "Megatron torch_dist TP=2, R17 patched",
7
+ "verification": "../../provenance/conversion-roundtrip/td_layer11_r17_roundtrip_verification.json"
8
+ }
9
+
code-links/README.md ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Source Code Links
2
+
3
+ The runnable implementation lives in GitHub:
4
+
5
+ ```text
6
+ https://github.com/fffoivos/glossapi-tokenizer-extension/tree/main/subprojects/03_apertus_extension_and_embedding_adaptation
7
+ ```
8
+
9
+ This Hugging Face release keeps artifact payloads, manifests, compact evidence,
10
+ and hydration instructions. It does not mirror the full scripts tree.
11
+
12
+ See:
13
+
14
+ ```text
15
+ github_subproject_manifest.json
16
+ ```
17
+
code-links/github_subproject_manifest.json ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "repo": "https://github.com/fffoivos/glossapi-tokenizer-extension",
3
+ "branch": "main",
4
+ "source_commit": "7c67cf11eb3d31f0ddd006f7d709709037db93a1",
5
+ "subproject": "subprojects/03_apertus_extension_and_embedding_adaptation",
6
+ "script_families": [
7
+ {
8
+ "family": "tokenizer_shipping",
9
+ "paths": [
10
+ "03_3_cscs_experiments_kickoff/ship/apertus_greek_modern_only_148480",
11
+ "03_3_cscs_experiments_kickoff/ship/apertus_greek_extended_153600"
12
+ ],
13
+ "artifacts": [
14
+ "tokenizer.modern-greek-17408",
15
+ "tokenizer.polytonic-plus-5120"
16
+ ]
17
+ },
18
+ {
19
+ "family": "corpus_build",
20
+ "paths": [
21
+ "03_2_apertus_c3_dedup_audit/CPT_DATASET_BUILD_RUNBOOK.md",
22
+ "03_4_implementation_experiments/init_bakeoff/corpus_build"
23
+ ],
24
+ "artifacts": [
25
+ "dataset.cpt-7b-mix"
26
+ ]
27
+ },
28
+ {
29
+ "family": "init_and_conversion",
30
+ "paths": [
31
+ "03_4_implementation_experiments/init_bakeoff/arms",
32
+ "03_4_implementation_experiments/init_bakeoff/megatron_patches"
33
+ ],
34
+ "artifacts": [
35
+ "checkpoint.td-layer11-init-r17-tp2",
36
+ "checkpoint.baseline-vanilla-3p5b-iter834",
37
+ "checkpoint.baseline-retok-3p5b-iter834"
38
+ ]
39
+ },
40
+ {
41
+ "family": "token_distillation",
42
+ "paths": [
43
+ "TOKEN_DISTILLATION_PLAN.md",
44
+ "03_4_implementation_experiments/init_bakeoff/token_distillation"
45
+ ],
46
+ "artifacts": [
47
+ "checkpoint.td-layer11-init-r17-tp2"
48
+ ]
49
+ },
50
+ {
51
+ "family": "training",
52
+ "paths": [
53
+ "TRAINING_RECIPE.md",
54
+ "03_4_implementation_experiments/init_bakeoff/bakeoff_training"
55
+ ],
56
+ "artifacts": [
57
+ "checkpoint.td-layer11-cpt-3p5b-iter834",
58
+ "checkpoint.baseline-vanilla-3p5b-iter834",
59
+ "checkpoint.baseline-retok-3p5b-iter834"
60
+ ]
61
+ },
62
+ {
63
+ "family": "evaluation",
64
+ "paths": [
65
+ "03_4_implementation_experiments/init_bakeoff/eval"
66
+ ],
67
+ "artifacts": [
68
+ "results.continuation-3p5b"
69
+ ]
70
+ }
71
+ ]
72
+ }
73
+
provenance/conversion-roundtrip/td_layer11_r17_roundtrip_verification.json ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "orig_only": [],
3
+ "trip_only": [],
4
+ "standard_max_abs_diff": 0.0,
5
+ "r17_max_abs_diff": 0.0,
6
+ "xielu_max_abs_diff": 0.0,
7
+ "qk_norm_max_abs_diff": 0.0,
8
+ "standard_changed_over_tol": [],
9
+ "r17_changed_over_tol": [],
10
+ "shape_mismatches": [],
11
+ "standard_changed_over_tol_count": 0,
12
+ "r17_changed_over_tol_count": 0,
13
+ "logits": {
14
+ "logit_max_abs_diff": 0.0,
15
+ "logit_mean_abs_diff_max": 0.0,
16
+ "per_prompt": [
17
+ {
18
+ "prompt": "Η Αθήνα είναι η πρωτεύουσα της",
19
+ "max_abs": 0.0,
20
+ "mean_abs": 0.0,
21
+ "reference_top_id": 72499,
22
+ "roundtrip_top_id": 72499,
23
+ "top_id_match": true
24
+ },
25
+ {
26
+ "prompt": "Ο Όμηρος έγραψε",
27
+ "max_abs": 0.0,
28
+ "mean_abs": 0.0,
29
+ "reference_top_id": 132093,
30
+ "roundtrip_top_id": 132093,
31
+ "top_id_match": true
32
+ },
33
+ {
34
+ "prompt": "The capital of Greece is",
35
+ "max_abs": 0.0,
36
+ "mean_abs": 0.0,
37
+ "reference_top_id": 132048,
38
+ "roundtrip_top_id": 132048,
39
+ "top_id_match": true
40
+ }
41
+ ]
42
+ }
43
+ }
provenance/conversion-roundtrip/vanilla_r17_roundtrip_verification.json ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "orig_only": [],
3
+ "trip_only": [],
4
+ "standard_max_abs_diff": 0.0,
5
+ "r17_max_abs_diff": 0.0,
6
+ "xielu_max_abs_diff": 0.0,
7
+ "qk_norm_max_abs_diff": 0.0,
8
+ "standard_changed_over_tol": [],
9
+ "r17_changed_over_tol": [],
10
+ "shape_mismatches": [],
11
+ "standard_changed_over_tol_count": 0,
12
+ "r17_changed_over_tol_count": 0,
13
+ "logits": {
14
+ "logit_max_abs_diff": 0.0,
15
+ "logit_mean_abs_diff_max": 0.0,
16
+ "per_prompt": [
17
+ {
18
+ "prompt": "Η Αθήνα είναι η πρωτεύουσα της",
19
+ "max_abs": 0.0,
20
+ "mean_abs": 0.0,
21
+ "reference_top_id": 72499,
22
+ "roundtrip_top_id": 72499,
23
+ "top_id_match": true
24
+ },
25
+ {
26
+ "prompt": "Ο Όμηρος έγραψε",
27
+ "max_abs": 0.0,
28
+ "mean_abs": 0.0,
29
+ "reference_top_id": 8329,
30
+ "roundtrip_top_id": 8329,
31
+ "top_id_match": true
32
+ },
33
+ {
34
+ "prompt": "The capital of Greece is",
35
+ "max_abs": 0.0,
36
+ "mean_abs": 0.0,
37
+ "reference_top_id": 48214,
38
+ "roundtrip_top_id": 48214,
39
+ "top_id_match": true
40
+ }
41
+ ]
42
+ }
43
+ }
provenance/dataset-build/CPT_DATASET_BUILD_RUNBOOK.md ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # CPT Dataset Build Runbook
2
+
3
+ This is the repeatable path for building an Apertus CPT dataset from the
4
+ published nanochat corpus.
5
+
6
+ ## Inputs
7
+
8
+ - Source corpus:
9
+ `fffoivos/glossapi-greek-nanochat-pretraining-dataset`
10
+ - Nanochat internal dedup bundle:
11
+ `dedup_metadata/wave2_20260426_builder_metadata_v2_latest_cleaner_20260507/builder_metadata`
12
+ - Apertus hard-drop overlay:
13
+ `fffoivos/apertus-c3-dedup-audit-dedup-20260519t010924z`
14
+ at `artifacts/dedup_20260519T010924Z/cpt_final_overlay/apertus_overlap_drop_docs.parquet`
15
+
16
+ The correct order is:
17
+
18
+ 1. Download the published nanochat source rows.
19
+ 2. Hard-exclude `apertus_overlap_drop_docs.parquet`.
20
+ 3. Replay nanochat internal dedup with `drop_intra_and_inter`.
21
+ 4. Build the final CPT mix/export from the remaining pool.
22
+
23
+ The order matters: if Apertus-overlapping docs are removed first, an internal
24
+ duplicate family can still keep a fresh alternate representative.
25
+
26
+ ## GCP Scratch VM
27
+
28
+ Use a scratch VM with a large disk. A practical starting point is a
29
+ `c4-highmem-32` or larger VM with a 1-2 TB SSD/PD disk. Build artifacts should
30
+ be uploaded to Hugging Face or GCS before teardown.
31
+
32
+ Example setup on the VM:
33
+
34
+ ```bash
35
+ sudo apt-get update
36
+ sudo apt-get install -y git python3-pip
37
+ python3 -m pip install --user duckdb pandas pyarrow huggingface_hub typer blake3 polars
38
+
39
+ git clone https://github.com/<your-org-or-user>/glossapi-tokenizer-extension.git
40
+ cd glossapi-tokenizer-extension
41
+ export PYTHONPATH="$PWD"
42
+ ```
43
+
44
+ ## Download Inputs
45
+
46
+ Do not build from the old local `/home/foivos/data/glossapi_work/hf_release_publish`
47
+ copy. Hydrate from the live HF repo so the `source_dataset` names and derived
48
+ `doc_key` values match the Apertus overlay and the `wave2` dedup bundle.
49
+
50
+ ```bash
51
+ export WORK=/mnt/disks/cpt_build
52
+ mkdir -p "$WORK"
53
+
54
+ huggingface-cli download fffoivos/glossapi-greek-nanochat-pretraining-dataset \
55
+ --repo-type dataset \
56
+ --local-dir "$WORK/nanochat" \
57
+ --include 'data/*.parquet' \
58
+ --include 'dedup_metadata/latest.json' \
59
+ --include 'dedup_metadata/wave2_20260426_builder_metadata_v2_latest_cleaner_20260507/builder_metadata/*'
60
+
61
+ huggingface-cli download fffoivos/apertus-c3-dedup-audit-dedup-20260519t010924z \
62
+ --repo-type dataset \
63
+ --local-dir "$WORK/apertus_audit" \
64
+ --include 'artifacts/dedup_20260519T010924Z/cpt_final_overlay/*'
65
+ ```
66
+
67
+ ## Build Fresh Deduped Pool
68
+
69
+ ```bash
70
+ export DEDUP_ROOT="$WORK/nanochat/dedup_metadata/wave2_20260426_builder_metadata_v2_latest_cleaner_20260507/builder_metadata"
71
+ export APERTUS_DROP="$WORK/apertus_audit/artifacts/dedup_20260519T010924Z/cpt_final_overlay/apertus_overlap_drop_docs.parquet"
72
+ export SELECTED="$WORK/cpt/selected_after_apertus_and_internal_dedup.parquet"
73
+
74
+ python3 -m glossapi_corpus_cli.cli mix-prepare-selected-input \
75
+ --output-root "$WORK/nanochat" \
76
+ --selected-input-path "$SELECTED" \
77
+ --exclude-doc-keys-path "$APERTUS_DROP" \
78
+ --dedup-metadata-root "$DEDUP_ROOT" \
79
+ --dedup-action drop_intra_and_inter \
80
+ --dedup-exact-stage strict_and_relaxed \
81
+ --dedup-similarity-threshold 0.85 \
82
+ --dedup-inter-dataset-policy share_aware
83
+ ```
84
+
85
+ `$SELECTED` is the deduplicated, Apertus-fresh source pool. If the CPT recipe
86
+ uses the whole remaining pool, this is the main dataset artifact.
87
+
88
+ ## Optional Source Mix
89
+
90
+ If the CPT run needs a sampled or weighted mix, build it from `$SELECTED`:
91
+
92
+ ```bash
93
+ python3 -m glossapi_corpus_cli.cli mix-build-from-selected-input \
94
+ --selected-input-path "$SELECTED" \
95
+ --mix-output-path "$WORK/cpt/final_cpt_mix.parquet" \
96
+ --source-mix-config-path "$WORK/cpt/source_mix.json"
97
+ ```
98
+
99
+ ## Publish And Teardown
100
+
101
+ Upload the final selected pool or mix before deleting the VM:
102
+
103
+ ```bash
104
+ huggingface-cli upload <target-hf-dataset-repo> "$WORK/cpt" . --repo-type dataset
105
+ ```
106
+
107
+ Then verify the HF repo contains the final parquet(s), summaries, and the
108
+ `cpt_final_overlay/summary.json` provenance before tearing down the VM.
provenance/dataset-build/MIX_RECIPE.md ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Mix recipes — bulk and anneal
2
+
3
+ The bakeoff (and future production CPT) consumes a stream of documents
4
+ interleaved from several sources with explicit per-source weights. Per
5
+ [`../../cpt_plan.md`](../../cpt_plan.md) v0.7 §2 + §4:
6
+
7
+ - **Bulk phase**: one shuffled-mixture stream, all corpora at target weights from token 0. This is what the bakeoff actually trains on.
8
+ - **Anneal phase**: final 10–20 % of *production* training (out of scope for the bakeoff). Mixture shifts to highest-priority subsets; replay drops from ~30 % → ~15 %; LR decays. We define the recipe here for completeness; the bakeoff never executes it.
9
+
10
+ Both recipes are JSON, in `recipes/`. The mix builder (`mix_builder.py`) reads either and emits a JSON-lines stream.
11
+
12
+ ## Three-step build path (reviewer round-2 Blocker 3 fix)
13
+
14
+ The CPT dataset build follows the canonical runbook at [`../../../03_2_apertus_c3_dedup_audit/CPT_DATASET_BUILD_RUNBOOK.md`](../../../03_2_apertus_c3_dedup_audit/CPT_DATASET_BUILD_RUNBOOK.md). **Order matters**: if Apertus-overlapping docs are removed first, an internal-duplicate family can still keep a fresh alternate representative.
15
+
16
+ ```
17
+ 1. bash pull_greek_corpus.sh # nanochat parquets + dedup_metadata + Apertus overlay
18
+ 2. bash prepare_greek_pool.sh # → $SELECTED parquet (Apertus-drop + drop_intra_and_inter)
19
+ 3. SELECTED=$WORK/cpt/selected_after_apertus_and_internal_dedup.parquet \
20
+ python3 mix_builder.py --recipe recipes/bulk.json --target-tokens 7_000_000_000 ...
21
+ ```
22
+
23
+ All six Greek `bulk.json` sources point at `local_parquet: ${SELECTED}` — the single post-dedup parquet — and filter by `source_dataset` value to slice into HPLT / literary / dialogue / academic / legal / dictionary buckets. The Apertus-overlap-drop is applied **upstream** in step 2 (not per-source in mix_builder), so it applies uniformly to all six categories rather than only to HPLT (the previous bug). Internal dedup with `drop_intra_and_inter` also happens in step 2 (was missing entirely before).
24
+
25
+ ## Composition (bulk recipe — what the bakeoff actually consumes)
26
+
27
+ Working defaults per v0.7 §2 + §4 + user answers 2026-05-20:
28
+
29
+ | Top-level bucket | Share | Sub-allocation |
30
+ |---|---:|---|
31
+ | Greek (post-Apertus-overlap-drop, post-internal-dedup) | **70 %** | see below |
32
+ | Non-Greek replay (24 languages, 3 tiers) | **24 %** | see below |
33
+ | Code | **4 %** | Intended: `bigcode/starcoderdata` / The Stack lineage (Apertus used StarCoder); 2026-05-21 CSCS fallback: `codeparrot/codeparrot-clean-train` |
34
+ | Math | **2 %** | `HuggingFaceTB/finemath` config `finemath-3plus` (Apertus stage-1 source per `submit_apertus_8b.sh:L29`) |
35
+
36
+ > **2026-05-21 rebalance.** Replay reduced from 26 % → 24 % to free 2 % for FineMath, taken entirely from English (FW-Edu) which went from 3.9 % → 1.9 %. The other 23 replay-language weights stay at their pre-rebalance values. Greek and code shares unchanged.
37
+
38
+ > **2026-05-21 CSCS run detail.** The live full-build recipe reads replay and FineMath from staged local single-shard parquets under `/iopsstor/scratch/cscs/fffoivos/cpt_corpus/{replay,math}`. This avoids repeated HF dataset-metadata resolution from seven concurrent shards, which hit HF's API rate limit. The Persian replay bucket uses the local FineWeb-2 `fas_Arab` fallback shard while preserving the recipe label `replay_t2_pes_Arab`.
39
+
40
+ > **OPUS Greek-English parallel** is listed as optional in v0.7 §4.4 but **not yet in the bakeoff bulk mix** — it needs different schema handling in `mix_builder.py` (its rows are `{translation: {el: ..., en: ...}}` rather than `{text: ...}`). Deferred to a future iteration of corpus_build.
41
+
42
+ ### Greek sub-allocation (70 % of total)
43
+
44
+ | Source | Share of Greek | HF id / filter |
45
+ |---|---:|---|
46
+ | **HPLT clean60 (fresh; Apertus-overlap overlay applied)** | 50 % of Greek = 35 % total | nanochat dataset, `source_dataset starts with HPLT__ell_Grek` + `apertus_overlap_drop_docs.parquet` exclude |
47
+ | Literary nanochat (artos-zois + Project_Gutenberg + Ekklisiastika + 1000_prwta + klasikh + Wikisource + dimodis_logotexnia + archetai) | 26 % of Greek = 18.2 % total | nanochat dataset, filter `source_dataset` ∈ literary list |
48
+ | Dialogue + textbooks (OPUS OpenSubtitles-el + openbook + Sxolika_vivlia + ert-press + istorima) | 9 % of Greek = 6.3 % total | nanochat dataset, filter |
49
+ | Academic (openarchives.gr + greek_phd + Apothetirio_Kallipos + Apothetirio_Pergamos) | 8 % of Greek = 5.6 % total | nanochat dataset, filter |
50
+ | Legal + civic (eurlex-greek-legislation + AI-team-UoA/greek_legal_code + opengov.gr-diaboyleuseis + ellinika_dedomena_europaikou_koinovouliou) | 5 % of Greek = 3.5 % total | nanochat dataset, filter |
51
+ | Dictionary + misc (modern-greek-dictionary capped + finewiki Greek half-weight + 95k_deigma + others) | 2 % of Greek = 1.4 % total | nanochat dataset, filter; modern-greek-dictionary explicitly capped per Claude-review note in `../../collegues_Apertus_plan.md` |
52
+
53
+ The HPLT half dominates by token mass (the underlying HPLT clean60 slice is ~50 B chars at v0.7 chars/token = ~14 B tokens; the GlossAPI sub-pools combined are smaller). The recipe weights are **probabilities for the interleaver**, which is what affects the per-step mix; effective token shares track these weights up to per-source exhaustion.
54
+
55
+ ### Non-Greek replay sub-allocation (24 % of total, across 24 languages)
56
+
57
+ Tier weights per v0.7 §4.2 (40–50 % T1 / 35–45 % T2 / 10–15 % T3); working defaults at the midpoint, scaled to the **24 % outer share** (post-2026-05-21 rebalance: English's share absorbed the 2 % shift to FineMath):
58
+
59
+ | Tier | Languages | Share of replay | Total share |
60
+ |---|---|---:|---:|
61
+ | **T1** (8 langs, FW2-HQ where Apertus used HQ) | eng, fra, deu, ita, spa, rus, arb, cmn | ~46 % | 11.0 % |
62
+ | **T2** (11 langs, FW2 where Apertus used standard) | tur, bul, srp, ron, heb, por, pol, nld, pes, ukr, jpn | ~41 % | 9.88 % |
63
+ | **T3** (5 langs, FW2; small per-lang) | lat, hye, kat, sqi (or als), mkd | ~13 % | 3.12 % |
64
+
65
+ Within each tier, weights are roughly equal *except* English gets ~17 % of T1 (≈ 1.9 % of total, post-rebalance) — still the largest single non-Greek language, but trimmed from 3.9 % to 1.9 % to make room for FineMath at 2 %. The remaining 7 T1 langs each stay at 1.3 % of total.
66
+
67
+ Per-language sources:
68
+
69
+ - T1 (Apertus quality-filtered the 20 high-resource langs at top-10 % per-language XLM-R): **`epfml/FineWeb2-HQ`** with `config_name = <iso639-3>_<script>` (Messmer, Sabolčec, Jaggi 2025, [arXiv:2502.10361](https://arxiv.org/abs/2502.10361); top-10 %, NOT "Score-3" — that's FineWeb-Edu's filter).
70
+ - T2 / T3 (Apertus used unfiltered FW2 for these): **`HuggingFaceFW/fineweb-2`** with `config_name = <iso639-3>_<script>` (v2.0.1 per Apertus tech report footnote 18).
71
+ - English specifically: prefer **`HuggingFaceFW/fineweb-edu`** Score-3 (Penedo et al. [arXiv:2406.17557](https://arxiv.org/abs/2406.17557); matches Apertus stage-5 cooldown). FineWeb2-HQ English is the fallback.
72
+
73
+ > **Reviewer flag**: cpt_plan.md v0.7 §4.2's "24 replay languages" framing (T1+T2+T3 = 8+11+5) is **our internal grouping**, not Apertus's. Apertus's tech report (arXiv:2509.14233 Appendix G, p.88-89) enumerates **20 high-resource languages** that receive quality+toxicity filtering; the other ~4 languages we include (T3: lat/hye/kat/sqi/mkd) are added by us for cultural/regional coverage relevant to Greek. Token-share targets per language are also our derivation, not from Apertus (the tech report only publishes document counts and percentages of FineWeb-2 documents, not training-mixture token shares).
74
+
75
+ ### Code (4 %)
76
+
77
+ | Source | HF id |
78
+ |---|---|
79
+ | Intended code replay | `bigcode/starcoderdata` (Apertus's pretraining source) |
80
+ | 2026-05-21 CSCS fallback | `codeparrot/codeparrot-clean-train` |
81
+
82
+ Use the default "all-permissive" subset when StarCoder/The Stack is accessible; no language filter (mixed-language source-code is fine for retention). The 2026-05-21 CSCS run uses `codeparrot/codeparrot-clean-train` because BigCode sources were gated or script-backed under the current auth/runtime. This preserves the intended 4 % code-retention pressure, but it is not an exact StarCoder-source match.
83
+
84
+ ### Math (2 %)
85
+
86
+ | Source | HF id + config |
87
+ |---|---|
88
+ | Math (web-derived high-quality math text) | `HuggingFaceTB/finemath` config `finemath-3plus` (Apertus stage-1 source per `submit_apertus_8b.sh:L29`) |
89
+
90
+ FineMath-3plus is the higher-quality subset of FineMath, selected for math content (problem statements, solutions, derivations) from CommonCrawl. Apertus uses `finemath-3plus-merge` in pretraining stage 1; the bakeoff includes it at the same 2 % share Apertus's stage-1 allocates within the broader mix (Apertus stage proportions aren't published per-source — 2 % is a reasonable default).
91
+
92
+ ## Composition (anneal recipe — defined but not run in the bakeoff)
93
+
94
+ Per v0.7 §3.2: in the final 10–20 % of production training, mixture shifts to highest-priority subsets and replay drops to ~15 %. Working pattern (between Llama 3 "narrow high-quality" and OLMo Dolmino "broad quality-curated"):
95
+
96
+ | Bucket | Bulk share | Anneal share | Reason |
97
+ |---|---:|---:|---|
98
+ | Greek high-quality literary (artos-zois + Project_Gutenberg + Wikisource + 1000_prwta) | 12 % | **30 %** | clean prose anchor |
99
+ | Greek academic + legal (openarchives + greek_phd + eurlex + greek_legal_code) | 9 % | **22 %** | domain depth |
100
+ | Greek dictionary (modern-greek-dictionary uncapped from anneal start) | 1 % | **15 %** | gap closure (Apertus_plan §"Final mix") |
101
+ | Greek dialogue + textbooks (OpenSubtitles + openbook + Sxolika + ert) | 6 % | **8 %** | maintained but de-emphasized |
102
+ | HPLT broad (kept reduced for register breadth) | 35 % | **10 %** | safety net against narrow-corpus overfit |
103
+ | Non-Greek replay (Tier 1 dominant) | 26 % | **12 %** | reduced per v0.7 §3.2 "30 % → 15 %" pattern; Tier 1 ≥ 70 % within replay during anneal |
104
+ | Code | 4 % | **3 %** | maintained at slightly reduced share |
105
+
106
+ The anneal recipe is `recipes/anneal.json`. It will be used in the production CPT (15–20 B tokens; final 10–20 % = ~2–4 B tokens of anneal) **after** the bakeoff picks an init winner. Not part of the bakeoff.
107
+
108
+ ## Builder usage
109
+
110
+ ```bash
111
+ # Generate the bakeoff bulk JSON-lines stream after the smoke passes
112
+ sbatch corpus_build/mix_builder_full.sbatch
113
+
114
+ # After shard concatenation, enforce NFC on the final JSONL stream too.
115
+ # This is CPU-only and preserves row order; unchanged rows stay byte-identical.
116
+ sbatch corpus_build/normalize_jsonl_nfc.sbatch
117
+
118
+ # Same shape for the anneal recipe (not run in the bakeoff)
119
+ python3 mix_builder.py \
120
+ --recipe recipes/anneal.json \
121
+ --target-tokens 3_000_000_000 \
122
+ --tokenizer /iopsstor/scratch/cscs/fffoivos/tokenizers/apertus_greek_modern_only_148480 \
123
+ --output /iopsstor/scratch/cscs/fffoivos/cpt_corpus/anneal_mix.jsonl \
124
+ --seed 20260520
125
+ ```
126
+
127
+ For sharded full builds, `mix_builder_full.sbatch` passes `--source-shard-index`
128
+ and `--source-shard-count` into `mix_builder.py`. This partitions each source's
129
+ eligible rows across array tasks before token-fair sampling, so the concatenated
130
+ bulk mix is not just seven repeats of the same source prefixes.
131
+
132
+ Output is JSON-lines. Each line is `{"text": "...", "source": "...", "doc_id": "...", "lang": "..."}`. Megatron-LM-Swiss-AI's `tools/preprocess_data.py` then converts JSON-lines → binary indexed dataset (`.bin` + `.idx`) for training.
133
+
134
+ NFC is enforced twice: first on source parquets with `normalize_nfc.sbatch`,
135
+ then on the final JSONL stream with `normalize_jsonl_nfc.sbatch`. The second
136
+ pass caught a small code-replay leak in the live bakeoff mix (`37` non-NFC rows
137
+ out of `5,754,172`) and produced
138
+ `/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix.nfc.jsonl` with manifest
139
+ `bulk_mix.nfc.manifest.json`.
140
+
141
+ Production-safe Vanilla/base-tokenizer binary, built from the NFC stream:
142
+
143
+ - prefix:
144
+ `/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix_base_nfc_megatron/bulk_mix_text_document`
145
+ - job: `2367579` on `xfer`, `COMPLETED`, `0:0`, elapsed `00:16:07`
146
+ - rows/sequences: `5,754,172`
147
+ - base-tokenized tokens: `9,831,704,774`
148
+ - local evidence:
149
+ `production_base_nfc_preprocess_2367579/`
150
+
151
+ The older bakeoff base/ext binaries were built before this NFC cleanup. The
152
+ NFC delta is tiny and does not change the bakeoff decision, but production
153
+ Vanilla CPT should use the `bulk_mix_base_nfc_megatron` prefix above.
154
+
155
+ Determinism: the `--seed` controls the interleave randomization. Same seed means the same JSONL text stream across runs. Vanilla and the extended arms then use different tokenizers/preprocessed Megatron binaries, so token IDs differ across tokenizer families even though the document order is shared.
156
+
157
+ ## Why two stages (build JSONL → preprocess to .bin/.idx)
158
+
159
+ Megatron's training reads its native binary format; converting on the fly during interleaving is awkward. Splitting the pipeline:
160
+
161
+ 1. `mix_builder.py` does the streaming interleave + budget-cap + writes JSONL (CPU job on `xfer`; do not use `normal` for CPU-only work because it allocates GPU nodes on Clariden).
162
+ 2. `normalize_jsonl_nfc.py` enforces NFC on the final JSONL stream (CPU job on `xfer`).
163
+ 3. `tools/preprocess_data.py` (Megatron) does the tokenization + binary packing (CPU job on `xfer`).
164
+ 4. Training reads the binary on `normal`.
165
+
166
+ This way each stage has a single clear job, and we can re-run any stage independently.
167
+
168
+ On current `xfer` nodes, `uenv`/torch are not visible, so Megatron's stock
169
+ `tools/preprocess_data.py` may not be runnable there. For the production Vanilla
170
+ NFC build, `preprocess_hf_jsonl_to_megatron.py` was used instead. It avoids
171
+ torch, writes the same Megatron indexed-dataset format, and was validated
172
+ byte-for-byte against the stock Megatron output on the first `1000` rows before
173
+ the full job was launched.
provenance/dataset-build/bulk_mix_text_document.manifest.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "input": "/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix.nfc.jsonl",
3
+ "output_prefix": "/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix_base_nfc_megatron/bulk_mix_text_document",
4
+ "bin": "/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix_base_nfc_megatron/bulk_mix_text_document.bin",
5
+ "idx": "/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix_base_nfc_megatron/bulk_mix_text_document.idx",
6
+ "tokenizer_model": "/iopsstor/scratch/cscs/fffoivos/models/apertus-8b-2509",
7
+ "json_key": "text",
8
+ "append_eod": true,
9
+ "workers": 64,
10
+ "chunk_size": 64,
11
+ "limit": 0,
12
+ "rows": 5754172,
13
+ "sequences": 5754172,
14
+ "documents": 5754173,
15
+ "tokens": 9831704774,
16
+ "bytes_read": 27125565083,
17
+ "wall_seconds": 960.677738904953,
18
+ "format": "Megatron indexed dataset v1, int32 document-level"
19
+ }
provenance/evals/CONTINUATION_3P5B_RESULTS_20260525.md ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 3.5B continuation results - Vanilla vs ReTok vs TD layer11
2
+
3
+ Generated UTC: `2026-05-25T05:23:53+00:00`.
4
+
5
+ This summarizes the continuation run `continuation_3p5b_20260524T143012Z`,
6
+ which extended Vanilla, ReTok, and TD layer11 from iter 476 (~2.0B tokens)
7
+ to iter 834 (~3.5B tokens). Local JSON snapshots live under
8
+ `per_iter_results/`; remote full artifacts remain on Clariden under
9
+ `/capstor/scratch/cscs/fffoivos/runs/eval/continuation_3p5b_20260524T143012Z_*`.
10
+
11
+ ## Bottom line
12
+
13
+ - TD layer11 is the best final benchmark arm overall: it is first on English
14
+ retention and multilingual aggregates, and narrowly first on the Greek
15
+ aggregate at iter 834.
16
+ - Vanilla still has the best tokenizer-fair heldout Greek BPC, but its
17
+ downstream Greek aggregate declined during the 2.0B -> 3.5B continuation.
18
+ - ReTok improves fastest on BPC and wins Greek MMLU / INCLUDE-44 Greek at
19
+ iter 834, but it remains behind TD and Vanilla on the Greek aggregate.
20
+ - If selecting for the actual downstream bakeoff objective, TD layer11 is now
21
+ the leading candidate. If selecting only for heldout BPC, Vanilla remains
22
+ ahead.
23
+
24
+ ## Aggregate scoreboard at iter 834
25
+
26
+ | Arm | Greek agg | Delta vs 476 | EN retention | Delta vs 476 | Multilingual | Delta vs 476 | BPC lower better | BPC delta |
27
+ |---|---:|---:|---:|---:|---:|---:|---:|---:|
28
+ | Vanilla | 0.4339 | -0.70 pp | 0.6782 | -0.36 pp | 0.4923 | +0.22 pp | 0.4724 | -0.0182 |
29
+ | ReTok | 0.4246 | +0.96 pp | 0.6786 | +0.36 pp | 0.4864 | -0.09 pp | 0.5390 | -0.0349 |
30
+ | TD layer11 | 0.4344 | +0.90 pp | 0.6865 | +0.38 pp | 0.4967 | +0.68 pp | 0.5054 | -0.0256 |
31
+
32
+ ## Per-task winners at iter 834
33
+
34
+ | Group | Task | Vanilla | ReTok | TD layer11 | Winner |
35
+ |---|---|---:|---:|---:|---|
36
+ | EN retention | `mmlu` | 0.5330 | 0.5565 | 0.5556 | ReTok |
37
+ | EN retention | `hellaswag` | 0.7573 | 0.7556 | 0.7632 | TD layer11 |
38
+ | EN retention | `arc_easy` | 0.7866 | 0.7576 | 0.7837 | Vanilla |
39
+ | EN retention | `arc_challenge` | 0.5230 | 0.5247 | 0.5358 | TD layer11 |
40
+ | EN retention | `piqa` | 0.7927 | 0.7851 | 0.7894 | Vanilla |
41
+ | EN retention | `winogrande` | 0.6764 | 0.6922 | 0.6914 | ReTok |
42
+ | Multilingual | `global_mmlu` | 0.4505 | 0.4603 | 0.4628 | TD layer11 |
43
+ | Multilingual | `xcopa` | 0.6178 | 0.5920 | 0.6156 | Vanilla |
44
+ | Multilingual | `xnli` | 0.4087 | 0.4070 | 0.4117 | TD layer11 |
45
+ | Greek | `global_mmlu_full_el` | 0.4145 | 0.4153 | 0.4036 | ReTok |
46
+ | Greek | `include_base_44_greek_few_shot_en` | 0.4022 | 0.4058 | 0.4004 | ReTok |
47
+ | Greek | `belebele_ell_Grek` | 0.5078 | 0.4933 | 0.5389 | TD layer11 |
48
+ | Greek | `arc_challenge_mt_el` | 0.4130 | 0.3899 | 0.4061 | Vanilla |
49
+ | Greek | `xnli_el` | 0.3831 | 0.3695 | 0.3851 | TD layer11 |
50
+ | Greek | `xquad_el` | 0.2868 | 0.3084 | 0.3364 | TD layer11 |
51
+ | Greek | `global_piqa_completions_ell_grek` | 0.6300 | 0.5900 | 0.5700 | Vanilla |
52
+
53
+ ## Change from iter 476 to iter 834
54
+
55
+ | Group | Task | Vanilla delta | ReTok delta | TD layer11 delta |
56
+ |---|---|---:|---:|---:|
57
+ | EN retention | `mmlu` | -0.09 pp | +0.24 pp | +0.56 pp |
58
+ | EN retention | `hellaswag` | -0.21 pp | +0.69 pp | +0.27 pp |
59
+ | EN retention | `arc_easy` | +0.13 pp | -0.59 pp | +0.29 pp |
60
+ | EN retention | `arc_challenge` | -0.43 pp | +0.94 pp | +0.85 pp |
61
+ | EN retention | `piqa` | -0.22 pp | -0.11 pp | -0.27 pp |
62
+ | EN retention | `winogrande` | -1.34 pp | +1.03 pp | +0.55 pp |
63
+ | Multilingual | `global_mmlu` | -0.64 pp | +0.14 pp | +1.34 pp |
64
+ | Multilingual | `xcopa` | +1.09 pp | -0.71 pp | +0.42 pp |
65
+ | Multilingual | `xnli` | +0.22 pp | +0.30 pp | +0.28 pp |
66
+ | Greek | `global_mmlu_full_el` | -0.69 pp | +1.62 pp | +1.77 pp |
67
+ | Greek | `include_base_44_greek_few_shot_en` | -1.63 pp | +3.26 pp | -0.36 pp |
68
+ | Greek | `belebele_ell_Grek` | -0.56 pp | -0.33 pp | +1.11 pp |
69
+ | Greek | `arc_challenge_mt_el` | -0.77 pp | +1.79 pp | +0.26 pp |
70
+ | Greek | `xnli_el` | -1.89 pp | -0.56 pp | +0.48 pp |
71
+ | Greek | `xquad_el` | -2.33 pp | -0.08 pp | +1.02 pp |
72
+ | Greek | `global_piqa_completions_ell_grek` | +3.00 pp | +1.00 pp | +2.00 pp |
73
+
74
+ ## New-token diagnostics
75
+
76
+ Measured on the 500-document heldout slice. Top-k is the fraction of
77
+ positions whose correct new token appears in the model's top-k predictions;
78
+ lower mean rank is better.
79
+
80
+ | Arm | Top-1 at new target | Delta from 585 | Top-5 at new target | Delta from 585 | Mean rank | Delta from 585 |
81
+ |---|---:|---:|---:|---:|---:|---:|
82
+ | ReTok | 0.3799 | +2.00 pp | 0.5469 | +2.11 pp | 228.9 | -31.4 |
83
+ | TD layer11 | 0.4105 | +1.43 pp | 0.5811 | +1.54 pp | 174.3 | -18.8 |
84
+
85
+ ## Artifact checklist
86
+
87
+ - Local packed-eval snapshots: `per_iter_results/{vanilla,retok,td}_iter{585,715,834}.json`.
88
+ - Local BPC snapshots: `per_iter_results/intrinsic/*_iter{585,715,834}_fair.json`.
89
+ - Local new-token diagnostics: `per_iter_results/diagnostics/{retok,td}_iter{585,715,834}_new_token_diagnostics.json`.
90
+ - Regenerated plots are written to `plots/`.
91
+ - Final remote packed eval job: `2376082`, state `COMPLETED`, exit `0:0`, elapsed `00:59:51`.
provenance/evals/EVAL_RECIPE.md ADDED
@@ -0,0 +1,321 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Eval recipe — V4 baseline + per-arm bakeoff eval
2
+
3
+ What we run, when, and what to expect out. **Engine**: [`swiss-ai/lm-evaluation-harness`](https://github.com/swiss-ai/lm-evaluation-harness) (Apertus team's fork — cited in Apertus tech report [arXiv:2509.14233](https://arxiv.org/abs/2509.14233) §5.1 footnote 45). **Citation**: Gao, Tow, Abbasi et al., Zenodo 2024, DOI [10.5281/zenodo.12608602](https://doi.org/10.5281/zenodo.12608602).
4
+
5
+ Two scopes:
6
+
7
+ - **V4 baseline** — full eval suite on unmodified `swiss-ai/Apertus-8B-2509`. One run, before the bakeoff fires. Output: per-benchmark mean + bootstrap CI. Gates the §5.6 hard-gate thresholds (how much regression on each benchmark counts as a "failure" for an arm).
8
+ - **Per-arm bakeoff eval** — same suite run on each arm's saved checkpoints in the 80–100 % range of its 2 B-token budget. Output: windowed-average score + bootstrap CI per arm. Drives §5.6 selection.
9
+
10
+ Both scopes use the **same task list and same harness flags** so the V4 baseline is the apples-to-apples comparator.
11
+
12
+ > **2026-05-21 takeover note.** V4 job `2334245` completed the then-current script, but that script accidentally omitted `global_mmlu` from Group 1. Treat its copied artifacts as a valid partial baseline for the listed tasks, not as the final Table-14 baseline. `run_eval.sbatch` now includes `global_mmlu`; rerun V4-HF and V4-post-conversion before filling final §5.6 thresholds.
13
+
14
+ ## Scope of tasks: match Apertus's pretraining-eval table, not post-training
15
+
16
+ The bakeoff compares **pretraining-stage** checkpoints (no SFT, no DPO). Apertus's tech report reports two distinct eval tables:
17
+
18
+ - **Table 14, p.38 (pretraining benchmarks)**: ARC (challenge + easy), HellaSwag, WinoGrande, PIQA, MMLU, Global-MMLU, XNLI (15 langs incl. Greek), XCOPA (11 langs). All run with harness-default shot counts per §5.1.
19
+ - **Table 22, p.44 (post-training benchmarks)**: GSM8K-CoT, HumanEval, MBPP, IFEval, BBH, BBQ, ToxiGen, HarmBench, etc. — generative / instruction-following tasks that require an SFT'd model.
20
+
21
+ Our **primary** retention metric is Table-14 tasks (Group 1 below). Table-22 tasks (GSM8K / HumanEval / MBPP / IFEval) we mark as **post-training only** and skip in the bakeoff — they shouldn't fluctuate from a CPT init choice on a non-instruction-tuned base.
22
+
23
+ ## Task list
24
+
25
+ Three groups. The wrappers in this directory take `--task-group {full|greek_only|retention_only}` so you can run them independently if needed.
26
+
27
+ ### Group 1: retention (Apertus pretraining-eval set per Table 14)
28
+
29
+ | Task | Capability | `lm-eval-harness` task name | Few-shot (harness default) |
30
+ |---|---|---|---|
31
+ | ARC-Challenge | reasoning | `arc_challenge` | 25 |
32
+ | ARC-Easy | reasoning | `arc_easy` | 25 |
33
+ | HellaSwag | commonsense | `hellaswag` | 10 |
34
+ | WinoGrande | coreference | `winogrande` | 5 |
35
+ | PIQA | physical commonsense | `piqa` | 0 |
36
+ | MMLU (57 subjects) | knowledge | `mmlu` | 5 |
37
+ | Global-MMLU (15 langs incl. Greek) | multilingual knowledge | `global_mmlu` | 5 |
38
+ | XNLI (15 langs incl. Greek) | multilingual NLI | `xnli` | 0 |
39
+ | XCOPA (11 langs) | multilingual commonsense | `xcopa` | 0 |
40
+
41
+ XNLI and Global-MMLU both include Greek (`xnli_el`, `global_mmlu_el`); these double as Greek-retention signals for the bakeoff. Per Apertus §5.1 footnote 45: *"All of our reported pretraining benchmarks follow the default configuration specified in lm-evaluation-harness"* — we adopt the same convention. Tasks **excluded** from the bakeoff because Apertus reports them only post-training: GSM8K, HumanEval, MBPP, IFEval, BBH (Table 22).
42
+
43
+ ### Group 2: Greek (native swissai-harness tasks + Belebele Greek)
44
+
45
+ **2026-05-21 update — empirically confirmed task availability.** The previous version of this table listed `arc_greek` / `hellaswag_greek` / `winogrande_greek` / `mmlu_greek` / `mmlu_pro_greek` / `truthfulqa_greek` / `medical_mcqa_greek` as `lm-eval-harness` task names. **Verified against the `swiss-ai/lm-evaluation-harness` clone on Clariden (2026-05-21, V4 attempt jobs 2333668 / 2333723):** those task names do not exist in the swissai harness — they live in the Meltemi/Krikri team's forks (`LeonVouk/lighteval`, `ilsp/lm-evaluation-harness-greek`) and have not landed upstream. The "reviewer flag" below was correct.
46
+
47
+ **What we actually ship at V4** (the names below resolve in `swiss-ai/lm-evaluation-harness` and were used for V4 job 2334245):
48
+
49
+ | Task | Source | `lm-eval-harness` task name | Few-shot |
50
+ |---|---|---|---|
51
+ | Greek ARC (machine-translated) | swissai harness | `arc_challenge_mt_el` | 25 |
52
+ | Greek MMLU (Global-MMLU, full Greek slice) | swissai harness | `global_mmlu_full_el` | 5 |
53
+ | Greek MMLU-44 (INCLUDE-44, native Greek, 7 subjects) | `CohereForAI/include-base-44`, config `Greek` | `include_base_44_greek_few_shot_en` (group of 7 subtasks) | 5 |
54
+ | Greek NLI | swissai harness | `xnli_el` | 0 |
55
+ | Greek QA | swissai harness | `xquad_el` | 0 |
56
+ | Greek PIQA (machine-translated) | swissai harness | `global_piqa_completions_ell_grek` | 0 |
57
+ | Belebele Greek | `facebook/belebele`, config `ell_Grek` | `belebele_ell_Grek` | 5 |
58
+
59
+ > **Reviewer flag (still open) — PF5 ILSP YAMLs.** The ILSP tasks the previous table claimed (`hellaswag_greek`, `winogrande_greek`, `mmlu_pro_greek`, `truthfulqa_greek`, `medical_mcqa_greek`) genuinely add Greek signal we don't currently have. The PF5 follow-up is to **port the YAML configs from `LeonVouk/lighteval` (or `ilsp/lm-evaluation-harness-greek`) into the swissai harness clone** so they resolve. Tracked as Task #55 in our running task list. Until PF5 lands, the bakeoff runs with the seven-task Greek list above + the multilingual coverage from Group 1.
60
+
61
+ Greek post-training-only tasks (`ilsp/mgsm_greek`, `ilsp/ifeval_greek`, `ilsp/mt-bench-greek`, `ilsp/m-ArenaHard_greek`) are out of scope for the pretraining-stage bakeoff — see "Scope of tasks" above.
62
+
63
+ The custom Greek evals from v0.7 §6.2 — polytonic continuation (out of bakeoff scope per the modern-only directive), morphology minimal pairs, language-ID drift, register preservation — run via Inspect AI as a separate sbatch (`run_inspect_evals.sbatch`, not in this iteration).
64
+
65
+ ### Group 3: safety / other
66
+
67
+ | Task | Source | Notes |
68
+ |---|---|---|
69
+ | HarmBench | `swiss-ai/harmbench` | Apertus team's curated harmful-behavior bench |
70
+ | PolyglotToxicityPrompts | `swiss-ai/polyglotoxicityprompts` | Multilingual toxicity (incl. Greek) |
71
+ | AttaQ Greek | `ilsp/attaq_greek` | Greek-targeted safety |
72
+ | Jailbreak-StrongReject Greek | `ilsp/Jailbreak-StrongReject-el` | Jailbreak resistance |
73
+
74
+ These are inspect-style evals, run via `inspect eval` rather than lm-eval-harness. Lower priority for the bakeoff (no §5.6 hard gate ties to them directly); useful for the eventual release.
75
+
76
+ ## Eval cadence
77
+
78
+ Per v0.7 §6.1:
79
+
80
+ - **Trajectory metrics** (training loss, per-bucket PPL, BPC trajectory, §5.3 new-token diagnostic suite): every 100 M tokens in the bakeoff (every ~25 global steps at 4 M tokens/step).
81
+ - **Downstream benchmarks** (Group 1 + Group 2): every 500 M tokens during training, plus a full sweep at the last 3–5 checkpoints in the 80–100 % budget range for selection.
82
+ - **V4 baseline**: once, before the bakeoff. Full suite × 1 run. Bootstrap CIs over eval samples (not over runs — most benchmark items are deterministic).
83
+
84
+ For 2 B-token bakeoff per arm: that's 4 mid-training benchmark runs (at 500 M, 1.0 B, 1.5 B, 2.0 B) and the last 3 (1.0 / 1.5 / 2.0 B) feed the windowed selection score.
85
+
86
+ ### Current 2026-05-22 operational cadence
87
+
88
+ Training writes Megatron `torch_dist` checkpoints, while lm-eval and the intrinsic metric jobs require HF-format model directories. Each evaluated checkpoint therefore has two stages:
89
+
90
+ 1. Convert the Megatron checkpoint to HF with [`convert_bakeoff_checkpoint_to_hf.sbatch`](convert_bakeoff_checkpoint_to_hf.sbatch).
91
+ 2. Run [`run_eval.sbatch`](run_eval.sbatch) and, when a held-out JSONL is available, [`run_tokenizer_fair_metrics.sbatch`](run_tokenizer_fair_metrics.sbatch) + [`run_new_token_diagnostics.sbatch`](run_new_token_diagnostics.sbatch).
92
+
93
+ Use [`submit_bakeoff_checkpoint_eval.sh`](submit_bakeoff_checkpoint_eval.sh) for the conversion/eval chain:
94
+
95
+ ```bash
96
+ RUN_TAG=bakeoff_1node_chain_20260522_005620 \
97
+ bash submit_bakeoff_checkpoint_eval.sh vanilla 65 greek_only
98
+ ```
99
+
100
+ For full bakeoff checkpoints where all three arms should be evaluated, prefer
101
+ the packed path. Clariden's normal partition can allocate/bill a whole 4-GPU
102
+ node even for a one-GPU `lm-eval` job; the packed submitter converts each arm
103
+ separately, then runs the three single-GPU full evals concurrently inside one
104
+ node allocation:
105
+
106
+ ```bash
107
+ RUN_TAG=bakeoff_1node_chain_20260522_005620 \
108
+ SUBMIT_INTRINSIC=1 \
109
+ EVAL_JSONL=/iopsstor/scratch/cscs/fffoivos/cpt_corpus/heldout/cpt_greek_heldout_500_20260522.jsonl \
110
+ bash submit_bakeoff_checkpoint_eval_packed.sh 390 full vanilla retok centroid
111
+ ```
112
+
113
+ For a live run, use [`watch_and_submit_checkpoint_evals.sh`](watch_and_submit_checkpoint_evals.sh)
114
+ to submit once per arm as soon as each checkpoint appears:
115
+
116
+ ```bash
117
+ RUN_TAG=bakeoff_1node_chain_20260522_005620 \
118
+ ITER=65 \
119
+ TASK_GROUP=greek_only \
120
+ POLL_SECONDS=300 \
121
+ nohup bash watch_and_submit_checkpoint_evals.sh \
122
+ > /capstor/scratch/cscs/fffoivos/runs/eval/watch_iter65.log 2>&1 &
123
+ ```
124
+
125
+ For full checkpoints in the live bakeoff, use
126
+ [`watch_and_submit_checkpoint_evals_packed.sh`](watch_and_submit_checkpoint_evals_packed.sh)
127
+ instead, so the watcher waits until all requested arms are complete and then
128
+ submits a single packed full-eval job:
129
+
130
+ ```bash
131
+ RUN_TAG=bakeoff_1node_chain_20260522_005620 \
132
+ ITER=390 \
133
+ TASK_GROUP=full \
134
+ SUBMIT_INTRINSIC=1 \
135
+ EVAL_JSONL=/iopsstor/scratch/cscs/fffoivos/cpt_corpus/heldout/cpt_greek_heldout_500_20260522.jsonl \
136
+ POLL_SECONDS=300 \
137
+ nohup bash watch_and_submit_checkpoint_evals_packed.sh \
138
+ > /capstor/scratch/cscs/fffoivos/runs/eval/watch_iter390_packed.log 2>&1 &
139
+ ```
140
+
141
+ The live bakeoff saves every 65 iterations, which is about 273 M tokens (`65 × 1024 × 4096`). The practical cadence is:
142
+
143
+ | Iteration | Tokens/arm | Eval action |
144
+ |---:|---:|---|
145
+ | 65 | ~273 M | Greek-only downstream smoke on all three arms; proves checkpoint save, conversion, and eval before waiting for late checkpoints. |
146
+ | 130 | ~545 M | Full downstream eval + intrinsic metrics/diagnostics if held-out JSONL is staged. |
147
+ | 260 | ~1.09 B | Full downstream eval + intrinsic metrics/diagnostics. |
148
+ | 390 | ~1.64 B | Full downstream eval + intrinsic metrics/diagnostics; enters the selection window. |
149
+ | 455 or final | ~1.91-2.00 B | Full downstream eval + intrinsic metrics/diagnostics; final selection evidence. |
150
+
151
+ The final arm choice should use the late-window checkpoints (390 plus the final one, and 260 as the nearest pre-window anchor if only two late checkpoints are available). The iteration-65 Greek-only run is not selection evidence; it is an operational canary to catch broken conversion/eval early.
152
+
153
+ ### TD layer11 direct-path eval handoff
154
+
155
+ The Token Distillation 2B run is a single selected arm, not the original
156
+ `${RUN_TAG}_${arm}` three-arm layout. Use the TD-specific wrappers so conversion
157
+ reads the direct checkpoint root and the HF tokenizer/config produced by the TD
158
+ layer11 R17 roundtrip:
159
+
160
+ ```bash
161
+ RUN_TAG=td_full25_layer11_2b_20260523T165038Z \
162
+ ITER=65 \
163
+ TASK_GROUP=greek_only \
164
+ POLL_SECONDS=300 \
165
+ nohup bash watch_and_submit_td_checkpoint_eval.sh \
166
+ > /capstor/scratch/cscs/fffoivos/runs/eval/watch_td_l11_iter65_greek_only.log 2>&1 &
167
+ ```
168
+
169
+ For selection checkpoints, enable intrinsic metrics against the staged Greek
170
+ held-out slice:
171
+
172
+ ```bash
173
+ RUN_TAG=td_full25_layer11_2b_20260523T165038Z \
174
+ ITER=390 \
175
+ TASK_GROUP=full \
176
+ SUBMIT_INTRINSIC=1 \
177
+ EVAL_JSONL=/iopsstor/scratch/cscs/fffoivos/cpt_corpus/heldout/cpt_greek_heldout_500_20260522.jsonl \
178
+ POLL_SECONDS=300 \
179
+ nohup bash watch_and_submit_td_checkpoint_eval.sh \
180
+ > /capstor/scratch/cscs/fffoivos/runs/eval/watch_td_l11_iter390_full.log 2>&1 &
181
+ ```
182
+
183
+ The TD wrapper submits `convert_bakeoff_checkpoint_to_hf.sbatch` with
184
+ `ARM=td_layer11` and defaults the tokenizer/config to:
185
+
186
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/hf_roundtrip`
187
+
188
+ Checkpoint conversion is not a dataset-build/preprocessing job: it imports
189
+ Megatron/PyTorch and requires the PyTorch `uenv`, which Clariden `xfer` nodes do
190
+ not expose. It therefore runs as a bounded one-GPU `debug` job. The sleeping
191
+ checkpoint watchers remain CPU-only `xfer` jobs.
192
+
193
+ For unattended monitoring, prefer the Slurm wrapper instead of keeping
194
+ sleeping watcher processes on a login SSH session:
195
+
196
+ ```bash
197
+ first="$(sbatch --parsable watch_td_checkpoint_evals.sbatch)"
198
+ second="$(sbatch --parsable --dependency=afterany:$first watch_td_checkpoint_evals.sbatch)"
199
+ echo "$first $second"
200
+ ```
201
+
202
+ The wrapper runs on `xfer` with one CPU and no GPU. It is safe to chain or
203
+ re-run because each per-checkpoint watcher has a `submitted` stamp.
204
+
205
+ ## §5.6 hard gates — to be filled from V4 baseline
206
+
207
+ Per v0.7 §5.6, a candidate arm **fails** if any of these gates trips. Thresholds are deliberately left as placeholders here — they're set **after** the V4 baseline run on unmodified Apertus-8B-2509 establishes the per-benchmark variance. The "fill from V4" step is on the post-V4 review checklist; until then these thresholds remain `PENDING(V4)`.
208
+
209
+ | # | Hard gate | Signal source | Failure rule | Threshold |
210
+ |---|---|---|---|---|
211
+ | HG1 | English / core retention regression | `results.json` from lm-eval-harness (ARC, HellaSwag, WinoGrande, PIQA, MMLU) | mean drop > X p.p. on any one of those 5, after windowed average over last 3-5 checkpoints in 80-100 % of budget | `X = PENDING(V4)` (suggest 3 p.p. as starting placeholder) |
212
+ | HG2 | Code retention regression (if code is a release requirement per Q A1) | lm-eval-harness code task (typically `humaneval` post-training; not in pretraining-eval table) | mean drop > Y p.p. | `Y = PENDING(V4 + Q A1)`; skip if code isn't a release requirement |
213
+ | HG3 | New-token row collapse (cosine clustering, near-zero usage) | [`compute_new_token_diagnostics.py`](compute_new_token_diagnostics.py) → `embedding.new_E_cos.mean_off_diag` AND `forward.d2_avg_prob_mass_new_per_pos` | `mean_off_diag > C_THRESH` OR `prob_mass_new < M_THRESH` | `C_THRESH = PENDING(V4)` (suggest 0.5 as starting placeholder — base Greek tokens typically sit at ~0.1-0.3 off-diag mean); `M_THRESH = PENDING(V4)` |
214
+ | HG4 | Polytonic text worsens vs base on character-normalized loss | [`compute_tokenizer_fair_metrics.py`](compute_tokenizer_fair_metrics.py) → `per_register.polytonic.nll_per_char` | arm value > base value | direct comparison; no separate threshold |
215
+ | HG5 | Throughput / memory hit disproportionate to Greek compression gain | Megatron training logs (`--log-throughput`) + tokenizer-fair `compression_ratio` | `(throughput_loss / compression_gain) > T_THRESH` | `T_THRESH = PENDING(V4)`; only fires for extended-vocab arms (ReTok/Centroid), not Vanilla |
216
+ | HG6 | Language-ID drift — model over-emits Greek in non-Greek prompts | Custom eval (§6.2; not yet implemented — Item 7 in COMPLETENESS_CHECK.md) | drift rate > D_THRESH | **`D_THRESH = PENDING(V4 + custom-eval-construction)`**; DEFERRED until §6.2 custom evals exist |
217
+
218
+ **Operational note.** HG1-HG5 can be computed from JSONs already produced by the existing eval flow. HG6 requires the custom Greek eval construction work (1-2 weeks per v0.7); it's expected to not be running in time for the first bakeoff pass and may need a substitute signal (e.g., `per_register.english.nll_per_char` from `compute_tokenizer_fair_metrics.py` on an English held-out slice — non-Greek text getting Greek-token outputs would spike English NLL).
219
+
220
+ **Why these thresholds aren't hard-coded:** the per-benchmark variance on Apertus-8B-base is unknown until we run V4. A "3 p.p. drop is a failure" rule is meaningless if the run-to-run variance of HellaSwag is itself 2 p.p. The V4 baseline + bootstrap CIs establish the noise floor, then "drop > 3× the noise floor on any benchmark" or similar becomes a defensible rule.
221
+
222
+ **Selection (not automated).** For non-failing arms, v0.7 §5.6 gives a weighted score (30-40 % Greek BPC, 25-35 % Greek benchmarks, 10-15 % polytonic, 15-25 % retention, 5-10 % efficiency). For a 3-arm bakeoff this is small enough to eyeball — see [`summarize_bakeoff.py`](summarize_bakeoff.py) for the helper that aggregates per-arm JSONs into one markdown table. **The final pick is a manual review against this table + the V4 thresholds**, not a numerical aggregate.
223
+
224
+ ## Statistical methodology
225
+
226
+ Per v0.7 §6.1 (Park et al. Oct 2025): downstream benchmark scores are noisy, and "run 3×" doesn't add information because the benchmarks are deterministic. The right way to get confidence intervals is **bootstrap over eval samples**.
227
+
228
+ `compute_bootstrap_cis.py` (this dir) takes `--log_samples` JSONL from lm-eval-harness, resamples eval items with replacement 1000 times, and reports per-task mean + 95 % CI.
229
+
230
+ **Selection scope** (per v0.7 §5.6): windowed average across the last 3–5 checkpoints in the 80–100 % range of each arm's budget. For training continuation post-winner, use the **raw** checkpoint at the end (not the averaged one), since the averaged model has no corresponding optimizer state.
231
+
232
+ ## Resources per eval run
233
+
234
+ V4 baseline (one run) on Clariden:
235
+
236
+ - partition: `normal`
237
+ - shape: `-N 1 -t 4:00:00 --gpus-per-node=1` (V4 currently runs 1-GPU; the early 4-GPU plan was scaled back after PF5 / task-name corrections cut total work)
238
+ - wall: ~1-2 h end-to-end for the seven Greek tasks + nine retention tasks at the corrected list (V4 job 2334245 mid-run as of 2026-05-21 12:30 UTC)
239
+ - batch size: `auto` (lm-eval-harness picks per task; observed `auto:1` → `32` for Apertus-8B on bf16)
240
+
241
+ ### lm-eval-harness install path (Clariden, 2026-05-21)
242
+
243
+ The uenv `pytorch/v2.9.1:v2`'s site-packages is read-only, so `pip install -e .` from the swissai clone fails with `[Errno 30] Read-only file system`. Workaround used by `run_eval.sbatch`:
244
+
245
+ ```bash
246
+ # One-time, as part of CSCS staging:
247
+ uenv start pytorch/v2.9.1:v2 --view=default
248
+ cd /iopsstor/scratch/cscs/fffoivos/code/eval/lm-evaluation-harness-swissai
249
+ pip install --target=/iopsstor/scratch/cscs/fffoivos/python_envs/lm_eval --quiet .
250
+ pip install --target=/iopsstor/scratch/cscs/fffoivos/python_envs/lm_eval --no-deps --quiet accelerate
251
+ # Delete the target's copy of huggingface-hub so the uenv's 0.36.0 wins over the
252
+ # pip-installed 1.x (transformers 4.57.0 pins hf_hub<1.0):
253
+ rm -rf /iopsstor/scratch/cscs/fffoivos/python_envs/lm_eval/huggingface_hub
254
+ rm -rf /iopsstor/scratch/cscs/fffoivos/python_envs/lm_eval/huggingface_hub-*.dist-info
255
+ ```
256
+
257
+ Then run_eval.sbatch sets `PYTHONPATH=/iopsstor/scratch/cscs/fffoivos/python_envs/lm_eval` and invokes `python3 -m lm_eval ...`. No `pip install -e .` at job-start time.
258
+
259
+ Per-arm bakeoff eval at one checkpoint:
260
+
261
+ - same shape, ~2 h
262
+ - run inline during training via Slurm `--dependency=afterok` on the checkpoint-save step, OR run separately after the training job completes
263
+
264
+ ## Files in this directory
265
+
266
+ - `EVAL_RECIPE.md` — this doc
267
+ - `pull_benchmarks.sh` — staging-time HF download for the benchmark datasets (and the swiss-ai eval scripts repo)
268
+ - `run_eval.sbatch` — parameterized eval job: `MODEL_PATH=… OUTPUT_DIR=… TASK_GROUP={full|greek_only|retention_only} sbatch run_eval.sbatch`
269
+ - `run_apertus_baseline.sh` — thin wrapper: V4 baseline on the unmodified Apertus-8B-2509 checkpoint
270
+ - `run_bakeoff_arm_eval.sh` — thin wrapper: per-arm eval, takes an arm's checkpoint dir as arg
271
+ - `convert_bakeoff_checkpoint_to_hf.sbatch` — bounded one-GPU `debug` job; converts one Megatron `torch_dist` bakeoff checkpoint to HF format for eval
272
+ - `run_megatron_convert_with_pg.py` — initializes the single-rank process group needed by Megatron `loader core` when reading `torch_dist` checkpoints
273
+ - `submit_bakeoff_checkpoint_eval.sh` — submits conversion plus lm-eval, with optional intrinsic metrics when `SUBMIT_INTRINSIC=1`
274
+ - `watch_and_submit_checkpoint_evals.sh` — lightweight watcher that stamps per-arm submissions and prevents duplicate checkpoint eval launches
275
+ - `submit_td_checkpoint_eval.sh` — direct-path TD layer11 conversion plus eval submitter for the selected TD 2B run
276
+ - `watch_and_submit_td_checkpoint_eval.sh` — lightweight direct-path TD watcher; submits once when a checkpoint directory and tracker are both ready
277
+ - `watch_td_checkpoint_evals.sbatch` — CPU-only `xfer` wrapper that runs the TD watcher set durably under Slurm
278
+ - `build_cpt_heldout_jsonl.py` / `build_cpt_heldout_jsonl.sbatch` — builds the 500-doc Greek held-out JSONL from the post-Apertus-dedup selected pool while excluding Greek doc_ids already used in `bulk_mix.jsonl`
279
+ - `compute_bootstrap_cis.py` — post-process: bootstrap CIs over the `--log_samples` outputs
280
+ - **`compute_tokenizer_fair_metrics.py`** — primary v0.7 §5.1 intrinsic metrics (BPC, NLL/char, NLL/word, tokens/word, chars/token, compression ratio, STRR). The cross-tokenizer-fair signal for comparing Vanilla (vocab 131,072) vs ReTok/Centroid (vocab 148,480). Has a `--stats-only` mode for tokenizer-only checks (no model load).
281
+ - **`run_tokenizer_fair_metrics.sbatch`** — sbatch wrapper for the above; 1 node × 1 GPU × 2 h. Runs at each bakeoff checkpoint where downstream eval also runs.
282
+ - **`compute_new_token_diagnostics.py`** — v0.7 §5.3 new-token integration diagnostic suite: 7 diagnostics over the 17,408 new IDs (rank of new target in next-token logits, prob-mass on new IDs, per-register entropy, top-1 substitution rate at new-target positions, greedy-gen new-token utilization, embedding L2-norm distribution new-vs-existing, cosine-similarity / effective-rank of new rows). Has `--embedding-only` mode that skips the forward-pass diagnostics (D1-D5) for cheap embedding-only health checks.
283
+ - **`run_new_token_diagnostics.sbatch`** — sbatch wrapper for the diagnostic suite; 1 node × 1 GPU × 2 h.
284
+
285
+ ## §5.3 new-token integration diagnostic suite — important
286
+
287
+ Per v0.7 §5.3, these 7 diagnostics are **"read at every bakeoff checkpoint"**:
288
+
289
+ | # | Diagnostic | What it catches |
290
+ |---|---|---|
291
+ | D1 | Rank of correct new token in next-token logits | New token invisible |
292
+ | D2 | Aggregate probability mass on new Greek tokens | Under- or over-emitted |
293
+ | D3 | New-token entropy by register | Polytonic rows collapsed or avoided |
294
+ | D4 | Top-k substitutions between new token and old subpieces | Model still prefers old segmentation |
295
+ | D5 | Greedy-gen new-token utilization rate | New rows exist but behaviorally dead |
296
+ | D6 | Embedding L2-norm distribution: new vs existing | Degenerate-subspace collapse |
297
+ | D7 | Cosine-similarity / effective-rank of new rows | Same-direction collapse |
298
+
299
+ `compute_new_token_diagnostics.py` implements all 7 in a single run (~10-15 min per checkpoint on one GH200). D6 + D7 are embedding-only (cheap; can run with `--embedding-only` for fast checks). D5 is the heaviest single diagnostic; `--skip-greedy` opts out.
300
+
301
+ ## Primary intrinsic metrics (v0.7 §5.1) — important
302
+
303
+ Per-token PPL is **not comparable** across the Vanilla arm (vocab 131,072) and the ReTok/Centroid arms (vocab 148,480). v0.7 §5.1 specifies these tokenizer-fair metrics as the **primary** signal for the bakeoff:
304
+
305
+ | Metric | Why |
306
+ |---|---|
307
+ | **BPC (bits per byte)** | Cleanest cross-tokenizer comparison |
308
+ | **NLL per Unicode character** | More interpretable for Greek/polytonic |
309
+ | **NLL per word** | Human-facing language metric |
310
+ | **tokens/word, chars/token, compression ratio** | Quantifies tokenizer efficiency |
311
+ | **STRR** (Subword-Tokenization Recovery Rate) | Fraction of held-out words that tokenize to a single token — whole-word preservation |
312
+
313
+ `compute_tokenizer_fair_metrics.py` computes all of these from one HF-format checkpoint + a held-out JSONL. Aggregates globally + per-source + per-register.
314
+
315
+ **Held-out eval slice**: ~100-500 docs covering modern Greek registers (encyclopedic / literary / academic / dialogue / legal / dictionary). The slice should be **outside** the bakeoff training mix. Current operational builder:
316
+
317
+ ```bash
318
+ sbatch build_cpt_heldout_jsonl.sbatch
319
+ ```
320
+
321
+ This samples from `/iopsstor/scratch/cscs/fffoivos/cpt_corpus/cpt/selected_after_apertus_and_internal_dedup.parquet`, excludes every Greek `doc_id` already present in `/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix.jsonl`, and fills quotas from the Greek source/register buckets in `corpus_build/recipes/bulk.json` that still have training-disjoint rows. The first full scan showed the current training mix exhausted the literary and dictionary/misc filters, so the default 500-doc slice redistributes those slots to HPLT, dialogue/textbooks, academic, and legal/civic. This is more aligned with the current CPT corpus than the older C3 val/test reconstruction, but it is a **training-disjoint intrinsic-metrics slice**, not a proof that all external benchmark test items were absent from the CPT source pool. Benchmark decontamination remains a separate check.
provenance/evals/V4_BENCHMARK_COMPARISON.md ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # V4-HF vs V4-post-conversion — Apertus-8B-2509 benchmark comparison
2
+
3
+ Companion to [`v4_baseline_corrected_20260521/README.md`](v4_baseline_corrected_20260521/README.md) and [`v4_postconv_retry_20260521/README.md`](v4_postconv_retry_20260521/README.md). Quantifies the R17 risk empirically: same Apertus weights, run through HF → Megatron → HF, then re-evaluated.
4
+
5
+ ## Per-task comparison
6
+
7
+ Top-level group scores per swissai lm-evaluation-harness. Stderrs are the harness defaults (analytic, not bootstrapped — see `compute_bootstrap_cis.py` for per-sample CIs if needed).
8
+
9
+ ### English retention (Apertus Table 14)
10
+
11
+ | Task | Metric | V4-HF | V4-postconv | Δ | Chance |
12
+ |---|---|---:|---:|---:|---:|
13
+ | `arc_challenge` | acc_norm | 0.5870 ±0.0144 | 0.2619 ±0.0128 | **−0.3251** | 0.25 |
14
+ | `arc_easy` | acc_norm | 0.8363 ±0.0076 | 0.2614 ±0.0090 | **−0.5749** | 0.25 |
15
+ | `hellaswag` | acc_norm | 0.7884 ±0.0041 | 0.2675 ±0.0044 | **−0.5209** | 0.25 |
16
+ | `winogrande` | acc | 0.6930 ±0.0130 | 0.5107 ±0.0140 | −0.1823 | 0.50 |
17
+ | `piqa` | acc_norm | 0.7992 ±0.0093 | 0.5212 ±0.0117 | −0.2780 | 0.50 |
18
+ | `mmlu` | acc | 0.5923 ±0.0039 | 0.2295 ±0.0035 | **−0.3628** | 0.25 |
19
+
20
+ `mmlu = 0.5923` on V4-HF matches the Apertus tech report Table 14 (≈0.59), confirming the eval pipeline is wired correctly.
21
+
22
+ ### Multilingual retention
23
+
24
+ | Task | Metric | V4-HF | V4-postconv | Δ | Chance |
25
+ |---|---|---:|---:|---:|---:|
26
+ | `global_mmlu` (15 langs) | acc | 0.5246 ±0.0063 | 0.2381 ±0.0054 | **−0.2865** | 0.25 |
27
+ | `xcopa` (11 langs) | acc | 0.6575 ±0.0063 | 0.5185 ±0.0067 | −0.1389 | 0.50 |
28
+ | `xnli` (15 langs) | acc | 0.4400 ±0.0026 | 0.3321 ±0.0024 | −0.1079 | 0.33 |
29
+
30
+ ### Greek slice
31
+
32
+ | Task | Metric | V4-HF | V4-postconv | Δ | Chance |
33
+ |---|---|---:|---:|---:|---:|
34
+ | `global_mmlu_full_el` | acc | 0.5155 ±0.0040 | 0.2295 ±0.0035 | **−0.2861** | 0.25 |
35
+ | `include_base_44_greek_few_shot_en` | acc | 0.5054 ±0.0208 | 0.1975 ±0.0169 | **−0.3080** | 0.25 |
36
+ | `belebele_ell_Grek` | acc | 0.6367 ±0.0160 | 0.2289 ±0.0140 | **−0.4078** | 0.25 |
37
+ | `arc_challenge_mt_el` | acc_norm | 0.4795 ±0.0146 | 0.2637 ±0.0129 | **−0.2159** | 0.25 |
38
+ | `xnli_el` | acc | 0.3984 ±0.0098 | 0.3333 ±0.0094 | −0.0651 | 0.33 |
39
+ | `xquad_el` | f1 | 0.5172 ±0.0117 | **0.0000 ±0.0000** | **−0.5172** | n/a |
40
+ | `global_piqa_completions_ell_grek` | acc_norm | 0.6200 ±0.0488 | 0.5400 ±0.0501 | −0.0800 | 0.50 |
41
+
42
+ ## Reading
43
+
44
+ 1. **V4-HF reproduces Apertus's published baseline.** Eval rig validated.
45
+ 2. **R17 is catastrophic, not cosmetic.** R1's "standard max abs diff = 0.0" was bit-exact only on the standard transformer tensors — the 128 reset xIELU αp/αn/β/ε parameters (per layer × 32 layers × 4 params) destroy the model's learned representations. Closed-form MC tasks fall to or below chance; extractive QA (`xquad_el`) collapses to zero f1 because the model cannot produce coherent text spans at all.
46
+ 3. **xIELU is the load-bearing R17 component.** xIELU's α-parameters are multiplicative slope gates: resetting them to the `XIELU.__init__` default (αp = αn = 0.8) destroys the learned activation shape across all 32 layers. The QK-Norm `q_norm`/`k_norm` weights happened to drift inside bf16 noise in the R1 diff (within 1e-3 threshold), but the xIELU resets are larger and they propagate through every forward pass.
47
+ 4. **Tasks that "survive" R17 are easy-baseline tasks.** `winogrande`, `piqa`, `xcopa`, `xnli`, `global_piqa_completions_ell_grek` retain near-chance behaviour because the random init still produces *some* output and binary/3-way MC is forgiving. The information-rich tasks (MMLU, ARC, HellaSwag, Belebele, XQuAD) collapse.
48
+
49
+ ## Bakeoff selection implications
50
+
51
+ This section describes the implication **for raw, unpatched HF → Megatron conversion**. After this comparison exposed the failure, `megatron_patches/patch_apertus_extras.py` was implemented and validated on the TP=2 bakeoff init checkpoints (`2341182`, `2341239`, `2341241`): patched Megatron → HF roundtrips have `standard_max_abs_diff = 0.0`, `r17_max_abs_diff = 0.0`, and `logit_max_abs_diff = 0.0`.
52
+
53
+ Therefore the actual bakeoff should use `megatron_tp2_r17patched`, not the raw `megatron_tp2` dirs. If someone intentionally runs the raw dirs, then the three arms start from approximately the V4-postconv baseline (R17-reset Apertus + the embedding-resize init choice they differ on), not from V4-HF. In that raw-conversion ablation, the §5.6 hard-gate plan in [`EVAL_RECIPE.md`](EVAL_RECIPE.md) would need to change:
54
+
55
+ - **Old framing (V4-HF reference):** "Arm X regresses > 3 p.p. from V4-HF on mmlu" → trivially fails for every arm at iteration 0 (each is 36 p.p. below V4-HF by construction).
56
+ - **New framing (V4-postconv reference):** "Arm X recovers > Y p.p. from V4-postconv on mmlu after 2B tokens, with bootstrap CI separating it from the other arms" → measurable signal.
57
+
58
+ The bakeoff is **recovery**, not retention. Concrete questions per arm:
59
+
60
+ - Which arm climbs off the chance floor fastest on the closed-form MC tasks (mmlu, hellaswag, arc_easy)?
61
+ - Which arm preserves the partially-surviving signals (winogrande, piqa, xcopa) without backsliding?
62
+ - Which arm recovers `xquad_el` extractive QA — i.e. produces non-empty answers?
63
+ - Greek-specific recovery is the primary bakeoff signal: which arm recovers `belebele_ell_Grek` and `global_mmlu_full_el` fastest?
64
+
65
+ If after 2B tokens no arm has recovered meaningfully past V4-postconv (e.g. all three sit at chance ±0.01 on mmlu), the bakeoff doesn't differentiate at this budget; either extend the budget or block on the production patcher (`megatron_patches/patch_apertus_extras.py`) that fixes R17 before training.
66
+
67
+ ## Production CPT prerequisite
68
+
69
+ R17 quantification confirmed the existing risk note in [`RISKS.md`](../../../RISKS.md): **the post-conversion xIELU/QK-Norm patcher is required before production CPT**, not just nice-to-have. Recovering 30-50 percentage points across MMLU/HellaSwag/ARC inside a 15-20B-token production CPT budget is unrealistic; the model must start from intact xIELU values.
70
+
71
+ The patcher is now implemented and has passed tensor + logit roundtrip checks for all three TP=2 init arms. The remaining optional confirmation is to run the full V4 eval on a patched roundtrip; the cheaper proof already shows the patched HF roundtrip is bit-exact to its HF source.
72
+
73
+ ## Artifacts
74
+
75
+ - `v4_baseline_corrected_20260521/results.json` — V4-HF full lm-eval-harness output.
76
+ - `v4_postconv_retry_20260521/{retention,greek}_results.json` — V4-postconv split runs (retention on job 2338020, Greek on job 2338021).
77
+ - Comparison script: `/tmp/v4_compare_full.py` (paths in script point at this dir).
provenance/token-distillation/RUN_LOG_20260523.md ADDED
@@ -0,0 +1,2299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Token Distillation Coverage Run Log - 2026-05-23
2
+
3
+ Purpose: run the first bounded Token Distillation gate, the CPU-only firing and
4
+ snippet-coverage prepass, on Clariden `xfer`. No GPU nodes are used for this
5
+ dataset/snippet work.
6
+
7
+ ## Local commits
8
+
9
+ - `b6d412a` - production decision state and initial TD prepass.
10
+ - `462ae2f` - first attempt to fix `uenv` path in Slurm.
11
+ - `b1aec29` - switch TD prepass launcher to a Python venv instead of `uenv`.
12
+ - `a05e3ab` - document xfer runtime and xfer-built venv.
13
+ - `77119b3` - add periodic progress logging.
14
+ - `65d8561` - document full TD coverage prepass launch.
15
+ - `c17c8ed` - pin vendored upstream Token Distillation source.
16
+ - `fcddd50` - add coverage-to-smoke/layer-pilot token selector.
17
+ - `dd9a27b` - add dependent TD coverage postprocess job.
18
+ - `6b2473c` - add TD preservation verifier.
19
+ - `bec2d02` - make TD preservation verifier xfer-safe.
20
+ - `993a82d` - support xfer Python in TD verifier.
21
+ - `bfa8a3c` - log full TD monitoring gates.
22
+ - `b23de6a` - update TD production gate state.
23
+ - `276afed` - log layer11 full TD checkpoint.
24
+ - `9c34f2f` - log full TD preservation pass.
25
+ - `957c46b` - add full TD preservation artifacts.
26
+ - `d6e7f20` - add full TD intrinsic eval results.
27
+ - `83d6934` - record full TD eval decision.
28
+ - `86da8f0` - add TD layer11 R17 roundtrip gate.
29
+ - `0143e01` - record TD layer11 R17 roundtrip pass.
30
+
31
+ ## TD0 pinned implementation source
32
+
33
+ Pinned upstream Token Distillation source for the next adapter step:
34
+
35
+ - upstream: `https://github.com/konstantinjdobler/token-distillation`
36
+ - commit: `35702b5809599ecd68b7845eca27a0d7b7cec0da`
37
+ - local vendored subset:
38
+ `external/token-distillation/`
39
+
40
+ Important integration note: do not call the package's high-level
41
+ `TokenDistillation.run(...)` entry point for Apertus production. It appends
42
+ tokens with `add_tokens(...)`; our ReTok arm uses an exact merge-extended
43
+ tokenizer with fixed IDs. The Apertus adapter should call the lower-level
44
+ training loop with an explicit `[131072, 148480)` mapping.
45
+
46
+ ## Failed handoffs and fixes
47
+
48
+ | Job | State | Cause | Fix |
49
+ |---:|---|---|---|
50
+ | `2349182` | failed | `uenv: command not found` inside xfer batch node | stopped using implicit `uenv` CLI |
51
+ | `2349183` | failed | `/usr/bin/uenv` exists on login but not on xfer compute node | confirmed xfer cannot rely on `uenv` |
52
+ | `2349184` | completed diagnostic | printed xfer PATH; confirmed no `uenv` on node `nid001306` | moved away from uenv |
53
+ | `2349185` | failed diagnostic | xfer system Python is 3.6 and lacks `tokenizers` | tested Python 3.11 path |
54
+ | `2349211` | failed smoke | venv was built on login (`aarch64`) but xfer is `x86_64`, so `tokenizers.abi3.so` could not load | created xfer-built venv |
55
+ | `2349237` | completed setup | created `/iopsstor/scratch/cscs/fffoivos/python_envs/td_coverage_py311_xfer` on xfer; installed `tokenizers==0.22.1` | launcher now defaults to this venv |
56
+ | `2349241` | completed smoke | 50k-token smoke produced coverage JSONL, summary JSON, and snippet index | proved launcher and artifact path |
57
+ | `2349259` | completed smoke | 50k-token smoke with `PROGRESS_TOKEN_INTERVAL=10000` printed progress JSON lines | proved long-run health logging |
58
+ | `2349342` | failed after full scan | strict prepass found 9 non-NFC docs in the first 2B-token scan and refused to emit coverage | added CPU-only JSONL NFC normalizer and reran prepass on `bulk_mix.nfc.jsonl` |
59
+
60
+ ## First full run attempt
61
+
62
+ Job: `2349342`
63
+
64
+ Command shape:
65
+
66
+ ```bash
67
+ cd /iopsstor/scratch/cscs/fffoivos/repo/03_apertus_extension_and_embedding_adaptation/03_4_implementation_experiments/init_bakeoff/token_distillation
68
+ sbatch --export=ALL,\
69
+ OUTPUT_DIR=/iopsstor/scratch/cscs/fffoivos/token_distillation/coverage_2b_modern_20260523T012000Z_r2,\
70
+ INPUT_JSONL=/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix.jsonl,\
71
+ TARGET_EXTENDED_TOKENS=2000000000,\
72
+ SNIPPETS_PER_TOKEN=100,\
73
+ PROGRESS_TOKEN_INTERVAL=5000000 \
74
+ td_coverage_prepass_xfer.sbatch
75
+ ```
76
+
77
+ Stable output directory:
78
+
79
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/coverage_2b_modern_20260523T012000Z_r2`
80
+
81
+ Expected artifacts:
82
+
83
+ - `td_coverage_prepass.jsonl`
84
+ - `td_coverage_summary.json`
85
+ - `td_snippet_index/snippets.jsonl`
86
+
87
+ Health at first check:
88
+
89
+ - Slurm state: `RUNNING` on `xfer`, node `nid001154`.
90
+ - Elapsed: `00:01:35`.
91
+ - `sstat` RSS: `2581400K`.
92
+ - Progress lines:
93
+ - `tokens_scanned=5042268`, `docs_seen=3244`
94
+ - `tokens_scanned=10003445`, `docs_seen=6118`
95
+
96
+ Approximate early throughput from progress lines: about 100k extended tokens/s,
97
+ so the 2B scan should be on the order of 5-6 hours if throughput remains
98
+ stable. This is an estimate, not a completion promise.
99
+
100
+ Health at 2026-05-22T23:29Z:
101
+
102
+ - Slurm state: `RUNNING` on `xfer`, node `nid001154`.
103
+ - Elapsed: `00:26:53`.
104
+ - Latest progress: `tokens_scanned=200000773`, `docs_seen=146900`.
105
+ - Stderr: empty.
106
+ - No final artifacts yet; `td_coverage_summary.json` is written only at
107
+ completion.
108
+
109
+ Health at 2026-05-22T23:37Z:
110
+
111
+ - Slurm state: `RUNNING` on `xfer`, node `nid001154`.
112
+ - Elapsed: `00:35:07`.
113
+ - Latest progress: `tokens_scanned=265000226`, `docs_seen=201079`.
114
+ - Stderr: empty.
115
+
116
+ Health at 2026-05-22T23:50Z:
117
+
118
+ - Slurm state: `RUNNING` on `xfer`, node `nid001154`.
119
+ - Elapsed: `00:48:28`.
120
+ - Latest progress: `tokens_scanned=365000047`, `docs_seen=285789`.
121
+ - Stderr: empty.
122
+ - No final artifacts yet.
123
+ - Dependent CPU-only postprocess queued as job `2349550`
124
+ (`afterok:2349342`). It will render `TD_COVERAGE_SUMMARY.md`, write
125
+ `TD_GATE_DECISION.json`, and create `pilot_selection/` only if the coverage
126
+ gate recommends TD.
127
+
128
+ Final state:
129
+
130
+ - Slurm state: `FAILED`, elapsed `04:14:40`, exit `1:0`.
131
+ - Last progress before failure:
132
+ `tokens_scanned=1995095832`, `docs_seen=1641638`,
133
+ `chars_seen=7468063507`.
134
+ - Error:
135
+ `Refusing to emit TD coverage: 9 docs were not NFC. Run on the post-normalize corpus or pass --no-require-nfc for a diagnostic-only scan.`
136
+ - The dependent postprocess job `2349550` was left with
137
+ `DependencyNeverSatisfied` and was cancelled.
138
+
139
+ Interpretation: this is a corpus invariant failure, not a TD coverage result.
140
+ Do not use `--no-require-nfc` for the decision gate.
141
+
142
+ ## NFC JSONL repair and rerun chain
143
+
144
+ Added:
145
+
146
+ - `corpus_build/normalize_jsonl_nfc.py`
147
+ - `corpus_build/normalize_jsonl_nfc.sbatch`
148
+
149
+ Local and Clariden validation:
150
+
151
+ - `python3 -m py_compile corpus_build/normalize_jsonl_nfc.py`
152
+ - `bash check_cpu_only_slurm.sh` passes with the JSONL normalizer included.
153
+ - Tiny local smoke confirmed only non-NFC text rows are rewritten.
154
+
155
+ Normalization job:
156
+
157
+ - Job: `2351373`
158
+ - Partition: `xfer`
159
+ - Input: `/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix.jsonl`
160
+ - Output: `/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix.nfc.jsonl`
161
+ - Manifest: `/iopsstor/scratch/cscs/fffoivos/cpt_corpus/bulk_mix.nfc.manifest.json`
162
+ - State: `COMPLETED`, elapsed `00:08:21`.
163
+
164
+ Manifest highlights:
165
+
166
+ - rows: `5,754,172`
167
+ - non-NFC docs before normalization: `37`
168
+ - changed docs: `37`
169
+ - missing/non-string text rows: `0`
170
+ - input bytes: `43,832,960,668`
171
+ - output bytes: `43,832,959,909`
172
+ - output SHA-256:
173
+ `205cb5ed80a6150064b290aaa0457463daf6c0e514e6c27b9ea3da28a479a8af`
174
+ - sampled changed rows are from `code_codeparrot_clean`.
175
+
176
+ Strict rerun chain:
177
+
178
+ | Job | Purpose | State at launch |
179
+ |---:|---|---|
180
+ | `2351374` | TD coverage prepass on `bulk_mix.nfc.jsonl` | running on `xfer` |
181
+ | `2351375` | TD coverage postprocess / gate | pending `afterok:2351374` |
182
+
183
+ Rerun output directory:
184
+
185
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/coverage_2b_modern_20260523T032424Z_nfc`
186
+
187
+ ## TD smoke wrapper readiness
188
+
189
+ Added `train_retok_td.py` and `train_retok_td.sbatch` for the second gate. They
190
+ are not launched automatically; only use them if the full coverage prepass
191
+ recommends TD.
192
+
193
+ Clariden dry-run validation on the completed 50k smoke artifacts:
194
+
195
+ - Selection artifact:
196
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_wrapper_dry_run_20260523_low/selection/td_pilot_token_selection.json`
197
+ - Dry-run manifest:
198
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_wrapper_dry_run_20260523_low/dry_run/retok_td_manifest.json`
199
+ - Result: loaded base and student tokenizers, grouped one real prepass snippet,
200
+ wrote manifest, and exited before model load/training.
201
+ - Note: this used `--min-status low_lt20` only to exercise the wrapper against
202
+ the tiny 50k diagnostic prepass. The real TD gate remains `enough_25` or
203
+ better on the full 2B prepass.
204
+
205
+ ## Decision gate after completion
206
+
207
+ Read `td_coverage_summary.json`:
208
+
209
+ - `recommended_next_step = run_full_td_100`: proceed to TD smoke/layer pilot.
210
+ - `recommended_next_step = run_td_25_with_flagged_tail`: run the paper-fast TD
211
+ setting and keep tail-token strategy explicit.
212
+ - `recommended_next_step = do_not_launch_full_td_inspect_coverage`: do not spend
213
+ GPU time; inspect tokenizer/corpus coverage first.
214
+
215
+ ## Strict full-2B coverage result
216
+
217
+ The strict rerun completed on the normalized JSONL:
218
+
219
+ - Prepass job: `2351374`, partition `xfer`, state `COMPLETED`,
220
+ elapsed `04:09:23`.
221
+ - Postprocess job: `2351375`, partition `xfer`, state `COMPLETED`,
222
+ elapsed `00:00:04`.
223
+ - Coverage directory:
224
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/coverage_2b_modern_20260523T032424Z_nfc`
225
+ - Gate file:
226
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/coverage_2b_modern_20260523T032424Z_nfc/TD_GATE_DECISION.json`
227
+
228
+ Gate decision:
229
+
230
+ ```json
231
+ {
232
+ "recommended_next_step": "run_full_td_100",
233
+ "selection_status": "created",
234
+ "enough_100_fraction": 0.9982192095588235,
235
+ "enough_25_fraction": 0.9990808823529411,
236
+ "low_lt25_count": 16,
237
+ "tokens_scanned": 2000000000,
238
+ "target_extended_tokens": 2000000000
239
+ }
240
+ ```
241
+
242
+ Summary:
243
+
244
+ - Input corpus: `bulk_mix.nfc.jsonl`.
245
+ - Extended tokens scanned: exactly `2,000,000,000`.
246
+ - Docs used: `1,645,852`.
247
+ - `require_nfc`: true.
248
+ - `non_nfc_docs`: 0.
249
+ - Status counts:
250
+ - `enough_100`: 17,377 tokens (99.82%).
251
+ - `enough_25`: 15 tokens (0.09%).
252
+ - `low_20_24`: 2 tokens.
253
+ - `low_lt20`: 3 tokens.
254
+ - `zero`: 11 tokens.
255
+ - Action counts:
256
+ - `td_100`: 17,377 tokens.
257
+ - `td_25`: 15 tokens.
258
+ - `keep_retok`: 5 tokens.
259
+ - `inspect`: 11 tokens.
260
+
261
+ Pilot selections were created under `pilot_selection/`:
262
+
263
+ - `smoke_token_ids.txt`: 512 tokens.
264
+ - `layer_pilot_token_ids.txt`: 2,048 tokens.
265
+
266
+ ## First TD smoke attempt
267
+
268
+ Launched a bounded one-GPU last-layer smoke, not full TD:
269
+
270
+ - Job: `2353063`
271
+ - Partition: `normal`
272
+ - Output directory:
273
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/retok_td_smoke_last_layer_20260523T074639Z`
274
+ - Settings: `TARGET_LAYER=-1`, `SNIPPETS_PER_TOKEN=25`, `EPOCHS=1`,
275
+ `BATCH_SIZE=16`.
276
+
277
+ Result:
278
+
279
+ - State: `FAILED`
280
+ - Elapsed: `00:00:29`
281
+ - Failure:
282
+ `token 140716: no snippets contain its base phrase after base tokenization`
283
+
284
+ Inspection showed token `140716` is an unstable byte-level/noisy token:
285
+
286
+ - `raw_token`: `"âľ"`
287
+ - `token_string`: `"�"`
288
+ - `base_subtoken_ids`: `[66122]`
289
+ - `extended_firings`: `132607`
290
+ - `status`: `enough_100`
291
+
292
+ The selected snippets' actual surfaces were assorted symbols, with different
293
+ base-token spans. This is not a TD training result; it is a wrapper/selection
294
+ invariant failure for unstable token mappings. These tokens should be logged,
295
+ skipped, and preserved at their ReTok initialization rather than crashing a
296
+ bounded smoke.
297
+
298
+ ## TD wrapper hardening
299
+
300
+ Updated `train_retok_td.py` and `train_retok_td.sbatch` so a selected token is
301
+ trained only if enough snippets reproduce its static base phrase under the base
302
+ tokenizer. Tokens that fail this check are recorded in
303
+ `retok_td_manifest.json` under `skipped_tokens` and remain frozen/preserved at
304
+ their existing ReTok initialization.
305
+
306
+ Default smoke behavior:
307
+
308
+ - `MIN_ACCEPTED_SNIPPETS_PER_TOKEN=$SNIPPETS_PER_TOKEN`
309
+ - `MIN_TRAINED_TOKEN_FRACTION=0.90`
310
+
311
+ This means a smoke can tolerate a small number of unstable/noisy selected
312
+ tokens, but fails before model load if too much of the selection is untrainable.
313
+
314
+ Validation:
315
+
316
+ - Local: `python3 -m py_compile train_retok_td.py`
317
+ - Clariden with job runtime env:
318
+ `uenv run pytorch/v2.9.1:v2 --view=default -- python3 -m py_compile train_retok_td.py`
319
+
320
+ Relaunched bounded smoke:
321
+
322
+ - Job: `2353091`
323
+ - Output directory:
324
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/retok_td_smoke_last_layer_20260523T075520Z`
325
+ - Initial state: pending on `normal`.
326
+
327
+ Result:
328
+
329
+ - State: `FAILED`
330
+ - Elapsed: `00:06:33`
331
+ - Allocation note: requested `gres/gpu=1`, but Clariden allocated the full
332
+ node (`gres/gpu=4`). Do not launch larger single-process TD jobs in this
333
+ shape without packing work across the node or accepting the inefficiency.
334
+ - The wrapper and model path succeeded:
335
+ - 510/512 selected tokens were trainable.
336
+ - 2 unstable byte-level/noisy tokens were skipped and preserved.
337
+ - Apertus/ReTok loaded and entered real training.
338
+ - Failure mode: CUDA OOM at step 471/796 during backward.
339
+ - OOM details:
340
+ - Tried to allocate `2.47 GiB`.
341
+ - GPU capacity `95.00 GiB`, free `1.83 GiB`.
342
+ - PyTorch allocated `76.45 GiB`, reserved-unallocated `15.94 GiB`.
343
+ - Error recommended `PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True`.
344
+
345
+ Interpretation: this is not a TD token-selection failure. It is the memory cost
346
+ of running upstream TD on Apertus-8B with `output_hidden_states=True`,
347
+ MSE-on-hiddens, and the untied-output CE path at `BATCH_SIZE=16`.
348
+
349
+ Follow-up fix:
350
+
351
+ - Default `BATCH_SIZE` for the sbatch reduced from `16` to `8`.
352
+ - `PYTORCH_ALLOC_CONF` defaults to `expandable_segments:True`.
353
+ - Next rerun should stay bounded and should not expand beyond the smoke until
354
+ the scheduler packing issue is handled.
355
+
356
+ ## Batch-8 smoke completion
357
+
358
+ Relaunched the same bounded 512-token last-layer smoke with batch 8:
359
+
360
+ - Job: `2353128`
361
+ - Output directory:
362
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/retok_td_smoke_last_layer_20260523T080555Z_bs8`
363
+ - State: `COMPLETED`
364
+ - Elapsed: `00:11:09`
365
+ - Allocation: full node despite one-GPU request
366
+ (`AllocTRES=cpu=288,gres/gpu=4,mem=450G,node=1`).
367
+ - Runtime settings:
368
+ - `TARGET_LAYER=-1`
369
+ - `SNIPPETS_PER_TOKEN=25`
370
+ - `BATCH_SIZE=8`
371
+ - `MIN_TRAINED_TOKEN_FRACTION=0.90`
372
+ - allocator config: `expandable_segments:True`
373
+
374
+ Manifest:
375
+
376
+ ```json
377
+ {
378
+ "requested_token_count": 512,
379
+ "trained_token_count": 510,
380
+ "skipped_token_count": 2,
381
+ "trained_token_fraction": 0.99609375,
382
+ "batch_size": 8,
383
+ "completed": true,
384
+ "elapsed_seconds": 657.6161992549896
385
+ }
386
+ ```
387
+
388
+ Output files include:
389
+
390
+ - `model-00001-of-00004.safetensors`
391
+ - `model-00002-of-00004.safetensors`
392
+ - `model-00003-of-00004.safetensors`
393
+ - `model-00004-of-00004.safetensors`
394
+ - `model.safetensors.index.json`
395
+ - tokenizer/config files
396
+ - `retok_td_manifest.json`
397
+
398
+ Smoke conclusion:
399
+
400
+ - The ReTok + TD wrapper can train and save an Apertus-8B HF checkpoint using
401
+ the vendored TD library path.
402
+ - For Apertus-8B, `BATCH_SIZE=16` is too close to memory limits; batch 8 plus
403
+ expandable segments works for the 512-token smoke.
404
+ - Scheduler packing remains unresolved: larger TD experiments should not be
405
+ launched as single-process jobs that burn a full four-GPU node unless we
406
+ deliberately pack independent TD work into the same allocation or decide that
407
+ the cost is acceptable.
408
+
409
+ ## Layer-pilot preparation
410
+
411
+ Checked the vendored package for a layer-suggestion tool. There is no separate
412
+ tool in the pinned implementation; the actionable upstream guidance is the
413
+ README note that target layers around the one-third mark can perform better
414
+ than the last layer.
415
+
416
+ Layer-pilot decision:
417
+
418
+ - Candidate A: `target_layer=-1` (paper-default last layer).
419
+ - Candidate B: `target_layer=11` (one-third-depth suggestion for Apertus-8B's
420
+ 32 transformer layers).
421
+ - Do not add a Candidate C unless a real Apertus-specific probe produces a
422
+ well-defined `L*`; do not invent one just to satisfy the plan wording.
423
+
424
+ Added `train_retok_td_layer_pilot_packed.sbatch` to run these candidates inside
425
+ one full-node allocation on separate GPUs. This addresses the observed
426
+ Clariden behavior where one-GPU requests are allocated/billed as full 4-GPU
427
+ nodes.
428
+
429
+ ## Packed layer pilot completion
430
+
431
+ Launched the packed layer pilot as a bounded two-candidate run:
432
+
433
+ - Job: `2353172`
434
+ - Output root:
435
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/retok_td_layer_pilot_20260523T082252Z`
436
+ - Candidates:
437
+ - `target_layer=-1`, label `last`, GPU 0.
438
+ - `target_layer=11`, label `layer11`, GPU 1.
439
+ - Selection: `1,024` requested tokens, `50` snippets per token,
440
+ `BATCH_SIZE=8`.
441
+ - State: `COMPLETED`
442
+ - Elapsed: `00:42:25`
443
+ - Allocation: full node
444
+ (`AllocTRES=billing=288,cpu=288,energy=3916310,gres/gpu=4,mem=450G,node=1`).
445
+
446
+ Top-level manifest:
447
+
448
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/retok_td_layer_pilot_20260523T082252Z/layer_pilot_manifest.json`
449
+
450
+ Manifest highlights:
451
+
452
+ | Target layer | Label | Requested | Trained | Skipped | Trained fraction | Elapsed |
453
+ |---:|---|---:|---:|---:|---:|---:|
454
+ | `-1` | `last` | 1,024 | 1,020 | 4 | 0.9961 | 2,533.7s |
455
+ | `11` | `layer11` | 1,024 | 1,020 | 4 | 0.9961 | 1,966.9s |
456
+
457
+ Both candidates saved HF checkpoints with tokenizer/config files and
458
+ `model.safetensors.index.json`.
459
+
460
+ Training-log note: `last` had low, stable reported loss around `0.017-0.022`.
461
+ `layer11` completed but showed large intermittent loss spikes and a high running
462
+ loss. This is a warning sign, not the selection criterion. The layer choice must
463
+ come from heldout Greek BPC/NLL plus D1/D2/D4/D5 new-token diagnostics against
464
+ the same ReTok baseline.
465
+
466
+ ## Packed intrinsic eval preparation
467
+
468
+ Added:
469
+
470
+ - `eval/run_td_pilot_intrinsics_packed.sbatch`
471
+ - `eval/summarize_td_pilot_intrinsics.py`
472
+
473
+ Purpose: evaluate the three relevant HF checkpoints in one full-node allocation:
474
+
475
+ - ReTok baseline:
476
+ `/iopsstor/scratch/cscs/fffoivos/init_checkpoints/modern_only_148480/retok`
477
+ - TD last-layer pilot:
478
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/retok_td_layer_pilot_20260523T082252Z/last`
479
+ - TD layer-11 pilot:
480
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/retok_td_layer_pilot_20260523T082252Z/layer11`
481
+
482
+ Heldout eval file:
483
+
484
+ `/iopsstor/scratch/cscs/fffoivos/cpt_corpus/heldout/cpt_greek_heldout_500_20260522.jsonl`
485
+
486
+ The packed eval runs:
487
+
488
+ - `compute_tokenizer_fair_metrics.py` for BPC/NLL/compression/STRR.
489
+ - `compute_new_token_diagnostics.py` for D1/D2/D4/D5 plus embedding-space
490
+ D6/D7 checks.
491
+
492
+ This keeps the TD layer decision bounded and avoids three separate full-node
493
+ eval allocations.
494
+
495
+ ## Packed intrinsic eval result
496
+
497
+ Submitted packed eval:
498
+
499
+ - Job: `2353771`
500
+ - Output root:
501
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_pilot_intrinsics_20260523T091637Z`
502
+ - State: `COMPLETED`
503
+ - Elapsed: `00:03:09`
504
+ - Allocation: full node
505
+ (`AllocTRES=billing=288,cpu=288,energy=296006,gres/gpu=4,mem=450G,node=1`).
506
+
507
+ Local copies of the compact result:
508
+
509
+ - `eval/td_pilot_intrinsics_20260523T091637Z/TD_PILOT_INTRINSICS_SUMMARY.md`
510
+ - `eval/td_pilot_intrinsics_20260523T091637Z/td_pilot_intrinsics_summary.json`
511
+ - `eval/td_pilot_intrinsics_20260523T091637Z/model_spec.tsv`
512
+
513
+ Primary metrics:
514
+
515
+ | Arm | BPC | Delta vs ReTok | D1 mean rank | D1 top1 | D1 top5 | D2 new mass | D4 top1-new | D5 greedy-new |
516
+ |---|---:|---:|---:|---:|---:|---:|---:|---:|
517
+ | ReTok | 2.9503 | 0.0000 | 3868.27 | 0.0065 | 0.0231 | 0.9821 | 0.9992 | 1.0000 |
518
+ | TD last | 2.7830 | -0.1673 | 3294.05 | 0.0146 | 0.0383 | 0.9796 | 0.9991 | 1.0000 |
519
+ | TD layer 11 | 2.7753 | -0.1750 | 3263.69 | 0.0148 | 0.0385 | 0.9795 | 0.9991 | 1.0000 |
520
+
521
+ Interpretation:
522
+
523
+ - Both TD pilot checkpoints materially improve heldout BPC and D1 rank over the
524
+ ReTok baseline.
525
+ - `target_layer=11` is slightly better than `target_layer=-1` on BPC and D1.
526
+ - The earlier `layer11` training-loss spikes did not show up as output-norm,
527
+ D4, or D5 instability in this intrinsic eval.
528
+ - Selected next TD target layer for the full-token challenger: `target_layer=11`.
529
+
530
+ Resource calibration:
531
+
532
+ - `layer11` pilot runtime was about `1,966.9s` for `1,020` trained tokens at
533
+ `50` snippets per token.
534
+ - A naive all-token `100`-snippet run would be roughly `18-19` wall hours on
535
+ one GPU, beyond `normal`'s 12h limit and wasteful on Clariden's 4-GPU node
536
+ allocations.
537
+ - The next full-token challenger should therefore start with the paper-fast
538
+ `25`-snippet setting, not the `100`-snippet setting. A later `100`-snippet or
539
+ `50`-snippet run is only justified if the fast full-token TD checkpoint clears
540
+ the gates but leaves quality ambiguous.
541
+
542
+ Selection artifact update:
543
+
544
+ - Regenerated `pilot_selection/` with an added all-eligible ID list:
545
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/coverage_2b_modern_20260523T032424Z_nfc/pilot_selection/full_td_token_ids.txt`
546
+ - Full-token eligible count: `17,392`.
547
+
548
+ ## Full-token 25-snippet TD launch
549
+
550
+ Launched the first full-token TD challenger using the paper-fast snippet budget:
551
+
552
+ - Job: `2353960`
553
+ - Output root:
554
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/retok_td_full25_layers_20260523T092602Z`
555
+ - Walltime: `10:00:00`
556
+ - Token IDs:
557
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/coverage_2b_modern_20260523T032424Z_nfc/pilot_selection/full_td_token_ids.txt`
558
+ - Coverage JSONL:
559
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/coverage_2b_modern_20260523T032424Z_nfc/td_coverage_prepass.jsonl`
560
+ - Snippets JSONL:
561
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/coverage_2b_modern_20260523T032424Z_nfc/td_snippet_index/snippets.jsonl`
562
+ - Candidates packed into the same allocation:
563
+ - `target_layer=-1`, label `last`, GPU 0.
564
+ - `target_layer=11`, label `layer11`, GPU 1.
565
+ - Runtime settings:
566
+ - `SNIPPETS_PER_TOKEN=25`
567
+ - `MIN_ACCEPTED_SNIPPETS_PER_TOKEN=25`
568
+ - `MAX_SELECTED_TOKENS=0` (full token list)
569
+ - `BATCH_SIZE=8`
570
+ - `MIN_TRAINED_TOKEN_FRACTION=0.99`
571
+
572
+ Startup health:
573
+
574
+ - Job state: `RUNNING` on `nid006119`.
575
+ - GPUs visible: `0,1,2,3`; training processes started on GPUs 0 and 1.
576
+ - Early process check showed both Python workers alive with GPU contexts
577
+ allocated (`~6.4 GiB` each) and high CPU during snippet preparation.
578
+
579
+ ## Full-token run babysitting and queued gates
580
+
581
+ Live checks on 2026-05-23 confirmed the full-token TD job has not restarted:
582
+
583
+ - Slurm job: `2353960`
584
+ - `scontrol` field: `Restarts=0`
585
+ - Node: `nid006119`
586
+ - Active processes:
587
+ - `target_layer=-1` on GPU 0
588
+ - `target_layer=11` on GPU 1
589
+ - GPU health check showed GPUs 0 and 1 saturated, while GPUs 2 and 3 were idle.
590
+ This is expected for the current two-candidate packed run; no extra CPU-only
591
+ work was placed on GPU nodes.
592
+
593
+ Progress snapshots:
594
+
595
+ | UTC time | last progress | last ETA | layer11 progress | layer11 ETA |
596
+ |---|---:|---:|---:|---:|
597
+ | 12:22 | 27,528 / 54,303 (50.7%) | 2:44:02 | 35,172 / 54,303 (64.8%) | 1:34:03 |
598
+ | 12:27 | 28,322 / 54,303 (52.2%) | 2:36:34 | 36,186 / 54,303 (66.6%) | 1:29:37 |
599
+ | 12:32 | 29,114 / 54,303 (53.6%) | 2:41:20 | 37,204 / 54,303 (68.5%) | 1:21:46 |
600
+ | 12:37 | 29,907 / 54,303 (55.1%) | 2:36:01 | 38,228 / 54,303 (70.4%) | 1:17:50 |
601
+ | 12:42 | 30,704 / 54,303 (56.5%) | 2:29:37 | 39,244 / 54,303 (72.3%) | 1:18:35 |
602
+ | 12:47 | 31,497 / 54,303 (58.0%) | 2:22:13 | 40,267 / 54,303 (74.2%) | 1:08:12 |
603
+ | 12:53 | 32,288 / 54,303 (59.5%) | 2:16:11 | 41,286 / 54,303 (76.0%) | 1:03:58 |
604
+ | 12:58 | 33,081 / 54,303 (60.9%) | 2:13:56 | 42,304 / 54,303 (77.9%) | 1:00:16 |
605
+ | 13:03 | 33,877 / 54,303 (62.4%) | 2:10:12 | 43,322 / 54,303 (79.8%) | 0:52:36 |
606
+ | 13:08 | 34,672 / 54,303 (63.8%) | 2:01:25 | 44,338 / 54,303 (81.6%) | 0:47:20 |
607
+ | 13:13 | 35,464 / 54,303 (65.3%) | 1:58:48 | 45,360 / 54,303 (83.5%) | 0:44:02 |
608
+ | 13:18 | 36,258 / 54,303 (66.8%) | 1:51:51 | 46,378 / 54,303 (85.4%) | 0:37:28 |
609
+ | 13:23 | 37,050 / 54,303 (68.2%) | 1:52:41 | 47,397 / 54,303 (87.3%) | 0:33:31 |
610
+ | 13:28 | 37,844 / 54,303 (69.7%) | 1:41:42 | 48,415 / 54,303 (89.2%) | 0:28:47 |
611
+ | 13:33 | 38,643 / 54,303 (71.2%) | 1:38:45 | 49,425 / 54,303 (91.0%) | 0:25:02 |
612
+ | 13:38 | 39,440 / 54,303 (72.6%) | 1:32:13 | 50,446 / 54,303 (92.9%) | 0:19:23 |
613
+ | 13:43 | 40,236 / 54,303 (74.1%) | 1:25:29 | 51,465 / 54,303 (94.8%) | 0:14:26 |
614
+ | 13:48 | 41,033 / 54,303 (75.6%) | 1:25:07 | 52,485 / 54,303 (96.7%) | 0:08:24 |
615
+ | 13:53 | 41,826 / 54,303 (77.0%) | 1:18:51 | 53,501 / 54,303 (98.5%) | 0:03:49 |
616
+ | 13:58 | 42,623 / 54,303 (78.5%) | 1:12:21 | 54,303 / 54,303 (100.0%) | 0:00:00 |
617
+
618
+ No `model.safetensors*` checkpoint files existed yet at these snapshots. The
619
+ manifests had already been written by the wrapper:
620
+
621
+ - `last/retok_td_manifest.json`
622
+ - `layer11/retok_td_manifest.json`
623
+
624
+ Both manifests report:
625
+
626
+ - `trained_token_count = 17,377`
627
+ - `skipped_token_count = 15`
628
+ - `snippets_per_token = 25`
629
+ - `min_accepted_snippets_per_token = 25`
630
+
631
+ ## Preservation verifier hardening
632
+
633
+ Added and then hardened the post-TD preservation verifier:
634
+
635
+ - Commit `6b2473c` - add `verify_td_preservation.py` and
636
+ `verify_td_preservation_xfer.sbatch`.
637
+ - Commit `bec2d02` - remove the torch dependency by parsing Safetensors
638
+ directly, so the check can run on `xfer` as CPU-only work.
639
+ - Commit `993a82d` - make the verifier compatible with `xfer`'s Python version
640
+ by replacing `int | None` annotations with `Optional[int]`.
641
+
642
+ The verifier now checks, from checkpoint artifacts only:
643
+
644
+ - state-dict key equality;
645
+ - tensor shape and dtype equality;
646
+ - exact byte preservation for every non-embedding tensor;
647
+ - exact byte preservation for all input/output embedding rows except the
648
+ trained new-token IDs;
649
+ - every trained new input/output row changed;
650
+ - trained rows are not all-zero and have no BF16/F16/F32 inf/nan bit patterns;
651
+ - xIELU and QK-Norm tensors are covered by the non-embedding exact check.
652
+
653
+ Diagnostics run while hardening:
654
+
655
+ | Job | Partition | Result | Meaning |
656
+ |---:|---|---|---|
657
+ | `2355602` | `xfer` | failed with `uenv: command not found` | confirmed `xfer` cannot use the PyTorch uenv; preservation must not depend on torch there |
658
+ | `2355617` | `xfer` | exposed Python syntax incompatibility | first xfer compile/help check caught `int | None` on the older xfer Python |
659
+ | `2355625` | `xfer` | completed | xfer compile/help check passed after the compatibility patch |
660
+
661
+ Local tests:
662
+
663
+ - `python3 -m py_compile verify_td_preservation.py`
664
+ - `bash -n verify_td_preservation_xfer.sbatch`
665
+ - synthetic tiny Safetensors roundtrip test of preserved rows, moved trained
666
+ rows, and unchanged xIELU-like tensor.
667
+
668
+ The xfer-safe verifier was synced to:
669
+
670
+ `/iopsstor/scratch/cscs/fffoivos/repo/03_apertus_extension_and_embedding_adaptation/03_4_implementation_experiments/init_bakeoff/token_distillation/`
671
+
672
+ ## Queued post-TD gates
673
+
674
+ Queued xfer preservation jobs behind the full TD job:
675
+
676
+ | Arm | Job | Partition | Dependency | Output |
677
+ |---|---:|---|---|---|
678
+ | `last` | `2355706` | `xfer` | `afterok:2353960` | `last/td_preservation_report.json` |
679
+ | `layer11` | `2355707` | `xfer` | `afterok:2353960` | `layer11/td_preservation_report.json` |
680
+
681
+ Queued packed intrinsic eval behind both preservation jobs:
682
+
683
+ - Job: `2355714`
684
+ - Partition: `normal`
685
+ - Dependency: `afterok:2355706:2355707`
686
+ - Output root:
687
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_intrinsics_20260523T124000Z`
688
+ - Model spec:
689
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_intrinsics_20260523T124000Z/model_spec.tsv`
690
+ - Arms:
691
+ - `retok`
692
+ - `td_full25_last`
693
+ - `td_full25_layer11`
694
+
695
+ This ordering means the full-token eval will only consume a GPU node if TD
696
+ training succeeds and both artifact-preservation checks pass.
697
+
698
+ ## Full-token layer11 artifact complete
699
+
700
+ `target_layer=11` completed first:
701
+
702
+ - Completion line: `=== layer complete: 11 ===`
703
+ - Completion timestamp: 2026-05-23 13:57:09 UTC
704
+ - Output dir:
705
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/retok_td_full25_layers_20260523T092602Z/layer11`
706
+ - Manifest: `completed = True`
707
+ - Elapsed: `16,254.8s`
708
+ - Final training size: `54,303` dataloader steps
709
+ - Manifest counts:
710
+ - `trained_token_count = 17,377`
711
+ - `skipped_token_count = 15`
712
+ - `target_layer = 11`
713
+ - `snippets_per_token = 25`
714
+ - `batch_size = 8`
715
+ - Saved model files:
716
+ - `model.safetensors.index.json`
717
+ - `model-00001-of-00004.safetensors`
718
+ - `model-00002-of-00004.safetensors`
719
+ - `model-00003-of-00004.safetensors`
720
+ - `model-00004-of-00004.safetensors`
721
+ - `config.json`, tokenizer files, and generation/special-token configs.
722
+
723
+ Final layer11 training log excerpts:
724
+
725
+ - `Total end-to-end time: 16068.92639554094`
726
+ - `saving TD checkpoint: .../retok_td_full25_layers_20260523T092602Z/layer11`
727
+ - `done in 16254.8s`
728
+
729
+ Overall Slurm job `2353960` remains `RUNNING` because the `last` candidate is
730
+ still training. At 13:58 UTC it was `42,725 / 54,303` (`78.7%`) with ETA
731
+ `1:13:53`.
732
+
733
+ ## Full-token training complete
734
+
735
+ The packed full-token TD training job completed cleanly:
736
+
737
+ - Job: `2353960`
738
+ - State: `COMPLETED`
739
+ - Elapsed: `05:45:53`
740
+ - Exit code: `0:0`
741
+ - Restart count observed while running: `0`
742
+
743
+ Additional `last` progress snapshots after `layer11` had completed:
744
+
745
+ | UTC time | last progress | last ETA |
746
+ |---|---:|---:|
747
+ | 14:03 | 43,519 / 54,303 (80.1%) | 1:06:42 |
748
+ | 14:08 | 44,302 / 54,303 (81.6%) | 1:04:37 |
749
+ | 14:13 | 45,099 / 54,303 (83.1%) | 0:57:57 |
750
+ | 14:18 | 45,892 / 54,303 (84.5%) | 0:52:19 |
751
+ | 14:23 | 46,689 / 54,303 (86.0%) | 0:47:19 |
752
+ | 14:28 | 47,483 / 54,303 (87.4%) | 0:41:06 |
753
+ | 14:33 | 48,279 / 54,303 (88.9%) | 0:39:44 |
754
+ | 14:38 | 49,074 / 54,303 (90.4%) | 0:32:19 |
755
+ | 14:43 | 49,869 / 54,303 (91.8%) | 0:28:37 |
756
+ | 14:48 | 50,663 / 54,303 (93.3%) | 0:22:41 |
757
+ | 14:53 | 51,459 / 54,303 (94.8%) | 0:17:04 |
758
+ | 14:58 | 52,245 / 54,303 (96.2%) | 0:12:52 |
759
+ | 15:03 | 53,038 / 54,303 (97.7%) | 0:07:52 |
760
+ | 15:08 | 53,830 / 54,303 (99.1%) | 0:02:57 |
761
+ | 15:13 | 54,303 / 54,303 (100.0%) | 0:00:00 |
762
+
763
+ `last` output dir:
764
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/retok_td_full25_layers_20260523T092602Z/last`
765
+
766
+ `last` artifact state:
767
+
768
+ - `model.safetensors.index.json` exists.
769
+ - `retok_td_manifest.json` was rewritten with `completed = True`.
770
+ - Manifest counts match `layer11`:
771
+ - `trained_token_count = 17,377`
772
+ - `skipped_token_count = 15`
773
+ - `snippets_per_token = 25`
774
+
775
+ ## Full-token preservation gates passed
776
+
777
+ Both xfer preservation jobs passed:
778
+
779
+ | Arm | Job | State | Elapsed | Report |
780
+ |---|---:|---|---:|---|
781
+ | `last` | `2355706` | `COMPLETED` | `00:01:36` | `last/td_preservation_report.json` |
782
+ | `layer11` | `2355707` | `COMPLETED` | `00:01:39` | `layer11/td_preservation_report.json` |
783
+
784
+ Summary from both preservation reports:
785
+
786
+ - `trained_token_count = 17,377`
787
+ - `non_embedding_changed_count = 0`
788
+ - `shape_mismatches = []`
789
+ - `dtype_mismatches = []`
790
+ - `xielu_changed = []`
791
+ - `qk_norm_changed = []`
792
+ - `lm_head.weight`:
793
+ - preserved rows changed: `0`
794
+ - trained rows changed: `17,377`
795
+ - trained rows unchanged: `0`
796
+ - nonfinite trained rows: `0`
797
+ - zero trained rows: `0`
798
+ - `model.embed_tokens.weight`:
799
+ - preserved rows changed: `0`
800
+ - trained rows changed: `17,377`
801
+ - trained rows unchanged: `0`
802
+ - nonfinite trained rows: `0`
803
+ - zero trained rows: `0`
804
+
805
+ Interpretation: artifact-level preservation passed for both full-token TD
806
+ candidates. xIELU, QK-Norm, all transformer tensors, and all untrained input and
807
+ output rows are byte-exact relative to the ReTok reference. Only the intended
808
+ new-token input/output rows moved.
809
+
810
+ The packed intrinsic eval job is now dependency-cleared:
811
+
812
+ - Job: `2355714`
813
+ - State after preservation: `PENDING`
814
+ - Reason: `Priority`
815
+ - Output root:
816
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_intrinsics_20260523T124000Z`
817
+
818
+ ## Full-token intrinsic eval complete
819
+
820
+ Packed intrinsic eval completed cleanly:
821
+
822
+ - Job: `2355714`
823
+ - State: `COMPLETED`
824
+ - Elapsed: `00:03:15`
825
+ - Exit code: `0:0`
826
+ - Output root:
827
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_intrinsics_20260523T124000Z`
828
+ - Local copy:
829
+ `../eval/td_full25_intrinsics_20260523T124000Z/`
830
+
831
+ Heldout Greek metrics:
832
+
833
+ | Arm | BPC | Delta vs ReTok | NLL/char | tokens/word | STRR |
834
+ |---|---:|---:|---:|---:|---:|
835
+ | `retok` | 2.9503 | 0.0000 | 3.4896 | 1.7352 | 0.4458 |
836
+ | `td_full25_last` | 1.4249 | -1.5254 | 1.6853 | 1.7352 | 0.4458 |
837
+ | `td_full25_layer11` | **1.3846** | **-1.5657** | **1.6376** | 1.7352 | 0.4458 |
838
+
839
+ New-token diagnostics:
840
+
841
+ | Arm | D1 mean rank | D1 top1 | D1 top5 | D2 new mass | D4 top1-new | D5 greedy-new | E norm ratio | U norm ratio |
842
+ |---|---:|---:|---:|---:|---:|---:|---:|---:|
843
+ | `retok` | 3868.27 | 0.0065 | 0.0231 | 0.9821 | 0.9992 | 1.0000 | 1.0578 | 1.0140 |
844
+ | `td_full25_last` | 1756.04 | 0.0381 | 0.1596 | 0.8194 | 0.9266 | 0.9980 | 1.0585 | 1.0195 |
845
+ | `td_full25_layer11` | **1617.48** | **0.0415** | **0.1722** | 0.8094 | 0.9153 | 0.9960 | 1.0590 | 1.0195 |
846
+
847
+ Interpretation:
848
+
849
+ - Full-token TD is not a marginal improvement over ReTok; it is a large
850
+ pre-CPT heldout-NLL improvement while preserving the extended tokenizer's
851
+ compression (`tokens/word` and `STRR` unchanged).
852
+ - `layer11` beats `last` on BPC and D1 rank/top-k, matching the pilot result.
853
+ - D2/D4/D5 move down from near-saturated ReTok use of new IDs, but remain high.
854
+ That is the desired direction here: less indiscriminate new-token mass while
855
+ keeping strong new-token availability.
856
+ - New input/output row norm ratios remain close to ReTok and do not show a norm
857
+ explosion.
858
+
859
+ Current decision:
860
+
861
+ - Select `td_full25_layer11` as the only TD checkpoint worth taking to the next
862
+ gate.
863
+ - Do not spend on a 50/100-snippet TD run before conversion/smoke; the 25-snippet
864
+ full-token checkpoint already clearly beats ReTok intrinsically.
865
+ - Next gate: R17-preserving HF -> Megatron conversion and roundtrip/load smoke
866
+ for `td_full25_layer11`.
867
+
868
+ ## TD layer11 R17 conversion and HF roundtrip passed
869
+
870
+ Before launching the conversion gate, I checked whether it could safely run on
871
+ `xfer` and avoid a GPU allocation. It could not:
872
+
873
+ | Job | Partition | State | Finding |
874
+ |---:|---|---|---|
875
+ | `2357552` | `xfer` | failed | `sbatch --uenv` did not provide `torch` |
876
+ | `2357556` | `xfer` | failed | explicit `uenv run` path still had no `torch` |
877
+ | `2357561` | `xfer` | failed | `srun` on this site rejected `--uenv=...` |
878
+
879
+ The conversion gate therefore ran as a bounded `debug` GPU job because it
880
+ requires PyTorch/model loading and includes an HF logit smoke. This was not a
881
+ CPU-only dataset/snippet path.
882
+
883
+ R17 roundtrip job:
884
+
885
+ - Job: `2357565`
886
+ - Partition: `debug`
887
+ - State: `COMPLETED`
888
+ - Elapsed: `00:02:06`
889
+ - Exit code: `0:0`
890
+ - Input HF TD checkpoint:
891
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/retok_td_full25_layers_20260523T092602Z/layer11`
892
+ - Raw Megatron output:
893
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/megatron_tp2_raw`
894
+ - R17-patched Megatron output:
895
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/megatron_tp2_r17patched`
896
+ - HF roundtrip output:
897
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/hf_roundtrip`
898
+ - Verification JSON on Clariden:
899
+ `/capstor/scratch/cscs/fffoivos/runs/td_r17_roundtrip_2357565/verification.json`
900
+ - Local evidence copy:
901
+ `../megatron_patches/td_layer11_r17_roundtrip_2357565/`
902
+
903
+ Verifier result:
904
+
905
+ | Check | Result |
906
+ |---|---:|
907
+ | `standard_max_abs_diff` | `0.0` |
908
+ | `r17_max_abs_diff` | `0.0` |
909
+ | `xielu_max_abs_diff` | `0.0` |
910
+ | `qk_norm_max_abs_diff` | `0.0` |
911
+ | `standard_changed_over_tol_count` | `0` |
912
+ | `shape_mismatches` | `[]` |
913
+ | `logit_max_abs_diff` | `0.0` |
914
+ | `logit_mean_abs_diff_max` | `0.0` |
915
+
916
+ All three smoke prompts had exact logit parity and matching top IDs:
917
+
918
+ - `Η Αθήνα είναι η πρωτεύουσα της`
919
+ - `Ο Όμηρος έγραψε`
920
+ - `The capital of Greece is`
921
+
922
+ Interpretation:
923
+
924
+ - The selected TD layer11 checkpoint is now proven safe through the
925
+ R17-preserving HF -> Megatron -> HF roundtrip.
926
+ - The raw HF -> Megatron route is still not acceptable in general; the safe
927
+ production artifact is the patched Megatron checkpoint above.
928
+ - Next gate: a very short Megatron load/train smoke from
929
+ `megatron_tp2_r17patched`, with saves disabled or pushed beyond the smoke,
930
+ before any longer CPT-scale run.
931
+
932
+ ## TD layer11 Megatron load/train smoke setup
933
+
934
+ Added `../bakeoff_training/submit_td_layer11_smoke.sh` so the next gate is a
935
+ reproducible bounded run, not a hand-typed one-off. It reuses
936
+ `bakeoff_train.sbatch` and only changes:
937
+
938
+ - `ARM=retok`, so the extended tokenizer and extended-tokenized Megatron data
939
+ are used.
940
+ - `INIT_CKPT`, pointed at the selected R17-patched TD checkpoint:
941
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/megatron_tp2_r17patched`
942
+ - `EXIT_INTERVAL=5`
943
+ - `SAVE_INTERVAL=999999`
944
+ - `EVAL_INTERVAL=999999`
945
+ - `TIME_LIMIT=01:00:00`
946
+
947
+ This gate is intentionally just a load/first-forward/backward/optimizer-step
948
+ smoke. It should not produce a CPT checkpoint or consume a long training window.
949
+
950
+ Launch:
951
+
952
+ - Job: `2357596`
953
+ - Partition: `normal`
954
+ - Output directory:
955
+ `/capstor/scratch/cscs/fffoivos/runs/bakeoff/smoke_td_full25_layer11_20260523T162614Z`
956
+ - Settings:
957
+ - `TIME_LIMIT=01:00:00`
958
+ - `EXIT_INTERVAL=5`
959
+ - `SAVE_INTERVAL=999999`
960
+ - `EVAL_INTERVAL=999999`
961
+ - `ARM=retok`
962
+ - `INIT_CKPT=/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/megatron_tp2_r17patched`
963
+
964
+ ## TD layer11 two-node efficiency smoke failed
965
+
966
+ Smoke result:
967
+
968
+ - Job: `2357684`
969
+ - State: `FAILED`
970
+ - Elapsed: `00:02:24`
971
+ - Exit code: `1:0`
972
+ - Nodes: `nid006031`, `nid007615`
973
+ - Local evidence copy:
974
+ `../bakeoff_training/smoke_td_layer11_2node_2357684/`
975
+
976
+ What passed before failure:
977
+
978
+ - The selected R17-patched checkpoint loaded successfully.
979
+ - The extended tokenizer/data were selected through `ARM=retok`.
980
+ - The `torchrun` world size was `8`.
981
+ - xIELU optimizer audit passed on all eight ranks with `missing=0`.
982
+
983
+ Failure:
984
+
985
+ - The job failed before iteration 1 during a data-parallel collective.
986
+ - Root error in stderr:
987
+ `NET/OFI Request ... Error: 16 (NO_SPACE)`.
988
+ - PyTorch surfaced it as:
989
+ `NCCL Error 2: unhandled system error`.
990
+
991
+ Decision:
992
+
993
+ - Do not spend the 2B TD arm on the two-node path right now.
994
+ - Use the reliable one-node path.
995
+ - `normal` partition has a `12:00:00` walltime cap, while one-node smoke
996
+ throughput implies about 17.5h for 2B. Therefore the safe 2B launch shape is
997
+ a one-node initial job plus an automatic resume job from the same checkpoint
998
+ directory.
999
+
1000
+ ## TD layer11 2B chained training launched
1001
+
1002
+ Launched the decision-useful 2B TD arm on the proven one-node path:
1003
+
1004
+ - Output directory:
1005
+ `/capstor/scratch/cscs/fffoivos/runs/bakeoff/td_full25_layer11_2b_20260523T165038Z`
1006
+ - Initial job: `2357704`
1007
+ - Resume job: `2357705`
1008
+ - Dependency: `afterany:2357704`
1009
+ - Partition: `normal`
1010
+ - Nodes: `1`
1011
+ - GPUs: `4`
1012
+ - Launch mode: `slurm`
1013
+ - Time limit per job: `12:00:00`
1014
+ - Save interval: `65`
1015
+ - Eval interval: `999999`
1016
+ - Chain resume: `1`
1017
+ - Init checkpoint:
1018
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/megatron_tp2_r17patched`
1019
+
1020
+ Reason for chained shape: the partition limit is 12h, and one-node smoke
1021
+ throughput gives an estimated 17-18h for 2B tokens. The first job should save
1022
+ periodic checkpoints; the second job should resume from
1023
+ `$OUTPUT_DIR/checkpoints`.
1024
+
1025
+ Initial live health:
1026
+
1027
+ - Job `2357704` started on `nid006069`.
1028
+ - Resume job `2357705` remains pending with `Dependency`, as intended.
1029
+ - Checkpoint load succeeded from the TD R17-patched init checkpoint.
1030
+ - Dataset build succeeded with the extended tokenizer/data prefix.
1031
+ - xIELU optimizer audit passed on all four ranks with `missing=0`.
1032
+ - First iteration completed:
1033
+ - timestamp: `2026-05-23 18:55:41`
1034
+ - iteration: `1/476`
1035
+ - consumed tokens: `0.004B`
1036
+ - loss: `8.928761`
1037
+ - grad norm: `153.597`
1038
+ - tokens/sec/GPU: `7553.6`
1039
+ - skipped iterations: `0`
1040
+ - NaN iterations: `0`
1041
+ - max allocated memory after iter 1: `61378.95 MB`
1042
+
1043
+ Interpretation: the decision-useful 2B TD arm is live and healthy on the proven
1044
+ one-node path. Expected remaining walltime from observed per-iteration timing is
1045
+ still longer than the 12h partition cap, so the dependent resume job is needed.
1046
+
1047
+ Follow-up health:
1048
+
1049
+ - At Slurm elapsed `00:06:18`, iteration 2 completed:
1050
+ - timestamp: `2026-05-23 18:57:55`
1051
+ - iteration: `2/476`
1052
+ - consumed tokens: `0.008B`
1053
+ - loss: `9.013231`
1054
+ - grad norm: `102.030`
1055
+ - tokens/sec/GPU: `7852.9`
1056
+ - skipped iterations: `0`
1057
+ - NaN iterations: `0`
1058
+
1059
+ At launch there were no other visible Slurm jobs for `fffoivos`.
1060
+
1061
+ ## TD layer11 Megatron load/train smoke passed
1062
+
1063
+ Smoke result:
1064
+
1065
+ - Job: `2357596`
1066
+ - State: `COMPLETED`
1067
+ - Elapsed: `00:13:19`
1068
+ - Exit code: `0:0`
1069
+ - Node: `nid007017`
1070
+ - Local evidence copy:
1071
+ `../bakeoff_training/smoke_td_layer11_2357596/`
1072
+
1073
+ The smoke loaded the selected R17-patched checkpoint, selected the extended
1074
+ tokenizer/data through `ARM=retok`, built the dataset, passed the first
1075
+ forward/backward/optimizer path, and exited at iteration 5.
1076
+
1077
+ Iteration metrics:
1078
+
1079
+ | Iter | Loss | Grad norm | Tokens/sec/GPU | Skipped | NaN |
1080
+ |---:|---:|---:|---:|---:|---:|
1081
+ | 1 | 8.928761 | 153.403 | 7546.1 | 0 | 0 |
1082
+ | 2 | 9.013231 | 101.992 | 7867.7 | 0 | 0 |
1083
+ | 3 | 8.947750 | 105.898 | 7907.7 | 0 | 0 |
1084
+ | 4 | 8.990582 | 106.622 | 7905.1 | 0 | 0 |
1085
+ | 5 | 8.853868 | 173.612 | 7849.6 | 0 | 0 |
1086
+
1087
+ Other health signals:
1088
+
1089
+ - Checkpoint load succeeded from:
1090
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/megatron_tp2_r17patched`
1091
+ - xIELU optimizer audit passed on all four ranks:
1092
+ `missing=0`, `dp_optimizer_alpha_params=64`.
1093
+ - Rank 0/1 memory after iteration 1:
1094
+ max allocated `61378.95 MB`, max reserved `61662.0 MB`.
1095
+ - The warnings were non-fatal NCCL/barrier/deprecation/shutdown warnings; no
1096
+ OOM, no NaN, and no skipped iterations appeared.
1097
+
1098
+ Unexpected save behavior and cleanup:
1099
+
1100
+ - `EXIT_INTERVAL=5` caused Megatron to save at exit despite
1101
+ `SAVE_INTERVAL=999999`, because the training loop saves on exit whenever
1102
+ `args.save` is set.
1103
+ - The smoke checkpoint was `138G`.
1104
+ - I captured `checkpoint_listing_before_cleanup.txt` locally, then removed the
1105
+ smoke checkpoint directory from Capstor. The remote smoke run directory is
1106
+ now `64K`.
1107
+ - I added a `DISABLE_SAVE=1` path for future TD smokes so this wrapper does not
1108
+ produce another accidental large checkpoint. Normal training still defaults
1109
+ to checkpointing enabled.
1110
+
1111
+ ## TD layer11 two-node efficiency smoke launched
1112
+
1113
+ Reason: the one-node smoke throughput is roughly `7.85k-7.91k tokens/sec/GPU`,
1114
+ which implies about 17.5 hours for the 2B TD arm on one 4-GPU node. Before
1115
+ launching the decision-useful 2B arm, I started a bounded two-node smoke to
1116
+ verify that the existing `torchrun` multi-node path works for this exact TD
1117
+ checkpoint/data stack.
1118
+
1119
+ Launch:
1120
+
1121
+ - Job: `2357684`
1122
+ - Partition: `normal`
1123
+ - Nodes: `2`
1124
+ - GPUs: `8`
1125
+ - Launch mode: `torchrun`
1126
+ - Output directory:
1127
+ `/capstor/scratch/cscs/fffoivos/runs/bakeoff/smoke_td_full25_layer11_2node_20260523T164424Z`
1128
+ - Settings:
1129
+ - `EXIT_INTERVAL=2`
1130
+ - `DISABLE_SAVE=1`
1131
+ - `SAVE_INTERVAL=999999`
1132
+ - `EVAL_INTERVAL=999999`
1133
+ - `ARM=retok`
1134
+ - `INIT_CKPT=/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/megatron_tp2_r17patched`
1135
+
1136
+ ## Continuation note: eval handoff and live 2B status
1137
+
1138
+ Timestamp: `2026-05-23T17:04:06Z`
1139
+
1140
+ I resumed from the TD 2B run and explicitly recorded the handoff steps so the
1141
+ run remains reconstructable.
1142
+
1143
+ Current live training state:
1144
+
1145
+ - Active training job: `2357704` (`td_l11_2b`)
1146
+ - Resume job: `2357705` (`td_l11_2b_resume`), pending on `afterany:2357704`
1147
+ - Run directory:
1148
+ `/capstor/scratch/cscs/fffoivos/runs/bakeoff/td_full25_layer11_2b_20260523T165038Z`
1149
+ - Init checkpoint:
1150
+ `/iopsstor/scratch/cscs/fffoivos/token_distillation/td_full25_layer11_r17_roundtrip_2357565/megatron_tp2_r17patched`
1151
+ - Status check at Slurm elapsed `00:15:13`: job `2357704` was running on
1152
+ `nid006069`.
1153
+ - Latest observed iteration: `6/476`
1154
+ - timestamp: `2026-05-23 19:06:46`
1155
+ - consumed tokens: `0.025B`
1156
+ - loss: `8.708739`
1157
+ - grad norm: `159.085`
1158
+ - tokens/sec/GPU: `7890.4`
1159
+ - skipped iterations: `0`
1160
+ - NaN iterations: `0`
1161
+
1162
+ Two-node smoke decision:
1163
+
1164
+ - Two-node smoke job `2357684` failed before iteration 1 with
1165
+ `NET/OFI ... Error: 16 (NO_SPACE)` and `NCCL Error 2`.
1166
+ - I did not switch the production TD 2B run to the two-node path. The active
1167
+ run remains on the reliable one-node path.
1168
+
1169
+ Eval handoff changes prepared locally:
1170
+
1171
+ - `eval/convert_bakeoff_checkpoint_to_hf.sbatch` now accepts
1172
+ `ARM=td_layer11` and defaults that arm to the TD layer11 R17-roundtripped HF
1173
+ tokenizer/config directory.
1174
+ - Added `eval/submit_td_checkpoint_eval.sh`, a direct-path submitter for the
1175
+ selected TD run's checkpoints.
1176
+ - The submitter preflights `EVAL_JSONL` before any `sbatch` submission when
1177
+ `SUBMIT_INTRINSIC=1`, so a misconfigured intrinsic run does not half-submit.
1178
+ - Added `eval/watch_and_submit_td_checkpoint_eval.sh`, a direct-path watcher
1179
+ that submits conversion/eval once both the checkpoint directory and
1180
+ `latest_checkpointed_iteration.txt` confirm the target iteration is ready.
1181
+ - Updated `eval/EVAL_RECIPE.md` with the TD direct-path eval handoff.
1182
+ - Verified the held-out intrinsic slice still exists at:
1183
+ `/iopsstor/scratch/cscs/fffoivos/cpt_corpus/heldout/cpt_greek_heldout_500_20260522.jsonl`
1184
+ with 500 docs and size `33M`.
1185
+
1186
+ Checkpoint watchers launched:
1187
+
1188
+ | Iter | Scope | Intrinsic | PID | Watch log |
1189
+ |---:|---|---:|---:|---|
1190
+ | 65 | `greek_only` | 0 | 198851 | `/capstor/scratch/cscs/fffoivos/runs/eval/watch_td_l11_iter65_greek_only.log` |
1191
+ | 130 | `full` | 1 | 198853 | `/capstor/scratch/cscs/fffoivos/runs/eval/watch_td_l11_iter130_full.log` |
1192
+ | 260 | `full` | 1 | 198854 | `/capstor/scratch/cscs/fffoivos/runs/eval/watch_td_l11_iter260_full.log` |
1193
+ | 390 | `full` | 1 | 198855 | `/capstor/scratch/cscs/fffoivos/runs/eval/watch_td_l11_iter390_full.log` |
1194
+ | 455 | `full` | 1 | 198856 | `/capstor/scratch/cscs/fffoivos/runs/eval/watch_td_l11_iter455_full.log` |
1195
+ | 476 | `full` | 1 | 198857 | `/capstor/scratch/cscs/fffoivos/runs/eval/watch_td_l11_iter476_full.log` |
1196
+
1197
+ All six watchers wrote their initial `waiting for iter_...` line at
1198
+ `2026-05-23T17:08:41Z`.
1199
+
1200
+ Watcher durability correction:
1201
+
1202
+ - The first watcher launch used `nohup` from the SSH login session. It wrote the
1203
+ state directories and initial logs, but the processes did not persist after
1204
+ the SSH session closed.
1205
+ - A direct `sbatch --wrap` attempt with a 36h xfer walltime failed because the
1206
+ requested time limit exceeded the partition limit.
1207
+ - I added `eval/watch_td_checkpoint_evals.sbatch`: one CPU, no GPU,
1208
+ `partition=xfer`, `time=11:50:00`, running the same watcher set under Slurm.
1209
+ - Durable watcher jobs:
1210
+ - `2357765` running on `xfer` (`td_l11_watch`), started at
1211
+ `2026-05-23T17:11:43Z` on `nid001154`.
1212
+ - `2357766` pending on `afterany:2357765`, same wrapper, to cover the second
1213
+ half of the chained 2B training window.
1214
+ - The wrapper reuses per-checkpoint `submitted` stamps, so the second watcher
1215
+ window can safely repeat all six targets without duplicate eval submissions.
1216
+
1217
+ Important resource guard:
1218
+
1219
+ - Checkpoint conversion remains a CPU-only `xfer` Slurm job through
1220
+ `slurm_cpu_only_guard.sh`.
1221
+ - Downstream lm-eval and intrinsic metrics remain GPU jobs, as intended.
1222
+
1223
+ ## Health pulse: pre-checkpoint TD 2B run
1224
+
1225
+ Timestamp: `2026-05-23T17:26:45Z`
1226
+
1227
+ Status:
1228
+
1229
+ - Training job `2357704` still running on `normal`, node `nid006069`, elapsed
1230
+ `00:34:33`.
1231
+ - Resume job `2357705` still pending on dependency, as intended.
1232
+ - Durable watcher job `2357765` still running on `xfer`, node `nid001154`,
1233
+ elapsed `00:14:52`.
1234
+ - Second watcher job `2357766` still pending on `afterany:2357765`, as
1235
+ intended.
1236
+
1237
+ Latest training line:
1238
+
1239
+ - Iteration: `14/476`
1240
+ - Timestamp in training log: `2026-05-23 19:24:29`
1241
+ - Consumed tokens: `0.059B`
1242
+ - Loss: `6.599847`
1243
+ - Grad norm: `23.327`
1244
+ - Tokens/sec/GPU: `7893.5`
1245
+ - Skipped iterations: `0`
1246
+ - NaN iterations: `0`
1247
+
1248
+ Checkpoint/eval state:
1249
+
1250
+ - No checkpoint files yet under the TD 2B checkpoint root; this is expected
1251
+ because the first save target is iteration `65`.
1252
+ - The iter-65 watcher is polling every 300 seconds and still waiting for
1253
+ `checkpoints/iter_0000065`.
1254
+
1255
+ ## Checkpoint 65 and eval canary handoff
1256
+
1257
+ Timestamp: `2026-05-23T19:24Z`
1258
+
1259
+ Training/checkpoint state:
1260
+
1261
+ - Training job `2357704` reached iteration `65/476`.
1262
+ - Iteration 65 metrics:
1263
+ - training-log timestamp: `2026-05-23 21:17:27`
1264
+ - consumed tokens: `0.273B`
1265
+ - loss: `3.919139`
1266
+ - grad norm: `5.525`
1267
+ - tokens/sec/GPU: `7888.5`
1268
+ - skipped iterations: `0`
1269
+ - NaN iterations: `0`
1270
+ - Checkpoint save completed:
1271
+ - checkpoint dir:
1272
+ `/capstor/scratch/cscs/fffoivos/runs/bakeoff/td_full25_layer11_2b_20260523T165038Z/checkpoints/iter_0000065`
1273
+ - tracker:
1274
+ `/capstor/scratch/cscs/fffoivos/runs/bakeoff/td_full25_layer11_2b_20260523T165038Z/checkpoints/latest_checkpointed_iteration.txt`
1275
+ contains `65`.
1276
+ - Training continued to iteration `66/476` after the async save.
1277
+
1278
+ Watcher/eval canary:
1279
+
1280
+ - Durable watcher `2357765` detected checkpoint 65 and submitted:
1281
+ - conversion job `2358857` (`tohf_td_l11_65`)
1282
+ - dependent Greek-only eval job `2358858`
1283
+
1284
+ Canary failure and correction:
1285
+
1286
+ - Conversion job `2358857` failed in `00:00:04` with exit `127:0`.
1287
+ - Root cause from stderr:
1288
+ `uenv: command not found`.
1289
+ - A fresh xfer probe job `2358876` confirmed that `xfer` node `nid001154` has
1290
+ no `uenv` binary at either `command -v uenv` or `/usr/bin/uenv`, matching the
1291
+ earlier TD notes for conversion gates.
1292
+ - I cancelled the dead dependent eval job `2358858`.
1293
+ - I changed `eval/convert_bakeoff_checkpoint_to_hf.sbatch` from a forced
1294
+ CPU-only `xfer` job to a bounded one-GPU `debug` job. This matches the earlier
1295
+ R17/TD conversion gate: Megatron checkpoint conversion imports PyTorch and
1296
+ needs the PyTorch uenv, so it cannot run on xfer on this site.
1297
+ - I removed `eval/convert_bakeoff_checkpoint_to_hf.sbatch` from
1298
+ `check_cpu_only_slurm.sh`'s CPU-only audit list. Dataset/build/preprocessing
1299
+ jobs remain guarded for `xfer`; checkpoint watchers also remain CPU-only
1300
+ `xfer` jobs.
1301
+
1302
+ Next action:
1303
+
1304
+ - Sync the corrected conversion script/docs to Clariden.
1305
+ - Resubmit the iter-65 conversion/eval chain and verify the Greek-only canary
1306
+ starts from the corrected conversion job.
1307
+
1308
+ ## Checkpoint 65 conversion recovery passed
1309
+
1310
+ Timestamp: `2026-05-23T19:28:04Z`
1311
+
1312
+ Local changes committed and synced:
1313
+
1314
+ - Commit: `8428b6d` (`Fix TD checkpoint conversion partition`)
1315
+ - Changed `eval/convert_bakeoff_checkpoint_to_hf.sbatch` to run on
1316
+ `debug` with one GPU and the PyTorch uenv.
1317
+ - Removed `eval/convert_bakeoff_checkpoint_to_hf.sbatch` from the CPU-only
1318
+ static audit list.
1319
+ - Updated `eval/EVAL_RECIPE.md` to distinguish:
1320
+ - true CPU-only dataset/build/watch jobs -> `xfer`
1321
+ - Megatron/PyTorch checkpoint conversion -> bounded one-GPU `debug`
1322
+
1323
+ Validation before resubmit:
1324
+
1325
+ - Local:
1326
+ - `bash -n eval/convert_bakeoff_checkpoint_to_hf.sbatch`
1327
+ - `bash -n check_cpu_only_slurm.sh`
1328
+ - `./check_cpu_only_slurm.sh`
1329
+ - Remote on Clariden mirror:
1330
+ - `bash -n eval/convert_bakeoff_checkpoint_to_hf.sbatch`
1331
+ - `bash -n check_cpu_only_slurm.sh`
1332
+ - `./check_cpu_only_slurm.sh`
1333
+
1334
+ All static checks passed. The CPU-only audit covers 10 true CPU-only jobs.
1335
+
1336
+ Resubmitted iter-65 canary:
1337
+
1338
+ - Command shape:
1339
+ `RUN_TAG=td_full25_layer11_2b_20260523T165038Z OVERWRITE=1 bash submit_td_checkpoint_eval.sh 65 greek_only`
1340
+ - Conversion job: `2358891` (`tohf_td_l11_65`)
1341
+ - Greek-only eval job: `2358892` (`eval_td_l11_65_greek_only`)
1342
+
1343
+ Conversion result:
1344
+
1345
+ - Job `2358891` completed successfully.
1346
+ - Partition: `debug`
1347
+ - Elapsed: `00:01:15`
1348
+ - Exit code: `0:0`
1349
+ - HF checkpoint:
1350
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000065_hf`
1351
+ - HF artifacts include:
1352
+ - `config.json`
1353
+ - `tokenizer.json`
1354
+ - `model.safetensors.index.json`
1355
+ - `model-00001-of-00004.safetensors` through `model-00004-of-00004.safetensors`
1356
+ - `bakeoff_conversion_metadata.json`
1357
+
1358
+ Eval state:
1359
+
1360
+ - Job `2358892` started on `normal`, node `nid007637`.
1361
+ - This is the Greek-only downstream canary for checkpoint 65.
1362
+
1363
+ ## Checkpoint 65 Greek-only canary passed
1364
+
1365
+ Timestamp: `2026-05-23T20:02:06Z`
1366
+
1367
+ Training state at refresh:
1368
+
1369
+ - Main TD 2B job `2357704` is still running on `normal`, node `nid006069`.
1370
+ - Resume job `2357705` remains pending behind `2357704`.
1371
+ - Durable checkpoint watcher `2357765` is still running on `xfer`, node
1372
+ `nid001154`.
1373
+ - Backup watcher `2357766` remains pending behind `2357765`.
1374
+ - Latest parsed training line: iteration `84/476`, consumed tokens `0.352B`,
1375
+ timestamp `2026-05-23 21:59:58`, loss `3.593952`, throughput
1376
+ `7876.2` tokens/sec/GPU, skipped iterations `0`, NaN iterations `0`.
1377
+ - Checkpoint tracker remains at `65`; next planned checkpoint is iteration
1378
+ `130`.
1379
+
1380
+ Greek-only canary result:
1381
+
1382
+ - Eval job `2358892` completed successfully.
1383
+ - Partition/node: `normal` / `nid007637`
1384
+ - Elapsed: `00:22:15`
1385
+ - Exit code: `0:0`
1386
+ - Result JSON:
1387
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000065_greek_only/results_2026-05-23T21-49-04.839736.json`
1388
+
1389
+ Headline metrics from checkpoint 65:
1390
+
1391
+ - `global_mmlu_full_el` accuracy: `0.3717419171`
1392
+ - `include_base_44_greek_few_shot_en` accuracy: `0.3713768116`
1393
+ - `xnli_el` accuracy: `0.3903614458`
1394
+ - `arc_challenge_mt_el` normalized accuracy: `0.3233788396`
1395
+ - `belebele_ell_Grek` accuracy: `0.4877777778`
1396
+ - `global_piqa_completions_ell_grek` normalized accuracy: `0.53`
1397
+ - `xquad_el` exact match: `0.1537815126`
1398
+ - `xquad_el` F1: `0.2992209373`
1399
+
1400
+ Interpretation:
1401
+
1402
+ - The corrected conversion/eval path works end to end from a live Megatron
1403
+ checkpoint to HF and then lm-eval.
1404
+ - Checkpoint 65 is an early canary, not a final recipe-selection checkpoint.
1405
+ It is useful because it proves the model is not collapsed after TD init and
1406
+ early CPT, and it validates the automation before the more decision-relevant
1407
+ checkpoint 130 full eval.
1408
+
1409
+ Next action:
1410
+
1411
+ - Keep monitoring the live training job and watcher.
1412
+ - At iteration `130`, verify that the watcher submits the full downstream eval
1413
+ and intrinsic eval chain with the corrected conversion job.
1414
+
1415
+ ## Runtime expectation after checkpoint 65
1416
+
1417
+ Timestamp: `2026-05-23T20:07:30Z`
1418
+
1419
+ Live training refresh:
1420
+
1421
+ - Main TD 2B job `2357704` is still running.
1422
+ - Latest parsed line: iteration `86/476`, consumed tokens `0.361B`, timestamp
1423
+ `2026-05-23 22:04:25`, loss `3.559302`, throughput `7874.4`
1424
+ tokens/sec/GPU, skipped iterations `0`, NaN iterations `0`.
1425
+ - Checkpoint tracker is still `65`.
1426
+
1427
+ Runtime note:
1428
+
1429
+ - The live Megatron ETA at iteration 86 is still about `14:25:33`, while job
1430
+ `2357704` has already used about `3:12` of its `12:00` allocation.
1431
+ - Therefore the first allocation is expected to hit walltime before iteration
1432
+ `476`.
1433
+ - This is not currently a failure condition because resume job `2357705` is
1434
+ already pending with the dependency chain. The next thing to watch later is
1435
+ that the handoff resumes from the latest completed checkpoint cleanly.
1436
+
1437
+ ## Checkpoint 130 saved and full eval chain submitted
1438
+
1439
+ Timestamp: `2026-05-23T21:48:33Z`
1440
+
1441
+ Training state:
1442
+
1443
+ - Main TD 2B job `2357704` is still running on `normal`, node `nid006069`.
1444
+ - Resume job `2357705` remains pending behind `2357704`.
1445
+ - Durable watcher `2357765` is still running on `xfer`, node `nid001154`.
1446
+ - Latest parsed training line after the checkpoint: iteration `132/476`,
1447
+ consumed tokens `0.554B`, timestamp `2026-05-23 23:46:27`, loss
1448
+ `3.140112`, throughput `7868.7` tokens/sec/GPU, skipped iterations `0`,
1449
+ NaN iterations `0`.
1450
+
1451
+ Checkpoint state:
1452
+
1453
+ - Iteration `130` was saved successfully.
1454
+ - Checkpoint tracker now reads `130`.
1455
+ - Checkpoint dirs currently present:
1456
+ - `iter_0000065`
1457
+ - `iter_0000130`
1458
+ - Save log included:
1459
+ - `saving checkpoint at iteration 130`
1460
+ - `scheduled an async checkpoint save at iteration 130`
1461
+ - `successfully saved checkpoint from iteration 130`
1462
+
1463
+ Watcher/eval state:
1464
+
1465
+ - Watcher `watch_td_l11_iter130_full.log` saw the checkpoint directory before
1466
+ the tracker updated, waited correctly, then submitted once tracker reached
1467
+ `130`.
1468
+ - Submission log:
1469
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z_watch_iter_0000130_full/submit.log`
1470
+ - Submitted jobs:
1471
+ - conversion: `2360120` (`tohf_td_l11_130`)
1472
+ - full lm-eval: `2360121` (`eval_td_l11_130_full`)
1473
+ - intrinsic BPC: `2360122` (`bpc_td_l11_130`)
1474
+ - new-token diagnostics: `2360123` (`diag_td_l11_130`)
1475
+
1476
+ Immediate verification:
1477
+
1478
+ - Conversion job `2360120` completed successfully on `debug`.
1479
+ - Elapsed: `00:01:13`
1480
+ - Exit code: `0:0`
1481
+ - HF output:
1482
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000130_hf`
1483
+ - The HF output contains the expected config/tokenizer/index metadata.
1484
+ - At this timestamp, full lm-eval job `2360121` and intrinsic BPC job
1485
+ `2360122` are running; diagnostics job `2360123` is pending for resources.
1486
+
1487
+ Next action:
1488
+
1489
+ - Wait for jobs `2360121`, `2360122`, and `2360123`.
1490
+ - Parse checkpoint-130 downstream metrics and intrinsic/new-token metrics.
1491
+ - Log and commit the checkpoint-130 results once they are complete.
1492
+
1493
+ ## Checkpoint 130 intrinsic and new-token diagnostics passed
1494
+
1495
+ Timestamp: `2026-05-23T21:56:40Z`
1496
+
1497
+ Completed jobs:
1498
+
1499
+ - Intrinsic BPC job `2360122` completed successfully.
1500
+ - Elapsed: `00:01:39`
1501
+ - Exit code: `0:0`
1502
+ - New-token diagnostics job `2360123` completed successfully.
1503
+ - Elapsed: `00:02:19`
1504
+ - Exit code: `0:0`
1505
+ - Full downstream lm-eval job `2360121` is still running at this timestamp.
1506
+
1507
+ Artifacts:
1508
+
1509
+ - Tokenizer-fair intrinsic metrics:
1510
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000130_tokenizer_fair_metrics.json`
1511
+ - New-token diagnostics:
1512
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000130_new_token_diagnostics.json`
1513
+
1514
+ Intrinsic metrics on the 500-doc Greek heldout slice:
1515
+
1516
+ - `n_docs`: `500`
1517
+ - `n_tokens`: `805972`
1518
+ - `chars_per_token`: `3.973178969`
1519
+ - `tokens_per_word`: `1.735161272`
1520
+ - `bpc_bits_per_byte`: `0.6531070974`
1521
+ - `nll_per_token`: `3.069195861`
1522
+ - STRR single-token word rate: `0.4458156518`
1523
+
1524
+ Per-register `bpc_bits_per_byte`:
1525
+
1526
+ - `academic`: `0.5755798070`
1527
+ - `dialogue_textbooks`: `0.8630783619`
1528
+ - `hplt_clean60`: `0.6225848939`
1529
+ - `legal_civic`: `0.4718179034`
1530
+
1531
+ Truncation caveat:
1532
+
1533
+ - `124/500` docs were truncated at the 4096-token scoring prefix.
1534
+ - `fraction_truncated`: `0.248`
1535
+ - This is acceptable as a same-slice checkpoint trend metric, but the absolute
1536
+ heldout BPC should be read with the script's caveat: char/byte/word counts
1537
+ are computed on the scored prefix, not the full text.
1538
+
1539
+ New-token diagnostics:
1540
+
1541
+ - New-token id range requested/applied: `17408` rows, base vocab `131072`,
1542
+ extended vocab `148480`.
1543
+ - Input embedding norm ratio, new/existing mean: `1.0589042902`.
1544
+ - Output embedding norm ratio, new/existing mean: `1.0192596912`.
1545
+ - New-input-row cosine sample:
1546
+ - mean off-diagonal: `0.0813974366`
1547
+ - p95 off-diagonal: `0.1582076550`
1548
+ - p99 off-diagonal: `0.3888086677`
1549
+ - New-input-row effective-rank sample:
1550
+ - participation ratio: `324.5376586914`
1551
+ - rank at 99% variance: `394/500`
1552
+ - Forward diagnostic over heldout positions:
1553
+ - positions total: `805472`
1554
+ - new-target positions: `276332`
1555
+ - average probability mass on new-token vocab per position: `0.3400108291`
1556
+ - new-target rank top-1: `0.2749410130`
1557
+ - new-target rank top-5: `0.4391746160`
1558
+ - new-target rank top-10: `0.5040169072`
1559
+ - new-target rank top-50: `0.6660864467`
1560
+ - top-1 prediction at new-target positions chose a new token `51.11%` of
1561
+ the time.
1562
+ - Greedy generation sanity sample:
1563
+ - prompts: `5`
1564
+ - generated tokens: `500`
1565
+ - generated new-token count: `103`
1566
+ - utilization rate: `0.206`
1567
+
1568
+ Interpretation:
1569
+
1570
+ - Intrinsics and diagnostics do not show a new-token collapse at checkpoint
1571
+ `130`.
1572
+ - New rows remain norm-compatible with existing rows, have non-degenerate
1573
+ sampled rank, and are being used by both forward scoring and greedy
1574
+ generation.
1575
+ - The next decision-useful evidence is the still-running full downstream eval
1576
+ for checkpoint `130`.
1577
+
1578
+ ## Checkpoint 130 full downstream eval passed
1579
+
1580
+ Timestamp: `2026-05-23T22:38:22Z`
1581
+
1582
+ Completed job:
1583
+
1584
+ - Full lm-eval job `2360121` completed successfully.
1585
+ - Elapsed: `00:46:45`
1586
+ - Exit code: `0:0`
1587
+
1588
+ Artifact paths:
1589
+
1590
+ - Remote result JSON:
1591
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000130_full/results_2026-05-24T00-34-38.581138.json`
1592
+ - Remote run metadata:
1593
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000130_full/run_metadata.json`
1594
+ - Local compact copies:
1595
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000130_results.json`
1596
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000130_run_metadata.json`
1597
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000130_tokenizer_fair_metrics.json`
1598
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000130_new_token_diagnostics.json`
1599
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000130_digest.md`
1600
+
1601
+ Headline full-eval metrics:
1602
+
1603
+ - `arc_challenge` acc_norm: `0.5537542662`
1604
+ - `arc_easy` acc_norm: `0.8000841751`
1605
+ - `hellaswag` acc_norm: `0.7598088030`
1606
+ - `winogrande` acc: `0.6850828729`
1607
+ - `piqa` acc_norm: `0.7997823721`
1608
+ - `mmlu` acc: `0.5484973650`
1609
+ - `global_mmlu` acc: `0.4703933786`
1610
+ - `xnli` acc: `0.4139759036`
1611
+ - `xcopa` acc: `0.6310909091`
1612
+ - `arc_challenge_mt_el` acc_norm: `0.3515358362`
1613
+ - `belebele_ell_Grek` acc_norm: `0.5`
1614
+ - `xnli_el` acc: `0.3791164659`
1615
+ - `xquad_el` exact_match: `0.1781512605`
1616
+ - `xquad_el` F1: `0.3713167220`
1617
+ - `global_mmlu_full_el` acc: `0.3847742487`
1618
+ - `include_base_44_greek_few_shot_en` acc: `0.3858695652`
1619
+ - `global_piqa_completions_ell_grek` acc_norm: `0.53`
1620
+
1621
+ Greek checkpoint-65 to checkpoint-130 deltas:
1622
+
1623
+ - `arc_challenge_mt_el` acc_norm: `+0.0281569966`
1624
+ - `arc_challenge_mt_el` raw acc: `+0.0418088737`
1625
+ - `belebele_ell_Grek` acc_norm: `+0.0122222222`
1626
+ - `global_mmlu_full_el` acc: `+0.0130323316`
1627
+ - `include_base_44_greek_few_shot_en` acc: `+0.0144927536`
1628
+ - `global_piqa_completions_ell_grek` acc_norm: `0.0`
1629
+ - `global_piqa_completions_ell_grek` raw acc: `-0.02`
1630
+ - `xnli_el` acc: `-0.0112449799`
1631
+ - `xquad_el` exact_match: `+0.0243697479`
1632
+ - `xquad_el` F1: `+0.0720957847`
1633
+
1634
+ Training state after eval completion:
1635
+
1636
+ - Main TD 2B job `2357704` is still running.
1637
+ - Latest parsed training line: iteration `154/476`, consumed tokens `0.646B`,
1638
+ timestamp `2026-05-24 00:35:15`, loss `3.060735`, throughput `7874.1`
1639
+ tokens/sec/GPU, skipped iterations `0`, NaN iterations `0`.
1640
+ - Checkpoint tracker remains `130`; next scheduled full checkpoint/eval gate is
1641
+ `260`.
1642
+
1643
+ Interpretation:
1644
+
1645
+ - Checkpoint 130 gives the first full TD downstream snapshot and the early
1646
+ Greek trend is mostly positive relative to the checkpoint-65 canary.
1647
+ - It is still too early to choose TD for production solely from this point:
1648
+ checkpoint `260`, later full checkpoints, and final comparison to the
1649
+ earlier Vanilla/ReTok/Centroid bakeoff are still required.
1650
+
1651
+ ## Intermediate checkpoint 195 saved
1652
+
1653
+ Timestamp: `2026-05-24T00:45:37Z`
1654
+
1655
+ Why this matters:
1656
+
1657
+ - Checkpoint `195` is not a scheduled downstream-eval gate, but it is the newest
1658
+ durable resume point for the live TD 2B run.
1659
+ - If the first 12h allocation hits walltime before the final iteration, the
1660
+ queued resume job should be able to resume from this or a later tracker value.
1661
+
1662
+ Training state at refresh:
1663
+
1664
+ - Main TD 2B job `2357704` is still running.
1665
+ - Resume job `2357705` remains pending.
1666
+ - Durable watcher `2357765` is still running on `xfer`.
1667
+ - Latest parsed training line: iteration `212/476`, consumed tokens `0.889B`,
1668
+ timestamp `2026-05-24 02:43:57`, loss `2.874373`, throughput `7879.1`
1669
+ tokens/sec/GPU, skipped iterations `0`, NaN iterations `0`.
1670
+ - Tracker now reads `195`.
1671
+ - Checkpoint dirs currently present:
1672
+ - `iter_0000065`
1673
+ - `iter_0000130`
1674
+ - `iter_0000195`
1675
+
1676
+ Checkpoint 195 save evidence:
1677
+
1678
+ - `saving checkpoint at iteration 195`
1679
+ - `scheduled an async checkpoint save at iteration 195`
1680
+ - `successfully saved checkpoint from iteration 195`
1681
+ - Directory:
1682
+ `/capstor/scratch/cscs/fffoivos/runs/bakeoff/td_full25_layer11_2b_20260523T165038Z/checkpoints/iter_0000195`
1683
+
1684
+ Next action:
1685
+
1686
+ - Continue monitoring toward scheduled full eval gate `260`.
1687
+
1688
+ ## Checkpoint 260 saved and full eval chain submitted
1689
+
1690
+ Timestamp: `2026-05-24T02:36:40Z`
1691
+
1692
+ Training state:
1693
+
1694
+ - Main TD 2B job `2357704` is still running.
1695
+ - Resume job `2357705` remains pending.
1696
+ - Durable watcher `2357765` is still running on `xfer`.
1697
+ - Latest parsed training line after the checkpoint: iteration `262/476`,
1698
+ consumed tokens `1.099B`, timestamp `2026-05-24 04:34:53`, loss
1699
+ `2.661077`, throughput `7877.0` tokens/sec/GPU, skipped iterations `0`,
1700
+ NaN iterations `0`.
1701
+
1702
+ Checkpoint state:
1703
+
1704
+ - Iteration `260` was saved successfully.
1705
+ - Checkpoint tracker now reads `260`.
1706
+ - Checkpoint dirs currently present:
1707
+ - `iter_0000065`
1708
+ - `iter_0000130`
1709
+ - `iter_0000195`
1710
+ - `iter_0000260`
1711
+ - Save log included:
1712
+ - `saving checkpoint at iteration 260`
1713
+ - `scheduled an async checkpoint save at iteration 260`
1714
+ - `successfully saved checkpoint from iteration 260`
1715
+
1716
+ Watcher/eval state:
1717
+
1718
+ - Watcher `watch_td_l11_iter260_full.log` submitted once tracker reached
1719
+ `260`.
1720
+ - Submission log:
1721
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z_watch_iter_0000260_full/submit.log`
1722
+ - Submitted jobs:
1723
+ - conversion: `2362712` (`tohf_td_l11_260`)
1724
+ - full lm-eval: `2362713` (`eval_td_l11_260_full`)
1725
+ - intrinsic BPC: `2362714` (`bpc_td_l11_260`)
1726
+ - new-token diagnostics: `2362715` (`diag_td_l11_260`)
1727
+
1728
+ Immediate verification:
1729
+
1730
+ - Conversion job `2362712` completed successfully on `debug`.
1731
+ - Elapsed: `00:01:10`
1732
+ - Exit code: `0:0`
1733
+ - HF output:
1734
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000260_hf`
1735
+ - At this timestamp, full lm-eval job `2362713`, intrinsic BPC job `2362714`,
1736
+ and diagnostics job `2362715` are running.
1737
+
1738
+ Next action:
1739
+
1740
+ - Wait for jobs `2362713`, `2362714`, and `2362715`.
1741
+ - Parse checkpoint-260 downstream metrics and intrinsic/new-token metrics.
1742
+ - Log and commit the checkpoint-260 results once they are complete.
1743
+
1744
+ ## Checkpoint 260 intrinsic and new-token diagnostics passed
1745
+
1746
+ Timestamp: `2026-05-24T02:42:20Z`
1747
+
1748
+ Completed jobs:
1749
+
1750
+ - Intrinsic BPC job `2362714` completed successfully.
1751
+ - Elapsed: `00:01:42`
1752
+ - Exit code: `0:0`
1753
+ - New-token diagnostics job `2362715` completed successfully.
1754
+ - Elapsed: `00:02:19`
1755
+ - Exit code: `0:0`
1756
+ - Full downstream lm-eval job `2362713` is still running at this timestamp.
1757
+
1758
+ Artifacts:
1759
+
1760
+ - Tokenizer-fair intrinsic metrics:
1761
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000260_tokenizer_fair_metrics.json`
1762
+ - New-token diagnostics:
1763
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000260_new_token_diagnostics.json`
1764
+
1765
+ Intrinsic metrics on the 500-doc Greek heldout slice:
1766
+
1767
+ - `n_docs`: `500`
1768
+ - `n_tokens`: `805972`
1769
+ - `chars_per_token`: `3.973178969`
1770
+ - `tokens_per_word`: `1.735161272`
1771
+ - `bpc_bits_per_byte`: `0.5670351472`
1772
+ - `nll_per_token`: `2.664711398`
1773
+ - STRR single-token word rate: `0.4458156518`
1774
+
1775
+ Per-register `bpc_bits_per_byte`:
1776
+
1777
+ - `academic`: `0.4819600870`
1778
+ - `dialogue_textbooks`: `0.7560400097`
1779
+ - `hplt_clean60`: `0.5585149641`
1780
+ - `legal_civic`: `0.3886621322`
1781
+
1782
+ Truncation caveat:
1783
+
1784
+ - Same as checkpoint `130`: `124/500` docs were truncated at the 4096-token
1785
+ scoring prefix, so absolute BPC should be treated as a same-slice trend
1786
+ metric rather than full-document perplexity.
1787
+
1788
+ New-token diagnostics:
1789
+
1790
+ - New-token id range applied: `17408` rows, base vocab `131072`, extended vocab
1791
+ `148480`.
1792
+ - Input embedding norm ratio, new/existing mean: `1.0588757992`.
1793
+ - Output embedding norm ratio, new/existing mean: `1.0193959475`.
1794
+ - New-input-row cosine sample:
1795
+ - mean off-diagonal: `0.0813098699`
1796
+ - p95 off-diagonal: `0.1580153704`
1797
+ - New-input-row effective-rank sample:
1798
+ - participation ratio: `324.6900024414`
1799
+ - rank at 99% variance: `395/500`
1800
+ - Forward diagnostic over heldout positions:
1801
+ - positions total: `805472`
1802
+ - new-target positions: `276332`
1803
+ - average probability mass on new-token vocab per position: `0.3411220586`
1804
+ - new-target rank top-1: `0.3517146042`
1805
+ - new-target rank top-5: `0.5200483476`
1806
+ - new-target rank top-10: `0.5848797823`
1807
+ - new-target rank top-50: `0.7358648293`
1808
+ - top-1 prediction at new-target positions chose a new token `59.52%` of the
1809
+ time.
1810
+ - Greedy generation sanity sample:
1811
+ - prompts: `5`
1812
+ - generated tokens: `500`
1813
+ - generated new-token count: `98`
1814
+ - utilization rate: `0.196`
1815
+
1816
+ Trend from checkpoint 130 to 260:
1817
+
1818
+ - Heldout BPC improved from `0.6531070974` to `0.5670351472`.
1819
+ - Heldout NLL/token improved from `3.069195861` to `2.664711398`.
1820
+ - New-target top-1 improved from `0.2749410130` to `0.3517146042`.
1821
+ - New-target top-10 improved from `0.5040169072` to `0.5848797823`.
1822
+ - Average probability mass on the new-token vocab is stable:
1823
+ `0.3400108291` -> `0.3411220586`.
1824
+ - New-row input/output norm ratios and sampled rank are stable.
1825
+
1826
+ Interpretation:
1827
+
1828
+ - Checkpoint `260` intrinsics show meaningful heldout improvement and stronger
1829
+ new-token prediction without evidence of new-row collapse.
1830
+ - The remaining checkpoint-260 evidence needed is the still-running full
1831
+ downstream eval.
1832
+
1833
+ ## Live ETA and walltime handoff check
1834
+
1835
+ Timestamp: `2026-05-24T03:17:12Z`
1836
+
1837
+ Training state:
1838
+
1839
+ - Main TD 2B job `2357704` is still running on `normal`.
1840
+ - Resume job `2357705` is pending on dependency.
1841
+ - Durable watcher `2357765` is still running on `xfer`; backup watcher
1842
+ `2357766` remains pending.
1843
+ - Latest parsed training line: iteration `281/476`, consumed tokens `1.179B`,
1844
+ timestamp `2026-05-24 05:17:02`, loss `2.658228`, throughput `7886.9`
1845
+ tokens/sec/GPU, skipped iterations `0`, NaN iterations `0`.
1846
+ - Checkpoint tracker still reads `260`; checkpoint dirs present are
1847
+ `65`, `130`, `195`, and `260`.
1848
+
1849
+ Checkpoint-260 full eval state:
1850
+
1851
+ - Full downstream eval job `2362713` is still running.
1852
+ - Elapsed at poll: `00:41:25`.
1853
+ - Output directory currently has `run_metadata.json`; the final
1854
+ `results_*.json` has not appeared yet.
1855
+ - Eval stdout has completed batch-size probing and selected batch size `40`.
1856
+
1857
+ Walltime / resume safety:
1858
+
1859
+ - Current allocation elapsed: `10:25:11` of `12:00:00`, with about `1:35`
1860
+ remaining at the poll.
1861
+ - At the observed iteration cadence, the allocation will not finish all
1862
+ `476` iterations; it should need the pending resume job.
1863
+ - The Slurm script has `#SBATCH --signal=SIGUSR2@600`, and the Megatron
1864
+ training code path for `--exit-signal-handler` was inspected on Clariden:
1865
+ on receiving SIGUSR2, it calls `save_checkpoint_and_time(...)` before
1866
+ exiting. This means the expected walltime handoff should save a fresh
1867
+ checkpoint near the end of the allocation rather than forcing the resume to
1868
+ fall back to checkpoint `260`.
1869
+
1870
+ ETA:
1871
+
1872
+ - Remaining active training time from iteration `281` is about `7h12m`.
1873
+ - If the resume job starts promptly after the first allocation exits, final
1874
+ training should land around `2026-05-24 12:45-13:15 CEST`.
1875
+ - Final conversion/eval should add roughly another hour, so benchmark-ready
1876
+ artifacts are expected around `2026-05-24 14:00 CEST`, plus any queue delay.
1877
+
1878
+ ## Checkpoint 260 full downstream eval landed
1879
+
1880
+ Timestamp: `2026-05-24T03:25:00Z`
1881
+
1882
+ Completed job:
1883
+
1884
+ - Full downstream eval job `2362713` completed successfully.
1885
+ - Elapsed: `00:44:57`
1886
+ - Exit code: `0:0`
1887
+ - Results:
1888
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000260_full/results_2026-05-24T05-20-34.834207.json`
1889
+
1890
+ Local compact evidence copied:
1891
+
1892
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000260_results.json`
1893
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000260_run_metadata.json`
1894
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000260_tokenizer_fair_metrics.json`
1895
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000260_new_token_diagnostics.json`
1896
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000260_digest.md`
1897
+
1898
+ Headline full-eval deltas vs checkpoint `130`:
1899
+
1900
+ - General capabilities are mixed to slightly down:
1901
+ - `arc_challenge` acc_norm `0.5367` (`-0.0171`)
1902
+ - `arc_easy` acc_norm `0.7824` (`-0.0177`)
1903
+ - `mmlu` acc `0.5385` (`-0.0100`)
1904
+ - `global_mmlu` acc `0.4467` (`-0.0237`)
1905
+ - `hellaswag` acc_norm `0.7617` (`+0.0019`)
1906
+ - `winogrande` acc `0.6882` (`+0.0032`)
1907
+ - Greek movement is mixed but still mostly useful:
1908
+ - `arc_challenge_mt_el` acc_norm `0.3891` (`+0.0375`)
1909
+ - `include_base_44_greek_few_shot_en` acc `0.4112` (`+0.0254`)
1910
+ - `global_piqa_completions_ell_grek` acc_norm `0.5600` (`+0.0300`)
1911
+ - `xnli_el` acc `0.3896` (`+0.0104`)
1912
+ - `belebele_ell_Grek` acc_norm `0.5022` (`+0.0022`)
1913
+ - `global_mmlu_full_el` acc `0.3774` (`-0.0074`)
1914
+ - `xquad_el` exact match `0.1571` (`-0.0210`), F1 `0.3711`
1915
+ (`-0.0003`)
1916
+
1917
+ Intrinsic/new-token trend vs checkpoint `130`:
1918
+
1919
+ - Heldout BPC improved `0.6531 -> 0.5670`.
1920
+ - Heldout NLL/token improved `3.0692 -> 2.6647`.
1921
+ - New-target top-1 improved `0.2749 -> 0.3517`.
1922
+ - New-target top-10 improved `0.5040 -> 0.5849`.
1923
+ - New-vocab probability mass stayed stable: `0.3400 -> 0.3411`.
1924
+ - New-row norm ratios and sampled effective rank stayed stable.
1925
+
1926
+ Interpretation:
1927
+
1928
+ - Checkpoint `260` keeps the strongest signal on intrinsic TD recovery and
1929
+ new-token prediction.
1930
+ - Downstream Greek is not uniformly monotonic, but several target Greek metrics
1931
+ improve from checkpoint `130` and most are above checkpoint `65`.
1932
+ - The main watch item for final selection is whether the final checkpoint
1933
+ restores or further erodes the small general-benchmark dips seen at `260`.
1934
+
1935
+ ## Walltime handoff preserved progress at checkpoint 320
1936
+
1937
+ Timestamp: `2026-05-24T04:49:24Z`
1938
+
1939
+ Main job `2357704` reached the Slurm signal handoff cleanly:
1940
+
1941
+ - Last pre-handoff training line: iteration `320/476`, consumed tokens
1942
+ `1.342B`, timestamp `2026-05-24 06:43:29`, loss `2.605217`, throughput
1943
+ `7891.8` tokens/sec/GPU, skipped iterations `0`, NaN iterations `0`.
1944
+ - Slurm/Megatron signal path fired after iteration `320`:
1945
+ - `saving checkpoint at iteration 320`
1946
+ - `scheduled an async checkpoint save at iteration 320`
1947
+ - `exiting program after receiving SIGUSR2`
1948
+ - `successfully saved checkpoint from iteration 320`
1949
+ - Checkpoint tracker advanced from `260` to `320`.
1950
+ - Checkpoint directory now exists:
1951
+ `/capstor/scratch/cscs/fffoivos/runs/bakeoff/td_full25_layer11_2b_20260523T165038Z/checkpoints/iter_0000320`
1952
+ - Checkpoint `iter_0000320` contains `common.pt`, `.metadata`,
1953
+ `metadata.json`, and all eight `*.distcp` shards.
1954
+
1955
+ Resume job `2357705` started automatically and loaded the handoff checkpoint:
1956
+
1957
+ - Resume job state at verification: `RUNNING`.
1958
+ - Resume stdout:
1959
+ - `loading distributed checkpoint ... at iteration 320`
1960
+ - `successfully loaded checkpoint ... at iteration 320`
1961
+ - `before the start of training step`
1962
+ - Resume stderr contains only expected warnings/deprecations and the xIELU
1963
+ optimizer audit:
1964
+ - rank 0/1/2/3 all report `model_alpha_params=64`,
1965
+ `dp_optimizer_alpha_params=64`, `missing=0`.
1966
+ - First resumed training line landed: iteration `321/476`, consumed tokens
1967
+ `1.346B`, timestamp `2026-05-24 06:48:21`, loss `2.629754`, skipped
1968
+ iterations `0`, NaN iterations `0`.
1969
+
1970
+ Interpretation:
1971
+
1972
+ - The configured `#SBATCH --signal=SIGUSR2@600` plus
1973
+ `--exit-signal-handler` path is proven live, not just code-inspected.
1974
+ - The handoff preserved progress beyond checkpoint `260`; the resumed run is
1975
+ continuing from checkpoint `320`.
1976
+ - Next planned evaluation checkpoint remains `390`; checkpoint `320` is a
1977
+ resume-safety checkpoint, not a scheduled eval point.
1978
+
1979
+ ## Resume checkpoint 325 and backup watcher handoff
1980
+
1981
+ Timestamp: `2026-05-24T05:05:02Z`
1982
+
1983
+ Resume/training state:
1984
+
1985
+ - Resume job `2357705` is still running on `normal`.
1986
+ - Latest parsed training line at poll: iteration `328/476`, consumed tokens
1987
+ `1.376B`, timestamp `2026-05-24 07:04:15`, loss `2.643836`, throughput
1988
+ `7892.9` tokens/sec/GPU, skipped iterations `0`, NaN iterations `0`.
1989
+ - Regular checkpoint `325` saved successfully after the resume.
1990
+ - Checkpoint tracker advanced to `325`.
1991
+ - Checkpoint `iter_0000325` contains `common.pt`, `.metadata`,
1992
+ `metadata.json`, and all eight `*.distcp` shards.
1993
+
1994
+ Watcher handoff:
1995
+
1996
+ - First durable watcher `2357765` reached its xfer walltime and ended with
1997
+ state `TIMEOUT`, elapsed `11:50:26`.
1998
+ - Backup watcher `2357766` started automatically via
1999
+ `afterany:2357765` and is running on `xfer`.
2000
+ - Backup watcher stdout confirms it restarted the watch specs:
2001
+ `65:greek_only:0 130:full:1 260:full:1 390:full:1 455:full:1 476:full:1`.
2002
+ - The checkpoint-390 watcher log now contains the backup start marker:
2003
+ `watch start RUN_TAG=td_full25_layer11_2b_20260523T165038Z ITER=390 TASK_GROUP=full`.
2004
+
2005
+ Interpretation:
2006
+
2007
+ - Training remains healthy after the resume and has made a normal scheduled
2008
+ checkpoint at `325`.
2009
+ - Eval automation remains covered through the backup xfer watcher.
2010
+ - Next decision-useful checkpoint remains `390`, expected to trigger the full
2011
+ eval plus intrinsic/new-token diagnostics chain.
2012
+
2013
+ ## Checkpoint 390 reached and eval chain submitted
2014
+
2015
+ Timestamp: `2026-05-24T07:27:54Z`
2016
+
2017
+ Training/checkpoint state:
2018
+
2019
+ - Resume job `2357705` is still running on `normal`.
2020
+ - Latest parsed training line at checkpoint: iteration `390/476`, consumed
2021
+ tokens `1.636B`, timestamp `2026-05-24 09:21:40 CEST`, loss `2.556699`,
2022
+ throughput `7881.9` tokens/sec/GPU, skipped iterations `0`, NaN iterations
2023
+ `0`.
2024
+ - Checkpoint `iter_0000390` exists and is complete: `common.pt`,
2025
+ `.metadata`, `metadata.json`, and all eight `*.distcp` shards are present.
2026
+ - Checkpoint tracker advanced to `390`.
2027
+
2028
+ Eval automation:
2029
+
2030
+ - Backup watcher `2357766` detected the complete checkpoint and submitted the
2031
+ full checkpoint-390 eval chain.
2032
+ - Submitted jobs:
2033
+ - conversion: `2364958` (`tohf_td_l11_390`, `debug`, running at check)
2034
+ - full lm-eval: `2364959` (`eval_td_l11_390_full`, dependency pending)
2035
+ - intrinsic BPC: `2364960` (`bpc_td_l11_390`, dependency pending)
2036
+ - new-token diagnostics: `2364961` (`diag_td_l11_390`, dependency pending)
2037
+ - Eval output root:
2038
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000390_full`
2039
+
2040
+ Interpretation:
2041
+
2042
+ - The resumed 2B TD run has reached the next planned decision checkpoint.
2043
+ - Eval automation is live after the xfer watcher handoff.
2044
+ - At the observed speed, training itself is still on track to finish near
2045
+ `2026-05-24 12:32 CEST`; checkpoint-390 results should land earlier, after
2046
+ conversion plus the full eval queue clears.
2047
+
2048
+ ## Checkpoint 390 eval completed and copied locally
2049
+
2050
+ Timestamp: `2026-05-24T08:13:32Z`
2051
+
2052
+ Eval jobs all completed successfully:
2053
+
2054
+ - conversion `2364958`: `COMPLETED`, `0:0`, elapsed `00:01:09`
2055
+ - full lm-eval `2364959`: `COMPLETED`, `0:0`, elapsed `00:44:40`
2056
+ - tokenizer-fair BPC `2364960`: `COMPLETED`, `0:0`, elapsed `00:01:52`
2057
+ - new-token diagnostics `2364961`: `COMPLETED`, `0:0`, elapsed `00:02:03`
2058
+
2059
+ Compact artifacts copied locally:
2060
+
2061
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000390_results.json`
2062
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000390_run_metadata.json`
2063
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000390_tokenizer_fair_metrics.json`
2064
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000390_new_token_diagnostics.json`
2065
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000390_digest.md`
2066
+
2067
+ Checkpoint-390 headline:
2068
+
2069
+ - Intrinsic/new-token recovery continued to improve:
2070
+ - BPC `0.5670 -> 0.5399` vs checkpoint `260`
2071
+ - new-target top-1 `0.3517 -> 0.3787`
2072
+ - greedy new-token utilization `0.196 -> 0.260`
2073
+ - Greek classification/reading signals were split:
2074
+ - improved vs `260`: `arc_challenge_mt_el` `+0.0119`,
2075
+ `belebele_ell_Grek` `+0.0311`, `global_mmlu_full_el` `+0.0073`
2076
+ - weaker vs `260`: `xnli_el` `-0.0116`,
2077
+ `include_base_44_greek_few_shot_en` `-0.0127`,
2078
+ `global_piqa_completions_ell_grek` `-0.0100`
2079
+ - largest regression: `xquad_el` exact match `-0.0437`, F1 `-0.0509`
2080
+ - General-preservation signals remain mixed:
2081
+ - MMLU/global-MMLU slightly recovered vs `260`
2082
+ - HellaSwag remains slightly above checkpoint `130`
2083
+ - ARC-Challenge, XNLI, and XCOPA are below checkpoint `260`
2084
+
2085
+ Training state at the same poll:
2086
+
2087
+ - Resume job `2357705` remained `RUNNING`.
2088
+ - Latest parsed line: iteration `413/476`, consumed tokens `1.732B`,
2089
+ timestamp `2026-05-24 10:12:42 CEST`, loss `2.544199`, throughput
2090
+ `7866.3` tokens/sec/GPU, skipped iterations `0`, NaN iterations `0`.
2091
+ - Training ETA from that line: `2:19:57`, putting finish near
2092
+ `2026-05-24 12:32-12:35 CEST`.
2093
+
2094
+ Interpretation:
2095
+
2096
+ - The checkpoint-390 evidence strengthens the case that TD is learning the new
2097
+ rows and Greek tokenization target.
2098
+ - It does not yet settle the production decision because XQuAD dropped sharply
2099
+ and general preservation remains mixed. Final checkpoint `476`, plus planned
2100
+ checkpoint `455`, should decide whether this is transient or a real
2101
+ over-training/preservation issue.
2102
+
2103
+ ## Checkpoint 455 reached and eval chain submitted
2104
+
2105
+ Timestamp: `2026-05-24T09:54:09Z`
2106
+
2107
+ Training/checkpoint state:
2108
+
2109
+ - Resume job `2357705` remains `RUNNING`.
2110
+ - Checkpoint training line: iteration `455/476`, consumed tokens `1.908B`,
2111
+ timestamp `2026-05-24 11:46:02 CEST`, loss `2.518627`, throughput
2112
+ `7869.0` tokens/sec/GPU, skipped iterations `0`, NaN iterations `0`.
2113
+ - Checkpoint `iter_0000455` saved successfully and tracker advanced to `455`.
2114
+ - Training continued past the checkpoint; latest poll after save was
2115
+ iteration `457/476`, consumed tokens `1.917B`, timestamp
2116
+ `2026-05-24 11:50:29 CEST`, loss `2.532910`, skipped iterations `0`,
2117
+ NaN iterations `0`.
2118
+
2119
+ Eval automation:
2120
+
2121
+ - Backup watcher `2357766` detected the complete checkpoint and submitted the
2122
+ checkpoint-455 full eval chain.
2123
+ - Submitted jobs:
2124
+ - conversion: `2366619` (`tohf_td_l11_455`), completed `0:0`,
2125
+ elapsed `00:01:12`
2126
+ - full lm-eval: `2366621` (`eval_td_l11_455_full`), running at last check
2127
+ - intrinsic BPC: `2366622` (`bpc_td_l11_455`), completed `0:0`,
2128
+ elapsed `00:01:40`
2129
+ - new-token diagnostics: `2366623` (`diag_td_l11_455`), completed `0:0`,
2130
+ elapsed `00:02:21`
2131
+
2132
+ Quick intrinsic/diagnostic artifacts copied locally:
2133
+
2134
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000455_tokenizer_fair_metrics.json`
2135
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000455_new_token_diagnostics.json`
2136
+
2137
+ Quick checkpoint-455 intrinsic comparison vs checkpoint `390`:
2138
+
2139
+ - BPC: `0.539879 -> 0.532765`
2140
+ - NLL/token: `2.537096 -> 2.503662`
2141
+ - new-target top-1: `0.378668 -> 0.384541`
2142
+ - new-target top-10: `0.612043 -> 0.617435`
2143
+ - new-vocab probability mass: `0.344027 -> 0.341786`
2144
+ - greedy new-token utilization: `0.260 -> 0.200`
2145
+
2146
+ Interpretation:
2147
+
2148
+ - Intrinsic likelihood and new-target ranking continued improving at
2149
+ checkpoint `455`.
2150
+ - Greedy new-token utilization dropped from checkpoint `390`; this is only a
2151
+ tiny prompt-sample diagnostic, so the full downstream eval remains the
2152
+ decision-useful signal.
2153
+ - Next actions are to wait for full eval `2366621`, copy/digest the complete
2154
+ checkpoint-455 evidence, then continue to final checkpoint `476`.
2155
+
2156
+ ## Checkpoint 455 full eval completed and copied locally
2157
+
2158
+ Timestamp: `2026-05-24T10:38:37Z`
2159
+
2160
+ Full eval `2366621` completed successfully:
2161
+
2162
+ - state `COMPLETED`, exit `0:0`, elapsed `00:46:46`
2163
+ - result JSON:
2164
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000455_full/results_2026-05-24T12-37-56.749011.json`
2165
+
2166
+ Compact artifacts copied locally:
2167
+
2168
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000455_results.json`
2169
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000455_run_metadata.json`
2170
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000455_tokenizer_fair_metrics.json`
2171
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000455_new_token_diagnostics.json`
2172
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000455_digest.md`
2173
+
2174
+ Checkpoint-455 full-eval headline:
2175
+
2176
+ - Intrinsic recovery continued vs checkpoint `390`:
2177
+ - BPC `0.5399 -> 0.5328`
2178
+ - new-target top-1 `0.3787 -> 0.3845`
2179
+ - new-target top-10 `0.6120 -> 0.6174`
2180
+ - Greek downstream vs checkpoint `390`:
2181
+ - recovered: `xnli_el` `+0.0060`, `xquad_el` F1 `+0.0067`,
2182
+ `global_mmlu_full_el` `+0.0006`,
2183
+ `include_base_44_greek_few_shot_en` `+0.0036`
2184
+ - moved down: `arc_challenge_mt_el` `-0.0094`,
2185
+ `belebele_ell_Grek` `-0.0122`,
2186
+ `global_piqa_completions_ell_grek` `-0.0100`
2187
+ - Same-checkpoint bakeoff comparison:
2188
+ - TD beats vanilla on Belebele, XQuAD F1, HellaSwag, and MMLU.
2189
+ - Vanilla still beats TD on Greek ARC, Greek MMLU, and the base-44 Greek
2190
+ aggregate.
2191
+
2192
+ Training/final checkpoint state at the same close-watch poll:
2193
+
2194
+ - Final training reached checkpoint `476/476` at `2026-05-24 12:32:40 CEST`.
2195
+ - Checkpoint `iter_0000476` saved successfully and tracker advanced to `476`.
2196
+ - Final eval chain submitted:
2197
+ - conversion `2367150`
2198
+ - full lm-eval `2367151`
2199
+ - intrinsic BPC `2367152`
2200
+ - new-token diagnostics `2367153`
2201
+
2202
+ Interpretation:
2203
+
2204
+ - Checkpoint `455` keeps TD ahead of ReTok/Centroid and confirms the new-token
2205
+ learning path is alive.
2206
+ - It does not clearly beat vanilla on the aggregate Greek criteria we care
2207
+ about. Final checkpoint `476` is now the decisive comparison point.
2208
+
2209
+ ## Final checkpoint 476 reached and quick checks passed
2210
+
2211
+ Timestamp: `2026-05-24T10:44:52Z`
2212
+
2213
+ Training completed the planned 2B TD run:
2214
+
2215
+ - Final training line: iteration `476/476`, consumed tokens `1.996B`,
2216
+ timestamp `2026-05-24 12:32:40 CEST`, loss `2.496399`, throughput
2217
+ `7874.3` tokens/sec/GPU, skipped iterations `0`, NaN iterations `0`.
2218
+ - Checkpoint `iter_0000476` saved successfully.
2219
+ - Checkpoint tracker advanced to `476`.
2220
+
2221
+ Final eval chain submitted and quick side checks completed:
2222
+
2223
+ - conversion `2367150`: `COMPLETED`, `0:0`, elapsed `00:01:09`
2224
+ - full lm-eval `2367151`: `RUNNING` at last check
2225
+ - intrinsic BPC `2367152`: `COMPLETED`, `0:0`, elapsed `00:01:44`
2226
+ - new-token diagnostics `2367153`: `COMPLETED`, `0:0`, elapsed `00:02:00`
2227
+
2228
+ Quick final artifacts copied locally:
2229
+
2230
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000476_tokenizer_fair_metrics.json`
2231
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000476_new_token_diagnostics.json`
2232
+
2233
+ Quick intrinsic/diagnostic comparison vs checkpoint `455`:
2234
+
2235
+ - BPC: `0.532765 -> 0.531084`
2236
+ - NLL/token: `2.503662 -> 2.495764`
2237
+ - new-target top-1: `0.384541 -> 0.386419`
2238
+ - new-target top-10: `0.617435 -> 0.619114`
2239
+ - new-vocab probability mass: `0.341786 -> 0.342453`
2240
+ - greedy new-token utilization: `0.200 -> 0.208`
2241
+
2242
+ Interpretation:
2243
+
2244
+ - The 2B TD training run itself is complete and clean.
2245
+ - Intrinsic/new-token learning continued improving through the final
2246
+ checkpoint.
2247
+ - The production decision still waits on full final lm-eval `2367151`, because
2248
+ checkpoint `455` remained mixed against vanilla on aggregate Greek tasks.
2249
+
2250
+ ## Final checkpoint 476 full eval completed
2251
+
2252
+ Timestamp: `2026-05-24T11:30:00Z`
2253
+
2254
+ Final full lm-eval completed cleanly:
2255
+
2256
+ - full lm-eval `2367151`: `COMPLETED`, `0:0`, elapsed `00:45:27`
2257
+ - generation phase completed at `2026-05-24 13:20:27 CEST`
2258
+ - aggregated results and per-task samples were written under:
2259
+ `/capstor/scratch/cscs/fffoivos/runs/eval/td_full25_layer11_2b_20260523T165038Z/iter_0000476_full`
2260
+
2261
+ Compact local artifacts copied:
2262
+
2263
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000476_results.json`
2264
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000476_run_metadata.json`
2265
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000476_tokenizer_fair_metrics.json`
2266
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000476_new_token_diagnostics.json`
2267
+ - `eval/live_summaries/td_full25_layer11_2b_20260523T165038Z_iter0000476_digest.md`
2268
+
2269
+ Final same-checkpoint TD-vs-vanilla highlights:
2270
+
2271
+ - TD wins: `belebele_ell_Grek` `+0.0144`, `xquad_el` F1 `+0.0161`,
2272
+ `mmlu` `+0.0161`, `hellaswag` `+0.0011`, `xnli` `+0.0024`, `xcopa`
2273
+ `+0.0045`; `arc_challenge` is tied.
2274
+ - Vanilla wins: `arc_challenge_mt_el` `+0.0171`, `global_mmlu_full_el`
2275
+ `+0.0355`, `include_base_44_greek_few_shot_en` `+0.0145`,
2276
+ `global_piqa_completions_ell_grek` `+0.0500`, and `global_mmlu`
2277
+ `+0.0075`.
2278
+
2279
+ Final intrinsic/tokenizer-local highlights:
2280
+
2281
+ - TD beats ReTok on heldout BPC: `0.5311` vs `0.5739`, and strongly beats
2282
+ Centroid: `0.8994`.
2283
+ - TD beats ReTok on new-target top-1/top-10: `0.3864`/`0.6191` vs
2284
+ `0.3497`/`0.5772`.
2285
+ - ReTok still has higher five-prompt greedy new-token utilization: `0.3580`
2286
+ vs TD `0.2080`; this is a weak diagnostic, but worth keeping visible.
2287
+ - TD/ReTok/Centroid preserve the Greek compression gain:
2288
+ `3.973` chars/token and `1.735` tokens/word, versus vanilla at `2.557`
2289
+ chars/token and `2.693` tokens/word.
2290
+
2291
+ Interpretation:
2292
+
2293
+ - TD is the strongest extended-tokenizer path and is no longer a failed
2294
+ initialization: it beats ReTok/Centroid broadly and recovers the new-token
2295
+ objective over the 2B challenger.
2296
+ - It still does not clearly beat the vanilla production path on the aggregate
2297
+ Greek/downstream preservation criteria. The safest default for the 15-20B CPT
2298
+ run remains vanilla unless compression/new-token behavior is promoted to a
2299
+ primary objective.
provenance/token-distillation/TOKEN_DISTILLATION_PLAN.md ADDED
@@ -0,0 +1,773 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Token Distillation Parallel Plan
2
+
3
+ Status: draft execution plan, 2026-05-22
4
+
5
+ Purpose: prepare a bounded Token Distillation challenger that can start quickly if
6
+ the current Vanilla / ReTok / Centroid bakeoff leaves ReTok promising but
7
+ under-initialized. This is a companion plan, not a change to the running
8
+ three-arm bakeoff.
9
+
10
+ Primary external references:
11
+
12
+ - Paper: https://arxiv.org/abs/2505.20133
13
+ - Official implementation: https://github.com/konstantinjdobler/token-distillation
14
+
15
+ ## 1. Decision Summary
16
+
17
+ Token Distillation is feasible for Apertus without inventing a new method. The
18
+ earlier "bracketed" status was too conservative if it was based on tied-vs-untied
19
+ embedding concerns. The official implementation learns input embeddings by
20
+ hidden-state distillation and has explicit untied-output handling through a
21
+ next-token CE path.
22
+
23
+ What is still real is integration risk:
24
+
25
+ - Apertus uses untied `embed_tokens` and `lm_head`, so `E` and `U` must be
26
+ checked independently.
27
+ - Our tokenizer is an extended BPE tokenizer with fixed production IDs, not a
28
+ base tokenizer plus `add_tokens(...)`.
29
+ - The distillation run must preserve xIELU and QK-Norm values and must survive
30
+ the same HF -> Megatron -> HF roundtrip gate as the other arms.
31
+ - Layer choice is not a free constant: the paper defaults to the final hidden
32
+ layer, while the package README says earlier target layers around the
33
+ one-third mark can work better. We will run a small layer pilot that tests
34
+ both: final layer plus the package-suggested one-third layer. If the
35
+ logit-lens/tuned-lens probe in Section 6.1 suggests a different layer, test
36
+ that as well.
37
+
38
+ ## 2. When To Start
39
+
40
+ Do not interrupt the running three-arm bakeoff. Token Distillation can begin
41
+ once all of these are true:
42
+
43
+ 1. The current bakeoff has reached the final scheduled checkpoint, or the
44
+ final checkpoint is safely saved and the remaining work is only evaluation.
45
+ 2. ReTok is not already decisively beaten by Vanilla on both Greek BPC and the
46
+ new-token diagnostics.
47
+ 3. One spare GH200 node can be used without delaying final bakeoff evals.
48
+ 4. The implementation runs first on a small token subset and passes all
49
+ preservation gates in Section 8.
50
+
51
+ Recommended trigger:
52
+
53
+ - Run the Token Distillation pilot if ReTok has healthy new-token behavior
54
+ but still trails Vanilla on Greek BPC or downstream Greek tasks.
55
+ - Do not run it if Vanilla is clearly best and ReTok has weak new-token use;
56
+ in that case the tokenizer extension itself is probably not helping enough.
57
+
58
+ ## 3. Experiment Shape
59
+
60
+ Name: `retok_td`
61
+
62
+ The experiment is not "TD from scratch." It is ReTok plus a TD refinement:
63
+
64
+ - Logical teacher: the original-tokenization path through the same frozen
65
+ Apertus weights. In implementation this does not need to be a second 8B model
66
+ in memory: the extended student can run the unmerged/base-tokenized sequence
67
+ under `torch.no_grad()` because all original rows and transformer weights are
68
+ frozen and identical to the base model.
69
+ - Student: ReTok-initialized HF checkpoint with the exact modern-only extended
70
+ tokenizer used by the current bakeoff.
71
+ - Input objective: hidden-state MSE between teacher runs using base-tokenized
72
+ spans and student runs using the corresponding single new token.
73
+ - Output objective: next-token CE on the merged sequence, with gradients allowed
74
+ to update only the new `lm_head` rows.
75
+ - Trainable parameters: new input rows and new output rows only.
76
+ - Frozen parameters: all transformer blocks, all original embedding/output
77
+ rows, xIELU scalars, QK-Norm weights, RMSNorm weights, and all other base
78
+ model parameters.
79
+
80
+ This isolates the question: "Does TD improve ReTok's placement of the new rows?"
81
+
82
+ ## 4. Model Format Plan
83
+
84
+ Token Distillation should run in HF format, not Megatron format.
85
+
86
+ Inputs:
87
+
88
+ - Teacher/reference HF model: the unmodified Apertus HF base, used for validation
89
+ and optional row-diff checks. Do not require it to stay resident during TD
90
+ training unless an implementation choice truly needs it.
91
+ - Teacher tokenizer: base 131,072-token Apertus tokenizer.
92
+ - Physical training model: ReTok HF init checkpoint for the modern-only
93
+ 148,480-token tokenizer. This model serves both the merged/student path and
94
+ the unmerged/logical-teacher path.
95
+ - Student tokenizer: exact shipped extended tokenizer from
96
+ `03_3_cscs_experiments_kickoff/ship/apertus_greek_modern_only_148480/`.
97
+
98
+ Outputs:
99
+
100
+ - HF checkpoint for `retok_td`.
101
+ - Exact student tokenizer copied through unchanged.
102
+ - A manifest with model paths, tokenizer hash, base vocab size, extended vocab
103
+ size, trainable row ranges, layer choice, data slice, and source commit of
104
+ the Token Distillation code.
105
+ - Megatron TP=2 `torch_dist` checkpoint produced with the same R17-preserving
106
+ conversion path used by the current bakeoff.
107
+
108
+ Sensitive point: do not let the reference implementation call
109
+ `target_tokenizer.add_tokens(...)` for production. That would create added-token
110
+ behavior and may change IDs/segmentation relative to our BPE extension. Patch or
111
+ wrap the implementation so the student tokenizer is loaded directly and treated
112
+ as authoritative.
113
+
114
+ Second sensitive point: do not load two 8B models just because the method is
115
+ described as teacher/student. The official training loop uses one extended model
116
+ for both the merged and unmerged forwards; preserve that memory-efficient shape
117
+ unless a later validation test proves it insufficient.
118
+
119
+ ## 5. Token Mapping And Data
120
+
121
+ For each new token ID in the extended tokenizer:
122
+
123
+ 1. Decode the token string using the same ByteLevel-aware readable-token logic
124
+ used in the tokenizer audits.
125
+ 2. Tokenize the same surface string with the base tokenizer to get the teacher
126
+ phrase IDs.
127
+ 3. Tokenize it with the extended tokenizer and verify it maps to exactly the
128
+ intended new token ID in the relevant context.
129
+ 4. Mine snippets from the CPT Greek corpus where that surface string occurs.
130
+
131
+ Use real corpus snippets, not generated snippets, for the main run. Generated
132
+ snippets are acceptable only as a fallback for very low-coverage tokens in a
133
+ separate flagged bucket.
134
+
135
+ Initial data budgets:
136
+
137
+ - Smoke: 256 to 512 high-frequency new tokens, 20 to 50 snippets per token.
138
+ - Layer pilot: 1,024 to 2,048 tokens, 50 snippets per token, comparing
139
+ last-layer TD against the package-suggested one-third-depth layer and, if
140
+ available, the Section 6.1 probe-suggested layer.
141
+ - Full modern challenger: all 17,408 modern new tokens at the paper-fast
142
+ `25`-snippet setting first. The `100`-snippet setting is supported by the
143
+ coverage result, but is a follow-up only if the fast full-token checkpoint
144
+ clears gates while leaving quality ambiguous.
145
+ - Production polytonic extension: only after the modern path passes; then repeat
146
+ for the additional +5,120 polytonic tokens.
147
+
148
+ Coverage policy:
149
+
150
+ - Do not silently skip tokens. Emit `coverage.json` with requested snippets,
151
+ found snippets, used snippets, and fallback action per token.
152
+ - Split results into enough-coverage and low-coverage buckets during analysis.
153
+ - If more than 10 percent of new tokens have fewer than 20 real snippets, stop
154
+ before full TD and inspect the token inventory/corpus mismatch.
155
+
156
+ ## 5.1 Firing Prepass On The Exact 2B Dataset
157
+
158
+ Before any GPU TD run, count actual new-token firings and usable snippets on the
159
+ exact normalized text/parquet slice that produced the 2B-token bakeoff dataset.
160
+ Do this on the pre-packed source text, not only on Megatron `.bin`, because TD
161
+ needs text spans and 50-token contexts.
162
+
163
+ This is a CPU/I/O job and should run as a sidecar only after the current bakeoff
164
+ final checkpoints are safely saved, or while final downstream evals are running.
165
+ Do not let it compete with training checkpoint saves or packed eval cache reads.
166
+
167
+ Output artifact:
168
+
169
+ - `td_coverage_prepass.jsonl`: one row per new token.
170
+ - `td_coverage_summary.json`: aggregate thresholds and recommended action.
171
+ - `td_snippet_index/`: sampled snippet references or extracted tokenized snippets
172
+ keyed by `new_token_id`.
173
+
174
+ Required row fields:
175
+
176
+ - `new_token_id`
177
+ - `token_string`
178
+ - `base_subtoken_ids`
179
+ - `base_subtoken_len`
180
+ - `extended_firings`
181
+ - `raw_surface_occurrences` where cheap to compute
182
+ - `usable_snippets_25`
183
+ - `usable_snippets_100`
184
+ - `docs_with_firing`
185
+ - `example_snippet_refs`
186
+ - `status`: `enough_100`, `enough_25`, `low_20_24`, `low_lt20`,
187
+ `zero`, or `mismatch`
188
+ - `recommended_action`: `td_100`, `td_25`, `keep_retok`,
189
+ `generated_fallback_candidate`, or `inspect`
190
+
191
+ Counting rule:
192
+
193
+ - A firing means the extended tokenizer actually emits that new token ID.
194
+ - Merge ancestry does not count.
195
+ - A surface substring does not count unless it corresponds to the emitted
196
+ new-token span under the extended tokenizer.
197
+ - For each firing span, tokenize the same surface span with the base tokenizer
198
+ to build the logical-teacher sequence.
199
+
200
+ Decision gate:
201
+
202
+ - If at least 90 percent of new tokens have `usable_snippets_100 >= 100`, mark
203
+ the corpus as high-coverage, but still run the first full-token challenger at
204
+ the paper-fast 25-snippet setting unless a prior full-token fast run has
205
+ already passed.
206
+ - If at least 90 percent have `usable_snippets_25 >= 25`, run TD at the paper's
207
+ fast 25-snippet setting and keep a flagged tail strategy.
208
+ - If more than 10 percent have `usable_snippets_25 < 25`, do not launch full TD.
209
+ Inspect whether the problem is dataset coverage, tokenizer/string decoding, or
210
+ low-value tail tokens.
211
+ - Tokens with `usable_snippets < 20` keep ReTok by default. Generated snippets
212
+ are allowed only as a separately reported fallback bucket.
213
+ - Tokens with `status = mismatch` block the TD run until the tokenizer/span
214
+ mapping is fixed.
215
+
216
+ ## 6. Layer Choice
217
+
218
+ **Default candidate for Apertus 8B: last layer (`target_layer = -1`). Required comparison candidate: package-suggested one-third-depth layer. No broad sweep.**
219
+
220
+ The paper argues for last layer as the conservative, portable default. Direct quotes:
221
+
222
+ > *"In practice, we simply use the last layer's hidden state but analyze this choice in Section 5.3."* — paper §3.2, p.4.
223
+
224
+ > *"For our main experiments, we choose to keep the last layer because this choice does not necessitate a model-specific sweep over target layers. Also, the last layer is a principled choice, as it guarantees that no subtoken interactions that are only modeled in later layers are excluded from the objective."* — paper §5.3 (per a second-pass review of the paper's layer-choice analysis).
225
+
226
+ The argument for the last layer is **conservative-and-correct**: any way the original subtoken sequence influenced downstream computation must, by construction, have shown up by the final hidden state. Matching there upper-bounds the objective. But the package README is explicit that earlier target layers around the one-third mark can yield better results in many cases. That means we should not pick last-layer only without checking the package-suggested alternative.
227
+
228
+ Implication for Apertus 8B specifically: run a **small** layer pilot, not a sweep.
229
+
230
+ - Candidate A: `target_layer = -1`, the paper-default last layer.
231
+ - Candidate B: `target_layer = ceil(num_hidden_layers / 3)` in HF hidden-state tuple indexing after confirming Section 16 Q11. For Apertus-8B's 32 transformer layers, expected candidate is `target_layer = 11` (roughly after the first third of blocks).
232
+ - Candidate C: if the Section 6.1 logit-lens/tuned-lens probe suggests a materially different detokenization layer `L*`, test that layer too. If `L*` is within +/-1 of Candidate B, do not add a third candidate.
233
+ - Implementation note from the first live smoke: the vendored package does **not** ship a separate layer-suggestion tool. Its actionable upstream guidance is the README note that one-third-depth target layers can work better than the last layer. Therefore the first layer pilot should compare Candidate A and Candidate B only, unless we have a well-defined Apertus-specific probe result.
234
+
235
+ Selection rule:
236
+
237
+ - Choose the candidate with better heldout Greek BPC/NLL and D1/D2/D4/D5 on the layer-pilot subset.
238
+ - If differences are within noise, choose last layer for portability and to avoid model-specific overfitting.
239
+ - Do not test more than three candidates unless the first TD run fails in a way that is clearly layer-specific.
240
+
241
+ For polytonic Phase 2 specifically (the +5,120 polytonic tokens, deferred per §5): **also default to last layer**. The detokenization machinery for unfamiliar diacritic-heavy sequences plausibly uses more late-layer compute than for typical modern words — the model has to reassemble diacritic + base-char interactions it saw less cleanly during pretraining. The conservative default earns its keep here.
242
+
243
+ ### 6.1 Layer-suggestion probe to find the "detokenization layer" L*
244
+
245
+ Before the layer pilot, run a cheap logit-lens probe to get our best Apertus-specific guess for where the residual stream finishes resolving multi-token Greek words into a single contextual representation:
246
+
247
+ 1. Take a held-out set of multi-token Greek words from our corpus (~200-500 words that the base tokenizer fragments into 2-5 subpieces).
248
+ 2. Run them through the **original Apertus base** (no TD), recording the residual stream at every layer at the position of the LAST subtoken.
249
+ 3. Project each layer's residual through Apertus's `lm_head` (logit lens) OR a learned per-layer linear probe (tuned lens — Belrose et al. 2023, *Eliciting Latent Predictions from Transformers with the Tuned Lens*, arXiv:2303.08112).
250
+ 4. Find the layer index `L*` where the top-1 projection first reliably matches the whole-word identity (i.e., where the model has "decided" what whole word it's processing).
251
+
252
+ For Llama-class 32-layer 8B models, `L*` is reportedly in the first third of layers (per a Kaplan et al. 2025 "Tokens to Words" line of work — **citation needs verification before being load-bearing**). For Apertus, plausibly similar (`L* ≈ 8-12` of 32), but Apertus's xIELU + QK-Norm could shift this; the only way to know is to run the probe.
253
+
254
+ **Cost:** one forward pass per probe sample × 32 layers of projection ≈ trivial on one GH200 (< 30 min for 500 words).
255
+
256
+ **What it gives us:** an *informative diagnostic* for the paper-quality writeup ("here's where Apertus does detokenization"), and a sanity check that last-layer TD isn't wasted compute (if `L* = 5` and we train at layer 32, we're propagating identical signal through 27 layers per backward pass). If we find `L* = 25+`, that's also informative — Apertus's late layers may be more LM-head-staging than Llama's, in which case last-layer is doubly the right choice.
257
+
258
+ **Action:** run the cheap logit-lens version after the first successful TD smoke
259
+ and before the layer pilot. If it suggests a clear `L*` that differs from the
260
+ one-third-depth layer, include `L*` as Candidate C in the layer pilot. The
261
+ heavier tuned-lens version remains optional and should not block the modern TD
262
+ path. Tracked as task TD7 in §9.
263
+
264
+ ## 7. Output Embeddings
265
+
266
+ Apertus has untied embeddings, so `lm_head` rows must be handled deliberately.
267
+
268
+ Primary output strategy:
269
+
270
+ - Start from the ReTok `lm_head` rows already present in the student checkpoint.
271
+ - During TD, train only the new output rows with next-token CE.
272
+ - Keep original output rows frozen and verify they are unchanged exactly.
273
+ - Keep the input hidden-state MSE and output CE accounting separate in logs.
274
+
275
+ Fallbacks:
276
+
277
+ - If CE makes output norms unstable, train only input rows and keep ReTok output
278
+ rows fixed.
279
+ - If ReTok output rows look bad before TD, use subtoken-mean output initialization
280
+ from the base output matrix, then CE-train only new output rows.
281
+
282
+ Avoid using a tied-embedding shortcut. It does not apply to Apertus.
283
+
284
+ ## 8. Verification Gates
285
+
286
+ The TD run is not usable until all of these pass.
287
+
288
+ Tokenizer gates:
289
+
290
+ - Extended tokenizer files are byte-identical before and after TD.
291
+ - Base special token IDs and extended special token IDs match the current
292
+ bakeoff tokenizer manifests.
293
+ - New token IDs equal the planned contiguous range.
294
+ - A fixed sample of Greek strings tokenizes exactly as in the ReTok arm.
295
+
296
+ Model gates:
297
+
298
+ - Original input rows unchanged exactly.
299
+ - Original output rows unchanged exactly.
300
+ - New input/output rows finite, nonzero, and within documented norm envelopes.
301
+ - xIELU scalar tensors unchanged exactly.
302
+ - QK-Norm tensors unchanged exactly.
303
+ - Logits on prompts that do not use new tokens remain unchanged or within a
304
+ documented numerical tolerance.
305
+
306
+ Roundtrip gates:
307
+
308
+ - Convert HF `retok_td` -> Megatron TP=2 with the R17-preserving path.
309
+ - Convert back or run the existing roundtrip verifier.
310
+ - Require zero or near-zero diff for xIELU, QK-Norm, and unchanged base rows.
311
+ - Run a short Megatron load/train smoke before queueing any CPT-scale arm.
312
+
313
+ Quality gates:
314
+
315
+ - Pre-CPT BPC should improve over ReTok on the heldout Greek slice.
316
+ - D1/D2/D4/D5 should improve or remain healthy versus ReTok.
317
+ - No obvious English retention regression on the small prompt/eval sanity set.
318
+ - If pre-CPT gates are neutral, do not spend a full 2B-token arm on TD.
319
+
320
+ ## 9. Implementation Tasks
321
+
322
+ Task TD0 - vendor or pin reference code:
323
+
324
+ - Pin the official Token Distillation repo commit in a manifest.
325
+ - Do not rely on a moving GitHub checkout from inside a Slurm job.
326
+
327
+ Task TD1 - exact-tokenizer adapter:
328
+
329
+ - Add a wrapper that accepts separate teacher and student tokenizers.
330
+ - Disable `add_tokens(...)` in the production path.
331
+ - Build explicit mapping:
332
+ `new_token_id -> token_string -> base_phrase_ids -> student_token_id`.
333
+
334
+ Task TD2 - local corpus snippet source:
335
+
336
+ - Implement a local JSONL/parquet snippet miner over the existing CPT corpus
337
+ slice.
338
+ - Cache snippets in a reusable artifact keyed by tokenizer hash and corpus hash.
339
+ - First mode is the Section 5.1 firing prepass: count actual extended-token
340
+ firings and usable snippets on the exact 2B bakeoff text slice, then produce
341
+ `td_coverage_prepass.jsonl`, `td_coverage_summary.json`, and
342
+ `td_snippet_index/`.
343
+
344
+ Task TD3 - embedding-only trainer:
345
+
346
+ - Load the ReTok HF student once and use it for both the merged/student forward
347
+ and the unmerged/logical-teacher forward.
348
+ - Freeze all non-new rows and all transformer parameters.
349
+ - Backprop hidden-state MSE to new input rows.
350
+ - Backprop CE to new output rows only.
351
+ - Emit loss, norm, gradient, and coverage telemetry.
352
+
353
+ Task TD4 - pilot runs:
354
+
355
+ - Run smoke on 256 to 512 high-frequency new tokens.
356
+ - Only choose smoke tokens from `status in {enough_100, enough_25}` in the
357
+ Section 5.1 prepass.
358
+ - Run the Section 6.1 logit-lens probe to get a candidate detokenization layer
359
+ `L*`.
360
+ - Run a layer pilot on 1,024 to 2,048 tokens comparing:
361
+ - `target_layer=-1` (paper default),
362
+ - `target_layer=ceil(num_hidden_layers / 3)` (package README suggestion;
363
+ expected Apertus-8B value: `11` after Q11 indexing confirmation),
364
+ - `target_layer=L*` if the probe suggests a materially different layer.
365
+ - Pick the output strategy before full TD.
366
+
367
+ Task TD5 - full modern TD:
368
+
369
+ - Run all 17,408 modern new tokens first at `snippets_per_token=25`.
370
+ - Keep `snippets_per_token=50/100` as a follow-up quality-budget test, not the
371
+ first full-token cost event.
372
+ - Save HF checkpoint, manifest, coverage, and diagnostics.
373
+ - Run verification gates.
374
+
375
+ Task TD6 - optional fourth CPT arm:
376
+
377
+ - Only after TD5 passes, convert to Megatron and run a short CPT smoke.
378
+ - If smoke passes and pre-CPT diagnostics beat ReTok, submit `retok_td` as a
379
+ separate fourth arm or a shorter challenger run.
380
+
381
+ ## 10. Risks And Mitigations
382
+
383
+ Tokenizer mismatch:
384
+
385
+ - Highest-risk integration point. Mitigation: never regenerate the tokenizer;
386
+ load the exact extended tokenizer and assert ID/sample-tokenization equality.
387
+
388
+ Layer mis-selection:
389
+
390
+ - Mitigation: test the paper-default last layer against the package-suggested
391
+ one-third-depth layer and, if available, the tool/probe-suggested layer.
392
+ Keep the candidate set tiny to avoid turning TD into a layer-sweep project.
393
+
394
+ Output-row instability:
395
+
396
+ - Mitigation: keep ReTok `U` as the starting point, CE-train only new rows, and
397
+ fall back to fixed ReTok `U` if norms or logits become unstable.
398
+
399
+ Silent base-model drift:
400
+
401
+ - Mitigation: exact row-diff checks after every pilot and full run.
402
+
403
+ xIELU/QK-Norm drift:
404
+
405
+ - Mitigation: freeze all non-embedding parameters and reuse the R17 roundtrip
406
+ verifier.
407
+
408
+ Coverage skew:
409
+
410
+ - Mitigation: coverage manifest, frequency buckets, and a hard stop if too many
411
+ tokens lack real snippets.
412
+
413
+ Resource overuse:
414
+
415
+ - Mitigation: one-node pilots first; do not queue a full fourth arm before the
416
+ current bakeoff result is interpretable.
417
+
418
+ ## 11. Expected Cost
419
+
420
+ Order-of-magnitude expectation:
421
+
422
+ - smoke: less than 1 node-hour,
423
+ - layer pilot: 1 to 2 node-hours,
424
+ - full modern TD: roughly 5-7 wall hours for the first full-token 25-snippet
425
+ challenger on one GH200-class process; more if run at 50/100 snippets,
426
+ - optional CPT challenger: same training cost shape as one current bakeoff arm.
427
+
428
+ The TD preparation is worth doing now because implementation and verification
429
+ can be made ready without spending the CPT-scale cost event.
430
+
431
+ > Compute reality check (paper, page 4): *"These restrictions ensure that our method is quick to run, initializing 2,500 new tokens on a single GPU in under 10 minutes."* (1× H100 80GB, AdamW, 25 snippets × 50 ctx tokens.) Our live Apertus layer pilot, however, is the better planning anchor: `1,020` trained tokens × `50` snippets at layer 11 took `1,966.9s`. Scaling that to `17,392` trainable tokens at `25` snippets gives roughly **4.7 wall hours** for the fast full-token run; scaling to `100` snippets gives roughly **18-19 wall hours**. Because Clariden normal nodes expose 4 GPUs and have a 12h limit, the first full-token TD challenger should be `25` snippets. A 50/100-snippet run is a separate follow-up, not the first full-token cost event.
432
+
433
+ ---
434
+
435
+ ## 12. Apertus-specific considerations
436
+
437
+ These are questions about how Apertus's architectural quirks interact with the official TD implementation. Each is tagged with priority and a `Resolution` line that gets filled in once verified.
438
+
439
+ ### A1. Position-encoding asymmetry between teacher and student sequences (RoPE phase shift)
440
+
441
+ **The mechanism.** When the teacher reads the unmerged sequence `[ctx_L, s1, ..., sk, ctx_R]` and the student reads the merged sequence `[ctx_L, T, ctx_R, PAD × (k-1)]`, the RoPE phase at every position *after* the merged-phrase position differs by `(k-1)` between teacher and student. Apertus uses RoPE with llama3-style scaling factor 8.0, so the phase difference manifests in the q/k rotations the model applies before the dot product.
442
+
443
+ **Resolution (from official code, train_loop.py:67-89):** the implementation **does** pad the merged sequence with PAD tokens at the end to match the unmerged length. Both teacher and student therefore see the same total sequence length, but the meaningful tokens occupy different positions:
444
+ - Teacher: real tokens at positions `[0, L+k+R-1]`, no padding.
445
+ - Student: real tokens at positions `[0, L+R-1]`, PAD at positions `[L+R, L+k+R-1]`.
446
+
447
+ The MSE loss is taken over positions selected by `unmerged_to_merged_mask == 1` (teacher) and `merged_seq != pad_id` (student). These two selections produce the same number of positions. The compare position for the assigned-phrase's last subtoken (teacher position `L+k-1`) is matched to the student position `L` (the single new token).
448
+
449
+ **Implication:** the RoPE phases at the compare positions for `ctx_R` tokens *differ between teacher and student* by `(k-1)`. The implementation accepts this and trusts that the model's downstream layers still produce comparable hidden states. The paper does the same. For modern Greek where `k` is typically 2-5, this is mild; for polytonic where `k` can be larger (more aggressive subword fragmentation), it's more pronounced. **Status: accepted as the paper's design**; we don't need to change it, but it's worth flagging as a known approximation.
450
+
451
+ **Action:** none for modern bakeoff. For the polytonic Phase 2 sub-plan (§9.5 below), consider whether `k > 8` tokens should be excluded from the TD set.
452
+
453
+ ### A2. Cached teacher hidden states — optional optimization, not first implementation
454
+
455
+ The official `train_loop.py:282-285` runs the teacher forward fresh on every epoch under `torch.no_grad()`. The teacher is frozen, so its hidden states for each `(snippet, target_position)` pair are **fixed across all epochs**. The plan should add caching:
456
+
457
+ - After dataloader construction, do one teacher forward pass over the whole dataset, save `og_hiddens[mask==1]` to disk keyed by snippet hash + target layer.
458
+ - During the training loop, skip the teacher forward entirely; read cached hiddens.
459
+
460
+ **Cache footprint:** ~17,408 tokens × 100 snippets × `~50` positions × 4096 dim × bf16 ≈ **700 GB per target layer**. Too big for one node's RAM and large enough that random per-batch reads could become an I/O problem if the dataloader shuffles globally.
461
+
462
+ If we want a tighter cache: store only the positions used by the loss (mask=1 positions), which is at most `~50` per snippet. Same order of magnitude.
463
+
464
+ **Cache key must include:** teacher checkpoint hash, dtype (bf16/fp32), `attn_implementation` (sdpa/flash-attn-2), `target_layer`, RoPE config, NFC version of the snippet text. Invalidation must trigger a fresh cache.
465
+
466
+ **Speedup:** potentially useful when repeating the same data/layer across several
467
+ LR or batch-size probes. For the first one-epoch run, caching may not beat the
468
+ simplicity of recomputing the teacher forward, especially if cache reads become
469
+ random.
470
+
471
+ **Action:** do **not** make caching a blocker for TD1-TD5. Implement uncached
472
+ first, then add a cache only if the layer pilot repeats the same target layer or
473
+ the teacher forward is empirically dominating wall time.
474
+
475
+ ### A3. NFC normalization on snippets — must match the corpus we trained on
476
+
477
+ `apertus_fidelity_checklist.md` V9: the CPT corpus is NFC-normalized in place by `normalize_nfc.sh`. The TD snippet miner must read from the **post-normalize parquet** (`cpt/selected_after_apertus_and_internal_dedup.parquet` after job 2335826), not the pre-normalize version. Any TD that conflates the two will see surface-string mismatches (e.g., NFD-decomposed Greek diacritics will not match new-token strings whose tokenizer was trained on NFC).
478
+
479
+ **Action:** assert in the snippet miner that the corpus was last modified after the normalize_nfc job's recorded timestamp; refuse to run if not.
480
+
481
+ ### A4. Mixed-precision recipe for TD
482
+
483
+ The official code uses `torch.autocast("cuda", dtype=torch.bfloat16)` with `mixed_precision=True`. This matches Apertus's bf16-main / fp32-master-grads pretraining recipe. **Recommendation:** keep the default. AdamW moment buffers are fp32 by default in PyTorch; with `weight_decay=0` (paper default) this is identical to Apertus's optimizer state for the trainable rows.
484
+
485
+ ### A5. Apertus-overlap-drop applied to the CPT corpus — soft consideration
486
+
487
+ The CPT corpus has `apertus_overlap_drop_docs.parquet` rows removed (the docs that overlap with Apertus's pretraining set). The TEACHER (Apertus base) has *seen* those dropped docs and presumably has sharper hidden states on them. Snippets drawn from the post-drop CPT corpus give a slightly noisier teacher.
488
+
489
+ For the modern-Greek TD, this is a minor effect — the corpus is still ~5B Greek tokens, plenty for snippets. But for the polytonic Phase 2 (where the corpus is thinner anyway), drawing some snippets from the pre-drop set could help. The pre-drop corpus exists at `/iopsstor/scratch/cscs/fffoivos/cpt_corpus/nanochat/data/*.parquet` (before the apertus-overlap drop overlay was applied).
490
+
491
+ **Action:** for modern TD, ignore. For polytonic TD, consider adding ~10-20% snippets from the pre-drop corpus to the pool.
492
+
493
+ ### A6. Polytonic snippet sourcing — a separate Phase 2 data problem
494
+
495
+ The plan's §5 mentions polytonic TD as a follow-on. The modern-only CPT corpus has almost no polytonic content (the corpus was Greek-modern-targeted). For the +5,120 polytonic tokens, snippets must come from elsewhere:
496
+
497
+ - The polytonic-marked subsets of the original GlossAPI corpus (pre-Apertus-overlap-drop).
498
+ - External polytonic sources: ancient/koine Wikipedia, Project Gutenberg Greek, the patristic / classical Greek corpus subsets.
499
+ - The `legacy/corpus_clean_normalization/` polytonic-flagged documents (per `glossapi_corpus_cli/pipeline.py`'s `derive_historical_flag`).
500
+
501
+ **Action:** Phase 2 TD requires a polytonic snippet pull as a prerequisite. Add as a separate work item; do not block modern TD on it.
502
+
503
+ ---
504
+
505
+ ## 13. Paper and repo specifics — verifications from the research pass
506
+
507
+ Each row records what the plan was assuming, what the paper / repo actually says, and the resulting action.
508
+
509
+ ### P1. The implementation uses `model.forward()` outputs, not custom attention hooks
510
+
511
+ **Plan assumption:** "Use `model.forward()` rather than reimplemented attention math" (per `cpt_plan.md v0.7 §13`'s general advice).
512
+
513
+ **Verified:** `train_loop.py:278` calls `model(merged_seq, output_hidden_states=True)`, `train_loop.py:285` calls `model(unmerged_seq, output_hidden_states=True)` under `torch.no_grad()`. The hidden states are read from `outputs["hidden_states"][target_layer]`. Standard HuggingFace API. **Compatible with Apertus's xIELU + QK-Norm** because both happen inside `model.forward()`.
514
+
515
+ **Action:** none. The QK-Norm worry from v0.6 §13 is genuinely moot for hidden-state TD.
516
+
517
+ ### P2. Learning rate, optimizer, scheduler, step count
518
+
519
+ **Plan assumption:** "LR ~1e-3 to 1e-4 AdamW, ~500-2000 steps".
520
+
521
+ **Verified from paper (p.4) + code (`train_loop.py:250-259`):**
522
+ - Optimizer: AdamW, `weight_decay=0.0`.
523
+ - Scheduler: **constant LR** (code comment: *"paper used linear warmup + decay but constant works fine and might even converge faster"*). The paper itself says *"linear warmup, constant rate"*.
524
+ - Default LR in code: `1e-4`. README: *"learning rates around 1e-4 work well for many models"*.
525
+ - Paper: *"For fair comparison, we sweep for the best learning rate for all methods that require a learning rate."* — they sweep per method.
526
+ - Step count: not directly named; controlled by `epochs * len(dataloader)`. Default `epochs=1`. With 17,408 tokens × 100 snippets / batch_size 16 ≈ 109,000 batches per epoch.
527
+
528
+ **Action:** start with `lr=1e-4, epochs=1, weight_decay=0, scheduler=constant` (paper + repo defaults). LR sweep is a Phase 2 optimization if results are off; do not sweep on the first run.
529
+
530
+ ### P3. Snippet count + length recommendations
531
+
532
+ **Plan assumption:** "100 snippets per token, snippet length not specified."
533
+
534
+ **Verified from paper (p.4) + README:**
535
+ - **Fast setting (used for main results):** `snippets_per_token=25, snippet_len=50`. *"2,500 new tokens on a single GPU in under 10 minutes"*.
536
+ - **Larger compute budget (paper §5.2):** `snippets_per_token=100, snippet_len=50`.
537
+ - README: *"We observe diminishing returns for scaling `snippet_len` beyond 50 and `snippets_per_token` beyond 100."*
538
+
539
+ **Recommendation after live Apertus pilot:** start the full-token challenger at
540
+ the paper-fast budget (`25, 50`). The coverage result says the corpus can
541
+ support `100` snippets for 99.82 percent of the new tokens, but the live runtime
542
+ estimate puts `100` snippets at roughly 18-19 wall hours on one GPU process.
543
+ Use `50/100` only after the fast full-token checkpoint is evaluated.
544
+
545
+ **Action:** set `snippets_per_token=25, snippet_len=50` for the first full
546
+ modern run. Keep `snippets_per_token=100` as a documented optional high-budget
547
+ follow-up.
548
+
549
+ ### P4. Snippet sampling and batch composition
550
+
551
+ **Verified from code (`tokdist.py:191-278`):**
552
+ - **Pattern matching:** uses Aho-Corasick (`ahocorasick.py`) to find all occurrences of new-token surface strings in a tokenized corpus, in a single linear pass.
553
+ - **Snippet size:** `offset_before = snippet_len*2`, `offset_after = snippet_len*2` (so candidates have up to ~4× snippet_len + pattern_len tokens), then truncated to exactly `snippet_len` with the pattern roughly centered.
554
+ - **Filtering:** if fewer than `snippets_per_token` usable snippets are found, the token is **skipped** (printed to stdout, returned in the `skipped` list). The plan's §5 coverage policy already mirrors this.
555
+ - **Shuffling:** `random.shuffle(truncated)` before truncation to `snippets_per_token`, to avoid sort-order bias.
556
+ - **BOS prefix:** `bos_prefix = [bos_token_id]` is prepended to every snippet.
557
+ - **Batches:** dataset is flat (one entry per (snippet, assigned_phrase) pair), dataloader uses `shuffle=True` so batches mix tokens.
558
+
559
+ **Action:** mirror this snippet-mining logic in our adapter; replace `HFDataSource.load_dataset(...)` with PyArrow streaming over our local CPT corpus parquets (the official code only knows how to read HF datasets).
560
+
561
+ ### P5. Loss normalization
562
+
563
+ **Verified from code (`train_loop.py:288-300`):**
564
+ - `torch.nn.functional.mse_loss(...)` with default `reduction='mean'` over `(num_selected_positions × hidden_dim)`.
565
+ - Teacher selection: `og_hiddens[unmerged_to_merged_mask == 1]` — selects positions of unmerged tokens NOT in the merged phrase, plus the LAST subtoken position of the merged phrase. Sum equals length of merged seq (before padding).
566
+ - Student selection: `token_distillation_hiddens[merged_seq != pad_id]` — non-pad positions. Same length.
567
+
568
+ **Implication:** the loss is averaged over **every position that the model produces in the merged sequence**, not only the new-token position. This means the gradient signal includes "your downstream context also has to match the teacher's downstream context after the substitution." Subtle but important: it pushes the new embedding to be compatible with *what the teacher does next*, not just to match the teacher *at the new token position*.
569
+
570
+ This is consistent with the paper's intuition (§3.1): *"the multiple subtokens t1, ..., tn have on other tokens attending to them in succeeding positions after seeing t*"*.
571
+
572
+ **Action:** preserve this behaviour in our adapter; do not "fix" it to be new-token-position-only.
573
+
574
+ ### P6. Output embeddings for untied models
575
+
576
+ **Plan assumption:** train new U rows via NTP on the same data.
577
+
578
+ **Verified from paper (p.4) + code (`train_loop.py:339-348`):**
579
+ - Paper: *"Since our method backpropagates gradients back from the hidden states, we do not learn output embeddings with our distillation-based objective."*
580
+ - Paper: *"In practice, for learning output embeddings, we can simply add a next-token prediction objective just for the output embeddings at a minimal computational overhead."*
581
+ - Code: separate `torch.autograd.backward([ce_loss], inputs=[lm_head.weight], retain_graph=True)` for output, and `loss.backward(inputs=[input_embeddings.weight])` for input.
582
+ - The original-row gradients are zeroed for both input and output (`train_loop.py:354-359`) before the optimizer step, so base rows never drift.
583
+
584
+ **Important nuance from paper (p.7):** *"a subtoken attention distillation objective is superior to next-token prediction for learning new token embeddings, the combination via a sum of the two objectives (Token Distillation + NTP) generally yields worse results than Token Distillation alone."* — so combining input MSE + input NTP on the SAME parameter is worse. The split (MSE on E, CE on U) is the right pattern.
585
+
586
+ **Action:** use `learn_output_with_ce=True` for the untied Apertus path. Train new U rows via the CE-on-merged-logits-of-next-token path. The CE loss is only computed on the merged sequence, not the unmerged.
587
+
588
+ ### P7. The "earlier target layer" claim — verified, but paper still defaults to LAST
589
+
590
+ **Plan assumption (§6):** *"the authors note that roughly one-third-depth layers often work better."*
591
+
592
+ **Verified from paper (p.4, §3.2 last paragraph):** *"In practice, we simply use the last layer's hidden state but analyze this choice in Section 5.3."*
593
+
594
+ **Verified from code (`tokdist.py:67`):** `target_layer: int = -1` default. Comment: *"or e.g. an early layer such as 6 or 7"* — a hint, not a claim of superiority.
595
+
596
+ **Verified from paper §5.3:** the authors report a slight downward trend as the
597
+ target approaches the last layer, and say earlier layers can improve results and
598
+ speed. They still use the last layer for main experiments because it avoids a
599
+ model-specific sweep and is principled: later subtoken interactions cannot be
600
+ excluded.
601
+
602
+ **Action:** run the small layer pilot in §6 before full modern TD: final layer
603
+ vs the one-third-depth layer, plus the probe-suggested layer if different.
604
+ Candidate selection uses the cheap gates in §6, not the full downstream suite.
605
+
606
+ ---
607
+
608
+ ## 14. Implementation specifics for our setup
609
+
610
+ ### 14.1 We must NOT use the high-level `TokenDistillation.run(...)` entry point
611
+
612
+ The official `run()` method calls `target_tokenizer.add_tokens(new_tokens)` (`tokdist.py:97, 523`) which **appends** new tokens to the source tokenizer. This is incompatible with our setup because:
613
+
614
+ - Our extended tokenizer (`apertus_greek_modern_only_148480/`) was built by **merge-rule extension** (`model.vocab` + `model.merges`), not by `add_tokens(...)`.
615
+ - The new-token IDs in our tokenizer occupy the range `[131072, 148480)` in a specific order determined by our BPE merge order.
616
+ - If `add_tokens(...)` is called on the original base tokenizer with our new-token strings, the resulting IDs will match our planned range *only if* the order matches — which is fragile and unverified.
617
+
618
+ **Action:** drop into the lower-level `train_embeddings()` function directly, with:
619
+ - Student `model = AutoModelForCausalLM.from_pretrained(retok_init_checkpoint)` — already has the 148,480 vocab.
620
+ - Student tokenizer loaded directly from our shipped extended bundle.
621
+ - Skip `_build_target_tokenizer`; skip `extend_pretrained_with_tokens_and_embeddings`.
622
+ - Construct `phrase_to_new_id` and `assigned_new_phrases` from our **known** new-token IDs.
623
+
624
+ ### 14.2 Snippet miner: PyArrow batch-streaming over local parquet, not HF datasets
625
+
626
+ The official `build_snippets_for_tokens_from_hf` uses `datasets.load_dataset(streaming=True)` over an HF dataset. Our corpus is local parquet on iopsstor. Replacement plan:
627
+
628
+ - Read `cpt/selected_after_apertus_and_internal_dedup.parquet` via `pyarrow.parquet.ParquetFile(...).iter_batches(batch_size=N)`.
629
+ - Tokenize each batch with the **base 131,072 tokenizer** (same as paper's "source tokenizer").
630
+ - Run Aho-Corasick (use the official `ahocorasick.py`, no need to reimplement) over the tokenized stream.
631
+ - Reuse the truncation + filtering logic from `build_snippets_for_tokens_from_hf` (offset_before, offset_after, snippet_len, snippets_per_token).
632
+ - Cache the tokenized parquet on iopsstor scratch keyed by `tokenizer.name_or_path + parquet hash`.
633
+
634
+ The tokenized-corpus cache (from the paper's `_tokenize_dataset_if_needed`) is **a real time-saver**: tokenizing the 47M-row Greek pool once with the base tokenizer takes ~30-60 min on one node. Don't re-tokenize per TD run.
635
+
636
+ ### 14.3 Frozen-parameter table (replaces vague "freeze everything else" in §3)
637
+
638
+ | Tensor | Trained? | Notes |
639
+ |---|---|---|
640
+ | `model.embed_tokens.weight[131072:148480, :]` | **YES** (MSE-on-hiddens loss) | new input rows |
641
+ | `lm_head.weight[131072:148480, :]` | **YES** (CE loss on merged seq) | new output rows |
642
+ | `model.embed_tokens.weight[:131072, :]` | NO (grad zeroed after backward) | base input rows, verified unchanged at end |
643
+ | `lm_head.weight[:131072, :]` | NO (grad zeroed after backward) | base output rows, verified unchanged at end |
644
+ | `model.layers.*.self_attn.{q,k,v,o}_proj.weight` | NO | attention QKV + output |
645
+ | `model.layers.*.self_attn.{q_norm, k_norm}.weight` | NO | QK-Norm (R17 sensitive — DO NOT TOUCH) |
646
+ | `model.layers.*.mlp.{up_proj, down_proj}.weight` | NO | MLP (xIELU lives between these) |
647
+ | `model.layers.*.mlp.act_fn.{alpha_p, alpha_n, beta, eps}` | NO | xIELU scalars (R17 sensitive — DO NOT TOUCH) |
648
+ | `model.layers.*.input_layernorm.weight` | NO | RMSNorm input |
649
+ | `model.layers.*.post_attention_layernorm.weight` | NO | RMSNorm post-attn |
650
+ | `model.norm.weight` | NO | final RMSNorm |
651
+
652
+ The official `train_embeddings` already implements this freeze pattern correctly via `param.requires_grad=False` for everything except E/U, and zeros gradients on the original rows after backward. **Verify post-TD that R17-sensitive tensors are unchanged** (use `verify_hf_roundtrip.py`'s R17/xIELU/QK-Norm diff functions).
653
+
654
+ ### 14.4 Padding direction — RIGHT-pad, not left
655
+
656
+ Code (`train_loop.py:106-140`) right-pads the merged sequence to the unmerged length. The loss explicitly excludes pad positions on both teacher and student sides. This is correct *for this objective* — the trailing PAD positions are not used by the loss, and causal attention from non-pad positions doesn't attend forward to pad.
657
+
658
+ **Action:** when porting to our adapter, keep right-padding. Don't try to "fix" it to left-padding (which would break the position-mapping logic).
659
+
660
+ ### 14.5 Single-GPU vs DDP
661
+
662
+ Paper experiments are on 1× H100. Clariden normal nodes expose four GH200 GPUs
663
+ as a node unit; there is no true single-GPU partition. **Recommendation:
664
+ single-process TD for the first full-token run to stay close to the official
665
+ implementation, but pack any genuinely useful independent comparison into the
666
+ same allocation.** For the immediate full-token challenger, that means layer 11
667
+ as the selected candidate and optionally last-layer as the conservative backup,
668
+ both at 25 snippets. Do not invent DDP or row-sharded merge machinery unless
669
+ single-process runtime becomes the blocker.
670
+
671
+ DDP correctness check for TD: with batches shuffled across tokens (§P4), each DDP rank sees a random sample of tokens per batch, so gradients average correctly over the embedding matrix. Verify the gradient zeroing-for-base-rows happens *after* gradient reduction (otherwise the AllReduce would distribute the zeroed grads, which is fine but the assertion at end-of-training would need adjustment).
672
+
673
+ ### 14.6 Compute budget — concrete numbers
674
+
675
+ Using live Apertus pilot scaling:
676
+
677
+ - Layer-11 pilot: 1,020 trained tokens × 50 snippets, batch 8, elapsed
678
+ `1,966.9s`.
679
+ - First full-token challenger: 17,392 trained tokens × 25 snippets. Linear
680
+ scaling estimate: about **4.7 wall hours**.
681
+ - Full-token 50 snippets: about **9.3 wall hours**.
682
+ - Full-token 100 snippets: about **18.6 wall hours**, beyond normal-partition
683
+ walltime for a single process.
684
+
685
+ Recommend setting walltime to 8h for the first full-token 25-snippet run, or
686
+ 12h if packing a same-allocation last-layer backup.
687
+
688
+ ---
689
+
690
+ ## 15. Tools and libraries we will use
691
+
692
+ | Concern | Tool | Notes |
693
+ |---|---|---|
694
+ | Model loading | `transformers` (pinned to uenv's 4.57.0) | has `ApertusForCausalLM` |
695
+ | TD library code | clone of `konstantinjdobler/token-distillation` at a pinned commit | use `train_embeddings()`, `ahocorasick.py`, and `utils.py`; **skip** `tokdist.TokenDistillation` |
696
+ | DDP / mixed precision | `accelerate` (already in our lm_eval target install) | wrap the train loop |
697
+ | Corpus streaming | `pyarrow.parquet.iter_batches` | already battle-tested by `mix_builder.py` |
698
+ | Tokenizer cache | `datasets.Dataset.save_to_disk` (already pulled into the uenv) | reuse the paper's caching pattern |
699
+ | Checkpoint surgery / verification | `safetensors` + our existing `verify_hf_roundtrip.py` | mandatory post-TD check (gate §8) |
700
+ | HF → Megatron conversion | `tools/checkpoint/convert.py` with our `loader_apertus_hf.py` | proven on R17 patch jobs 2341182/2341239/2341241 |
701
+ | Telemetry / loss curves | TensorBoard (already wired in bakeoff_train.sbatch) | optional but cheap |
702
+ | **Layer-suggestion probe (§6.1)** | [`AlignmentResearch/tuned-lens`](https://github.com/AlignmentResearch/tuned-lens) — Belrose et al. 2023, arXiv:2303.08112 | logit-lens is free (project residual through Apertus's existing `lm_head`); tuned-lens trains a small per-layer affine probe (~minutes per layer on one GH200). For finding a candidate `L*`, logit-lens is sufficient on first pass. If it suggests a layer materially different from the one-third-depth package suggestion, include that layer in the pilot. |
703
+ | Multi-token Greek word inventory (for the §6.1 probe) | one-pass scan of the corpus + base tokenizer | reuse the Aho-Corasick driver from TD2; just emit the set of `(word, k)` where `k > 1` is the base-tokenizer fragment count |
704
+
705
+ **Pinning the TD repo:** the official repo is small (~10 Python files) and stable. Vendor at a pinned commit hash into `subprojects/.../init_bakeoff/td/external/token_distillation/` so a moving GitHub HEAD can't break our run. Pin should land before TD0.
706
+
707
+ ---
708
+
709
+ ## 16. Open questions that still need answers
710
+
711
+ Carried forward; will be resolved before TD1 lands.
712
+
713
+ | # | Question | Source | How to answer |
714
+ |---|---|---|---|
715
+ | Q1 | Does the paper / package actually suggest testing an earlier layer? | paper §5.3 + package README | RESOLVED: yes. Paper keeps last layer as the default to avoid model-specific sweeps; package README says earlier target layers around the one-third mark can yield better results in many cases. Plan tests both. |
716
+ | Q2 | What's the empirical coverage for our 17,408 new tokens against the 5B-Greek-token CPT corpus? | local Aho-Corasick prepass | run a one-pass coverage check before launching TD; gate as per §5 of the plan |
717
+ | Q3 | How many tokens fragment into k > 8 base subtokens (where RoPE phase shift may be too large)? | base tokenizer applied to all 17,408 new-token surface strings | trivial offline check; report distribution of k |
718
+ | Q4 | Does the paper sweep batch_size, or is `batch_size=1` (repo default) actually their setting? | paper appendix C / repo example.py | check arxiv:2505.20133 appendix C; example.py uses default which is `batch_size=1` — but the paper says *"We set the batch size to optimize throughput"* (p.4), so they presumably batch in practice |
719
+ | Q5 | Does the bakeoff differentiate ReTok vs Centroid enough on §5.3 D5/D2/D7 diagnostics to gate TD on (per `SUGGESTIONS.md §7.2`)? | bakeoff arm eval | answered by reading per-arm §5.3 diagnostics after each arm's mid-training checkpoint |
720
+ | Q6 | For polytonic TD (Phase 2), what snippet sources have enough polytonic content? | survey of available polytonic corpora | external work; descope from modern-only TD plan |
721
+ | Q7 | Does the TD-trained checkpoint round-trip through `tools/checkpoint/convert.py` with **zero R17 drift** (since we never touched xIELU/QK-Norm during TD)? | run R17 verifier post-TD | mechanical; reuse `verify_hf_roundtrip.py` |
722
+ | Q8 | When we combine TD (input MSE) with NTP (output CE) on Apertus's untied head, does the NTP loss act as a regularizer (paper p.7 says yes for tied) or as a confound (paper p.7 says yes for untied combination on same param)? | the paper warns about TD+NTP on the SAME param being worse; our case is TD on E + NTP on U, which is the paper's recommended pattern | implementation Q only — code already does this split correctly per `learn_output_with_ce=True` |
723
+ | Q9 | Should the TD eval gate (§8 "Pre-CPT BPC should improve over ReTok") use a numerical threshold (e.g. >2× bootstrap stderr of ReTok)? | calibrate from V4-HF bootstrap CIs | depends on `compute_bootstrap_cis.py` results on V4 |
724
+ | Q10 | Verify the "Kaplan et al. 2025 *Tokens to Words*" citation referenced in §6.1 before relying on the "L* ≈ first-third of layers" empirical claim | arXiv / Google Scholar search | one-off literature check; if the citation doesn't pan out, the §6.1 probe still works as a self-contained logit-lens diagnostic — we just lose the prior expectation about where L* should land |
725
+ | Q11 | Confirm the HF hidden-state indexing convention for `target_layer = -1` on Apertus. HF returns `outputs.hidden_states[0] = embedding output` and `outputs.hidden_states[N] = output of transformer block N`. For Apertus (32 layers), `hidden_states[-1]` should be the final transformer block's output BEFORE final RMSNorm and `lm_head`. Confirm this matches what the paper means by "last layer." | quick `model.forward(..., output_hidden_states=True)` shape check on Apertus + cross-check vs `tokdist.py` reading `hidden_states[target_layer]` | mechanical; trivial offline check. If the paper means "post-final-norm representation" we'd need `target_layer = -1` to be the post-norm layer or apply the final norm manually before comparing. |
726
+
727
+ ---
728
+
729
+ ## 17. Notes from the research pass (paper + repo, 2026-05-22)
730
+
731
+ Direct quotes from arxiv:2505.20133 v3 + the official repo, kept here so we don't re-derive them.
732
+
733
+ **Method (paper §3.2, p.4):**
734
+
735
+ > *"We learn e* by minimizing the mean-squared error between hidden states for a given target layer l: min_{e*} E_{s∼S} [ 1/|M(s_τ, s_τ*)| · Σ_{(i,j)∈M(s_τ,s_τ*)} || H_{e*}^{(l)}(s_τ*)_i − H^{(l)}(s_τ)_j ||²₂ ]. In practice, we simply use the last layer's hidden state but analyze this choice in Section 5.3."*
736
+
737
+ **Hyperparameters (paper §3.3, p.4):**
738
+
739
+ > *"We employ a simple setup and use the AdamW (Kingma & Ba 2017; Loshchilov & Hutter 2019) optimizer for all trainable parameters. We set the batch size to optimize throughput and run all experiments on Nvidia H100 80GB GPUs. We do not use weight decay and maintain a constant learning rate with a linear warmup. For fair comparison, we sweep for the best learning rate for all methods that require a learning rate. Since our method is aimed to serve as an initialization rather than as full-scale further training, we restrict the number of example sequences to a maximum of 25 per target token and truncate to a context length of 50 tokens. These restrictions ensure that our method is quick to run, initializing 2,500 new tokens on a single GPU in under 10 minutes."*
740
+
741
+ **Output embeddings (paper §3.3, p.4):**
742
+
743
+ > *"Since our method backpropagates gradients back from the hidden states, we do not learn output embeddings with our distillation-based objective. In fact, this is not possible, as our new tokens are not part of the original model that serves as the "teacher". In practice, for learning output embeddings, we can simply add a next-token prediction objective just for the output embeddings at a minimal computational overhead or freely combine our method with any other method for initializing output embeddings."*
744
+
745
+ **Snippet retrieval (paper §3.3, p.4):**
746
+
747
+ > *"Our main approach is to simply retrieve snippets that contain our target tokens from a domain-specific or general corpus. This can be implemented efficiently using the algorithm proposed by Aho & Corasick (1975). Then we can truncate the snippets to a small window around our target token to optimize computational efficiency."*
748
+
749
+ **Freezing original embeddings (paper §5.1, p.7):**
750
+
751
+ > *"Note that for Token Distillation, we only optimize new token embeddings. Therefore, we also compare against the NTP baseline, where we similarly optimize only the new token embeddings."*
752
+
753
+ **Combining TD + NTP on the same parameter is worse than TD alone (paper §5.1, p.7):**
754
+
755
+ > *"In support of our argument that a subtoken attention distillation objective is superior to next-token prediction for learning new token embeddings, the combination via a sum of the two objectives (Token Distillation + NTP) generally yields worse results than Token Distillation alone."*
756
+
757
+ > *"However, we can add a dynamic downweighting factor (see Section 4.2) to the next-token prediction objective (Token Distillation + αNTP), which mostly alleviates the negative interference while keeping the regularizing effect."*
758
+
759
+ (Implication for us: the α-NTP "regularizer" pattern is only beneficial when applied to the **input** embedding via a tied head — i.e., adds an output-loss component that backprops through the tied input/output matrix. For Apertus's *untied* setup, the equivalent is the separate CE-on-U pass we already use; we should NOT additionally add α-NTP on the input E.)
760
+
761
+ **Tied-vs-untied (paper §5.1, p.7):**
762
+
763
+ > *"Note that in Table 2, only for Llama-3.2-3B, Token Distillation obtains results that are on par with random initialization. Llama-3.2-3B(-i) are the only models in our lineup with tied embedding weights. Our objective does not explicitly enforce a bound on the norm of the new embedding, which in this case led to a failure mode of always generating a specific new embedding with very large norm."*
764
+
765
+ (Apertus is **untied**, so this failure mode doesn't apply. Confirms the bracketing was over-cautious on the tied/untied dimension.)
766
+
767
+ **Layer choice rationale (paper §5.3) — second pass:**
768
+
769
+ > *"For our main experiments, we choose to keep the last layer because this choice does not necessitate a model-specific sweep over target layers. Also, the last layer is a principled choice, as it guarantees that no subtoken interactions that are only modeled in later layers are excluded from the objective."*
770
+
771
+ > *"[Earlier target layers] can be much faster if we select early target layers. We leave further exploration of this as an exciting direction for future work."*
772
+
773
+ (§5.3 also reports a slight downward trend in quality as the target approaches the last layer — i.e., earlier layers can marginally improve. The paper still defaults to last because the marginal gain doesn't justify a broad per-model sweep. For our one-shot Apertus adaptation, §6 now runs the smallest useful check: last layer vs the package-suggested one-third-depth layer, plus the probe-suggested `L*` only if it is materially different.)
provenance/tokenizer-selection/CHOSEN_CUTOFF.md ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Chosen cutoff — 17,408 (curated + backfilled to alignment)
2
+
3
+ **Decision date**: 2026-05-18.
4
+ **Decided by**: user, based on the evidence in [`REPORT.md`](REPORT.md) and the
5
+ knee-analysis plot [`artifacts/plots/knee_analysis.png`](artifacts/plots/knee_analysis.png).
6
+ **Reviewer rounds addressed**: 2 (alignment + handoff-ambiguity).
7
+
8
+ ## The decision
9
+
10
+ | field | value |
11
+ |---|---|
12
+ | **Added units** | **17,408** |
13
+ | **Total vocab (ship)** | **148,480** = 131,072 base + 17,408 added |
14
+ | **Alignment** | 148,480 = **128 × 1160 = 256 × 580** ✓ |
15
+ | **Apertus front-end contract** | Preserved — Apertus base ids 0..131,071 unchanged verbatim |
16
+ | **Curation mechanism** | **Built directly into the tokenizer.** 69 noise tokens (`02_1_5/manifests/removal_list.jsonl` in-cutoff scope) skipped during BPE merge selection; the next 69 valid merges from c3_full backfilled to maintain 17,408 useful added tokens |
17
+ | **Cascade-skips** | **0** — none of the 17,408 backfilled merges depended on a curated merge as a sub-component |
18
+ | **Merges walked from c3_full** | 17,477 (= 17,408 accepted + 69 skipped-for-removal) |
19
+ | **Ship artifact** | [`variants/c3_added_17408_curated_padded/tokenizer.json`](variants/c3_added_17408_curated_padded/tokenizer.json) |
20
+ | **Build manifest** | [`manifests/curated_padded_at_17408_manifest.json`](manifests/curated_padded_at_17408_manifest.json) |
21
+
22
+ ## Why the backfilled tokenizer is the canonical ship
23
+
24
+ Two reviewer rounds rejected the obvious candidates:
25
+
26
+ | candidate | vocab | alignment | append-only | status |
27
+ |---|---:|:---:|:---:|---|
28
+ | Raw `c3_added_17408` (no curation) | 148,480 | ✓ 256-aligned | ✓ preserved | metrics good, but ships 69 noise tokens |
29
+ | Pruned `c3_added_17408_curated` (Option 2 of CURATION_REPORT) | 148,411 | ✗ NOT 128-aligned | ✗ ids renumbered | **rejected by reviewer round 2** — alignment + contract broken |
30
+ | **Backfilled `c3_added_17408_curated_padded`** | **148,480** | **✓ 256-aligned** | **✓ preserved** | **canonical ship artifact** |
31
+
32
+ The backfilled construction (built by [`scripts/01c_build_curated_backfilled.py`](scripts/01c_build_curated_backfilled.py))
33
+ walks c3_full's merge sequence in order, **skips** the 69 in-cutoff
34
+ ids from `02_1_5/manifests/removal_list.jsonl`, and **accepts** the
35
+ first 17,408 surviving merges. Because BPE merges only depend on
36
+ earlier merges as sub-components, the merge-graph validator runs
37
+ during build — no kept merge ends up depending on a skipped one
38
+ (measured cascade-skips at this cutoff: 0).
39
+
40
+ This makes the curation **structural**, not a runtime mask: the noise
41
+ tokens are *not in the vocab at all*, but vocab size + alignment +
42
+ Apertus base-id preservation are intact.
43
+
44
+ ## Why 17,408 (the cutoff itself)
45
+
46
+ From the 0 → 25,600 sweep at 1k step:
47
+
48
+ | criterion | result at 17,408 |
49
+ |---|---|
50
+ | Greek fertility on C3_val held-out (the decision-relevant axis) | 1.345 (−44.2 % vs apertus_base 2.41) |
51
+ | % of theoretical-max fertility improvement captured | **82.4 %** (asymptote y∞ = 1.118; full sweep at 25,600 captures 88.4 %) |
52
+ | Marginal-Δ% per added 1k | first cutoff where the next 1k buys **< 1 %** |
53
+ | TFG @ Apertus-55 | 0.11613 (vs apertus_base 0.11606; +0.06 % — basis points; the metric is structurally biased against script-isolated extensions, see `REPORT.md`) |
54
+ | Apertus alignment | 17,408 = 1024 × 17; total 148,480 = 256 × 580 ✓ |
55
+
56
+ **The fertility / knee analysis is the load-bearing argument.** The
57
+ MorphScore recall bump at 17,408 (0.689 → 0.694) is real but small
58
+ (recall is "essentially flat" 0.686–0.695 across the entire sweep);
59
+ treat it as supporting color, not an independent pillar.
60
+
61
+ The real claim: pick the cutoff where each additional 1k of vocab buys
62
+ less than 1 % of fertility improvement — that's 17,408 — and it
63
+ also happens to be Apertus-aligned, captures >80 % of the maximum
64
+ achievable Greek-fertility gain, and sits at the second MorphScore
65
+ per-word milestone (clean inflectional splits for common Greek
66
+ nominal/verbal paradigms).
67
+
68
+ ## What got curated out
69
+
70
+ The full `02_1_5/manifests/removal_list.jsonl` enumerates 104 noise
71
+ tokens. In-cutoff scope at 17,408 (ids < 148,480) is **69 ids**:
72
+
73
+ | removal_class | count | glossary category |
74
+ |---|---:|---|
75
+ | `mixed_script_artifact` | 50 | `mixed_script_token` (Greek-Latin homoglyphs + punct+Greek BPE fragments like `.Ε`, `,τι`, `/και`) |
76
+ | `pdf_postscript_glyph` | 9 | `postscript_glyph` (PDF font-glyph residue like `/Α`, `/η`) |
77
+ | `cleaner_linenewline_bpe_fragment` | 3 | `latin_acronym` (`LIN`, `ENEW`, `LINENEW` — BPE pieces of `LINENEWLINE`) |
78
+ | `latin1_utf8_mojibake` | 3 | `mojibake` (`ÉÉ`-family) |
79
+ | `cleaner_linenewline_placeholder` | 2 | `code_identifier` (`LINENEWLINE`, `NEWLINENEWLINE`) |
80
+ | `cleaner_extraction_tag` | 2 | `latin_fragment` (`-missing`, `-decoded`) |
81
+ | **total** | **69** | |
82
+
83
+ Per-id list with `decoded` strings: [`manifests/removal_mask_at_17408.jsonl`](manifests/removal_mask_at_17408.jsonl).
84
+
85
+ ## Verification — directly measured (no extrapolation)
86
+
87
+ ### Pairwise on Apertus-55 FLORES+ (TokEval, lines config)
88
+
89
+ | metric | raw 17,408 | **padded (ship)** | Δ vs raw |
90
+ |---|---:|---:|---:|
91
+ | TFG (Apertus-55, lower better) | 0.116128 | 0.116126 | −0.000002 |
92
+ | Rényi-2.5 efficiency (Apertus-55) | 8.428021 | 8.427630 | −0.000391 |
93
+ | UTF-8 completeness rate (Apertus-55) | 0.979127 | 0.979125 | −0.000002 |
94
+ | UTF-8 char split rate (Apertus-55) | 0.010320 | 0.010320 | +0.000001 |
95
+ | Fertility (Apertus-55, mean tokens/line) | 44.7535 | 44.7536 | +0.000093 |
96
+ | Compression rate (Apertus-55) | 0.022345 | 0.022345 | −0.000000 |
97
+ | Vocab utilization (Apertus-55) | 0.489278 | 0.489251 | −0.000027 |
98
+
99
+ ### MorphScore Greek (UD-derived, n=693)
100
+
101
+ | metric | raw 17,408 | **padded (ship)** | Δ vs raw |
102
+ |---|---:|---:|---:|
103
+ | recall | 0.6940 | 0.6940 | 0.0000 |
104
+ | precision | 0.6912 | 0.6912 | 0.0000 |
105
+ | mean token-char ratio | 0.3364 | 0.3357 | −0.0007 |
106
+
107
+ ### In-domain Greek held-outs (02_1_3 harness on gcloud)
108
+
109
+ | slice | raw 17,408 | **padded (ship)** | Δ vs raw |
110
+ |---|---:|---:|---:|
111
+ | C2_val — Greek word fertility | 1.3598 | 1.3591 | −0.00065 |
112
+ | C2_test — Greek word fertility | 1.4124 | 1.4118 | −0.00060 |
113
+ | C3_val — Greek word fertility | 1.3456 | 1.3450 | −0.00051 |
114
+ | C3_test — Greek word fertility | 1.4011 | 1.4007 | −0.00032 |
115
+
116
+ **Reading**: every directly-measured metric is either flat or **marginally
117
+ better** for the backfilled variant. The 69 swapped-in tokens (positions
118
+ 17,409..17,477 in c3_full's merge order) fire slightly more usefully on
119
+ real Greek than the 69 noise tokens they replaced. Direction is
120
+ consistent across all 4 in-domain Greek slices on fertility — small
121
+ magnitude but a real, structural win, not noise.
122
+
123
+ ## Embedding-budget cost
124
+
125
+ | component | per-token (BF16) | total at cutoff 17,408 |
126
+ |---|---:|---:|
127
+ | Embedding row (4096 × 2 bytes) | 8 KiB | 17,408 × 8 KiB = **136 MiB** new |
128
+ | LM head row (4096 × 2 bytes, `tie_word_embeddings=False`) | 8 KiB | 17,408 × 8 KiB = **136 MiB** new |
129
+ | **Δ vs apertus_base** | 16 KiB | **272 MiB** added (= 17,408 × 16 KiB) |
130
+ | Cumulative embed + LM head | — | 2.27 GiB (2.00 GiB Apertus base + 272 MiB added) |
131
+ | Δ as % of full 8 B model | — | ~1.7 % |
132
+
133
+ ## Downstream handoff to `02_2_tokenizer_implementation`
134
+
135
+ **Canonical contract:**
136
+
137
+ 1. Consume `variants/c3_added_17408_curated_padded/tokenizer.json`
138
+ verbatim. Vocab is 148,480 (256-aligned), ids 0..131,071 are exactly
139
+ the Apertus base, ids 131,072..148,479 are 17,408 BPE-merged Greek-
140
+ extension tokens with the 69 noise tokens filtered out at build
141
+ time.
142
+ 2. **No runtime curation logic needed.** The pruning is structural, not
143
+ a mask. `03_apertus_extension_and_embedding_adaptation` can warm-
144
+ start every added-id embedding from byte-fallback averaging without
145
+ any "skip these 69" branch.
146
+ 3. The mask manifest `manifests/removal_mask_at_17408.jsonl` is still
147
+ shipped for documentation — it tells the implementer **which 69
148
+ noise tokens were filtered out** so they appear in any future audit
149
+ trail, but it is NOT something the implementer needs to apply at
150
+ runtime.
151
+
152
+ **Alternative (do not ship)**: the pruned `c3_added_17408_curated`
153
+ variant remains on disk under `variants/`. It is an ablation artifact
154
+ only — alignment-broken and append-only-broken.
155
+
156
+ ## Post-decision firing-count attribution
157
+
158
+ After the cutoff decision, the canonical tokenizer was run over the exact
159
+ C3 BPE training corpus (`train.parquet` plus row-aligned
160
+ `train_manifest.parquet`) to measure how often every token fires in:
161
+
162
+ 1. `glossapi_nanochat_only`;
163
+ 2. `hplt_only`;
164
+ 3. `glossapi_nanochat_plus_hplt`;
165
+ 4. every exact `source_dataset`.
166
+
167
+ Completed-run summary:
168
+
169
+ - [`FIRING_COUNT_RUN_20260518.md`](FIRING_COUNT_RUN_20260518.md)
170
+ - [`FIRING_COUNT_README.md`](FIRING_COUNT_README.md)
171
+ - [`manifests/firing_count_20260518_run_summary_augmented.json`](manifests/firing_count_20260518_run_summary_augmented.json)
172
+
173
+ The compact parquet bundle is published to the Apertus-extension HF repo
174
+ under:
175
+
176
+ ```text
177
+ experiments/02_1_7_intrinsic_eval_sweep_20260518/firing_counts_c3_added_17408_curated_padded/
178
+ ```
179
+
180
+ Headline result: the 50/50 corpus is balanced by token mass
181
+ (`glossapi_nanochat_only` 49.79%, HPLT 50.21%), not by row count. All
182
+ 17,408 added tokens fire in GlossAPI-nanochat; 27 are zero in HPLT; none
183
+ are zero in the combined C3 corpus.
184
+
185
+ ## Build reproduction (deterministic)
186
+
187
+ ```bash
188
+ cd subprojects/02_1_tokenizer_experiments/02_1_7_intrinsic_eval_sweep
189
+ $VENV/python scripts/01c_build_curated_backfilled.py
190
+ ```
191
+
192
+ The builder:
193
+ 1. Loads Apertus base (`tokenizers_local/apertus_base/tokenizer.json`)
194
+ and full C3 (`tokenizers_local/c3_full/tokenizer.json`, 156,672 vocab).
195
+ 2. Reads the 104-token removal list from `02_1_5/manifests/removal_list.jsonl`.
196
+ 3. Walks c3_full added merges in order; skips those whose result is in
197
+ the removal list and cascade-skips those depending on a skipped
198
+ token; accepts the first 17,408 surviving merges.
199
+ 4. Renumbers accepted merge results to ids 131,072..148,479.
200
+ 5. Writes `variants/c3_added_17408_curated_padded/tokenizer.json` and
201
+ the build manifest.
202
+
203
+ ## Pinned ship artifact
204
+
205
+ ```
206
+ variants/c3_added_17408_curated_padded/tokenizer.json
207
+ sha256: 358ae3f29ac17c99769d6d437339e28657d5fcaed3486f8550feed3d6adfc394
208
+ vocab: 148,480 (128-aligned ✓, 256-aligned ✓)
209
+ Apertus front-end contract: PRESERVED (ids 0..131,071 verbatim)
210
+ Curation: 69 noise-token ids structurally absent (filtered at build)
211
+ Build manifest: manifests/curated_padded_at_17408_manifest.json
212
+ ```
213
+
214
+ ```
215
+ variants/c3_added_17408_curated/tokenizer.json ← ablation only, do NOT ship
216
+ vocab: 148,411 (not aligned, renumbered ids)
217
+
218
+ variants/c3_added_17408/tokenizer.json ← raw, no curation
219
+ vocab: 148,480 (aligned), but ships 69 noise tokens
220
+ ```
provenance/tokenizer-selection/CUTOFF_SWEEP_REPORT.md ADDED
@@ -0,0 +1,441 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 02_1_7 Intrinsic Eval Sweep — REPORT.md (final)
2
+
3
+ > **The cutoff decision is in [`CHOSEN_CUTOFF.md`](CHOSEN_CUTOFF.md).**
4
+ > This report is the evidence base. The ship artifact and the canonical
5
+ > handoff to `02_2_tokenizer_implementation` are documented there.
6
+
7
+ **Sweep date**: 2026-05-17 → 2026-05-18 (extended 0 → 25,600 added tokens at 1k step + curated+backfilled ship variant).
8
+ **Tokenizers**: 33 (apertus_base + 25 raw cutoff variants + 6 curated twins + 1 curated+backfilled ship variant). The 6 curated twins + the 8 past-chosen-cutoff raw variants are kept under `variants/_archive/` as evidence-only artifacts.
9
+ **Rows in merged parquet**: 178,658.
10
+ **Sources**: tokeval-lines (Apertus-55), tokeval-words (Apertus-55), our_suite_02_1_3 (in-domain Greek held-outs on gcloud), morphscore (catherinearnett/morphscore Greek UD).
11
+ **TokEval commit**: `0c4a9c641e78c8243ac753976267fd50675197cb`.
12
+
13
+ ## Headline plot — 4 metrics on one chart, in-domain
14
+
15
+ Greek fertility on C3_val (actual in-domain held-out), TFG on
16
+ Apertus-55 multilingual, MorphScore Greek recall, and added-vocab
17
+ utilization on C3_val. All four shown as % improvement over
18
+ `apertus_base`, with the sign flipped on lower-is-better metrics so
19
+ **up always means the cutoff is doing something good**.
20
+
21
+ ![headline](artifacts/plots/headline_4metric_in_domain.png)
22
+
23
+ ## Tier 1 — in-domain Greek (02_1_3 harness on gcloud)
24
+
25
+ This is the **decision-relevant** axis: actual Greek text from C2/C3
26
+ training-distribution held-outs (anti-joined, cleaned) plus 4 latest
27
+ glossAPI HF datasets. Not FLORES+. The 02_1_3 harness computes Greek-
28
+ specific metrics including space-fertility (the historical fertility
29
+ number this project has been tracking).
30
+
31
+ ### Greek word fertility per held-out slice
32
+
33
+ | variant_id | added_tokens | curated | C2_test | C2_val | C3_test | C3_val | latest_glossAPI__archetai | latest_glossAPI__artos_zois | latest_glossAPI__eellak_articles | latest_glossAPI__opengov_deliberations_v2 |
34
+ |---|---|---|---|---|---|---|---|---|---|---|
35
+ | apertus_base | 0 | | 2.5252 | 2.4228 | 2.4212 | 2.4113 | 3.2305 | 2.9122 | 2.3686 | 2.5214 |
36
+ | add_1024 | 1024 | | 2.1531 | 2.0890 | 2.1172 | 2.0799 | 2.6112 | 2.3456 | 1.9725 | 2.1126 |
37
+ | add_2048 | 2048 | | 1.9937 | 1.9315 | 1.9611 | 1.9222 | 2.4310 | 2.1844 | 1.7989 | 1.9428 |
38
+ | add_3072 | 3072 | | 1.8816 | 1.8231 | 1.8550 | 1.8102 | 2.3065 | 2.0641 | 1.6805 | 1.8217 |
39
+ | add_4096 | 4096 | | 1.8017 | 1.7408 | 1.7749 | 1.7281 | 2.2217 | 1.9848 | 1.5981 | 1.7414 |
40
+ | add_5120 | 5120 | | 1.7386 | 1.6752 | 1.7120 | 1.6608 | 2.1594 | 1.9278 | 1.5334 | 1.6706 |
41
+ | add_6144 | 6144 | | 1.6852 | 1.6238 | 1.6593 | 1.6106 | 2.1035 | 1.8698 | 1.4796 | 1.6212 |
42
+ | add_7168 | 7168 | | 1.6425 | 1.5795 | 1.6182 | 1.5668 | 2.0622 | 1.8320 | 1.4390 | 1.5727 |
43
+ | add_8192 | 8192 | | 1.6032 | 1.5413 | 1.5850 | 1.5293 | 2.0209 | 1.7983 | 1.4048 | 1.5376 |
44
+ | add_9216 | 9216 | | 1.5711 | 1.5112 | 1.5533 | 1.4975 | 1.9857 | 1.7663 | 1.3748 | 1.5018 |
45
+ | add_10240 | 10240 | | 1.5434 | 1.4859 | 1.5259 | 1.4713 | 1.9616 | 1.7426 | 1.3503 | 1.4751 |
46
+ | add_11264 | 11264 | | 1.5178 | 1.4635 | 1.5015 | 1.4475 | 1.9291 | 1.7188 | 1.3275 | 1.4496 |
47
+ | add_11264_curated | 11264 | ✓ | 1.5179 | 1.4636 | 1.5018 | 1.4477 | 1.9293 | | 1.3275 | |
48
+ | add_12288 | 12288 | | 1.4959 | 1.4413 | 1.4794 | 1.4253 | 1.9078 | 1.7006 | 1.3083 | 1.4252 |
49
+ | add_12288_curated | 12288 | ✓ | 1.4960 | 1.4414 | 1.4797 | 1.4256 | 1.9080 | | 1.3084 | |
50
+ | add_13312 | 13312 | | 1.4750 | 1.4225 | 1.4602 | 1.4061 | 1.8875 | | 1.2912 | |
51
+ | add_14336 | 14336 | | 1.4574 | 1.4042 | 1.4437 | 1.3883 | 1.8726 | | 1.2753 | |
52
+ | add_15360 | 15360 | | 1.4421 | 1.3874 | 1.4284 | 1.3723 | 1.8539 | | 1.2629 | |
53
+ | add_15360_curated | 15360 | ✓ | 1.4423 | 1.3876 | 1.4288 | 1.3727 | 1.8542 | | 1.2630 | |
54
+ | add_16384 | 16384 | | 1.4259 | 1.3728 | 1.4137 | 1.3586 | 1.8413 | | 1.2504 | |
55
+ | add_17408 | 17408 | | 1.4124 | 1.3598 | 1.4011 | 1.3456 | 1.8253 | | 1.2399 | |
56
+ | add_18432 | 18432 | | 1.3998 | 1.3478 | 1.3888 | 1.3323 | 1.8131 | | 1.2298 | |
57
+ | add_19456 | 19456 | | 1.3877 | 1.3365 | 1.3778 | 1.3208 | 1.7988 | | 1.2191 | |
58
+ | add_20480 | 20480 | | 1.3776 | 1.3263 | 1.3672 | 1.3107 | 1.7859 | | 1.2112 | |
59
+ | add_20480_curated | 20480 | ✓ | 1.3779 | 1.3264 | 1.3677 | 1.3112 | 1.7864 | | 1.2114 | |
60
+ | add_21504 | 21504 | | 1.3673 | 1.3165 | 1.3573 | 1.3013 | 1.7749 | | 1.2037 | |
61
+ | add_22528 | 22528 | | 1.3578 | 1.3074 | 1.3480 | 1.2915 | 1.7651 | | 1.1945 | |
62
+ | add_23552 | 23552 | | 1.3488 | 1.2986 | 1.3390 | 1.2831 | 1.7545 | | 1.1879 | |
63
+ | add_24576 | 24576 | | 1.3402 | 1.2907 | 1.3304 | 1.2748 | 1.7452 | | 1.1819 | |
64
+ | add_25600 | 25600 | | 1.3324 | 1.2826 | 1.3211 | 1.2671 | 1.7383 | | 1.1748 | |
65
+ | add_25600_curated | 25600 | ✓ | 1.3328 | 1.2828 | 1.3216 | 1.2676 | 1.7388 | | 1.1750 | |
66
+
67
+ ![per-slice-fertility](artifacts/plots/fertility_per_in_domain_slice.png)
68
+
69
+ ### Added-vocab utilization rate per slice
70
+
71
+ **The cutoff signal for diminishing returns**: when this drops, the
72
+ added tokens stop firing on in-domain text.
73
+
74
+ | variant_id | added_tokens | curated | C2_test | C2_val | C3_test | C3_val | latest_glossAPI__archetai | latest_glossAPI__artos_zois | latest_glossAPI__eellak_articles | latest_glossAPI__opengov_deliberations_v2 |
75
+ |---|---|---|---|---|---|---|---|---|---|---|
76
+ | add_1024 | 1024 | | 0.9980 | 0.9971 | 0.9951 | 0.9941 | 0.9844 | 0.9844 | 0.9580 | 0.9658 |
77
+ | add_2048 | 2048 | | 0.9971 | 0.9956 | 0.9932 | 0.9927 | 0.9722 | 0.9736 | 0.9575 | 0.9731 |
78
+ | add_3072 | 3072 | | 0.9941 | 0.9925 | 0.9896 | 0.9867 | 0.9639 | 0.9619 | 0.9456 | 0.9661 |
79
+ | add_4096 | 4096 | | 0.9905 | 0.9883 | 0.9851 | 0.9834 | 0.9578 | 0.9529 | 0.9282 | 0.9541 |
80
+ | add_5120 | 5120 | | 0.9891 | 0.9871 | 0.9803 | 0.9793 | 0.9453 | 0.9406 | 0.9154 | 0.9494 |
81
+ | add_6144 | 6144 | | 0.9875 | 0.9842 | 0.9761 | 0.9753 | 0.9259 | 0.9248 | 0.8984 | 0.9383 |
82
+ | add_7168 | 7168 | | 0.9845 | 0.9801 | 0.9689 | 0.9713 | 0.9106 | 0.9083 | 0.8797 | 0.9297 |
83
+ | add_8192 | 8192 | | 0.9812 | 0.9757 | 0.9608 | 0.9669 | 0.8958 | 0.8933 | 0.8569 | 0.9181 |
84
+ | add_9216 | 9216 | | 0.9776 | 0.9712 | 0.9533 | 0.9613 | 0.8800 | 0.8760 | 0.8396 | 0.9065 |
85
+ | add_10240 | 10240 | | 0.9722 | 0.9648 | 0.9466 | 0.9546 | 0.8646 | 0.8610 | 0.8190 | 0.8923 |
86
+ | add_11264 | 11264 | | 0.9688 | 0.9579 | 0.9379 | 0.9464 | 0.8507 | 0.8475 | 0.8005 | 0.8780 |
87
+ | add_11264_curated | 11264 | ✓ | 0.9693 | 0.9582 | 0.9384 | 0.9469 | 0.8512 | | 0.8010 | |
88
+ | add_12288 | 12288 | | 0.9631 | 0.9508 | 0.9272 | 0.9390 | 0.8367 | 0.8311 | 0.7827 | 0.8657 |
89
+ | add_12288_curated | 12288 | ✓ | 0.9637 | 0.9512 | 0.9277 | 0.9396 | 0.8372 | | 0.7832 | |
90
+ | add_13312 | 13312 | | 0.9564 | 0.9428 | 0.9173 | 0.9305 | 0.8239 | | 0.7620 | |
91
+ | add_14336 | 14336 | | 0.9496 | 0.9356 | 0.9058 | 0.9206 | 0.8094 | | 0.7449 | |
92
+ | add_15360 | 15360 | | 0.9412 | 0.9279 | 0.8941 | 0.9113 | 0.7953 | | 0.7277 | |
93
+ | add_15360_curated | 15360 | ✓ | 0.9418 | 0.9285 | 0.8948 | 0.9118 | 0.7959 | | 0.7280 | |
94
+ | add_16384 | 16384 | | 0.9343 | 0.9191 | 0.8851 | 0.9028 | 0.7825 | | 0.7108 | |
95
+ | add_17408 | 17408 | | 0.9282 | 0.9115 | 0.8755 | 0.8943 | 0.7706 | | 0.6945 | |
96
+ | add_18432 | 18432 | | 0.9190 | 0.9025 | 0.8628 | 0.8845 | 0.7584 | | 0.6774 | |
97
+ | add_19456 | 19456 | | 0.9107 | 0.8941 | 0.8516 | 0.8754 | 0.7477 | | 0.6621 | |
98
+ | add_20480 | 20480 | | 0.9006 | 0.8833 | 0.8389 | 0.8640 | 0.7364 | | 0.6467 | |
99
+ | add_20480_curated | 20480 | ✓ | 0.9014 | 0.8839 | 0.8397 | 0.8644 | 0.7367 | | 0.6468 | |
100
+ | add_21504 | 21504 | | 0.8922 | 0.8738 | 0.8277 | 0.8536 | 0.7255 | | 0.6328 | |
101
+ | add_22528 | 22528 | | 0.8835 | 0.8641 | 0.8165 | 0.8426 | 0.7129 | | 0.6187 | |
102
+ | add_23552 | 23552 | | 0.8744 | 0.8535 | 0.8043 | 0.8318 | 0.7020 | | 0.6056 | |
103
+ | add_24576 | 24576 | | 0.8643 | 0.8436 | 0.7931 | 0.8218 | 0.6926 | | 0.5928 | |
104
+ | add_25600 | 25600 | | 0.8540 | 0.8337 | 0.7825 | 0.8111 | 0.6837 | | 0.5811 | |
105
+ | add_25600_curated | 25600 | ✓ | 0.8547 | 0.8341 | 0.7832 | 0.8115 | 0.6841 | | 0.5811 | |
106
+
107
+ ### Chars-per-token (compression) per slice
108
+
109
+ | variant_id | added_tokens | curated | C2_test | C2_val | C3_test | C3_val | latest_glossAPI__archetai | latest_glossAPI__artos_zois | latest_glossAPI__eellak_articles | latest_glossAPI__opengov_deliberations_v2 |
110
+ |---|---|---|---|---|---|---|---|---|---|---|
111
+ | apertus_base | 0 | | 2.5272 | 2.6307 | 2.5220 | 2.6093 | 1.9618 | 2.1190 | 2.7354 | 2.4872 |
112
+ | add_1024 | 1024 | | 2.8957 | 2.9795 | 2.8053 | 2.9632 | 2.2963 | 2.5023 | 3.1155 | 2.8748 |
113
+ | add_2048 | 2048 | | 3.0882 | 3.1770 | 2.9767 | 3.1678 | 2.4146 | 2.6379 | 3.3165 | 3.0769 |
114
+ | add_3072 | 3072 | | 3.2389 | 3.3283 | 3.1048 | 3.3312 | 2.5037 | 2.7476 | 3.4750 | 3.2358 |
115
+ | add_4096 | 4096 | | 3.3559 | 3.4528 | 3.2086 | 3.4609 | 2.5693 | 2.8259 | 3.5868 | 3.3503 |
116
+ | add_5120 | 5120 | | 3.4543 | 3.5596 | 3.2951 | 3.5760 | 2.6185 | 2.8843 | 3.6816 | 3.4577 |
117
+ | add_6144 | 6144 | | 3.5429 | 3.6486 | 3.3721 | 3.6676 | 2.6660 | 2.9475 | 3.7676 | 3.5373 |
118
+ | add_7168 | 7168 | | 3.6167 | 3.7275 | 3.4344 | 3.7508 | 2.7028 | 2.9907 | 3.8373 | 3.6195 |
119
+ | add_8192 | 8192 | | 3.6871 | 3.7988 | 3.4864 | 3.8250 | 2.7385 | 3.0285 | 3.8953 | 3.6810 |
120
+ | add_9216 | 9216 | | 3.7470 | 3.8584 | 3.5380 | 3.8900 | 2.7696 | 3.0650 | 3.9468 | 3.7473 |
121
+ | add_10240 | 10240 | | 3.8004 | 3.9087 | 3.5828 | 3.9460 | 2.7910 | 3.0940 | 3.9901 | 3.7973 |
122
+ | add_11264 | 11264 | | 3.8506 | 3.9550 | 3.6242 | 3.9977 | 2.8219 | 3.1247 | 4.0310 | 3.8464 |
123
+ | add_11264_curated | 11264 | ✓ | 3.8476 | 3.9516 | 3.6189 | 3.9933 | 2.8197 | | 4.0278 | |
124
+ | add_12288 | 12288 | | 3.8950 | 4.0015 | 3.6628 | 4.0480 | 2.8423 | 3.1476 | 4.0669 | 3.8945 |
125
+ | add_12288_curated | 12288 | ✓ | 3.8918 | 3.9980 | 3.6573 | 4.0433 | 2.8401 | | 4.0635 | |
126
+ | add_13312 | 13312 | | 3.9379 | 4.0412 | 3.6963 | 4.0918 | 2.8629 | | 4.0987 | |
127
+ | add_14336 | 14336 | | 3.9747 | 4.0811 | 3.7261 | 4.1332 | 2.8769 | | 4.1289 | |
128
+ | add_15360 | 15360 | | 4.0083 | 4.1188 | 3.7552 | 4.1711 | 2.8956 | | 4.1534 | |
129
+ | add_15360_curated | 15360 | ✓ | 4.0046 | 4.1143 | 3.7493 | 4.1657 | 2.8931 | | 4.1495 | |
130
+ | add_16384 | 16384 | | 4.0438 | 4.1516 | 3.7828 | 4.2050 | 2.9085 | | 4.1785 | |
131
+ | add_17408 | 17408 | | 4.0742 | 4.1816 | 3.8070 | 4.2375 | 2.9254 | | 4.1999 | |
132
+ | add_18432 | 18432 | | 4.1028 | 4.2097 | 3.8310 | 4.2705 | 2.9380 | | 4.2235 | |
133
+ | add_19456 | 19456 | | 4.1306 | 4.2374 | 3.8536 | 4.3001 | 2.9528 | | 4.2455 | |
134
+ | add_20480 | 20480 | | 4.1545 | 4.2622 | 3.8750 | 4.3267 | 2.9655 | | 4.2617 | |
135
+ | add_20480_curated | 20480 | ✓ | 4.1499 | 4.2563 | 3.8684 | 4.3201 | 2.9624 | | 4.2572 | |
136
+ | add_21504 | 21504 | | 4.1784 | 4.2855 | 3.8943 | 4.3511 | 2.9782 | | 4.2775 | |
137
+ | add_22528 | 22528 | | 4.2010 | 4.3071 | 3.9129 | 4.3768 | 2.9885 | | 4.2972 | |
138
+ | add_23552 | 23552 | | 4.2227 | 4.3289 | 3.9320 | 4.3993 | 2.9995 | | 4.3192 | |
139
+ | add_24576 | 24576 | | 4.2438 | 4.3490 | 3.9494 | 4.4223 | 3.0097 | | 4.3320 | |
140
+ | add_25600 | 25600 | | 4.2630 | 4.3692 | 3.9684 | 4.4437 | 3.0180 | | 4.3479 | |
141
+ | add_25600_curated | 25600 | ✓ | 4.2576 | 4.3627 | 3.9614 | 4.4366 | 3.0147 | | 4.3430 | |
142
+
143
+ ## Tier 1 — paper-aligned (TokEval on Apertus-55 FLORES+)
144
+
145
+ These match the eval surface area the Apertus paper §2.2 uses; cite
146
+ for cross-paper comparison (Meister 2025 / Foroutan et al. 2025a).
147
+
148
+ ### TFG (Apertus-55 multilingual fairness)
149
+
150
+ **Lower = more fair.** U-shape with minimum at ~4k — the only metric
151
+ with a clear non-monotonic optimum on this run.
152
+
153
+ | variant_id | added_tokens | curated | value |
154
+ |---|---|---|---|
155
+ | apertus_base | 0 | | 0.1161 |
156
+ | add_1024 | 1024 | | 0.1150 |
157
+ | add_2048 | 2048 | | 0.1146 |
158
+ | add_3072 | 3072 | | 0.1144 |
159
+ | add_4096 | 4096 | | 0.1144 |
160
+ | add_5120 | 5120 | | 0.1145 |
161
+ | add_6144 | 6144 | | 0.1146 |
162
+ | add_7168 | 7168 | | 0.1148 |
163
+ | add_8192 | 8192 | | 0.1149 |
164
+ | add_9216 | 9216 | | 0.1151 |
165
+ | add_10240 | 10240 | | 0.1152 |
166
+ | add_11264 | 11264 | | 0.1154 |
167
+ | add_11264_curated | 11264 | ✓ | 0.1154 |
168
+ | add_12288 | 12288 | | 0.1155 |
169
+ | add_12288_curated | 12288 | ✓ | 0.1155 |
170
+ | add_13312 | 13312 | | 0.1157 |
171
+ | add_14336 | 14336 | | 0.1158 |
172
+ | add_15360 | 15360 | | 0.1159 |
173
+ | add_15360_curated | 15360 | ✓ | 0.1159 |
174
+ | add_16384 | 16384 | | 0.1160 |
175
+ | add_17408 | 17408 | | 0.1161 |
176
+ | add_18432 | 18432 | | 0.1162 |
177
+ | add_19456 | 19456 | | 0.1163 |
178
+ | add_20480 | 20480 | | 0.1164 |
179
+ | add_20480_curated | 20480 | ✓ | 0.1164 |
180
+ | add_21504 | 21504 | | 0.1165 |
181
+ | add_22528 | 22528 | | 0.1166 |
182
+ | add_23552 | 23552 | | 0.1167 |
183
+ | add_24576 | 24576 | | 0.1168 |
184
+ | add_25600 | 25600 | | 0.1169 |
185
+ | add_25600_curated | 25600 | ✓ | 0.1169 |
186
+
187
+ ### Fertility (FLORES+ Greek, words config)
188
+
189
+ Same shape as the in-domain fertility above but on cleaner narrower
190
+ data — values are lower (clean Greek is easier to tokenize).
191
+
192
+ | variant_id | added_tokens | curated | value |
193
+ |---|---|---|---|
194
+ | apertus_base | 0 | | 2.2041 |
195
+ | add_1024 | 1024 | | 1.9825 |
196
+ | add_2048 | 2048 | | 1.8545 |
197
+ | add_3072 | 3072 | | 1.7639 |
198
+ | add_4096 | 4096 | | 1.7003 |
199
+ | add_5120 | 5120 | | 1.6408 |
200
+ | add_6144 | 6144 | | 1.5989 |
201
+ | add_7168 | 7168 | | 1.5617 |
202
+ | add_8192 | 8192 | | 1.5309 |
203
+ | add_9216 | 9216 | | 1.5065 |
204
+ | add_10240 | 10240 | | 1.4809 |
205
+ | add_11264 | 11264 | | 1.4599 |
206
+ | add_11264_curated | 11264 | ✓ | 1.4607 |
207
+ | add_12288 | 12288 | | 1.4417 |
208
+ | add_12288_curated | 12288 | ✓ | 1.4426 |
209
+ | add_13312 | 13312 | | 1.4228 |
210
+ | add_14336 | 14336 | | 1.4076 |
211
+ | add_15360 | 15360 | | 1.3941 |
212
+ | add_15360_curated | 15360 | ✓ | 1.3951 |
213
+ | add_16384 | 16384 | | 1.3816 |
214
+ | add_17408 | 17408 | | 1.3693 |
215
+ | add_18432 | 18432 | | 1.3582 |
216
+ | add_19456 | 19456 | | 1.3481 |
217
+ | add_20480 | 20480 | | 1.3399 |
218
+ | add_20480_curated | 20480 | ✓ | 1.3408 |
219
+ | add_21504 | 21504 | | 1.3317 |
220
+ | add_22528 | 22528 | | 1.3225 |
221
+ | add_23552 | 23552 | | 1.3146 |
222
+ | add_24576 | 24576 | | 1.3076 |
223
+ | add_25600 | 25600 | | 1.3008 |
224
+ | add_25600_curated | 25600 | ✓ | 1.3018 |
225
+
226
+ ## Tier 2 — multi-criteria supplement
227
+
228
+ ### MorphScore Greek (catherinearnett/morphscore)
229
+
230
+ 21,428 Greek words from UD Greek-GDT with gold morpheme boundaries;
231
+ `n=693` after the freq-scale + length filter. **Recall** = fraction of
232
+ gold morpheme boundaries the tokenizer hits; **precision** = fraction
233
+ of tokenizer boundaries that hit a real morpheme boundary; **token-
234
+ char ratio** = mean tokens-per-character (lower = less over-segmenting).
235
+
236
+ | variant_id | added_tokens | curated | macro_f1 | macro_precision | macro_recall | mean_token_char_ratio | micro_f1 | micro_precision | micro_recall | morphscore_precision | morphscore_precision_std | morphscore_recall | morphscore_recall_std | num_samples |
237
+ |---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
238
+ | apertus_base | 0 | | 0.0210 | 0.0152 | 0.0339 | 0.4871 | 0.0217 | 0.0160 | 0.0338 | 0.6829 | 0.0034 | 0.6979 | 0.0034 | 693.0000 |
239
+ | add_1024 | 1024 | | 0.0179 | 0.0133 | 0.0274 | 0.4426 | 0.0189 | 0.0144 | 0.0274 | 0.6823 | 0.0034 | 0.6940 | 0.0034 | 693.0000 |
240
+ | add_2048 | 2048 | | 0.0126 | 0.0095 | 0.0188 | 0.4213 | 0.0133 | 0.0103 | 0.0187 | 0.6812 | 0.0034 | 0.6890 | 0.0034 | 693.0000 |
241
+ | add_3072 | 3072 | | 0.0130 | 0.0099 | 0.0188 | 0.4073 | 0.0136 | 0.0107 | 0.0187 | 0.6813 | 0.0034 | 0.6890 | 0.0034 | 693.0000 |
242
+ | add_4096 | 4096 | | 0.0125 | 0.0096 | 0.0180 | 0.3944 | 0.0134 | 0.0107 | 0.0180 | 0.6816 | 0.0034 | 0.6890 | 0.0034 | 693.0000 |
243
+ | add_5120 | 5120 | | 0.0116 | 0.0089 | 0.0166 | 0.3833 | 0.0126 | 0.0101 | 0.0166 | 0.6817 | 0.0034 | 0.6883 | 0.0034 | 693.0000 |
244
+ | add_6144 | 6144 | | 0.0114 | 0.0089 | 0.0159 | 0.3730 | 0.0122 | 0.0100 | 0.0158 | 0.6816 | 0.0034 | 0.6872 | 0.0034 | 693.0000 |
245
+ | add_7168 | 7168 | | 0.0109 | 0.0085 | 0.0152 | 0.3669 | 0.0118 | 0.0097 | 0.0151 | 0.6815 | 0.0034 | 0.6870 | 0.0034 | 693.0000 |
246
+ | add_8192 | 8192 | | 0.0100 | 0.0078 | 0.0137 | 0.3637 | 0.0107 | 0.0088 | 0.0137 | 0.6812 | 0.0034 | 0.6859 | 0.0034 | 693.0000 |
247
+ | add_9216 | 9216 | | 0.0100 | 0.0078 | 0.0137 | 0.3588 | 0.0108 | 0.0090 | 0.0137 | 0.6814 | 0.0034 | 0.6861 | 0.0034 | 693.0000 |
248
+ | add_10240 | 10240 | | 0.0101 | 0.0079 | 0.0137 | 0.3546 | 0.0109 | 0.0091 | 0.0137 | 0.6868 | 0.0034 | 0.6915 | 0.0034 | 693.0000 |
249
+ | add_11264 | 11264 | | 0.0095 | 0.0075 | 0.0130 | 0.3507 | 0.0104 | 0.0087 | 0.0130 | 0.6866 | 0.0034 | 0.6909 | 0.0034 | 693.0000 |
250
+ | add_11264_curated | 11264 | ✓ | 0.0095 | 0.0075 | 0.0130 | 0.3507 | 0.0104 | 0.0087 | 0.0130 | 0.6866 | 0.0034 | 0.6909 | 0.0034 | 693.0000 |
251
+ | add_12288 | 12288 | | 0.0096 | 0.0076 | 0.0130 | 0.3478 | 0.0105 | 0.0088 | 0.0130 | 0.6866 | 0.0034 | 0.6909 | 0.0034 | 693.0000 |
252
+ | add_12288_curated | 12288 | ✓ | 0.0096 | 0.0076 | 0.0130 | 0.3478 | 0.0105 | 0.0088 | 0.0130 | 0.6866 | 0.0034 | 0.6909 | 0.0034 | 693.0000 |
253
+ | add_13312 | 13312 | | 0.0090 | 0.0071 | 0.0123 | 0.3465 | 0.0099 | 0.0083 | 0.0122 | 0.6866 | 0.0034 | 0.6908 | 0.0034 | 693.0000 |
254
+ | add_14336 | 14336 | | 0.0090 | 0.0071 | 0.0123 | 0.3454 | 0.0099 | 0.0083 | 0.0122 | 0.6867 | 0.0034 | 0.6909 | 0.0034 | 693.0000 |
255
+ | add_15360 | 15360 | | 0.0079 | 0.0063 | 0.0108 | 0.3419 | 0.0088 | 0.0074 | 0.0108 | 0.6863 | 0.0034 | 0.6892 | 0.0034 | 693.0000 |
256
+ | add_15360_curated | 15360 | ✓ | 0.0079 | 0.0063 | 0.0108 | 0.3419 | 0.0088 | 0.0074 | 0.0108 | 0.6863 | 0.0034 | 0.6892 | 0.0034 | 693.0000 |
257
+ | add_16384 | 16384 | | 0.0081 | 0.0065 | 0.0108 | 0.3393 | 0.0088 | 0.0075 | 0.0108 | 0.6864 | 0.0034 | 0.6892 | 0.0034 | 693.0000 |
258
+ | add_17408 | 17408 | | 0.0081 | 0.0065 | 0.0108 | 0.3364 | 0.0089 | 0.0076 | 0.0108 | 0.6912 | 0.0034 | 0.6940 | 0.0034 | 693.0000 |
259
+ | add_18432 | 18432 | | 0.0083 | 0.0067 | 0.0108 | 0.3339 | 0.0089 | 0.0076 | 0.0108 | 0.6912 | 0.0034 | 0.6940 | 0.0034 | 693.0000 |
260
+ | add_19456 | 19456 | | 0.0078 | 0.0064 | 0.0101 | 0.3311 | 0.0084 | 0.0072 | 0.0101 | 0.6922 | 0.0034 | 0.6947 | 0.0034 | 693.0000 |
261
+ | add_20480 | 20480 | | 0.0078 | 0.0064 | 0.0101 | 0.3298 | 0.0084 | 0.0072 | 0.0101 | 0.6922 | 0.0034 | 0.6947 | 0.0034 | 693.0000 |
262
+ | add_20480_curated | 20480 | ✓ | 0.0078 | 0.0064 | 0.0101 | 0.3298 | 0.0084 | 0.0072 | 0.0101 | 0.6922 | 0.0034 | 0.6947 | 0.0034 | 693.0000 |
263
+ | add_21504 | 21504 | | 0.0078 | 0.0064 | 0.0101 | 0.3282 | 0.0084 | 0.0072 | 0.0101 | 0.6924 | 0.0034 | 0.6949 | 0.0034 | 693.0000 |
264
+ | add_22528 | 22528 | | 0.0078 | 0.0064 | 0.0101 | 0.3265 | 0.0084 | 0.0073 | 0.0101 | 0.6924 | 0.0034 | 0.6949 | 0.0034 | 693.0000 |
265
+ | add_23552 | 23552 | | 0.0078 | 0.0064 | 0.0101 | 0.3244 | 0.0085 | 0.0073 | 0.0101 | 0.6926 | 0.0034 | 0.6950 | 0.0034 | 693.0000 |
266
+ | add_24576 | 24576 | | 0.0079 | 0.0065 | 0.0101 | 0.3240 | 0.0085 | 0.0073 | 0.0101 | 0.6926 | 0.0034 | 0.6950 | 0.0034 | 693.0000 |
267
+ | add_25600 | 25600 | | 0.0079 | 0.0065 | 0.0101 | 0.3225 | 0.0085 | 0.0074 | 0.0101 | 0.6926 | 0.0034 | 0.6950 | 0.0034 | 693.0000 |
268
+ | add_25600_curated | 25600 | ✓ | 0.0079 | 0.0065 | 0.0101 | 0.3225 | 0.0085 | 0.0074 | 0.0101 | 0.6926 | 0.0034 | 0.6950 | 0.0034 | 693.0000 |
269
+
270
+ ![morphscore](artifacts/plots/morphscore_greek.png)
271
+
272
+ **Reading**: recall is essentially flat (~0.69) across all cutoffs —
273
+ the added vocabulary does not appreciably improve morpheme-boundary
274
+ alignment. Precision improves marginally (+0.5 % at 11k). The
275
+ **token-char ratio drops 29 %** (0.49 → 0.35), confirming the added
276
+ vocab makes Greek encoding more compact without dramatically improving
277
+ morphological structure capture. Useful nuance the 4 paper metrics
278
+ don't see.
279
+
280
+ ### Rényi-2.5 efficiency (Apertus-55 global)
281
+
282
+ | variant_id | added_tokens | curated | value |
283
+ |---|---|---|---|
284
+ | apertus_base | 0 | | 8.4483 |
285
+ | add_1024 | 1024 | | 8.4429 |
286
+ | add_2048 | 2048 | | 8.4400 |
287
+ | add_3072 | 3072 | | 8.4377 |
288
+ | add_4096 | 4096 | | 8.4362 |
289
+ | add_5120 | 5120 | | 8.4348 |
290
+ | add_6144 | 6144 | | 8.4338 |
291
+ | add_7168 | 7168 | | 8.4329 |
292
+ | add_8192 | 8192 | | 8.4321 |
293
+ | add_9216 | 9216 | | 8.4315 |
294
+ | add_10240 | 10240 | | 8.4308 |
295
+ | add_11264 | 11264 | | 8.4303 |
296
+ | add_11264_curated | 11264 | ✓ | 8.4299 |
297
+ | add_12288 | 12288 | | 8.4298 |
298
+ | add_12288_curated | 12288 | ✓ | 8.4295 |
299
+ | add_13312 | 13312 | | 8.4294 |
300
+ | add_14336 | 14336 | | 8.4290 |
301
+ | add_15360 | 15360 | | 8.4286 |
302
+ | add_15360_curated | 15360 | ✓ | 8.4283 |
303
+ | add_16384 | 16384 | | 8.4283 |
304
+ | add_17408 | 17408 | | 8.4280 |
305
+ | add_18432 | 18432 | | 8.4277 |
306
+ | add_19456 | 19456 | | 8.4275 |
307
+ | add_20480 | 20480 | | 8.4273 |
308
+ | add_20480_curated | 20480 | ✓ | 8.4269 |
309
+ | add_21504 | 21504 | | 8.4271 |
310
+ | add_22528 | 22528 | | 8.4268 |
311
+ | add_23552 | 23552 | | 8.4266 |
312
+ | add_24576 | 24576 | | 8.4264 |
313
+ | add_25600 | 25600 | | 8.4263 |
314
+ | add_25600_curated | 25600 | ✓ | 8.4259 |
315
+
316
+ ### UTF-8 completeness (Apertus-55 global)
317
+
318
+ | variant_id | added_tokens | curated | value |
319
+ |---|---|---|---|
320
+ | apertus_base | 0 | | 0.9792 |
321
+ | add_1024 | 1024 | | 0.9792 |
322
+ | add_2048 | 2048 | | 0.9792 |
323
+ | add_3072 | 3072 | | 0.9792 |
324
+ | add_4096 | 4096 | | 0.9792 |
325
+ | add_5120 | 5120 | | 0.9792 |
326
+ | add_6144 | 6144 | | 0.9791 |
327
+ | add_7168 | 7168 | | 0.9791 |
328
+ | add_8192 | 8192 | | 0.9792 |
329
+ | add_9216 | 9216 | | 0.9791 |
330
+ | add_10240 | 10240 | | 0.9791 |
331
+ | add_11264 | 11264 | | 0.9791 |
332
+ | add_11264_curated | 11264 | ✓ | 0.9791 |
333
+ | add_12288 | 12288 | | 0.9791 |
334
+ | add_12288_curated | 12288 | ✓ | 0.9791 |
335
+ | add_13312 | 13312 | | 0.9791 |
336
+ | add_14336 | 14336 | | 0.9791 |
337
+ | add_15360 | 15360 | | 0.9791 |
338
+ | add_15360_curated | 15360 | ✓ | 0.9791 |
339
+ | add_16384 | 16384 | | 0.9791 |
340
+ | add_17408 | 17408 | | 0.9791 |
341
+ | add_18432 | 18432 | | 0.9791 |
342
+ | add_19456 | 19456 | | 0.9791 |
343
+ | add_20480 | 20480 | | 0.9791 |
344
+ | add_20480_curated | 20480 | ✓ | 0.9791 |
345
+ | add_21504 | 21504 | | 0.9791 |
346
+ | add_22528 | 22528 | | 0.9791 |
347
+ | add_23552 | 23552 | | 0.9791 |
348
+ | add_24576 | 24576 | | 0.9791 |
349
+ | add_25600 | 25600 | | 0.9791 |
350
+ | add_25600_curated | 25600 | ✓ | 0.9791 |
351
+
352
+ ## Curated-arm delta (consumes 02_1_5 removal_list)
353
+
354
+ Curated twins remove 39 (at 11,264) / 44 (at 12,288) tokens after
355
+ merge-graph validation. **In every metric tested, the delta vs the
356
+ un-curated variant is essentially zero** — 39/44 token removal is free.
357
+
358
+ ### Cutoff 11,264
359
+
360
+ | metric | source | raw | curated | Δ |
361
+ |---|---|---|---|---|
362
+ | greek_word_space_fertility | our_suite_02_1_3 | 1.5444 | 1.5313 | -0.0131 |
363
+ | chars_per_token | our_suite_02_1_3 | 3.6564 | 3.7098 | 0.0534 |
364
+ | eval_added_vocab_utilization_rate | our_suite_02_1_3 | 0.8985 | 0.9108 | 0.0124 |
365
+ | tokenizer_fairness_gini | tokeval-lines | 0.1154 | 0.1154 | -0.0000 |
366
+ | renyi_efficiency | tokeval-lines | 8.4303 | 8.4299 | -0.0004 |
367
+ | utf8_token_integrity | tokeval-lines | 0.9791 | 0.9791 | 0.0000 |
368
+ | morphscore_recall | morphscore | 0.6909 | 0.6909 | 0.0000 |
369
+ | morphscore_precision | morphscore | 0.6866 | 0.6866 | 0.0000 |
370
+ | mean_token_char_ratio | morphscore | 0.3507 | 0.3507 | 0.0000 |
371
+
372
+ ### Cutoff 12,288
373
+
374
+ | metric | source | raw | curated | Δ |
375
+ |---|---|---|---|---|
376
+ | greek_word_space_fertility | our_suite_02_1_3 | 1.5230 | 1.5098 | -0.0131 |
377
+ | chars_per_token | our_suite_02_1_3 | 3.6948 | 3.7490 | 0.0542 |
378
+ | eval_added_vocab_utilization_rate | our_suite_02_1_3 | 0.8870 | 0.9004 | 0.0134 |
379
+ | tokenizer_fairness_gini | tokeval-lines | 0.1155 | 0.1155 | -0.0000 |
380
+ | renyi_efficiency | tokeval-lines | 8.4298 | 8.4295 | -0.0004 |
381
+ | utf8_token_integrity | tokeval-lines | 0.9791 | 0.9791 | -0.0000 |
382
+ | morphscore_recall | morphscore | 0.6909 | 0.6909 | 0.0000 |
383
+ | morphscore_precision | morphscore | 0.6866 | 0.6866 | 0.0000 |
384
+ | mean_token_char_ratio | morphscore | 0.3478 | 0.3478 | 0.0000 |
385
+
386
+ ## Methodology delta — TokEval-fertility vs 02_1_3-fertility on Greek
387
+
388
+ Same 15 tokenizers, same target (Greek), different eval sets and
389
+ different normalizations. **TokEval = FLORES+ ell_Grek, words config.**
390
+ **02_1_3 = our in-domain held-outs, greek_word_space_fertility.**
391
+
392
+ Use this to decide which fertility number to cite — TokEval for paper
393
+ comparability, 02_1_3 for in-domain decision-making.
394
+
395
+ | variant_id | added_tokens | TokEval (FLORES+ Greek) | 02_1_3 (C3_val) |
396
+ |---|---|---|---|
397
+ | apertus_base | 0 | 2.2041 | 2.4113 |
398
+ | add_1024 | 1024 | 1.9825 | 2.0799 |
399
+ | add_2048 | 2048 | 1.8545 | 1.9222 |
400
+ | add_3072 | 3072 | 1.7639 | 1.8102 |
401
+ | add_4096 | 4096 | 1.7003 | 1.7281 |
402
+ | add_5120 | 5120 | 1.6408 | 1.6608 |
403
+ | add_6144 | 6144 | 1.5989 | 1.6106 |
404
+ | add_7168 | 7168 | 1.5617 | 1.5668 |
405
+ | add_8192 | 8192 | 1.5309 | 1.5293 |
406
+ | add_9216 | 9216 | 1.5065 | 1.4975 |
407
+ | add_10240 | 10240 | 1.4809 | 1.4713 |
408
+ | add_11264 | 11264 | 1.4599 | 1.4475 |
409
+ | add_11264_curated | 11264 | 1.4607 | 1.4477 |
410
+ | add_12288 | 12288 | 1.4417 | 1.4253 |
411
+ | add_12288_curated | 12288 | 1.4426 | 1.4256 |
412
+ | add_13312 | 13312 | 1.4228 | 1.4061 |
413
+ | add_14336 | 14336 | 1.4076 | 1.3883 |
414
+ | add_15360 | 15360 | 1.3941 | 1.3723 |
415
+ | add_15360_curated | 15360 | 1.3951 | 1.3727 |
416
+ | add_16384 | 16384 | 1.3816 | 1.3586 |
417
+ | add_17408 | 17408 | 1.3693 | 1.3456 |
418
+ | add_18432 | 18432 | 1.3582 | 1.3323 |
419
+ | add_19456 | 19456 | 1.3481 | 1.3208 |
420
+ | add_20480 | 20480 | 1.3399 | 1.3107 |
421
+ | add_20480_curated | 20480 | 1.3408 | 1.3112 |
422
+ | add_21504 | 21504 | 1.3317 | 1.3013 |
423
+ | add_22528 | 22528 | 1.3225 | 1.2915 |
424
+ | add_23552 | 23552 | 1.3146 | 1.2831 |
425
+ | add_24576 | 24576 | 1.3076 | 1.2748 |
426
+ | add_25600 | 25600 | 1.3008 | 1.2671 |
427
+ | add_25600_curated | 25600 | 1.3018 | 1.2676 |
428
+
429
+ ## Reproduction
430
+
431
+ ```bash
432
+ cd subprojects/02_1_tokenizer_experiments/02_1_7_intrinsic_eval_sweep
433
+ $VENV/python scripts/01_build_variants_inline.py # local 13 variants
434
+ $VENV/python scripts/01b_build_curated_variants.py # 2 curated twins
435
+ $VENV/python scripts/02_prep_eval_configs.py
436
+ bash scripts/03a_run_tokeval.sh # TokEval 2 jobs (~30 min)
437
+ # gcloud: resume → run 02_1_3 harness for our 4 in-house slices → suspend
438
+ $VENV/python scripts/07_morphscore_greek.py # MorphScore Greek
439
+ $VENV/python scripts/08_merge_all.py # merge all 4 sources
440
+ $VENV/python scripts/09_render_final_report.py # this file + plots
441
+ ```
provenance/tokenizer-selection/curated_padded_at_17408_manifest.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "variant_id": "add_17408_curated_padded",
3
+ "added_tokens": 17408,
4
+ "total_vocab": 148480,
5
+ "alignment_128": true,
6
+ "alignment_256": true,
7
+ "apertus_base_preserved_verbatim": true,
8
+ "removal_list_source": "/home/foivos/Projects/glossapi-tokenizer-extension/subprojects/02_1_tokenizer_experiments/02_1_5_added_token_curation/manifests/removal_list.jsonl",
9
+ "removal_list_size_full": 104,
10
+ "merges_walked_from_c3_full": 17477,
11
+ "merges_skipped_for_removal": 69,
12
+ "merges_skipped_for_cascade": 0,
13
+ "merges_accepted": 17408,
14
+ "ship_artifact_path": "/home/foivos/Projects/glossapi-tokenizer-extension/subprojects/02_1_tokenizer_experiments/02_1_7_intrinsic_eval_sweep/variants/c3_added_17408_curated_padded/tokenizer.json"
15
+ }
provenance/tokenizer-selection/firing_count_20260518_run_summary_augmented.json ADDED
The diff for this file is too large to render. See raw diff
 
results/SUMMARY.md ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 3.5B continuation results - Vanilla vs ReTok vs TD layer11
2
+
3
+ Generated UTC: `2026-05-25T05:23:53+00:00`.
4
+
5
+ This summarizes the continuation run `continuation_3p5b_20260524T143012Z`,
6
+ which extended Vanilla, ReTok, and TD layer11 from iter 476 (~2.0B tokens)
7
+ to iter 834 (~3.5B tokens). Local JSON snapshots live under
8
+ `per_iter_results/`; remote full artifacts remain on Clariden under
9
+ `/capstor/scratch/cscs/fffoivos/runs/eval/continuation_3p5b_20260524T143012Z_*`.
10
+
11
+ ## Bottom line
12
+
13
+ - TD layer11 is the best final benchmark arm overall: it is first on English
14
+ retention and multilingual aggregates, and narrowly first on the Greek
15
+ aggregate at iter 834.
16
+ - Vanilla still has the best tokenizer-fair heldout Greek BPC, but its
17
+ downstream Greek aggregate declined during the 2.0B -> 3.5B continuation.
18
+ - ReTok improves fastest on BPC and wins Greek MMLU / INCLUDE-44 Greek at
19
+ iter 834, but it remains behind TD and Vanilla on the Greek aggregate.
20
+ - If selecting for the actual downstream bakeoff objective, TD layer11 is now
21
+ the leading candidate. If selecting only for heldout BPC, Vanilla remains
22
+ ahead.
23
+
24
+ ## Aggregate scoreboard at iter 834
25
+
26
+ | Arm | Greek agg | Delta vs 476 | EN retention | Delta vs 476 | Multilingual | Delta vs 476 | BPC lower better | BPC delta |
27
+ |---|---:|---:|---:|---:|---:|---:|---:|---:|
28
+ | Vanilla | 0.4339 | -0.70 pp | 0.6782 | -0.36 pp | 0.4923 | +0.22 pp | 0.4724 | -0.0182 |
29
+ | ReTok | 0.4246 | +0.96 pp | 0.6786 | +0.36 pp | 0.4864 | -0.09 pp | 0.5390 | -0.0349 |
30
+ | TD layer11 | 0.4344 | +0.90 pp | 0.6865 | +0.38 pp | 0.4967 | +0.68 pp | 0.5054 | -0.0256 |
31
+
32
+ ## Per-task winners at iter 834
33
+
34
+ | Group | Task | Vanilla | ReTok | TD layer11 | Winner |
35
+ |---|---|---:|---:|---:|---|
36
+ | EN retention | `mmlu` | 0.5330 | 0.5565 | 0.5556 | ReTok |
37
+ | EN retention | `hellaswag` | 0.7573 | 0.7556 | 0.7632 | TD layer11 |
38
+ | EN retention | `arc_easy` | 0.7866 | 0.7576 | 0.7837 | Vanilla |
39
+ | EN retention | `arc_challenge` | 0.5230 | 0.5247 | 0.5358 | TD layer11 |
40
+ | EN retention | `piqa` | 0.7927 | 0.7851 | 0.7894 | Vanilla |
41
+ | EN retention | `winogrande` | 0.6764 | 0.6922 | 0.6914 | ReTok |
42
+ | Multilingual | `global_mmlu` | 0.4505 | 0.4603 | 0.4628 | TD layer11 |
43
+ | Multilingual | `xcopa` | 0.6178 | 0.5920 | 0.6156 | Vanilla |
44
+ | Multilingual | `xnli` | 0.4087 | 0.4070 | 0.4117 | TD layer11 |
45
+ | Greek | `global_mmlu_full_el` | 0.4145 | 0.4153 | 0.4036 | ReTok |
46
+ | Greek | `include_base_44_greek_few_shot_en` | 0.4022 | 0.4058 | 0.4004 | ReTok |
47
+ | Greek | `belebele_ell_Grek` | 0.5078 | 0.4933 | 0.5389 | TD layer11 |
48
+ | Greek | `arc_challenge_mt_el` | 0.4130 | 0.3899 | 0.4061 | Vanilla |
49
+ | Greek | `xnli_el` | 0.3831 | 0.3695 | 0.3851 | TD layer11 |
50
+ | Greek | `xquad_el` | 0.2868 | 0.3084 | 0.3364 | TD layer11 |
51
+ | Greek | `global_piqa_completions_ell_grek` | 0.6300 | 0.5900 | 0.5700 | Vanilla |
52
+
53
+ ## Change from iter 476 to iter 834
54
+
55
+ | Group | Task | Vanilla delta | ReTok delta | TD layer11 delta |
56
+ |---|---|---:|---:|---:|
57
+ | EN retention | `mmlu` | -0.09 pp | +0.24 pp | +0.56 pp |
58
+ | EN retention | `hellaswag` | -0.21 pp | +0.69 pp | +0.27 pp |
59
+ | EN retention | `arc_easy` | +0.13 pp | -0.59 pp | +0.29 pp |
60
+ | EN retention | `arc_challenge` | -0.43 pp | +0.94 pp | +0.85 pp |
61
+ | EN retention | `piqa` | -0.22 pp | -0.11 pp | -0.27 pp |
62
+ | EN retention | `winogrande` | -1.34 pp | +1.03 pp | +0.55 pp |
63
+ | Multilingual | `global_mmlu` | -0.64 pp | +0.14 pp | +1.34 pp |
64
+ | Multilingual | `xcopa` | +1.09 pp | -0.71 pp | +0.42 pp |
65
+ | Multilingual | `xnli` | +0.22 pp | +0.30 pp | +0.28 pp |
66
+ | Greek | `global_mmlu_full_el` | -0.69 pp | +1.62 pp | +1.77 pp |
67
+ | Greek | `include_base_44_greek_few_shot_en` | -1.63 pp | +3.26 pp | -0.36 pp |
68
+ | Greek | `belebele_ell_Grek` | -0.56 pp | -0.33 pp | +1.11 pp |
69
+ | Greek | `arc_challenge_mt_el` | -0.77 pp | +1.79 pp | +0.26 pp |
70
+ | Greek | `xnli_el` | -1.89 pp | -0.56 pp | +0.48 pp |
71
+ | Greek | `xquad_el` | -2.33 pp | -0.08 pp | +1.02 pp |
72
+ | Greek | `global_piqa_completions_ell_grek` | +3.00 pp | +1.00 pp | +2.00 pp |
73
+
74
+ ## New-token diagnostics
75
+
76
+ Measured on the 500-document heldout slice. Top-k is the fraction of
77
+ positions whose correct new token appears in the model's top-k predictions;
78
+ lower mean rank is better.
79
+
80
+ | Arm | Top-1 at new target | Delta from 585 | Top-5 at new target | Delta from 585 | Mean rank | Delta from 585 |
81
+ |---|---:|---:|---:|---:|---:|---:|
82
+ | ReTok | 0.3799 | +2.00 pp | 0.5469 | +2.11 pp | 228.9 | -31.4 |
83
+ | TD layer11 | 0.4105 | +1.43 pp | 0.5811 | +1.54 pp | 174.3 | -18.8 |
84
+
85
+ ## Artifact checklist
86
+
87
+ - Local packed-eval snapshots: `per_iter_results/{vanilla,retok,td}_iter{585,715,834}.json`.
88
+ - Local BPC snapshots: `per_iter_results/intrinsic/*_iter{585,715,834}_fair.json`.
89
+ - Local new-token diagnostics: `per_iter_results/diagnostics/{retok,td}_iter{585,715,834}_new_token_diagnostics.json`.
90
+ - Regenerated plots are written to `plots/`.
91
+ - Final remote packed eval job: `2376082`, state `COMPLETED`, exit `0:0`, elapsed `00:59:51`.
results/benchmark_table.csv ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ arm,greek_aggregate,greek_delta_vs_iter476_pp,english_retention,english_delta_vs_iter476_pp,multilingual,multilingual_delta_vs_iter476_pp,bpc_lower_better,bpc_delta
2
+ Vanilla,0.4339,-0.70,0.6782,-0.36,0.4923,0.22,0.4724,-0.0182
3
+ ReTok,0.4246,0.96,0.6786,0.36,0.4864,-0.09,0.5390,-0.0349
4
+ TD layer11,0.4344,0.90,0.6865,0.38,0.4967,0.68,0.5054,-0.0256
5
+
results/continuation_3p5b_summary.json ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "diag_rows": [
3
+ {
4
+ "arm": "retok",
5
+ "mean_rank": 228.9052154654546,
6
+ "mean_rank_delta_from_585": -31.404831868911288,
7
+ "top1": 0.3798836182563004,
8
+ "top1_delta_from_585": 0.019972352098200752,
9
+ "top5": 0.5469290563525036,
10
+ "top5_delta_from_585": 0.021119522892752207
11
+ },
12
+ {
13
+ "arm": "td",
14
+ "mean_rank": 174.2876756944545,
15
+ "mean_rank_delta_from_585": -18.7823704818841,
16
+ "top1": 0.41053515336624063,
17
+ "top1_delta_from_585": 0.014301637161096115,
18
+ "top5": 0.5811415254114616,
19
+ "top5_delta_from_585": 0.015358337072796546
20
+ }
21
+ ],
22
+ "generated_utc": "2026-05-25T05:23:53+00:00",
23
+ "group_rows": [
24
+ {
25
+ "EN retention": {
26
+ "delta": -0.0036023994242395663,
27
+ "iter476": 0.6817902499718899,
28
+ "iter834": 0.6781878505476503
29
+ },
30
+ "Greek": {
31
+ "delta": -0.0069518253078383885,
32
+ "iter476": 0.44085471366912354,
33
+ "iter834": 0.43390288836128516
34
+ },
35
+ "Multilingual": {
36
+ "delta": 0.002230923643585403,
37
+ "iter476": 0.4900917349227056,
38
+ "iter834": 0.492322658566291
39
+ },
40
+ "arm": "vanilla",
41
+ "bpc": {
42
+ "delta": -0.018193672749048873,
43
+ "iter476": 0.4905790115645303,
44
+ "iter834": 0.47238533881548145
45
+ }
46
+ },
47
+ {
48
+ "EN retention": {
49
+ "delta": 0.0036478269859219203,
50
+ "iter476": 0.6749804337638333,
51
+ "iter834": 0.6786282607497552
52
+ },
53
+ "Greek": {
54
+ "delta": 0.00956345274685877,
55
+ "iter476": 0.41502996652924373,
56
+ "iter834": 0.4245934192761025
57
+ },
58
+ "Multilingual": {
59
+ "delta": -0.0009003749821289708,
60
+ "iter476": 0.48733830931505984,
61
+ "iter834": 0.48643793433293087
62
+ },
63
+ "arm": "retok",
64
+ "bpc": {
65
+ "delta": -0.03491945208518521,
66
+ "iter476": 0.57388731113822,
67
+ "iter834": 0.5389678590530348
68
+ }
69
+ },
70
+ {
71
+ "EN retention": {
72
+ "delta": 0.0037544227559322962,
73
+ "iter476": 0.6827725274715655,
74
+ "iter834": 0.6865269502274978
75
+ },
76
+ "Greek": {
77
+ "delta": 0.008970722628639627,
78
+ "iter476": 0.4253979832454272,
79
+ "iter834": 0.43436870587406684
80
+ },
81
+ "Multilingual": {
82
+ "delta": 0.006784718226652775,
83
+ "iter476": 0.48993351359709303,
84
+ "iter834": 0.4967182318237458
85
+ },
86
+ "arm": "td",
87
+ "bpc": {
88
+ "delta": -0.02564778560419223,
89
+ "iter476": 0.531084014463596,
90
+ "iter834": 0.5054362288594038
91
+ }
92
+ }
93
+ ],
94
+ "iterations": [
95
+ 476,
96
+ 585,
97
+ 715,
98
+ 834
99
+ ],
100
+ "task_rows": [
101
+ {
102
+ "deltas": {
103
+ "retok": 0.002350092579404661,
104
+ "td": 0.005554764278592805,
105
+ "vanilla": -0.0009257940464321157
106
+ },
107
+ "group": "EN retention",
108
+ "label": "MMLU",
109
+ "task": "mmlu",
110
+ "values": {
111
+ "retok": 0.5565446517590087,
112
+ "td": 0.5556188577125766,
113
+ "vanilla": 0.5330437259649623
114
+ },
115
+ "winner": "retok"
116
+ },
117
+ {
118
+ "deltas": {
119
+ "retok": 0.006871141206930886,
120
+ "td": 0.0026887074287991197,
121
+ "vanilla": -0.0020912168890659943
122
+ },
123
+ "group": "EN retention",
124
+ "label": "HellaSwag",
125
+ "task": "hellaswag",
126
+ "values": {
127
+ "retok": 0.7556263692491536,
128
+ "td": 0.7631945827524398,
129
+ "vanilla": 0.7573192591117307
130
+ },
131
+ "winner": "td"
132
+ },
133
+ {
134
+ "deltas": {
135
+ "retok": -0.005892255892255949,
136
+ "td": 0.002946127946127919,
137
+ "vanilla": 0.0012626262626262985
138
+ },
139
+ "group": "EN retention",
140
+ "label": "ARC Easy",
141
+ "task": "arc_easy",
142
+ "values": {
143
+ "retok": 0.7575757575757576,
144
+ "td": 0.7836700336700336,
145
+ "vanilla": 0.7866161616161617
146
+ },
147
+ "winner": "vanilla"
148
+ },
149
+ {
150
+ "deltas": {
151
+ "retok": 0.009385665529010212,
152
+ "td": 0.008532423208191142,
153
+ "vanilla": -0.004266211604095571
154
+ },
155
+ "group": "EN retention",
156
+ "label": "ARC Challenge",
157
+ "task": "arc_challenge",
158
+ "values": {
159
+ "retok": 0.5247440273037542,
160
+ "td": 0.5358361774744027,
161
+ "vanilla": 0.523037542662116
162
+ },
163
+ "winner": "td"
164
+ },
165
+ {
166
+ "deltas": {
167
+ "retok": -0.0010881392818281599,
168
+ "td": -0.002720348204570233,
169
+ "vanilla": -0.0021762785636560977
170
+ },
171
+ "group": "EN retention",
172
+ "label": "PIQA",
173
+ "task": "piqa",
174
+ "values": {
175
+ "retok": 0.7850924918389554,
176
+ "td": 0.7894450489662677,
177
+ "vanilla": 0.7927094668117519
178
+ },
179
+ "winner": "vanilla"
180
+ },
181
+ {
182
+ "deltas": {
183
+ "retok": 0.010260457774269871,
184
+ "td": 0.005524861878453136,
185
+ "vanilla": -0.013417521704814472
186
+ },
187
+ "group": "EN retention",
188
+ "label": "Winogrande",
189
+ "task": "winogrande",
190
+ "values": {
191
+ "retok": 0.6921862667719021,
192
+ "td": 0.691397000789266,
193
+ "vanilla": 0.6764009471191792
194
+ },
195
+ "winner": "retok"
196
+ },
197
+ {
198
+ "deltas": {
199
+ "retok": 0.001391122832608005,
200
+ "td": 0.013387865279933964,
201
+ "vanilla": -0.006411768438843168
202
+ },
203
+ "group": "Multilingual",
204
+ "label": "Global MMLU",
205
+ "task": "global_mmlu",
206
+ "values": {
207
+ "retok": 0.4602990774298503,
208
+ "td": 0.4628181979660652,
209
+ "vanilla": 0.4504750950855104
210
+ },
211
+ "winner": "td"
212
+ },
213
+ {
214
+ "deltas": {
215
+ "retok": -0.007090909090909148,
216
+ "td": 0.0041818181818181754,
217
+ "vanilla": 0.010909090909090868
218
+ },
219
+ "group": "Multilingual",
220
+ "label": "XCOPA",
221
+ "task": "xcopa",
222
+ "values": {
223
+ "retok": 0.592,
224
+ "td": 0.6156363636363636,
225
+ "vanilla": 0.6178181818181818
226
+ },
227
+ "winner": "vanilla"
228
+ },
229
+ {
230
+ "deltas": {
231
+ "retok": 0.0029986613119142858,
232
+ "td": 0.0027844712182061304,
233
+ "vanilla": 0.0021954484605086755
234
+ },
235
+ "group": "Multilingual",
236
+ "label": "XNLI",
237
+ "task": "xnli",
238
+ "values": {
239
+ "retok": 0.4070147255689424,
240
+ "td": 0.41170013386880855,
241
+ "vanilla": 0.4086746987951807
242
+ },
243
+ "winner": "td"
244
+ },
245
+ {
246
+ "deltas": {
247
+ "retok": 0.016165788349237986,
248
+ "td": 0.017732516735507742,
249
+ "vanilla": -0.006907847884916718
250
+ },
251
+ "group": "Greek",
252
+ "label": "Greek MMLU",
253
+ "task": "global_mmlu_full_el",
254
+ "values": {
255
+ "retok": 0.4152542372881356,
256
+ "td": 0.4036462042444096,
257
+ "vanilla": 0.4144708730950007
258
+ },
259
+ "winner": "retok"
260
+ },
261
+ {
262
+ "deltas": {
263
+ "retok": 0.03260869565217395,
264
+ "td": -0.0036231884057971175,
265
+ "vanilla": -0.016304347826086973
266
+ },
267
+ "group": "Greek",
268
+ "label": "INCLUDE-44 Greek",
269
+ "task": "include_base_44_greek_few_shot_en",
270
+ "values": {
271
+ "retok": 0.4057971014492754,
272
+ "td": 0.4003623188405797,
273
+ "vanilla": 0.40217391304347827
274
+ },
275
+ "winner": "retok"
276
+ },
277
+ {
278
+ "deltas": {
279
+ "retok": -0.0033333333333332993,
280
+ "td": 0.011111111111111072,
281
+ "vanilla": -0.005555555555555536
282
+ },
283
+ "group": "Greek",
284
+ "label": "Belebele Greek",
285
+ "task": "belebele_ell_Grek",
286
+ "values": {
287
+ "retok": 0.49333333333333335,
288
+ "td": 0.5388888888888889,
289
+ "vanilla": 0.5077777777777778
290
+ },
291
+ "winner": "td"
292
+ },
293
+ {
294
+ "deltas": {
295
+ "retok": 0.017918088737201354,
296
+ "td": 0.0025597269624573205,
297
+ "vanilla": -0.007679180887372017
298
+ },
299
+ "group": "Greek",
300
+ "label": "ARC Challenge MT-el",
301
+ "task": "arc_challenge_mt_el",
302
+ "values": {
303
+ "retok": 0.38993174061433444,
304
+ "td": 0.4061433447098976,
305
+ "vanilla": 0.4129692832764505
306
+ },
307
+ "winner": "vanilla"
308
+ },
309
+ {
310
+ "deltas": {
311
+ "retok": -0.005622489959839383,
312
+ "td": 0.004819277108433773,
313
+ "vanilla": -0.01887550200803212
314
+ },
315
+ "group": "Greek",
316
+ "label": "XNLI Greek",
317
+ "task": "xnli_el",
318
+ "values": {
319
+ "retok": 0.36947791164658633,
320
+ "td": 0.385140562248996,
321
+ "vanilla": 0.38313253012048193
322
+ },
323
+ "winner": "td"
324
+ },
325
+ {
326
+ "deltas": {
327
+ "retok": -0.0007925802174291174,
328
+ "td": 0.010195614888764415,
329
+ "vanilla": -0.02334034299290566
330
+ },
331
+ "group": "Greek",
332
+ "label": "XQuAD Greek F1",
333
+ "task": "xquad_el",
334
+ "values": {
335
+ "retok": 0.3083596106010522,
336
+ "td": 0.3363996221856959,
337
+ "vanilla": 0.2867958412158067
338
+ },
339
+ "winner": "td"
340
+ },
341
+ {
342
+ "deltas": {
343
+ "retok": 0.010000000000000009,
344
+ "td": 0.019999999999999907,
345
+ "vanilla": 0.030000000000000027
346
+ },
347
+ "group": "Greek",
348
+ "label": "PIQA Greek",
349
+ "task": "global_piqa_completions_ell_grek",
350
+ "values": {
351
+ "retok": 0.59,
352
+ "td": 0.57,
353
+ "vanilla": 0.63
354
+ },
355
+ "winner": "vanilla"
356
+ }
357
+ ],
358
+ "tokens_b": {
359
+ "476": 1.996488704,
360
+ "585": 2.45366784,
361
+ "715": 2.99892736,
362
+ "834": 3.498049536
363
+ }
364
+ }
results/plots/global_mmlu_full_el_subcategories_van_td.png ADDED

Git LFS Details

  • SHA256: 13337a7976d4ca46c6c3db03014a2207ba81a42796c285410dc3f4ad26007cd9
  • Pointer size: 131 Bytes
  • Size of remote file: 156 kB
results/plots/include_base_44_greek_subjects_van_td.png ADDED

Git LFS Details

  • SHA256: 6375661e9c50fd4b9f32db79a9c77375aaadbb878fab8a61019802978af3ac0e
  • Pointer size: 131 Bytes
  • Size of remote file: 349 kB
results/plots/intrinsic_trajectories.png ADDED

Git LFS Details

  • SHA256: a44571c0aca767ace369a89534632a9b4618bc01391c0b20bb0f04f1c34a8830
  • Pointer size: 131 Bytes
  • Size of remote file: 231 kB
results/plots/intrinsic_van_td.png ADDED

Git LFS Details

  • SHA256: 975e0c58604e6189f45182e07cf178bb94bead39130385aae36ed95c065ed2ad
  • Pointer size: 131 Bytes
  • Size of remote file: 146 kB
results/plots/trajectories.png ADDED

Git LFS Details

  • SHA256: ab072600c16be4aab4fe36ebd5b7fe3a216f1bf5ac391687733667f6231ff486
  • Pointer size: 131 Bytes
  • Size of remote file: 368 kB
results/plots/trajectories_per_task.png ADDED

Git LFS Details

  • SHA256: 375efc4b55341c0a1060fb9d7ccaa8774db66c8ca554683100449e15b1541a44
  • Pointer size: 131 Bytes
  • Size of remote file: 303 kB
results/plots/trajectories_per_task_van_td.png ADDED

Git LFS Details

  • SHA256: ea2a02ecd33210ada4c9a5d1f7832246de07205cc4bbc5679aedb6959f93bfbe
  • Pointer size: 131 Bytes
  • Size of remote file: 304 kB
results/plots/trajectories_van_td.png ADDED

Git LFS Details

  • SHA256: a54f94603549ddaf022297a2f691a688fb6283d793394f482531211b42dfa3a3
  • Pointer size: 131 Bytes
  • Size of remote file: 270 kB
results/plots/trajectories_van_td_gap.png ADDED

Git LFS Details

  • SHA256: d49ee1c80666418e6f36b649b63c9a80fb2808bb365d31e481a6c58c97053d11
  • Pointer size: 131 Bytes
  • Size of remote file: 171 kB
tokenizer/modern-greek-17408/README.md ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Modern Greek Tokenizer, 148480 Vocab
2
+
3
+ This is the canonical modern Greek tokenizer extension for Apertus.
4
+
5
+ Properties:
6
+
7
+ - base model: `swiss-ai/Apertus-8B-2509`;
8
+ - method: merge-rule BPE extension, not `add_tokens`;
9
+ - base vocab preserved: `131072`;
10
+ - added modern Greek tokens: `17408`;
11
+ - total vocab: `148480`;
12
+ - alignment: divisible by `128` and `256`;
13
+ - first 1000 special/reserved ids preserved;
14
+ - `tokenizer.json` SHA-256:
15
+ `358ae3f29ac17c99769d6d437339e28657d5fcaed3486f8550feed3d6adfc394`.
16
+
17
+ Selection evidence is in:
18
+
19
+ ```text
20
+ ../../provenance/tokenizer-selection/CHOSEN_CUTOFF.md
21
+ ```
22
+
tokenizer/modern-greek-17408/manifest.json ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "apertus_greek_modern_only_148480",
3
+ "purpose": "Apertus-compatible modern-Greek-only tokenizer: base 131,072 + C3 modern Greek (+17,408 curated+backfilled) = 148,480 = 256 × 580. Use this for the three-arm Vanilla/ReTok/Distillation init comparison.",
4
+ "vocab_size": 148480,
5
+ "base_apertus_vocab": 131072,
6
+ "added_modern_greek_c3": 17408,
7
+ "added_polytonic_greek": 0,
8
+ "alignment": {
9
+ "128": true,
10
+ "256": true,
11
+ "factor_256": 580
12
+ },
13
+ "first_1000_preserved": true,
14
+ "front_end_contract": {
15
+ "normalizer": null,
16
+ "pre_tokenizer": "Sequence(Split(GPT-2 regex) → ByteLevel)",
17
+ "decoder": "ByteLevel",
18
+ "model_type": "BPE",
19
+ "special_tokens": {
20
+ "unk": 0,
21
+ "bos": 1,
22
+ "eos": 2,
23
+ "pad": 3,
24
+ "reserved_count": 1000
25
+ }
26
+ },
27
+ "loadable_via": "transformers.AutoTokenizer.from_pretrained() → PreTrainedTokenizerFast",
28
+ "sha256": {
29
+ "tokenizer.json": "358ae3f29ac17c99769d6d437339e28657d5fcaed3486f8550feed3d6adfc394",
30
+ "tokenizer_config.json": "ea64a17b41e1deaa7469212f413676129f33977ca3a48767f0ca68dc346df502",
31
+ "special_tokens_map.json": "816ec96e37c6d15e3cbc535dc146c898a7218f209fc154384f31fc1e6ad31ba5"
32
+ }
33
+ }
tokenizer/modern-greek-17408/special_tokens_map.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": {
3
+ "content": "<s>",
4
+ "lstrip": false,
5
+ "normalized": false,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "eos_token": {
10
+ "content": "</s>",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "pad_token": {
17
+ "content": "<pad>",
18
+ "lstrip": false,
19
+ "normalized": false,
20
+ "rstrip": false,
21
+ "single_word": false
22
+ },
23
+ "unk_token": {
24
+ "content": "<unk>",
25
+ "lstrip": false,
26
+ "normalized": false,
27
+ "rstrip": false,
28
+ "single_word": false
29
+ }
30
+ }