User01110 commited on
Commit
564ee09
·
0 Parent(s):

CMA-1M Mini release

Browse files
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: transformers
3
+ pipeline_tag: text-generation
4
+ language:
5
+ - en
6
+ tags:
7
+ - custom_code
8
+ - causal-lm
9
+ - cma
10
+ - small-language-model
11
+ - base-model
12
+ - byte-level
13
+ - safetensors
14
+ datasets:
15
+ - HuggingFaceFW/fineweb_edu_100BT-shuffled
16
+ - mlfoundations/dclm-baseline-1.0-parquet
17
+ - HuggingFaceTB/dclm-edu
18
+ - HuggingFaceTB/smollm-corpus
19
+ - HuggingFaceTB/finemath
20
+ widget:
21
+ - text: "The process of photosynthesis"
22
+ example_title: Science
23
+ - text: "Once upon a time, in a quiet village"
24
+ example_title: Story
25
+ - text: "A computer program is"
26
+ example_title: Technology
27
+ ---
28
+
29
+ # CMA-1M Mini
30
+
31
+ > [!WARNING]
32
+ > **Experimental research model ? generations are fully unreliable.** CMA-1M Mini
33
+ > exists only as a test bed for understanding how Channel-Mixing Attention works,
34
+ > where it helps, and where its limits and failure modes appear. Do not treat its
35
+ > output as factual, safe, coherent, or suitable for production or real-world
36
+ > decisions.
37
+
38
+ CMA-1M Mini is a **958,692-parameter base causal language model** built to test
39
+ Channel-Mixing Attention (CMA) at very small scale. It combines causal grouped-query
40
+ token attention with content-dependent mixing across each token's hidden channels.
41
+ The model uses a lossless byte-level tokenizer, tied embeddings, native BF16 weights,
42
+ and a 2,048-token context window.
43
+
44
+ | | |
45
+ |---|---|
46
+ | Parameters | 958,692 |
47
+ | Architecture | Decoder-only CMA causal LM |
48
+ | Context | 2,048 byte tokens |
49
+ | Vocabulary | 260 tokens: 256 bytes + PAD/BOS/EOS/UNK |
50
+ | Weight format | BF16 Safetensors |
51
+ | Intended interface | Plain-text completion |
52
+
53
+ > This is a pretrained base model, not a chat or instruction model. Give it ordinary
54
+ > text to continue; no chat template or role markers are required.
55
+
56
+ ## Quick start
57
+
58
+ The architecture is provided as custom Transformers code, so
59
+ `trust_remote_code=True` is required. PyTorch 2.5 or newer is recommended.
60
+
61
+ ```python
62
+ import torch
63
+ from transformers import AutoModelForCausalLM, AutoTokenizer
64
+
65
+ repo_id = "User01110/CMA-1M-Mini"
66
+ device = "cuda" if torch.cuda.is_available() else "cpu"
67
+ dtype = (
68
+ torch.bfloat16
69
+ if device == "cuda" and torch.cuda.is_bf16_supported()
70
+ else torch.float32
71
+ )
72
+
73
+ tokenizer = AutoTokenizer.from_pretrained(
74
+ repo_id,
75
+ trust_remote_code=True,
76
+ )
77
+ model = AutoModelForCausalLM.from_pretrained(
78
+ repo_id,
79
+ trust_remote_code=True,
80
+ dtype=dtype,
81
+ ).to(device).eval()
82
+
83
+ prompt = "The process of photosynthesis"
84
+ inputs = tokenizer(prompt, return_tensors="pt")
85
+ inputs = {name: tensor.to(device) for name, tensor in inputs.items()}
86
+
87
+ with torch.inference_mode():
88
+ output = model.generate(
89
+ **inputs,
90
+ max_new_tokens=96,
91
+ do_sample=False,
92
+ )
93
+
94
+ print(tokenizer.decode(output[0], skip_special_tokens=True))
95
+ ```
96
+
97
+ The tokenizer automatically prepends `<bos>` during normal encoding. It does not
98
+ append `<eos>` to a prompt; generation ends when the model emits EOS or reaches the
99
+ requested length. If you deliberately use `add_special_tokens=False`, prepend BOS
100
+ yourself.
101
+
102
+ ## Generation options
103
+
104
+ The included generation defaults are deterministic decoding with a repetition
105
+ penalty of 1.2. Override them per request as needed.
106
+
107
+ | Goal | Recommended settings |
108
+ |---|---|
109
+ | Reproducible completion | `do_sample=False` |
110
+ | Balanced sampling | `do_sample=True, temperature=0.8, top_p=0.9, top_k=50` |
111
+ | More varied text | `do_sample=True, temperature=1.0, top_p=0.95` |
112
+ | Reduce loops | `repetition_penalty=1.1` to `1.2` |
113
+ | Beam search | `do_sample=False, num_beams=4` |
114
+ | Output length | Set `max_new_tokens`; keep prompt + output within 2,048 tokens |
115
+
116
+ Example with sampling:
117
+
118
+ ```python
119
+ with torch.inference_mode():
120
+ output = model.generate(
121
+ **inputs,
122
+ max_new_tokens=128,
123
+ do_sample=True,
124
+ temperature=0.8,
125
+ top_p=0.9,
126
+ top_k=50,
127
+ repetition_penalty=1.15,
128
+ )
129
+ ```
130
+
131
+ For the high-level pipeline API:
132
+
133
+ ```python
134
+ import torch
135
+ from transformers import pipeline
136
+
137
+ generator = pipeline(
138
+ "text-generation",
139
+ model="User01110/CMA-1M-Mini",
140
+ tokenizer="User01110/CMA-1M-Mini",
141
+ trust_remote_code=True,
142
+ dtype="auto",
143
+ device=0 if torch.cuda.is_available() else -1,
144
+ )
145
+
146
+ result = generator(
147
+ "In a distant future,",
148
+ max_new_tokens=80,
149
+ do_sample=True,
150
+ temperature=0.8,
151
+ top_p=0.9,
152
+ )
153
+ print(result[0]["generated_text"])
154
+ ```
155
+
156
+ To score text rather than generate it:
157
+
158
+ ```python
159
+ encoded = tokenizer("CMA models text one byte at a time.", return_tensors="pt")
160
+ encoded = {name: tensor.to(device) for name, tensor in encoded.items()}
161
+
162
+ with torch.inference_mode():
163
+ result = model(**encoded, labels=encoded["input_ids"])
164
+
165
+ print(float(result.loss))
166
+ ```
167
+
168
+ ## Tokenizer and context
169
+
170
+ - Every UTF-8 byte has a token, so ordinary text cannot become out-of-vocabulary.
171
+ - The four control tokens are `<pad>` (0), `<bos>` (1), `<eos>` (2), and `<unk>` (3).
172
+ - The context limit is 2,048 **byte tokens**, not 2,048 words or subword tokens.
173
+ - Non-ASCII text usually consumes multiple byte tokens per character.
174
+ - For long inputs, explicitly keep the most recent 2,048 tokens rather than relying
175
+ on implicit truncation.
176
+ - The tokenizer has no arithmetic-specific splitting, chat template, or hidden prompt
177
+ transformation.
178
+
179
+ ## Architecture
180
+
181
+ | Component | Configuration |
182
+ |---|---|
183
+ | Hidden width / layers | 128 / 6 |
184
+ | Token attention | 4 query heads, 2 key-value heads |
185
+ | Position encoding | Contiguous-half rotary embeddings, no scaling |
186
+ | CMA layout | 8 channel slots x 16 channels |
187
+ | CMA routing | 2 heads, expansion 2, content-dependent softmax mixing |
188
+ | CMA initialization | 90% diagonal routing prior with a dense base path |
189
+ | Feed-forward gate | SiLU-gated routed values |
190
+ | Normalization | RMSNorm |
191
+ | Embeddings | Input and output weights tied |
192
+ | Attention runtime | Native PyTorch scaled-dot-product attention |
193
+
194
+ For each token, CMA projects dense values, reshapes them into channel slots, and
195
+ learns a softmax mixing matrix between those slots. A bounded learned coefficient
196
+ controls the routed difference from the dense base value, so routing enriches rather
197
+ than replaces the fallback path.
198
+
199
+ The exported generation implementation does not maintain a KV cache. This keeps the
200
+ custom model compact and straightforward, but long autoregressive generations will
201
+ recompute the active context and are slower than cached generation.
202
+
203
+ ## Training data
204
+
205
+ The model was pretrained as a general causal language model on the following mixture.
206
+ Percentages describe the trained-token mixture.
207
+
208
+ | Source | Share |
209
+ |---|---:|
210
+ | [FineWeb-Edu 100BT](https://huggingface.co/datasets/HuggingFaceFW/fineweb_edu_100BT-shuffled) | 45% |
211
+ | [DCLM-Baseline 1.0](https://huggingface.co/datasets/mlfoundations/dclm-baseline-1.0-parquet) | 25% |
212
+ | [DCLM-Edu](https://huggingface.co/datasets/HuggingFaceTB/dclm-edu) | 10% |
213
+ | [Cosmopedia v2](https://huggingface.co/datasets/HuggingFaceTB/smollm-corpus) | 10% |
214
+ | [FineMath 4+](https://huggingface.co/datasets/HuggingFaceTB/finemath) | 10% |
215
+
216
+ No benchmark-specific prompts, task detectors, arithmetic vocabulary, or
217
+ inference-time answer rules are built into the model.
218
+
219
+ ## Evaluation
220
+
221
+ Evaluation is zero-shot. The four lm-eval tasks use normalized accuracy when
222
+ provided by lm-eval 0.4.12. ArithMark-2 uses raw continuation log-likelihood sums.
223
+ Weights are evaluated in BF16 with FP32 likelihood softmax and an automatic BOS
224
+ prefix.
225
+
226
+ | Benchmark | Accuracy |
227
+ |---|---:|
228
+ | HellaSwag | 29.35% |
229
+ | ARC-Easy | 29.29% |
230
+ | ARC-Challenge | 21.76% |
231
+ | PIQA | 54.62% |
232
+ | ArithMark-2 | 27.44% |
233
+ | **Open SLM Leaderboard-style average** | **34.23%** |
234
+
235
+ The combined score is
236
+ `(HellaSwag + mean(ARC-Easy, ARC-Challenge) + PIQA + ArithMark-2) / 4`.
237
+ This is a report-only reproduction of the leaderboard formula, not an official
238
+ leaderboard submission. WikiText-103 normalized validation BPB is **1.6974**.
239
+ Exact machine-readable results are available in
240
+ [`benchmark_results.json`](./benchmark_results.json).
241
+
242
+ ## Intended use and limitations
243
+
244
+ CMA-1M Mini is intended for architecture research, educational experiments,
245
+ lightweight language-model tooling, and controlled comparisons at tiny scale.
246
+
247
+ - At fewer than one million parameters, generations are short-range and frequently
248
+ incoherent; the model should not be treated as a knowledge source.
249
+ - It is not instruction-tuned, conversationally aligned, tool-using, or safety-tuned.
250
+ - Training data is predominantly English even though byte tokenization can represent
251
+ any UTF-8 text.
252
+ - Outputs may reproduce biases, inaccuracies, or undesirable patterns from public
253
+ training corpora.
254
+ - Do not use it for consequential medical, legal, financial, or safety decisions.
255
+ - Loading custom code executes files from the repository. Review the code or pin a
256
+ trusted revision in security-sensitive environments.
257
+
258
+ ## Repository contents
259
+
260
+ - `model.safetensors` — BF16 model weights
261
+ - `modeling_cma.py` — Transformers-compatible CMA implementation
262
+ - `config.json` and `generation_config.json` — architecture and decoding defaults
263
+ - `tokenizer.json` and `tokenizer_config.json` — deterministic byte tokenizer
264
+ - `benchmark_results.json` — exact evaluation metrics and protocol metadata
265
+ - `training_config.json` — reproducibility configuration
266
+
benchmark_results.json ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "step": 12000,
3
+ "parameters": 958692,
4
+ "lm_eval_version": "0.4.12",
5
+ "evaluation_dtype": "bfloat16",
6
+ "softmax_dtype": "float32",
7
+ "evaluation_autocast": false,
8
+ "num_fewshot": 0,
9
+ "bos_prefix": true,
10
+ "leaderboard_accuracy": {
11
+ "arc_easy": 0.29292929292929293,
12
+ "arc_challenge": 0.2175767918088737,
13
+ "hellaswag": 0.29346743676558457,
14
+ "piqa": 0.5462459194776932
15
+ },
16
+ "lm_eval_metric_policy": "acc_norm when available, otherwise acc",
17
+ "selection_metric": "validation.normalized_bpb (lower is better)",
18
+ "arithmark_2.0": {
19
+ "acc": 0.2744,
20
+ "correct": 686,
21
+ "total": 2500,
22
+ "by_operator_count": {
23
+ "1": {
24
+ "acc": 0.2552,
25
+ "correct": 319,
26
+ "total": 1250
27
+ },
28
+ "2": {
29
+ "acc": 0.30666666666666664,
30
+ "correct": 230,
31
+ "total": 750
32
+ },
33
+ "3": {
34
+ "acc": 0.274,
35
+ "correct": 137,
36
+ "total": 500
37
+ }
38
+ }
39
+ },
40
+ "arc_average": 0.2552530423690833,
41
+ "open_slm_leaderboard_average": 0.34234159965309024,
42
+ "average_formula": "(hellaswag + mean(arc_easy, arc_challenge) + piqa + arithmark_2.0) / 4",
43
+ "validation": {
44
+ "loss": 1.1765458586014317,
45
+ "perplexity": 3.2431525260156,
46
+ "normalized_bpb": 1.6973968755827331,
47
+ "tokens": 1144831,
48
+ "normalized_utf8_bytes": 1144831,
49
+ "window": 2048,
50
+ "stride": 1024
51
+ }
52
+ }
config.json ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "CMAForCausalLM"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "modeling_cma.CMAConfig",
7
+ "AutoModelForCausalLM": "modeling_cma.CMAForCausalLM"
8
+ },
9
+ "model_type": "cma",
10
+ "vocab_size": 260,
11
+ "seq_len": 2048,
12
+ "max_position_embeddings": 2048,
13
+ "n_positions": 2048,
14
+ "n_ctx": 2048,
15
+ "d_model": 128,
16
+ "n_layers": 6,
17
+ "n_heads": 4,
18
+ "n_kv_heads": 2,
19
+ "chunk": 16,
20
+ "cma_heads": 2,
21
+ "expand": 2,
22
+ "cma_identity_prob": 0.9,
23
+ "bos_token_id": 1,
24
+ "eos_token_id": 2,
25
+ "pad_token_id": 0,
26
+ "tie_word_embeddings": true,
27
+ "safe_serialization": true,
28
+ "minimum_torch_version": "2.5",
29
+ "torch_dtype": "bfloat16",
30
+ "transformers_version": "5.13.0"
31
+ }
generation_config.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token_id": 1,
3
+ "eos_token_id": 2,
4
+ "pad_token_id": 0,
5
+ "do_sample": false,
6
+ "repetition_penalty": 1.2
7
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:79ccdc8674a3bb2dd32c3d6eba6fffec2ed1e4e55254ad2ebf8dda1c42bf2c4b
3
+ size 2127320
modeling_cma.py ADDED
@@ -0,0 +1,375 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import math
3
+
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.nn.functional as F
7
+ # CMA is text-only. Disable Transformers' optional vision backend before it
8
+ # imports PreTrainedModel: some cloud images expose a system torchvision built
9
+ # against a different PyTorch, which otherwise crashes on torchvision::nms.
10
+ import transformers as _transformers
11
+ import transformers.utils as _transformers_utils
12
+ from transformers.utils import import_utils as _transformers_import_utils
13
+
14
+
15
+ def _cma_torchvision_unavailable():
16
+ return False
17
+
18
+
19
+ _transformers_import_utils._torchvision_available = False
20
+ _transformers_import_utils.is_torchvision_available = _cma_torchvision_unavailable
21
+ _transformers_import_utils.is_torchvision_v2_available = _cma_torchvision_unavailable
22
+ _transformers_utils.is_torchvision_available = _cma_torchvision_unavailable
23
+ _transformers_utils.is_torchvision_v2_available = _cma_torchvision_unavailable
24
+ _transformers.is_torchvision_available = _cma_torchvision_unavailable
25
+ _transformers.is_torchvision_v2_available = _cma_torchvision_unavailable
26
+ try:
27
+ from transformers import GenerationMixin
28
+ except ImportError:
29
+ from transformers.generation import GenerationMixin
30
+ from transformers import PretrainedConfig, PreTrainedModel
31
+ from transformers.modeling_outputs import CausalLMOutputWithPast
32
+
33
+
34
+ class CMAConfig(PretrainedConfig):
35
+ model_type = "cma"
36
+
37
+ def __init__(
38
+ self,
39
+ vocab_size=260,
40
+ seq_len=2048,
41
+ d_model=128,
42
+ n_layers=6,
43
+ n_heads=4,
44
+ n_kv_heads=2,
45
+ chunk=16,
46
+ cma_heads=2,
47
+ expand=2,
48
+ cma_identity_prob=0.90,
49
+ max_position_embeddings=None,
50
+ n_positions=None,
51
+ n_ctx=None,
52
+ **kwargs,
53
+ ):
54
+ super().__init__(**kwargs)
55
+ self.vocab_size = vocab_size
56
+ self.seq_len = seq_len
57
+ self.max_position_embeddings = max_position_embeddings or seq_len
58
+ self.n_positions = n_positions or self.max_position_embeddings
59
+ self.n_ctx = n_ctx or self.max_position_embeddings
60
+ self.d_model = d_model
61
+ self.n_layers = n_layers
62
+ self.n_heads = n_heads
63
+ self.n_kv_heads = n_kv_heads
64
+ self.chunk = chunk
65
+ self.cma_heads = cma_heads
66
+ self.expand = expand
67
+ self.cma_identity_prob = cma_identity_prob
68
+
69
+
70
+ class RMSNorm(nn.Module):
71
+ def __init__(self, d):
72
+ super().__init__()
73
+ self.w = nn.Parameter(torch.ones(d))
74
+
75
+ def forward(self, x):
76
+ return F.rms_norm(
77
+ x, (x.shape[-1],), self.w.to(dtype=x.dtype), eps=1e-6
78
+ )
79
+
80
+
81
+ def rope_cache(seq_len, head_dim, device, base=10000.0):
82
+ inv = 1.0 / (
83
+ base ** (torch.arange(0, head_dim, 2, device=device).float() / head_dim)
84
+ )
85
+ t = torch.arange(seq_len, device=device).float()
86
+ freqs = torch.outer(t, inv)
87
+ return torch.cos(freqs), torch.sin(freqs)
88
+
89
+
90
+ def apply_rope(x, cos, sin):
91
+ x1, x2 = x.chunk(2, dim=-1)
92
+ return torch.cat([x1 * cos - x2 * sin, x2 * cos + x1 * sin], dim=-1)
93
+
94
+
95
+ class TokenAttention(nn.Module):
96
+ def __init__(self, d, n_heads, n_kv_heads):
97
+ super().__init__()
98
+ if d % n_heads or n_heads % n_kv_heads:
99
+ raise ValueError("d_model % n_heads and n_heads % n_kv_heads must be zero.")
100
+ self.h, self.kv_h, self.hd = n_heads, n_kv_heads, d // n_heads
101
+ self.q = nn.Linear(d, d, bias=False)
102
+ self.k = nn.Linear(d, n_kv_heads * self.hd, bias=False)
103
+ self.v = nn.Linear(d, n_kv_heads * self.hd, bias=False)
104
+ self.o = nn.Linear(d, d, bias=False)
105
+ self.qn, self.kn = RMSNorm(self.hd), RMSNorm(self.hd)
106
+
107
+ def forward(self, x, cos, sin):
108
+ B, T, d = x.shape
109
+ q = self.q(x).view(B, T, self.h, self.hd).transpose(1, 2)
110
+ k = self.k(x).view(B, T, self.kv_h, self.hd).transpose(1, 2)
111
+ v = self.v(x).view(B, T, self.kv_h, self.hd).transpose(1, 2)
112
+ q, k = self.qn(q), self.kn(k)
113
+ q, k = apply_rope(q, cos, sin), apply_rope(k, cos, sin)
114
+ # Native GQA keeps compact K/V heads and lets SDPA select a fused CUDA
115
+ # implementation without materializing repeated K/V activations.
116
+ y = F.scaled_dot_product_attention(
117
+ q,
118
+ k,
119
+ v,
120
+ is_causal=True,
121
+ enable_gqa=self.h != self.kv_h,
122
+ )
123
+ return self.o(y.transpose(1, 2).reshape(B, T, d))
124
+
125
+
126
+ class CMA(nn.Module):
127
+ def __init__(self, d, chunk=16, heads=2, expand=2, identity_prob=0.90):
128
+ super().__init__()
129
+ if min(d, chunk, heads, expand) <= 0:
130
+ raise ValueError("CMA dimensions and expansion must be positive.")
131
+ if d % chunk or chunk % heads:
132
+ raise ValueError("CMA requires d % chunk == 0 and chunk % heads == 0.")
133
+ if d // chunk < 2:
134
+ raise ValueError("CMA requires at least two channel slots.")
135
+ if not 0.0 < identity_prob < 1.0:
136
+ raise ValueError("cma_identity_prob must be between zero and one.")
137
+
138
+ self.d, self.n, self.c, self.h = d, d // chunk, chunk, heads
139
+ self.hd, self.expand = chunk // heads, expand
140
+ self.chunk_emb = nn.Parameter(torch.randn(self.n, chunk) * 0.02)
141
+ self.wqk = nn.Parameter(torch.randn(self.n, chunk, 2 * chunk) * 0.02)
142
+ self.global_proj = nn.Linear(d, chunk, bias=False)
143
+ self.wv = nn.Linear(d, d * expand, bias=False)
144
+ self.bias = nn.Parameter(torch.zeros(heads, self.n, self.n))
145
+ self.qn, self.kn = RMSNorm(self.hd), RMSNorm(self.hd)
146
+ self.logit_scale = nn.Parameter(torch.zeros(heads))
147
+ self.layer_gain = nn.Parameter(torch.zeros(heads))
148
+ self.route_gate_weight = nn.Parameter(torch.randn(heads, self.hd) * 0.02)
149
+ self.route_gate_bias = nn.Parameter(torch.zeros(heads))
150
+ self.gate = nn.Linear(d, d * expand, bias=False)
151
+ self.o = nn.Linear(d * expand, d, bias=False)
152
+ nn.init.zeros_(self.o.weight)
153
+
154
+ diagonal_bias = math.log(
155
+ (self.n - 1) * identity_prob / (1.0 - identity_prob)
156
+ )
157
+ with torch.no_grad():
158
+ self.bias.add_(torch.eye(self.n) * diagonal_bias)
159
+
160
+ def _routing(self, x):
161
+ batch_tokens = x.numel() // self.d
162
+ xc = x.reshape(batch_tokens, self.n, self.c)
163
+ global_state = self.global_proj(x).reshape(batch_tokens, 1, self.c)
164
+ q_input = xc + self.chunk_emb + global_state
165
+ value_slots = self.wv(x).reshape(
166
+ batch_tokens, self.n, self.h, self.hd, self.expand
167
+ )
168
+ key_input = value_slots.mean(dim=-1).reshape(batch_tokens, self.n, self.c)
169
+ key_input = key_input + self.chunk_emb
170
+
171
+ q = torch.einsum("bnc,nco->bno", q_input, self.wqk[..., : self.c])
172
+ k = torch.einsum("bnc,nco->bno", key_input, self.wqk[..., self.c :])
173
+ v = value_slots.reshape(
174
+ batch_tokens, self.n, self.h, self.hd * self.expand
175
+ ).transpose(1, 2)
176
+ q = self.qn(q.reshape(batch_tokens, self.n, self.h, self.hd)).transpose(1, 2)
177
+ k = self.kn(k.reshape(batch_tokens, self.n, self.h, self.hd)).transpose(1, 2)
178
+ q = F.normalize(q.float(), dim=-1).to(v.dtype)
179
+ k = F.normalize(k.float(), dim=-1).to(v.dtype)
180
+
181
+ scale = self.logit_scale.clamp(max=math.log(100.0)).exp()
182
+ logits = (q * scale.view(1, self.h, 1, 1).to(q.dtype)) @ k.transpose(-2, -1)
183
+ logits = logits + self.bias.unsqueeze(0).to(logits.dtype)
184
+ attn = F.softmax(logits, dim=-1, dtype=torch.float32).to(v.dtype)
185
+ routed = attn @ v
186
+ route_signal = (
187
+ (q.float() * self.route_gate_weight.float().view(1, self.h, 1, self.hd)).sum(-1)
188
+ + self.route_gate_bias.float().view(1, self.h, 1)
189
+ + self.layer_gain.float().view(1, self.h, 1)
190
+ )
191
+ route_coeff = torch.tanh(route_signal).to(v.dtype)
192
+ contribution = route_coeff.unsqueeze(-1) * (routed - v)
193
+ return v, attn, route_coeff, contribution, logits
194
+
195
+ def forward(self, x):
196
+ B, T, _ = x.shape
197
+ v, _, _, contribution, _ = self._routing(x)
198
+ y = (v + contribution).transpose(1, 2).reshape(B, T, self.d * self.expand)
199
+ return self.o(y * F.silu(self.gate(x)))
200
+
201
+ @torch.no_grad()
202
+ def diagnostic_stats(self, x):
203
+ probe_count = x.shape[0] if x.ndim > 2 else 1
204
+ v, attn, route_coeff, contribution, logits = self._routing(x)
205
+ B, T, _ = x.shape
206
+ base = v.transpose(1, 2).reshape(B, T, self.d * self.expand)
207
+ routed = (v + contribution).transpose(1, 2).reshape(
208
+ B, T, self.d * self.expand
209
+ )
210
+ gate = F.silu(self.gate(x))
211
+ base_output = self.o(base * gate)
212
+ routed_output = self.o(routed * gate)
213
+ output_delta = (routed_output - base_output).reshape(-1, self.d)
214
+ token_effect = (
215
+ output_delta.float().norm(dim=-1)
216
+ / routed_output.reshape(-1, self.d).float().norm(dim=-1).clamp_min(1e-12)
217
+ )
218
+ probe_effect = token_effect.reshape(probe_count, -1).mean(dim=-1)
219
+ probs = attn.float().clamp_min(1e-9)
220
+ entropy = -(probs * probs.log()).sum(dim=-1) / math.log(self.n)
221
+ diagonal_mass = probs.diagonal(dim1=-2, dim2=-1).mean()
222
+ if self.h > 1:
223
+ flattened = probs.transpose(0, 1).reshape(self.h, -1)
224
+ normalized = F.normalize(flattened, dim=-1)
225
+ similarity = normalized @ normalized.mT
226
+ head_similarity = (
227
+ similarity.sum() - similarity.diagonal().sum()
228
+ ) / (self.h * (self.h - 1))
229
+ else:
230
+ head_similarity = probs.new_zeros(())
231
+ return {
232
+ "token_effect": token_effect,
233
+ "probe_effect": probe_effect,
234
+ "entropy": entropy.mean().item(),
235
+ "diagonal_mass": diagonal_mass.item(),
236
+ "head_similarity": head_similarity.item(),
237
+ "gate_abs": route_coeff.float().abs().mean().item(),
238
+ "gate_saturation": (route_coeff.float().abs() > 0.95).float().mean().item(),
239
+ "logit_max": logits.float().abs().max().item(),
240
+ }
241
+
242
+
243
+ class Block(nn.Module):
244
+ def __init__(self, config):
245
+ super().__init__()
246
+ d = config.d_model
247
+ self.n1, self.n2 = RMSNorm(d), RMSNorm(d)
248
+ self.attn = TokenAttention(d, config.n_heads, config.n_kv_heads)
249
+ self.mix = CMA(
250
+ d,
251
+ config.chunk,
252
+ config.cma_heads,
253
+ config.expand,
254
+ config.cma_identity_prob,
255
+ )
256
+
257
+ def forward(self, x, cos, sin):
258
+ x = x + self.attn(self.n1(x), cos, sin)
259
+ x = x + self.mix(self.n2(x))
260
+ return x
261
+
262
+
263
+ class CMAModel(nn.Module):
264
+ def __init__(self, config):
265
+ super().__init__()
266
+ d = config.d_model
267
+ self.config = config
268
+ self.emb = nn.Embedding(config.vocab_size, d)
269
+ self.blocks = nn.ModuleList(Block(config) for _ in range(config.n_layers))
270
+ self.norm = RMSNorm(d)
271
+ hd = d // config.n_heads
272
+ cos, sin = rope_cache(config.seq_len, hd, "cpu")
273
+ self.register_buffer("cos", cos)
274
+ self.register_buffer("sin", sin)
275
+
276
+ def forward_hidden(self, idx):
277
+ if idx.size(1) > self.config.seq_len:
278
+ idx = idx[:, -self.config.seq_len :]
279
+ x = self.emb(idx)
280
+ device_type = x.device.type
281
+ rope_dtype = (
282
+ torch.get_autocast_dtype(device_type)
283
+ if torch.is_autocast_enabled(device_type)
284
+ else x.dtype
285
+ )
286
+ cos = self.cos[: idx.size(1)].to(device=idx.device, dtype=rope_dtype)
287
+ sin = self.sin[: idx.size(1)].to(device=idx.device, dtype=rope_dtype)
288
+ for b in self.blocks:
289
+ x = b(x, cos, sin)
290
+ return self.norm(x)
291
+
292
+
293
+ class CMAForCausalLM(PreTrainedModel, GenerationMixin):
294
+ config_class = CMAConfig
295
+ base_model_prefix = "model"
296
+ _tied_weights_keys = {"head.weight": "model.emb.weight"}
297
+ all_tied_weights_keys = {"head.weight": "model.emb.weight"}
298
+
299
+ def __init__(self, config):
300
+ super().__init__(config)
301
+ self.model = CMAModel(config)
302
+ self.head = nn.Linear(config.d_model, config.vocab_size, bias=False)
303
+ # Modern Transformers creates loader metadata and performs configured
304
+ # tying in post_init(); omitting it leaves all_tied_weights_keys absent.
305
+ self.post_init()
306
+ self.head.weight = self.model.emb.weight
307
+
308
+ def get_input_embeddings(self):
309
+ return self.model.emb
310
+
311
+ def set_input_embeddings(self, value):
312
+ self.model.emb = value
313
+
314
+ def get_output_embeddings(self):
315
+ return self.head
316
+
317
+ def set_output_embeddings(self, new_embeddings):
318
+ self.head = new_embeddings
319
+
320
+ def raw_logits(self, idx):
321
+ return self.head(self.model.forward_hidden(idx))
322
+
323
+ def logits(self, idx):
324
+ return self.raw_logits(idx)
325
+
326
+ def _masked_logits(self, input_ids, attention_mask):
327
+ if attention_mask is None or bool(attention_mask.all()):
328
+ return self.logits(input_ids)
329
+
330
+ B, T = input_ids.shape
331
+ out = None
332
+ for i in range(B):
333
+ keep = attention_mask[i].bool().nonzero(as_tuple=False).flatten()
334
+ if keep.numel() == 0:
335
+ keep = torch.tensor([T - 1], device=input_ids.device)
336
+ trimmed = input_ids[i, keep].unsqueeze(0)
337
+ logits_i = self.logits(trimmed)
338
+ if out is None:
339
+ out = logits_i.new_zeros(B, T, logits_i.size(-1))
340
+ out[i, keep, :] = logits_i[0, -keep.numel() :, :]
341
+ return out
342
+
343
+ def forward(
344
+ self,
345
+ input_ids=None,
346
+ attention_mask=None,
347
+ labels=None,
348
+ use_cache=False,
349
+ past_key_values=None,
350
+ **kwargs,
351
+ ):
352
+ if input_ids.size(1) > self.config.seq_len:
353
+ input_ids = input_ids[:, -self.config.seq_len :]
354
+ if attention_mask is not None:
355
+ attention_mask = attention_mask[:, -self.config.seq_len :]
356
+ if labels is not None:
357
+ labels = labels[:, -self.config.seq_len :]
358
+ logits = self._masked_logits(input_ids, attention_mask)
359
+ loss = None
360
+ if labels is not None:
361
+ shift_logits = logits[:, :-1, :].contiguous()
362
+ shift_labels = labels[:, 1:].contiguous()
363
+ loss = F.cross_entropy(
364
+ shift_logits.view(-1, shift_logits.size(-1)).float(),
365
+ shift_labels.view(-1),
366
+ ignore_index=-100,
367
+ )
368
+ return CausalLMOutputWithPast(loss=loss, logits=logits, past_key_values=None)
369
+
370
+ def prepare_inputs_for_generation(self, input_ids, **kwargs):
371
+ attention_mask = kwargs.get("attention_mask")
372
+ result = {"input_ids": input_ids[:, -self.config.seq_len :]}
373
+ if attention_mask is not None:
374
+ result["attention_mask"] = attention_mask[:, -self.config.seq_len :]
375
+ return result
tokenizer.json ADDED
@@ -0,0 +1,377 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "version": "1.0",
3
+ "truncation": null,
4
+ "padding": null,
5
+ "added_tokens": [
6
+ {
7
+ "id": 0,
8
+ "content": "<pad>",
9
+ "single_word": false,
10
+ "lstrip": false,
11
+ "rstrip": false,
12
+ "normalized": false,
13
+ "special": true
14
+ },
15
+ {
16
+ "id": 1,
17
+ "content": "<bos>",
18
+ "single_word": false,
19
+ "lstrip": false,
20
+ "rstrip": false,
21
+ "normalized": false,
22
+ "special": true
23
+ },
24
+ {
25
+ "id": 2,
26
+ "content": "<eos>",
27
+ "single_word": false,
28
+ "lstrip": false,
29
+ "rstrip": false,
30
+ "normalized": false,
31
+ "special": true
32
+ },
33
+ {
34
+ "id": 3,
35
+ "content": "<unk>",
36
+ "single_word": false,
37
+ "lstrip": false,
38
+ "rstrip": false,
39
+ "normalized": false,
40
+ "special": true
41
+ }
42
+ ],
43
+ "normalizer": null,
44
+ "pre_tokenizer": {
45
+ "type": "ByteLevel",
46
+ "add_prefix_space": false,
47
+ "trim_offsets": true,
48
+ "use_regex": true
49
+ },
50
+ "post_processor": {
51
+ "type": "TemplateProcessing",
52
+ "single": [
53
+ {
54
+ "SpecialToken": {
55
+ "id": "<bos>",
56
+ "type_id": 0
57
+ }
58
+ },
59
+ {
60
+ "Sequence": {
61
+ "id": "A",
62
+ "type_id": 0
63
+ }
64
+ }
65
+ ],
66
+ "pair": [
67
+ {
68
+ "SpecialToken": {
69
+ "id": "<bos>",
70
+ "type_id": 0
71
+ }
72
+ },
73
+ {
74
+ "Sequence": {
75
+ "id": "A",
76
+ "type_id": 0
77
+ }
78
+ },
79
+ {
80
+ "Sequence": {
81
+ "id": "B",
82
+ "type_id": 0
83
+ }
84
+ }
85
+ ],
86
+ "special_tokens": {
87
+ "<bos>": {
88
+ "id": "<bos>",
89
+ "ids": [
90
+ 1
91
+ ],
92
+ "tokens": [
93
+ "<bos>"
94
+ ]
95
+ }
96
+ }
97
+ },
98
+ "decoder": {
99
+ "type": "ByteLevel",
100
+ "add_prefix_space": true,
101
+ "trim_offsets": true,
102
+ "use_regex": true
103
+ },
104
+ "model": {
105
+ "type": "BPE",
106
+ "dropout": null,
107
+ "unk_token": "<unk>",
108
+ "continuing_subword_prefix": null,
109
+ "end_of_word_suffix": null,
110
+ "fuse_unk": false,
111
+ "byte_fallback": false,
112
+ "ignore_merges": false,
113
+ "vocab": {
114
+ "<pad>": 0,
115
+ "<bos>": 1,
116
+ "<eos>": 2,
117
+ "<unk>": 3,
118
+ "!": 4,
119
+ "\"": 5,
120
+ "#": 6,
121
+ "$": 7,
122
+ "%": 8,
123
+ "&": 9,
124
+ "'": 10,
125
+ "(": 11,
126
+ ")": 12,
127
+ "*": 13,
128
+ "+": 14,
129
+ ",": 15,
130
+ "-": 16,
131
+ ".": 17,
132
+ "/": 18,
133
+ "0": 19,
134
+ "1": 20,
135
+ "2": 21,
136
+ "3": 22,
137
+ "4": 23,
138
+ "5": 24,
139
+ "6": 25,
140
+ "7": 26,
141
+ "8": 27,
142
+ "9": 28,
143
+ ":": 29,
144
+ ";": 30,
145
+ "<": 31,
146
+ "=": 32,
147
+ ">": 33,
148
+ "?": 34,
149
+ "@": 35,
150
+ "A": 36,
151
+ "B": 37,
152
+ "C": 38,
153
+ "D": 39,
154
+ "E": 40,
155
+ "F": 41,
156
+ "G": 42,
157
+ "H": 43,
158
+ "I": 44,
159
+ "J": 45,
160
+ "K": 46,
161
+ "L": 47,
162
+ "M": 48,
163
+ "N": 49,
164
+ "O": 50,
165
+ "P": 51,
166
+ "Q": 52,
167
+ "R": 53,
168
+ "S": 54,
169
+ "T": 55,
170
+ "U": 56,
171
+ "V": 57,
172
+ "W": 58,
173
+ "X": 59,
174
+ "Y": 60,
175
+ "Z": 61,
176
+ "[": 62,
177
+ "\\": 63,
178
+ "]": 64,
179
+ "^": 65,
180
+ "_": 66,
181
+ "`": 67,
182
+ "a": 68,
183
+ "b": 69,
184
+ "c": 70,
185
+ "d": 71,
186
+ "e": 72,
187
+ "f": 73,
188
+ "g": 74,
189
+ "h": 75,
190
+ "i": 76,
191
+ "j": 77,
192
+ "k": 78,
193
+ "l": 79,
194
+ "m": 80,
195
+ "n": 81,
196
+ "o": 82,
197
+ "p": 83,
198
+ "q": 84,
199
+ "r": 85,
200
+ "s": 86,
201
+ "t": 87,
202
+ "u": 88,
203
+ "v": 89,
204
+ "w": 90,
205
+ "x": 91,
206
+ "y": 92,
207
+ "z": 93,
208
+ "{": 94,
209
+ "|": 95,
210
+ "}": 96,
211
+ "~": 97,
212
+ "¡": 98,
213
+ "¢": 99,
214
+ "£": 100,
215
+ "¤": 101,
216
+ "¥": 102,
217
+ "¦": 103,
218
+ "§": 104,
219
+ "¨": 105,
220
+ "©": 106,
221
+ "ª": 107,
222
+ "«": 108,
223
+ "¬": 109,
224
+ "®": 110,
225
+ "¯": 111,
226
+ "°": 112,
227
+ "±": 113,
228
+ "²": 114,
229
+ "³": 115,
230
+ "´": 116,
231
+ "µ": 117,
232
+ "¶": 118,
233
+ "·": 119,
234
+ "¸": 120,
235
+ "¹": 121,
236
+ "º": 122,
237
+ "»": 123,
238
+ "¼": 124,
239
+ "½": 125,
240
+ "¾": 126,
241
+ "¿": 127,
242
+ "À": 128,
243
+ "Á": 129,
244
+ "Â": 130,
245
+ "Ã": 131,
246
+ "Ä": 132,
247
+ "Å": 133,
248
+ "Æ": 134,
249
+ "Ç": 135,
250
+ "È": 136,
251
+ "É": 137,
252
+ "Ê": 138,
253
+ "Ë": 139,
254
+ "Ì": 140,
255
+ "Í": 141,
256
+ "Î": 142,
257
+ "Ï": 143,
258
+ "Ð": 144,
259
+ "Ñ": 145,
260
+ "Ò": 146,
261
+ "Ó": 147,
262
+ "Ô": 148,
263
+ "Õ": 149,
264
+ "Ö": 150,
265
+ "×": 151,
266
+ "Ø": 152,
267
+ "Ù": 153,
268
+ "Ú": 154,
269
+ "Û": 155,
270
+ "Ü": 156,
271
+ "Ý": 157,
272
+ "Þ": 158,
273
+ "ß": 159,
274
+ "à": 160,
275
+ "á": 161,
276
+ "â": 162,
277
+ "ã": 163,
278
+ "ä": 164,
279
+ "å": 165,
280
+ "æ": 166,
281
+ "ç": 167,
282
+ "è": 168,
283
+ "é": 169,
284
+ "ê": 170,
285
+ "ë": 171,
286
+ "ì": 172,
287
+ "í": 173,
288
+ "î": 174,
289
+ "ï": 175,
290
+ "ð": 176,
291
+ "ñ": 177,
292
+ "ò": 178,
293
+ "ó": 179,
294
+ "ô": 180,
295
+ "õ": 181,
296
+ "ö": 182,
297
+ "÷": 183,
298
+ "ø": 184,
299
+ "ù": 185,
300
+ "ú": 186,
301
+ "û": 187,
302
+ "ü": 188,
303
+ "ý": 189,
304
+ "þ": 190,
305
+ "ÿ": 191,
306
+ "Ā": 192,
307
+ "ā": 193,
308
+ "Ă": 194,
309
+ "ă": 195,
310
+ "Ą": 196,
311
+ "ą": 197,
312
+ "Ć": 198,
313
+ "ć": 199,
314
+ "Ĉ": 200,
315
+ "ĉ": 201,
316
+ "Ċ": 202,
317
+ "ċ": 203,
318
+ "Č": 204,
319
+ "č": 205,
320
+ "Ď": 206,
321
+ "ď": 207,
322
+ "Đ": 208,
323
+ "đ": 209,
324
+ "Ē": 210,
325
+ "ē": 211,
326
+ "Ĕ": 212,
327
+ "ĕ": 213,
328
+ "Ė": 214,
329
+ "ė": 215,
330
+ "Ę": 216,
331
+ "ę": 217,
332
+ "Ě": 218,
333
+ "ě": 219,
334
+ "Ĝ": 220,
335
+ "ĝ": 221,
336
+ "Ğ": 222,
337
+ "ğ": 223,
338
+ "Ġ": 224,
339
+ "ġ": 225,
340
+ "Ģ": 226,
341
+ "ģ": 227,
342
+ "Ĥ": 228,
343
+ "ĥ": 229,
344
+ "Ħ": 230,
345
+ "ħ": 231,
346
+ "Ĩ": 232,
347
+ "ĩ": 233,
348
+ "Ī": 234,
349
+ "ī": 235,
350
+ "Ĭ": 236,
351
+ "ĭ": 237,
352
+ "Į": 238,
353
+ "į": 239,
354
+ "İ": 240,
355
+ "ı": 241,
356
+ "IJ": 242,
357
+ "ij": 243,
358
+ "Ĵ": 244,
359
+ "ĵ": 245,
360
+ "Ķ": 246,
361
+ "ķ": 247,
362
+ "ĸ": 248,
363
+ "Ĺ": 249,
364
+ "ĺ": 250,
365
+ "Ļ": 251,
366
+ "ļ": 252,
367
+ "Ľ": 253,
368
+ "ľ": 254,
369
+ "Ŀ": 255,
370
+ "ŀ": 256,
371
+ "Ł": 257,
372
+ "ł": 258,
373
+ "Ń": 259
374
+ },
375
+ "merges": []
376
+ }
377
+ }
tokenizer_config.json ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "bos_token": "<bos>",
4
+ "clean_up_tokenization_spaces": false,
5
+ "eos_token": "<eos>",
6
+ "model_max_length": 2048,
7
+ "pad_token": "<pad>",
8
+ "tokenizer_class": "TokenizersBackend",
9
+ "unk_token": "<unk>"
10
+ }
training_config.json ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "steps": 20000,
3
+ "batch_size": 512,
4
+ "grad_accum": 4,
5
+ "seq_len": 2048,
6
+ "eval_seq_len": 2048,
7
+ "d_model": 128,
8
+ "n_layers": 6,
9
+ "n_heads": 4,
10
+ "n_kv_heads": 2,
11
+ "chunk": 16,
12
+ "cma_heads": 2,
13
+ "expand": 2,
14
+ "cma_identity_prob": 0.9,
15
+ "lr": 0.001,
16
+ "muon_momentum": 0.95,
17
+ "muon_ns_steps": 5,
18
+ "muon_adjust_lr_fn": "match_rms_adamw",
19
+ "warmup": 500,
20
+ "wd": 0.01,
21
+ "grad_clip": 5.0,
22
+ "log_every": 5,
23
+ "early_eval_step": 1000,
24
+ "diag_every": 1000,
25
+ "eval_every": 2000,
26
+ "val_batch_size": 32,
27
+ "val_batches": 0,
28
+ "val_stride": 1024,
29
+ "infer_tokens": 512,
30
+ "infer_repeat_penalty": 1.2,
31
+ "infer_prompt": "The process of photosynthesis",
32
+ "lm_eval_tasks": "arc_easy,arc_challenge,hellaswag,piqa",
33
+ "lm_eval_batch_size": "auto",
34
+ "lm_eval_device": "cuda",
35
+ "lm_eval_dtype": "bfloat16",
36
+ "lm_eval_softmax_dtype": "float32",
37
+ "lm_eval_expected_version": "0.4.12",
38
+ "lm_eval_retries": 3,
39
+ "lm_eval_export_dir": "CMA_1M_Mini_lm_eval_hf",
40
+ "lm_eval_output_dir": "lm_eval_results_CMA_1M_Mini",
41
+ "arithmark_batch_size": 16,
42
+ "arithmark_data_path": "benchmark_cache/arithmark_2.0.jsonl",
43
+ "arithmark_force_download": false,
44
+ "recipe_version": "CMA_1M_mini_byte_c16_h2_e2_muon_w500_cosine20k_b512_ga4_ctx2k_async_v7",
45
+ "hf_repo_id": "User01110/CMA-1M-Mini",
46
+ "hf_repo_private": false,
47
+ "hub_upload_retries": 3,
48
+ "tokenizer_name": "local-byte-level",
49
+ "tokenizer_revision": "byte-v1",
50
+ "data_seed": 1337,
51
+ "shuffle_buffer": 50000,
52
+ "tokenize_batch_size": 64,
53
+ "compile": true
54
+ }