Angshul commited on
Commit
ea51a3d
·
verified ·
1 Parent(s): 8387861

Release TransWave 96.13M C4 checkpoint

Browse files
CITATION.cff ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ cff-version: 1.2.0
2
+ message: "If you use TransWave, please cite this software repository."
3
+ title: "TransWave"
4
+ type: software
5
+ authors:
6
+ - family-names: "Majumdar"
7
+ given-names: "Angshul"
8
+ year: 2026
9
+ version: 1.0.0
README.md ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: agpl-3.0
3
+ language:
4
+ - en
5
+ library_name: transformers
6
+ datasets:
7
+ - allenai/c4
8
+ tags:
9
+ - causal-lm
10
+ - byte-level
11
+ - raw-byte
12
+ - attention-free
13
+ - meyer
14
+ - wavelet
15
+ ---
16
+
17
+
18
+ # TransWave
19
+
20
+
21
+ TransWave is a 96.13M-parameter attention-free causal raw-byte language model using learned block-local lifting and learned Meyer-structured multiresolution memory.
22
+
23
+
24
+ This repository contains the best checkpoint from the completed C4 English pretraining run.
25
+
26
+
27
+ ## Checkpoint
28
+
29
+
30
+ - Architecture: `causal_transwave_blocklifting_meyer_byte_lm_g4_v2`
31
+ - Parameters: 96,130,040
32
+ - Input vocabulary: 256 raw byte values
33
+ - External BPE/SentencePiece tokenizer: none
34
+ - Trained C4 context: 20,480 model tokens
35
+ - Structural architecture maximum: 32,768 raw-byte tokens
36
+ - Physical training batch: 280
37
+ - Training tokens consumed: 4,499,988,480
38
+ - Optimizer steps: 785
39
+ - Dataset: `allenai/c4:en`
40
+ - Objective: exact causal next-byte NLL
41
+ - Source commit: `5cae31b81e15160379ded79f32bcbb443d7db9f7`
42
+
43
+
44
+ One model token is one raw UTF-8 byte.
45
+
46
+
47
+ ## Validation result
48
+
49
+
50
+ The run exhausted its 4.5B-token budget before reaching the PPL=3 early-stop target.
51
+
52
+
53
+ - Best/final held-out NLL: 2.228725893
54
+ - Best/final byte perplexity: 9.288024598
55
+ - Validation tokens: 16,773,120
56
+
57
+
58
+ ## Tokenization
59
+
60
+
61
+ There are two distinct layers and they should not be conflated.
62
+
63
+
64
+ `TransWaveByteTokenizer` is the Hugging Face input codec. It converts text to raw UTF-8 byte IDs 0...255 and back. It has no BPE merges and no learned external vocabulary.
65
+
66
+
67
+ The learned tokenizer is inside the neural network itself. `CTWBlockLiftingTokenizer` contains the trained shared byte embedding, three learned lifting stages and the learned cross-scale mixer. Those learned parameters are contained in `best_model.pt` and are loaded as part of `CTWModel`.
68
+
69
+
70
+ ## Architecture
71
+
72
+
73
+ Eight raw bytes form one block. A shared 256-entry embedding maps each byte to 96 channels. Three learned block-local lifting stages recursively produce eight multiresolution scales, giving a 768-dimensional block state.
74
+
75
+
76
+ Each of 12 layers combines a learned 512-block causal Meyer/Bernstein spectral FIR, learned full 8x8 scale mixing, learned spectral gates, a separate strictly causal DWConv7 path, RMS normalization and a SwiGLU feed-forward network of width 2816.
77
+
78
+
79
+ The global block representation is shifted by one block before decoding: block b is predicted from h[b-1], never h[b]. Within each target block, an 8-step GRUCell decoder of width 256 predicts bytes autoregressively while reusing the shared byte embedding for the classifier.
80
+
81
+
82
+ ## Load
83
+
84
+
85
+ ```python
86
+ import torch
87
+ from transformers import AutoTokenizer, AutoModelForCausalLM
88
+
89
+
90
+ repo = "Angshul/TransWave"
91
+
92
+
93
+ tokenizer = AutoTokenizer.from_pretrained(
94
+ repo,
95
+ trust_remote_code=True,
96
+ use_fast=False,
97
+ )
98
+
99
+
100
+ model = AutoModelForCausalLM.from_pretrained(
101
+ repo,
102
+ trust_remote_code=True,
103
+ ).eval()
104
+
105
+
106
+ ids = tokenizer(
107
+ "TransWave operates on raw UTF-8 bytes.",
108
+ return_tensors="pt",
109
+ )["input_ids"]
110
+
111
+
112
+ # Exact scoring currently requires complete 8-byte blocks.
113
+ ids = ids[:, : (ids.shape[1] // 8) * 8]
114
+
115
+
116
+ with torch.no_grad():
117
+ out = model(input_ids=ids, labels=ids)
118
+
119
+
120
+ print("NLL:", float(out.loss))
121
+ print("PPL:", float(torch.exp(out.loss)))
122
+ ```
123
+
124
+
125
+ ## Reference byte generation
126
+
127
+
128
+ The custom model exposes `generate_bytes`, an exact but deliberately simple reference generator:
129
+
130
+
131
+ ```python
132
+ prompt = tokenizer("The future of", return_tensors="pt")["input_ids"]
133
+
134
+
135
+ generated = model.generate_bytes(
136
+ prompt,
137
+ max_new_tokens=64,
138
+ do_sample=True,
139
+ temperature=0.8,
140
+ top_k=40,
141
+ )
142
+
143
+
144
+ print(tokenizer.decode(generated[0].tolist()))
145
+ ```
146
+
147
+
148
+ The reference generator recomputes completed-block context as needed; it is intended for correctness and checkpoint inspection, not optimized streaming throughput.
149
+
150
+
151
+ ## Context note
152
+
153
+
154
+ The architecture contains positional parameters for 4,096 eight-byte blocks = 32,768 raw-byte tokens. This checkpoint was trained on 20,480-token C4 contexts, so positions beyond 20,480 were not exercised in this C4 pretraining run.
155
+
156
+
157
+ ## Provenance
158
+
159
+
160
+ Implementation: https://github.com/AngshulMajumdar/TransWaveV1
161
+
162
+
163
+ Paper: https://openreview.net/forum?id=3a22WBU5kT
164
+
165
+
166
+ The Hugging Face portability layer preserves the trained architecture. The only device-portability change in `transwave_core.py` is that the two explicitly-disabled CUDA autocast regions in the Meyer FFT path use the parameter device type, allowing the checkpoint to load and score on CPU as well as CUDA.
SOURCE_COMMIT.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ 5cae31b81e15160379ded79f32bcbb443d7db9f7
__init__.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from .configuration_transwave import TransWaveConfig
2
+ from .modeling_transwave import TransWaveForCausalLM
3
+ from .tokenization_transwave import TransWaveByteTokenizer
4
+
5
+
6
+ __all__ = ["TransWaveConfig", "TransWaveForCausalLM", "TransWaveByteTokenizer"]
best_model.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cf398ece0870515225b15e0038cfd6715aa4ab00d5152a7f6164e1ede1724086
3
+ size 384624999
config.json ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "transwave_meyer",
3
+ "architectures": ["TransWaveForCausalLM"],
4
+ "auto_map": {
5
+ "AutoConfig": "configuration_transwave.TransWaveConfig",
6
+ "AutoModelForCausalLM": "modeling_transwave.TransWaveForCausalLM"
7
+ },
8
+ "vocab_size": 256,
9
+ "byte_dim": 96,
10
+ "bytes_per_block": 8,
11
+ "num_scales": 8,
12
+ "hidden_size": 768,
13
+ "max_position_embeddings": 32768,
14
+ "block_context": 4096,
15
+ "num_hidden_layers": 12,
16
+ "num_groups": 12,
17
+ "meyer_bands": 12,
18
+ "meyer_controls_per_band": 8,
19
+ "meyer_kernel_blocks": 512,
20
+ "local_kernel_blocks": 7,
21
+ "intermediate_size": 2816,
22
+ "decoder_hidden_size": 256,
23
+ "trained_context_length": 20480,
24
+ "architecture_id": "causal_transwave_blocklifting_meyer_byte_lm_g4_v2",
25
+ "training_dataset": "allenai/c4:en",
26
+ "training_tokens": 4499988480,
27
+ "training_steps": 785,
28
+ "training_physical_batch": 280,
29
+ "validation_nll": 2.228725892720205,
30
+ "validation_ppl": 9.288024597671594,
31
+ "source_commit": "5cae31b81e15160379ded79f32bcbb443d7db9f7",
32
+ "tie_word_embeddings": true
33
+ }
configuration_transwave.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import PretrainedConfig
2
+
3
+
4
+ class TransWaveConfig(PretrainedConfig):
5
+
6
+ model_type = "transwave_meyer"
7
+
8
+
9
+ def __init__(
10
+ self,
11
+ vocab_size=256,
12
+ byte_dim=96,
13
+ bytes_per_block=8,
14
+ num_scales=8,
15
+ hidden_size=768,
16
+ max_position_embeddings=32768,
17
+ block_context=4096,
18
+ num_hidden_layers=12,
19
+ num_groups=12,
20
+ meyer_bands=12,
21
+ meyer_controls_per_band=8,
22
+ meyer_kernel_blocks=512,
23
+ local_kernel_blocks=7,
24
+ intermediate_size=2816,
25
+ decoder_hidden_size=256,
26
+ trained_context_length=20480,
27
+ architecture_id="causal_transwave_blocklifting_meyer_byte_lm_g4_v2",
28
+ **kwargs,
29
+ ):
30
+
31
+ # config.json may already supply this.
32
+ # Never provide it twice.
33
+
34
+ kwargs.setdefault(
35
+ "tie_word_embeddings",
36
+ True,
37
+ )
38
+
39
+ super().__init__(
40
+ **kwargs
41
+ )
42
+
43
+ self.vocab_size = vocab_size
44
+
45
+ self.byte_dim = byte_dim
46
+
47
+ self.bytes_per_block = bytes_per_block
48
+
49
+ self.num_scales = num_scales
50
+
51
+ self.hidden_size = hidden_size
52
+
53
+ self.max_position_embeddings = (
54
+ max_position_embeddings
55
+ )
56
+
57
+ self.block_context = block_context
58
+
59
+ self.num_hidden_layers = (
60
+ num_hidden_layers
61
+ )
62
+
63
+ self.num_groups = num_groups
64
+
65
+ self.meyer_bands = meyer_bands
66
+
67
+ self.meyer_controls_per_band = (
68
+ meyer_controls_per_band
69
+ )
70
+
71
+ self.meyer_kernel_blocks = (
72
+ meyer_kernel_blocks
73
+ )
74
+
75
+ self.local_kernel_blocks = (
76
+ local_kernel_blocks
77
+ )
78
+
79
+ self.intermediate_size = (
80
+ intermediate_size
81
+ )
82
+
83
+ self.decoder_hidden_size = (
84
+ decoder_hidden_size
85
+ )
86
+
87
+ self.trained_context_length = (
88
+ trained_context_length
89
+ )
90
+
91
+ self.architecture_id = (
92
+ architecture_id
93
+ )
modeling_transwave.py ADDED
@@ -0,0 +1,300 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+
4
+ import os
5
+ import torch
6
+ import torch.nn.functional as F
7
+
8
+
9
+ from huggingface_hub import hf_hub_download
10
+ from transformers import PreTrainedModel
11
+ from transformers.modeling_outputs import CausalLMOutput
12
+
13
+
14
+ try:
15
+ from .configuration_transwave import TransWaveConfig
16
+ from .transwave_core import (
17
+ CTWModel,
18
+ BYTE_VOCAB,
19
+ BYTE_DIM,
20
+ BYTES_PER_BLOCK,
21
+ BYTE_DECODER_DIM,
22
+ )
23
+ except ImportError:
24
+ from configuration_transwave import TransWaveConfig
25
+ from transwave_core import (
26
+ CTWModel,
27
+ BYTE_VOCAB,
28
+ BYTE_DIM,
29
+ BYTES_PER_BLOCK,
30
+ BYTE_DECODER_DIM,
31
+ )
32
+
33
+
34
+
35
+
36
+ EXPECTED_PARAMS = 96_130_040
37
+
38
+
39
+
40
+
41
+ class TransWaveForCausalLM(PreTrainedModel):
42
+ config_class = TransWaveConfig
43
+ base_model_prefix = "transwave"
44
+ main_input_name = "input_ids"
45
+ _tied_weights_keys = ["transwave.decoder.shared_embedding.weight"]
46
+
47
+
48
+ def __init__(self, config):
49
+ super().__init__(config)
50
+ self.transwave = CTWModel()
51
+ # Do not call post_init(): CTWModel already performs the architecture's
52
+ # exact initialization. The trained checkpoint is loaded afterwards.
53
+
54
+
55
+ def get_input_embeddings(self):
56
+ return self.transwave.tokenizer.byte_embedding
57
+
58
+
59
+ def set_input_embeddings(self, value):
60
+ self.transwave.tokenizer.byte_embedding = value
61
+ self.transwave.decoder.shared_embedding = value
62
+
63
+
64
+ def get_output_embeddings(self):
65
+ return self.transwave.decoder.shared_embedding
66
+
67
+
68
+ @classmethod
69
+ def from_pretrained(cls, pretrained_model_name_or_path, *model_args, **kwargs):
70
+ config = kwargs.pop("config", None)
71
+ revision = kwargs.pop("revision", None)
72
+ cache_dir = kwargs.pop("cache_dir", None)
73
+ token = kwargs.pop("token", None)
74
+ local_files_only = kwargs.pop("local_files_only", False)
75
+ torch_dtype = kwargs.pop("torch_dtype", None)
76
+ kwargs.pop("trust_remote_code", None)
77
+ kwargs.pop("use_safetensors", None)
78
+
79
+
80
+ if config is None:
81
+ config = TransWaveConfig.from_pretrained(
82
+ pretrained_model_name_or_path,
83
+ revision=revision,
84
+ cache_dir=cache_dir,
85
+ token=token,
86
+ local_files_only=local_files_only,
87
+ )
88
+
89
+
90
+ model = cls(config)
91
+
92
+
93
+ path = os.fspath(pretrained_model_name_or_path)
94
+ if os.path.isdir(path):
95
+ ckpt_path = os.path.join(path, "best_model.pt")
96
+ else:
97
+ ckpt_path = hf_hub_download(
98
+ repo_id=path,
99
+ filename="best_model.pt",
100
+ revision=revision,
101
+ cache_dir=cache_dir,
102
+ token=token,
103
+ local_files_only=local_files_only,
104
+ )
105
+
106
+
107
+ checkpoint = torch.load(
108
+ ckpt_path,
109
+ map_location="cpu",
110
+ weights_only=False,
111
+ )
112
+ state = checkpoint["model"] if isinstance(checkpoint, dict) and "model" in checkpoint else checkpoint
113
+
114
+
115
+ incompatible = model.transwave.load_state_dict(state, strict=True)
116
+ if incompatible.missing_keys or incompatible.unexpected_keys:
117
+ raise RuntimeError(
118
+ f"Checkpoint mismatch. Missing={incompatible.missing_keys}, "
119
+ f"unexpected={incompatible.unexpected_keys}"
120
+ )
121
+
122
+
123
+ n_params = sum(p.numel() for p in model.transwave.parameters())
124
+ if n_params != EXPECTED_PARAMS:
125
+ raise RuntimeError(f"Parameter count {n_params:,} != {EXPECTED_PARAMS:,}")
126
+
127
+
128
+ if torch_dtype not in (None, "auto"):
129
+ model = model.to(dtype=torch_dtype)
130
+
131
+
132
+ model.eval()
133
+ return model
134
+
135
+
136
+ def nll(self, input_ids, checkpoint_layers=False):
137
+ return self.transwave.nll(
138
+ input_ids,
139
+ checkpoint_layers=checkpoint_layers,
140
+ )
141
+
142
+
143
+ def contexts(self, input_ids, checkpoint_layers=False):
144
+ return self.transwave.contexts(
145
+ input_ids,
146
+ checkpoint_layers=checkpoint_layers,
147
+ )
148
+
149
+
150
+ def teacher_forced_logits(self, input_ids):
151
+ context, target_blocks = self.transwave.contexts(
152
+ input_ids,
153
+ checkpoint_layers=False,
154
+ )
155
+ decoder = self.transwave.decoder
156
+ batch, blocks, _ = context.shape
157
+ n = batch * blocks
158
+
159
+
160
+ hidden = torch.tanh(
161
+ decoder.context_proj(context)
162
+ ).reshape(n, BYTE_DECODER_DIM)
163
+
164
+
165
+ previous = decoder.bos[None, :].expand(n, -1)
166
+ position_logits = []
167
+
168
+
169
+ for r in range(BYTES_PER_BLOCK):
170
+ decoder_input = previous + decoder.byte_position[r][None, :]
171
+ hidden = decoder.gru(decoder_input, hidden)
172
+ z = decoder.to_byte_space(decoder.norm(hidden))
173
+ logits = F.linear(z, decoder.shared_embedding.weight)
174
+ position_logits.append(
175
+ logits.reshape(batch, blocks, BYTE_VOCAB)
176
+ )
177
+ target = target_blocks[:, :, r].reshape(-1).long()
178
+ previous = decoder.shared_embedding(target)
179
+
180
+
181
+ logits = torch.stack(position_logits, dim=2)
182
+ return logits.reshape(
183
+ batch,
184
+ blocks * BYTES_PER_BLOCK,
185
+ BYTE_VOCAB,
186
+ )
187
+
188
+
189
+ def forward(
190
+ self,
191
+ input_ids=None,
192
+ labels=None,
193
+ return_dict=None,
194
+ **kwargs,
195
+ ):
196
+ if input_ids is None:
197
+ raise ValueError("input_ids are required")
198
+ if input_ids.ndim != 2:
199
+ raise ValueError("input_ids must have shape [batch, tokens]")
200
+ if input_ids.shape[1] % BYTES_PER_BLOCK != 0:
201
+ raise ValueError("TransWave scoring length must be divisible by 8")
202
+
203
+
204
+ if labels is not None:
205
+ if labels.shape != input_ids.shape or not torch.equal(labels, input_ids):
206
+ raise ValueError(
207
+ "TransWave performs the causal shift internally; "
208
+ "for exact scoring/training, labels must equal input_ids."
209
+ )
210
+
211
+
212
+ logits = self.teacher_forced_logits(input_ids)
213
+ loss = self.transwave.nll(
214
+ input_ids,
215
+ checkpoint_layers=False,
216
+ )
217
+
218
+
219
+ if return_dict is False:
220
+ return (loss, logits)
221
+
222
+
223
+ return CausalLMOutput(
224
+ loss=loss,
225
+ logits=logits,
226
+ )
227
+
228
+
229
+ @torch.no_grad()
230
+ def generate_bytes(
231
+ self,
232
+ input_ids,
233
+ max_new_tokens=32,
234
+ do_sample=False,
235
+ temperature=1.0,
236
+ top_k=None,
237
+ ):
238
+ if input_ids.ndim != 2 or input_ids.shape[0] != 1:
239
+ raise ValueError("generate_bytes currently supports batch size 1")
240
+ out = input_ids.long().clone()
241
+ device = next(self.parameters()).device
242
+ out = out.to(device)
243
+
244
+
245
+ for _ in range(int(max_new_tokens)):
246
+ total = out.shape[1]
247
+ complete = (total // BYTES_PER_BLOCK) * BYTES_PER_BLOCK
248
+ r = total - complete
249
+
250
+
251
+ if complete == 0:
252
+ block_context = self.transwave.bos_context[None, :].to(device)
253
+ else:
254
+ _, blocks = self.transwave.encode_completed_blocks(
255
+ out[:, :complete],
256
+ checkpoint_layers=False,
257
+ )
258
+ h, _ = self.transwave.encode_completed_blocks(
259
+ out[:, :complete],
260
+ checkpoint_layers=False,
261
+ )
262
+ block_context = h[:, -1, :]
263
+
264
+
265
+ decoder = self.transwave.decoder
266
+ hidden = torch.tanh(decoder.context_proj(block_context))
267
+ previous = decoder.bos[None, :]
268
+
269
+
270
+ current = out[:, complete:]
271
+ logits = None
272
+ for j in range(r + 1):
273
+ decoder_input = previous + decoder.byte_position[j][None, :]
274
+ hidden = decoder.gru(decoder_input, hidden)
275
+ z = decoder.to_byte_space(decoder.norm(hidden))
276
+ logits = F.linear(z, decoder.shared_embedding.weight)
277
+ if j < r:
278
+ previous = decoder.shared_embedding(current[:, j])
279
+
280
+
281
+ scores = logits.float() / max(float(temperature), 1e-6)
282
+ if top_k is not None and int(top_k) > 0:
283
+ k = min(int(top_k), BYTE_VOCAB)
284
+ threshold = torch.topk(scores, k, dim=-1).values[:, -1:]
285
+ scores = scores.masked_fill(scores < threshold, float("-inf"))
286
+
287
+
288
+ if do_sample:
289
+ next_id = torch.multinomial(
290
+ torch.softmax(scores, dim=-1),
291
+ num_samples=1,
292
+ )
293
+ else:
294
+ next_id = scores.argmax(dim=-1, keepdim=True)
295
+
296
+
297
+ out = torch.cat([out, next_id], dim=1)
298
+
299
+
300
+ return out
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ torch>=2.5
2
+ numpy>=1.26
3
+ transformers>=4.46,<5
4
+ huggingface_hub>=0.26
smoke_test.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+
4
+ import math
5
+ from pathlib import Path
6
+
7
+
8
+ import torch
9
+ from transformers import AutoConfig, AutoModelForCausalLM, AutoTokenizer
10
+
11
+
12
+ ROOT = Path(__file__).resolve().parent
13
+ EXPECTED_PARAMS = 96_130_040
14
+
15
+
16
+ print("1/6 tokenizer load + UTF-8 round trip")
17
+ tok = AutoTokenizer.from_pretrained(
18
+ ROOT,
19
+ trust_remote_code=True,
20
+ use_fast=False,
21
+ )
22
+ sample = "TransWave — raw bytes ✓"
23
+ ids = tok(sample, return_tensors="pt")["input_ids"]
24
+ decoded = tok.decode(ids[0].tolist())
25
+ assert decoded == sample, (decoded, sample)
26
+ assert tok.vocab_size == 256
27
+
28
+
29
+ print("2/6 config")
30
+ cfg = AutoConfig.from_pretrained(ROOT, trust_remote_code=True)
31
+ assert cfg.architecture_id == "causal_transwave_blocklifting_meyer_byte_lm_g4_v2"
32
+ assert cfg.trained_context_length == 20480
33
+ assert cfg.vocab_size == 256
34
+
35
+
36
+ print("3/6 trained checkpoint load")
37
+ model = AutoModelForCausalLM.from_pretrained(
38
+ ROOT,
39
+ trust_remote_code=True,
40
+ ).eval()
41
+ n = sum(p.numel() for p in model.transwave.parameters())
42
+ assert n == EXPECTED_PARAMS, n
43
+
44
+
45
+ print("4/6 exact finite NLL")
46
+ torch.manual_seed(20261012)
47
+ x = torch.randint(0, 256, (1, 32), dtype=torch.long)
48
+ with torch.no_grad():
49
+ direct = model.transwave.nll(x, checkpoint_layers=False)
50
+ wrapped = model(input_ids=x, labels=x).loss
51
+ assert torch.isfinite(direct)
52
+ assert torch.isfinite(wrapped)
53
+ assert abs(float(direct - wrapped)) < 2e-5
54
+ print("NLL:", float(wrapped), "PPL:", math.exp(float(wrapped)))
55
+
56
+
57
+ print("5/6 future-perturbation causality")
58
+ a = torch.randint(0, 256, (1, 32), dtype=torch.long)
59
+ b = a.clone()
60
+ b[:, 16:] = torch.randint(0, 256, b[:, 16:].shape, dtype=torch.long)
61
+ with torch.no_grad():
62
+ ca, _ = model.transwave.contexts(a, checkpoint_layers=False)
63
+ cb, _ = model.transwave.contexts(b, checkpoint_layers=False)
64
+ diff = float((ca[:, :3, :] - cb[:, :3, :]).abs().max())
65
+ assert diff <= 2e-4, diff
66
+ print("future->past max diff:", diff)
67
+
68
+
69
+ print("6/6 reference generation")
70
+ prompt = tok("abcdefgh", return_tensors="pt")["input_ids"]
71
+ with torch.no_grad():
72
+ y = model.generate_bytes(prompt, max_new_tokens=2, do_sample=False)
73
+ assert y.shape == (1, 10)
74
+ assert int(y.min()) >= 0 and int(y.max()) <= 255
75
+
76
+
77
+ print("SMOKE TEST: PASS")
special_tokens_map.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {}
tokenization_transwave.py ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+
6
+ from transformers import PreTrainedTokenizer
7
+
8
+
9
+ class TransWaveByteTokenizer(PreTrainedTokenizer):
10
+
11
+ vocab_files_names = {
12
+ "vocab_file": "vocab.json"
13
+ }
14
+
15
+ model_input_names = [
16
+ "input_ids"
17
+ ]
18
+
19
+
20
+ def __init__(
21
+ self,
22
+ vocab_file=None,
23
+ model_max_length=20480,
24
+ **kwargs,
25
+ ):
26
+
27
+ self.vocab_file = vocab_file
28
+
29
+ self._id_to_token = [
30
+ f"<0x{i:02X}>"
31
+ for i in range(256)
32
+ ]
33
+
34
+ self._token_to_id = {
35
+ token: i
36
+ for i, token
37
+ in enumerate(self._id_to_token)
38
+ }
39
+
40
+ # Values may already arrive through tokenizer_config.json.
41
+ # Never pass the same keyword twice.
42
+
43
+ kwargs.setdefault(
44
+ "model_max_length",
45
+ model_max_length,
46
+ )
47
+
48
+ kwargs.setdefault(
49
+ "clean_up_tokenization_spaces",
50
+ False,
51
+ )
52
+
53
+ super().__init__(**kwargs)
54
+
55
+
56
+ @property
57
+ def vocab_size(self):
58
+
59
+ return 256
60
+
61
+
62
+ def get_vocab(self):
63
+
64
+ vocab = dict(
65
+ self._token_to_id
66
+ )
67
+
68
+ vocab.update(
69
+ self.added_tokens_encoder
70
+ )
71
+
72
+ return vocab
73
+
74
+
75
+ def _tokenize(
76
+ self,
77
+ text,
78
+ **kwargs,
79
+ ):
80
+
81
+ return [
82
+ self._id_to_token[b]
83
+ for b in text.encode("utf-8")
84
+ ]
85
+
86
+
87
+ def _convert_token_to_id(
88
+ self,
89
+ token,
90
+ ):
91
+
92
+ if token not in self._token_to_id:
93
+ raise ValueError(
94
+ f"Unknown byte token: {token}"
95
+ )
96
+
97
+ return self._token_to_id[token]
98
+
99
+
100
+ def _convert_id_to_token(
101
+ self,
102
+ index,
103
+ ):
104
+
105
+ index = int(index)
106
+
107
+ if not 0 <= index < 256:
108
+ raise ValueError(
109
+ f"Byte id out of range: {index}"
110
+ )
111
+
112
+ return self._id_to_token[index]
113
+
114
+
115
+ def convert_tokens_to_string(
116
+ self,
117
+ tokens,
118
+ ):
119
+
120
+ data = bytearray()
121
+
122
+ for token in tokens:
123
+
124
+ if token in self._token_to_id:
125
+ data.append(
126
+ self._token_to_id[token]
127
+ )
128
+
129
+ return bytes(data).decode(
130
+ "utf-8",
131
+ errors="replace",
132
+ )
133
+
134
+
135
+ def save_vocabulary(
136
+ self,
137
+ save_directory,
138
+ filename_prefix=None,
139
+ ):
140
+
141
+ os.makedirs(
142
+ save_directory,
143
+ exist_ok=True,
144
+ )
145
+
146
+ filename = (
147
+ (
148
+ filename_prefix + "-"
149
+ )
150
+ if filename_prefix
151
+ else ""
152
+ ) + "vocab.json"
153
+
154
+ path = os.path.join(
155
+ save_directory,
156
+ filename,
157
+ )
158
+
159
+ vocab = {
160
+ token: i
161
+ for i, token
162
+ in enumerate(self._id_to_token)
163
+ }
164
+
165
+ with open(
166
+ path,
167
+ "w",
168
+ encoding="utf-8",
169
+ ) as f:
170
+
171
+ json.dump(
172
+ vocab,
173
+ f,
174
+ ensure_ascii=False,
175
+ indent=2,
176
+ )
177
+
178
+ return (path,)
tokenizer_config.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "tokenizer_class": "TransWaveByteTokenizer",
3
+ "model_max_length": 20480,
4
+ "clean_up_tokenization_spaces": false,
5
+ "auto_map": {
6
+ "AutoTokenizer": ["tokenization_transwave.TransWaveByteTokenizer", null]
7
+ }
8
+ }
training_metrics.jsonl ADDED
The diff for this file is too large to render. See raw diff
 
training_protocol.json ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architecture": "causal_transwave_blocklifting_meyer_byte_lm_g4_v2",
3
+ "source_commit": "5cae31b81e15160379ded79f32bcbb443d7db9f7",
4
+ "parameters": 96130040,
5
+ "dataset": "allenai/c4:en",
6
+ "objective": "exact causal next-byte NLL",
7
+ "context_tokens": 20480,
8
+ "physical_batch": 280,
9
+ "tokens_per_full_step": 5734400,
10
+ "maximum_training_tokens": 4499996672,
11
+ "usable_training_tokens": 4499988480,
12
+ "target_ppl": 3.0,
13
+ "base_lr": 0.0001,
14
+ "min_lr": 1e-05,
15
+ "warmup_fraction": 0.01,
16
+ "grad_clip": 1.0,
17
+ "model_seed": 20261010,
18
+ "order_seed": 20261011,
19
+ "allocator": "expandable_segments:True,garbage_collection_threshold:0.80",
20
+ "fingerprint": "370d05a6d2672fc7838726e78e8fe267b4b9c480b4f3708b64e7136beea128fd"
21
+ }
training_result.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "release": "TransWave-Meyer-96M-C4",
3
+ "architecture": "causal_transwave_blocklifting_meyer_byte_lm_g4_v2",
4
+ "source_commit": "5cae31b81e15160379ded79f32bcbb443d7db9f7",
5
+ "parameters": 96130040,
6
+ "dataset": "allenai/c4:en",
7
+ "context_tokens": 20480,
8
+ "physical_batch": 280,
9
+ "tokens_per_full_step": 5734400,
10
+ "usable_training_tokens": 4499988480,
11
+ "tokens_seen": 4499988480,
12
+ "steps": 785,
13
+ "target_ppl": 3.0,
14
+ "best_full_validation_nll": 2.228725892720205,
15
+ "best_full_validation_ppl": 9.288024597671594,
16
+ "final_validation": {
17
+ "nll": 2.228725892720205,
18
+ "ppl": 9.288024597671594,
19
+ "tokens": 16773120,
20
+ "contexts": 819
21
+ },
22
+ "stop_reason": "maximum_4p5B_token_budget_exhausted",
23
+ "wall_hours": 2.553788356317414
24
+ }
transwave_core.py ADDED
@@ -0,0 +1,3576 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+
4
+ import math
5
+ import torch
6
+ import torch.nn as nn
7
+ import torch.nn.functional as F
8
+ from torch.utils.checkpoint import checkpoint as torch_checkpoint
9
+
10
+
11
+ ARCH = "causal_transwave_blocklifting_meyer_byte_lm_g4_v2"
12
+ BYTE_VOCAB = 256
13
+ BYTE_DIM = 96
14
+ BYTES_PER_BLOCK = 8
15
+ N_SCALES = 8
16
+ MODEL_DIM = 768
17
+ MODEL_CONTEXT = 4096
18
+ RAW_BYTES_PER_SEQUENCE = MODEL_CONTEXT * BYTES_PER_BLOCK
19
+ N_LAYERS = 12
20
+ N_GROUPS = 12
21
+ CHANNELS_PER_GROUP = BYTE_DIM // N_GROUPS
22
+ N_MEYER_BANDS = 12
23
+ N_BAND_CONTROLS = 8
24
+ MEYER_KERNEL = 512
25
+ LOCAL_KERNEL = 7
26
+ FFN_DIM = 2816
27
+ BYTE_DECODER_DIM = 256
28
+ HEAD_CHUNK = 32768
29
+
30
+
31
+ assert BYTE_DIM * BYTES_PER_BLOCK == MODEL_DIM
32
+ assert RAW_BYTES_PER_SEQUENCE == 32768
33
+ assert BYTE_DIM % N_GROUPS == 0
34
+
35
+
36
+ class CTWLocalBlockDelta(
37
+ nn.Module
38
+ ):
39
+
40
+
41
+ def __init__(
42
+ self,
43
+ dim=BYTE_DIM,
44
+ groups=12,
45
+ expansion=2,
46
+ ):
47
+
48
+
49
+ super().__init__()
50
+
51
+
52
+
53
+
54
+ if (
55
+ dim
56
+ %
57
+ groups
58
+ !=
59
+ 0
60
+ ):
61
+
62
+
63
+ raise ValueError(
64
+ "dim must be divisible by groups"
65
+ )
66
+
67
+
68
+
69
+
70
+ hidden = (
71
+ dim
72
+ *
73
+ expansion
74
+ )
75
+
76
+
77
+
78
+
79
+ if (
80
+ hidden
81
+ %
82
+ groups
83
+ !=
84
+ 0
85
+ ):
86
+
87
+
88
+ raise ValueError(
89
+ "expanded dimension must be divisible by groups"
90
+ )
91
+
92
+
93
+
94
+
95
+ self.depthwise = nn.Conv1d(
96
+ dim,
97
+ dim,
98
+ kernel_size=3,
99
+ padding=1,
100
+ groups=dim,
101
+ bias=True,
102
+ )
103
+
104
+
105
+
106
+
107
+ self.mix_in = nn.Conv1d(
108
+ dim,
109
+ hidden,
110
+ kernel_size=1,
111
+ groups=groups,
112
+ bias=True,
113
+ )
114
+
115
+
116
+
117
+
118
+ self.mix_out = nn.Conv1d(
119
+ hidden,
120
+ dim,
121
+ kernel_size=1,
122
+ groups=groups,
123
+ bias=True,
124
+ )
125
+
126
+
127
+
128
+
129
+ # Haar-like initialization:
130
+ # residual branch starts exactly at zero.
131
+
132
+
133
+ nn.init.zeros_(
134
+ self.mix_out.weight
135
+ )
136
+
137
+
138
+
139
+
140
+ nn.init.zeros_(
141
+ self.mix_out.bias
142
+ )
143
+
144
+
145
+
146
+
147
+ def forward(
148
+ self,
149
+ x,
150
+ ):
151
+
152
+
153
+ y = x.transpose(
154
+ 1,
155
+ 2,
156
+ )
157
+
158
+
159
+
160
+
161
+ y = self.depthwise(
162
+ y
163
+ )
164
+
165
+
166
+
167
+
168
+ y = F.silu(
169
+ y
170
+ )
171
+
172
+
173
+
174
+
175
+ y = self.mix_in(
176
+ y
177
+ )
178
+
179
+
180
+
181
+
182
+ y = F.silu(
183
+ y
184
+ )
185
+
186
+
187
+
188
+
189
+ y = self.mix_out(
190
+ y
191
+ )
192
+
193
+
194
+
195
+
196
+ return y.transpose(
197
+ 1,
198
+ 2,
199
+ )
200
+
201
+
202
+
203
+
204
+ class CTWLiftingStage(
205
+ nn.Module
206
+ ):
207
+
208
+
209
+ def __init__(
210
+ self,
211
+ dim=BYTE_DIM,
212
+ groups=12,
213
+ expansion=2,
214
+ ):
215
+
216
+
217
+ super().__init__()
218
+
219
+
220
+
221
+
222
+ self.predict_delta = (
223
+ CTWLocalBlockDelta(
224
+ dim=dim,
225
+ groups=groups,
226
+ expansion=expansion,
227
+ )
228
+ )
229
+
230
+
231
+
232
+
233
+ self.update_delta = (
234
+ CTWLocalBlockDelta(
235
+ dim=dim,
236
+ groups=groups,
237
+ expansion=expansion,
238
+ )
239
+ )
240
+
241
+
242
+
243
+
244
+ def predict(
245
+ self,
246
+ even,
247
+ ):
248
+
249
+
250
+ return (
251
+ even
252
+ +
253
+ self.predict_delta(
254
+ even
255
+ )
256
+ )
257
+
258
+
259
+
260
+
261
+ def update(
262
+ self,
263
+ detail,
264
+ ):
265
+
266
+
267
+ return (
268
+ 0.5
269
+ *
270
+ detail
271
+ +
272
+ self.update_delta(
273
+ detail
274
+ )
275
+ )
276
+
277
+
278
+
279
+
280
+ def forward(
281
+ self,
282
+ x,
283
+ ):
284
+
285
+
286
+ if (
287
+ x.ndim != 3
288
+ or
289
+ x.shape[1] % 2 != 0
290
+ ):
291
+
292
+
293
+ raise ValueError(
294
+ "Expected [N,T,C] with even T."
295
+ )
296
+
297
+
298
+
299
+
300
+ even = x[
301
+ :,
302
+ 0::2,
303
+ :
304
+ ]
305
+
306
+
307
+
308
+
309
+ odd = x[
310
+ :,
311
+ 1::2,
312
+ :
313
+ ]
314
+
315
+
316
+
317
+
318
+ detail = (
319
+ odd
320
+ -
321
+ self.predict(
322
+ even
323
+ )
324
+ )
325
+
326
+
327
+
328
+
329
+ coarse = (
330
+ even
331
+ +
332
+ self.update(
333
+ detail
334
+ )
335
+ )
336
+
337
+
338
+
339
+
340
+ return (
341
+ coarse,
342
+ detail,
343
+ )
344
+
345
+
346
+
347
+
348
+ class CTWCrossScaleMixer(
349
+ nn.Module
350
+ ):
351
+
352
+
353
+ def __init__(
354
+ self,
355
+ scales=N_SCALES,
356
+ dim=BYTE_DIM,
357
+ groups=N_GROUPS,
358
+ ):
359
+
360
+
361
+ super().__init__()
362
+
363
+
364
+
365
+
366
+ if (
367
+ dim
368
+ %
369
+ groups
370
+ !=
371
+ 0
372
+ ):
373
+
374
+
375
+ raise ValueError(
376
+ "dim must be divisible by groups"
377
+ )
378
+
379
+
380
+
381
+
382
+ self.scales = int(
383
+ scales
384
+ )
385
+
386
+
387
+
388
+
389
+ self.dim = int(
390
+ dim
391
+ )
392
+
393
+
394
+
395
+
396
+ self.groups = int(
397
+ groups
398
+ )
399
+
400
+
401
+
402
+
403
+ self.channels_per_group = (
404
+ self.dim
405
+ //
406
+ self.groups
407
+ )
408
+
409
+
410
+
411
+
412
+ # M_g = I + Delta_g
413
+
414
+
415
+ self.scale_delta = nn.Parameter(
416
+
417
+
418
+ torch.zeros(
419
+ self.groups,
420
+ self.scales,
421
+ self.scales,
422
+ )
423
+ )
424
+
425
+
426
+
427
+
428
+ # Content-dependent gain.
429
+
430
+
431
+ self.gate_weight = nn.Parameter(
432
+
433
+
434
+ torch.zeros(
435
+ self.groups,
436
+ self.scales,
437
+ self.channels_per_group,
438
+ )
439
+ )
440
+
441
+
442
+
443
+
444
+ self.gate_bias = nn.Parameter(
445
+
446
+
447
+ torch.zeros(
448
+ self.groups,
449
+ self.scales,
450
+ )
451
+ )
452
+
453
+
454
+
455
+
456
+ def forward(
457
+ self,
458
+ z,
459
+ ):
460
+
461
+
462
+ if (
463
+ z.ndim != 4
464
+ or
465
+ z.shape[2]
466
+ !=
467
+ self.scales
468
+ or
469
+ z.shape[3]
470
+ !=
471
+ self.dim
472
+ ):
473
+
474
+
475
+ raise ValueError(
476
+
477
+
478
+ f"Expected "
479
+ f"[B,L,{self.scales},{self.dim}]"
480
+ )
481
+
482
+
483
+
484
+
485
+ b, l, s, _ = z.shape
486
+
487
+
488
+
489
+
490
+ zg = z.reshape(
491
+ b,
492
+ l,
493
+ s,
494
+ self.groups,
495
+ self.channels_per_group,
496
+ )
497
+
498
+
499
+
500
+
501
+ gate_logits = torch.einsum(
502
+ "blsgc,gsc->blsg",
503
+ zg,
504
+ self.gate_weight,
505
+ )
506
+
507
+
508
+
509
+
510
+ gate_logits = (
511
+ gate_logits
512
+ /
513
+ math.sqrt(
514
+ self.channels_per_group
515
+ )
516
+ +
517
+ self.gate_bias.transpose(
518
+ 0,
519
+ 1,
520
+ )
521
+ )
522
+
523
+
524
+
525
+
526
+ # Zero logits -> gain exactly 1.
527
+
528
+
529
+ gain = (
530
+ 2.0
531
+ *
532
+ torch.sigmoid(
533
+ gate_logits
534
+ )
535
+ )
536
+
537
+
538
+
539
+
540
+ zg = (
541
+ zg
542
+ *
543
+ gain
544
+ .to(
545
+ zg.dtype
546
+ )
547
+ .unsqueeze(
548
+ -1
549
+ )
550
+ )
551
+
552
+
553
+
554
+
555
+ eye = torch.eye(
556
+ self.scales,
557
+ device=z.device,
558
+ dtype=z.dtype,
559
+ ).unsqueeze(
560
+ 0
561
+ )
562
+
563
+
564
+
565
+
566
+ mix = (
567
+ eye
568
+ +
569
+ self.scale_delta.to(
570
+ z.dtype
571
+ )
572
+ )
573
+
574
+
575
+
576
+
577
+ mixed = torch.einsum(
578
+ "blsgc,gts->bltgc",
579
+ zg,
580
+ mix,
581
+ )
582
+
583
+
584
+
585
+
586
+ return mixed.reshape(
587
+ b,
588
+ l,
589
+ s,
590
+ self.dim,
591
+ )
592
+
593
+
594
+
595
+
596
+ class CTWBlockLiftingTokenizer(
597
+ nn.Module
598
+ ):
599
+
600
+
601
+ def __init__(
602
+ self,
603
+ ):
604
+
605
+
606
+ super().__init__()
607
+
608
+
609
+
610
+
611
+ self.byte_embedding = nn.Embedding(
612
+ BYTE_VOCAB,
613
+ BYTE_DIM,
614
+ )
615
+
616
+
617
+
618
+
619
+ nn.init.normal_(
620
+
621
+
622
+ self.byte_embedding.weight,
623
+
624
+
625
+ mean=0.0,
626
+
627
+
628
+ std=(
629
+ BYTE_DIM
630
+ **
631
+ -0.5
632
+ ),
633
+ )
634
+
635
+
636
+
637
+
638
+ self.stages = nn.ModuleList(
639
+
640
+
641
+ [
642
+
643
+
644
+ CTWLiftingStage(
645
+ dim=BYTE_DIM,
646
+ groups=N_GROUPS,
647
+ expansion=2,
648
+ )
649
+
650
+
651
+ for _ in range(
652
+ 3
653
+ )
654
+ ]
655
+ )
656
+
657
+
658
+
659
+
660
+ self.cross_scale = (
661
+ CTWCrossScaleMixer(
662
+ scales=N_SCALES,
663
+ dim=BYTE_DIM,
664
+ groups=N_GROUPS,
665
+ )
666
+ )
667
+
668
+
669
+
670
+
671
+ def forward(
672
+ self,
673
+ byte_ids,
674
+ ):
675
+
676
+
677
+ if (
678
+ byte_ids.ndim
679
+ !=
680
+ 2
681
+ ):
682
+
683
+
684
+ raise ValueError(
685
+ "Expected byte IDs [B,8L]."
686
+ )
687
+
688
+
689
+
690
+
691
+ b, t = byte_ids.shape
692
+
693
+
694
+
695
+
696
+ if (
697
+ t
698
+ %
699
+ BYTES_PER_BLOCK
700
+ !=
701
+ 0
702
+ ):
703
+
704
+
705
+ raise ValueError(
706
+ "Byte length must be divisible by 8."
707
+ )
708
+
709
+
710
+
711
+
712
+ l = (
713
+ t
714
+ //
715
+ BYTES_PER_BLOCK
716
+ )
717
+
718
+
719
+
720
+
721
+ # -------------------------------------------------------------
722
+ # CRITICAL CAUSAL CHANGE:
723
+ #
724
+ # each completed eight-byte block becomes an independent item
725
+ # before ANY lifting convolution is applied.
726
+ # -------------------------------------------------------------
727
+
728
+
729
+ blocks = (
730
+ byte_ids
731
+ .long()
732
+ .reshape(
733
+ b,
734
+ l,
735
+ BYTES_PER_BLOCK,
736
+ )
737
+ )
738
+
739
+
740
+
741
+
742
+ x = self.byte_embedding(
743
+
744
+
745
+ blocks.reshape(
746
+ b
747
+ *
748
+ l,
749
+ BYTES_PER_BLOCK,
750
+ )
751
+ )
752
+
753
+
754
+
755
+
756
+ details = []
757
+
758
+
759
+
760
+
761
+ coarse = x
762
+
763
+
764
+
765
+
766
+ for stage in self.stages:
767
+
768
+
769
+ (
770
+ coarse,
771
+ detail,
772
+ ) = stage(
773
+ coarse
774
+ )
775
+
776
+
777
+
778
+
779
+ details.append(
780
+ detail
781
+ )
782
+
783
+
784
+
785
+
786
+ # D0=4, D1=2, D2=1, S3=1.
787
+
788
+
789
+ packed = torch.cat(
790
+
791
+
792
+ [
793
+ details[0],
794
+ details[1],
795
+ details[2],
796
+ coarse,
797
+ ],
798
+
799
+
800
+ dim=1,
801
+ )
802
+
803
+
804
+
805
+
806
+ if (
807
+ packed.shape[1]
808
+ !=
809
+ N_SCALES
810
+ ):
811
+
812
+
813
+ raise RuntimeError(
814
+ "Lifting scale packing mismatch."
815
+ )
816
+
817
+
818
+
819
+
820
+ z = packed.reshape(
821
+ b,
822
+ l,
823
+ N_SCALES,
824
+ BYTE_DIM,
825
+ )
826
+
827
+
828
+
829
+
830
+ return self.cross_scale(
831
+ z
832
+ )
833
+
834
+
835
+
836
+
837
+ # =============================================================================
838
+ # RMS NORM / SWIGLU
839
+ # =============================================================================
840
+
841
+
842
+ class CTWRMSNorm(
843
+ nn.Module
844
+ ):
845
+
846
+
847
+ def __init__(
848
+ self,
849
+ dim,
850
+ eps=1e-6,
851
+ ):
852
+
853
+
854
+ super().__init__()
855
+
856
+
857
+
858
+
859
+ self.weight = nn.Parameter(
860
+ torch.ones(
861
+ dim
862
+ )
863
+ )
864
+
865
+
866
+
867
+
868
+ self.eps = eps
869
+
870
+
871
+
872
+
873
+ def forward(
874
+ self,
875
+ x,
876
+ ):
877
+
878
+
879
+ xf = x.float()
880
+
881
+
882
+
883
+
884
+ y = (
885
+ xf
886
+ *
887
+ torch.rsqrt(
888
+
889
+
890
+ xf.pow(2).mean(
891
+ dim=-1,
892
+ keepdim=True,
893
+ )
894
+ +
895
+ self.eps
896
+ )
897
+ )
898
+
899
+
900
+
901
+
902
+ return (
903
+ y.to(
904
+ x.dtype
905
+ )
906
+ *
907
+ self.weight.to(
908
+ x.dtype
909
+ )
910
+ )
911
+
912
+
913
+
914
+
915
+ class CTWSwiGLU(
916
+ nn.Module
917
+ ):
918
+
919
+
920
+ def __init__(
921
+ self,
922
+ dim,
923
+ hidden,
924
+ ):
925
+
926
+
927
+ super().__init__()
928
+
929
+
930
+
931
+
932
+ self.gate = nn.Linear(
933
+ dim,
934
+ hidden,
935
+ )
936
+
937
+
938
+
939
+
940
+ self.value = nn.Linear(
941
+ dim,
942
+ hidden,
943
+ )
944
+
945
+
946
+
947
+
948
+ self.out = nn.Linear(
949
+ hidden,
950
+ dim,
951
+ )
952
+
953
+
954
+
955
+
956
+ for m in (
957
+ self.gate,
958
+ self.value,
959
+ self.out,
960
+ ):
961
+
962
+
963
+ nn.init.xavier_uniform_(
964
+ m.weight
965
+ )
966
+
967
+
968
+
969
+
970
+ nn.init.zeros_(
971
+ m.bias
972
+ )
973
+
974
+
975
+
976
+
977
+ def forward(
978
+ self,
979
+ x,
980
+ ):
981
+
982
+
983
+ return self.out(
984
+
985
+
986
+ F.silu(
987
+ self.gate(
988
+ x
989
+ )
990
+ )
991
+
992
+
993
+ *
994
+
995
+
996
+ self.value(
997
+ x
998
+ )
999
+ )
1000
+
1001
+
1002
+
1003
+
1004
+ # =============================================================================
1005
+ # MEYER BASIS
1006
+ # =============================================================================
1007
+
1008
+
1009
+ def ctw_meyer_nu(
1010
+ x,
1011
+ ):
1012
+
1013
+
1014
+ x = x.clamp(
1015
+ 0.0,
1016
+ 1.0,
1017
+ )
1018
+
1019
+
1020
+
1021
+
1022
+ return (
1023
+ x**4
1024
+ *
1025
+ (
1026
+ 35.0
1027
+ -
1028
+ 84.0 * x
1029
+ +
1030
+ 70.0 * x**2
1031
+ -
1032
+ 20.0 * x**3
1033
+ )
1034
+ )
1035
+
1036
+
1037
+
1038
+
1039
+ def ctw_build_meyer_basis(
1040
+ kernel_size,
1041
+ bands,
1042
+ controls,
1043
+ ):
1044
+
1045
+
1046
+ nf = (
1047
+ kernel_size
1048
+ //
1049
+ 2
1050
+ +
1051
+ 1
1052
+ )
1053
+
1054
+
1055
+
1056
+
1057
+ f = torch.linspace(
1058
+ 0.0,
1059
+ 1.0,
1060
+ nf,
1061
+ dtype=torch.float32,
1062
+ )
1063
+
1064
+
1065
+
1066
+
1067
+ edges = torch.linspace(
1068
+ 0.0,
1069
+ 1.0,
1070
+ bands + 1,
1071
+ dtype=torch.float32,
1072
+ )
1073
+
1074
+
1075
+
1076
+
1077
+ windows = []
1078
+
1079
+
1080
+
1081
+
1082
+ for j in range(
1083
+ bands
1084
+ ):
1085
+
1086
+
1087
+ left = float(
1088
+ edges[j]
1089
+ )
1090
+
1091
+
1092
+
1093
+
1094
+ right = float(
1095
+ edges[j + 1]
1096
+ )
1097
+
1098
+
1099
+
1100
+
1101
+ delta = (
1102
+ 0.35
1103
+ *
1104
+ (
1105
+ right
1106
+ -
1107
+ left
1108
+ )
1109
+ )
1110
+
1111
+
1112
+
1113
+
1114
+ if j == 0:
1115
+
1116
+
1117
+ left_gate = torch.ones_like(
1118
+ f
1119
+ )
1120
+
1121
+
1122
+ else:
1123
+
1124
+
1125
+ a = (
1126
+ left
1127
+ -
1128
+ delta
1129
+ )
1130
+
1131
+
1132
+
1133
+
1134
+ b = (
1135
+ left
1136
+ +
1137
+ delta
1138
+ )
1139
+
1140
+
1141
+
1142
+
1143
+ u = (
1144
+ f
1145
+ -
1146
+ a
1147
+ ) / max(
1148
+ b - a,
1149
+ 1e-8,
1150
+ )
1151
+
1152
+
1153
+
1154
+
1155
+ left_gate = torch.sin(
1156
+
1157
+
1158
+ 0.5
1159
+ *
1160
+ math.pi
1161
+ *
1162
+ ctw_meyer_nu(
1163
+ u
1164
+ )
1165
+ )
1166
+
1167
+
1168
+
1169
+
1170
+ left_gate = torch.where(
1171
+ f <= a,
1172
+ torch.zeros_like(
1173
+ f
1174
+ ),
1175
+ left_gate,
1176
+ )
1177
+
1178
+
1179
+
1180
+
1181
+ left_gate = torch.where(
1182
+ f >= b,
1183
+ torch.ones_like(
1184
+ f
1185
+ ),
1186
+ left_gate,
1187
+ )
1188
+
1189
+
1190
+
1191
+
1192
+ if j == bands - 1:
1193
+
1194
+
1195
+ right_gate = torch.ones_like(
1196
+ f
1197
+ )
1198
+
1199
+
1200
+ else:
1201
+
1202
+
1203
+ a = (
1204
+ right
1205
+ -
1206
+ delta
1207
+ )
1208
+
1209
+
1210
+
1211
+
1212
+ b = (
1213
+ right
1214
+ +
1215
+ delta
1216
+ )
1217
+
1218
+
1219
+
1220
+
1221
+ u = (
1222
+ f
1223
+ -
1224
+ a
1225
+ ) / max(
1226
+ b - a,
1227
+ 1e-8,
1228
+ )
1229
+
1230
+
1231
+
1232
+
1233
+ right_gate = torch.cos(
1234
+
1235
+
1236
+ 0.5
1237
+ *
1238
+ math.pi
1239
+ *
1240
+ ctw_meyer_nu(
1241
+ u
1242
+ )
1243
+ )
1244
+
1245
+
1246
+
1247
+
1248
+ right_gate = torch.where(
1249
+ f <= a,
1250
+ torch.ones_like(
1251
+ f
1252
+ ),
1253
+ right_gate,
1254
+ )
1255
+
1256
+
1257
+
1258
+
1259
+ right_gate = torch.where(
1260
+ f >= b,
1261
+ torch.zeros_like(
1262
+ f
1263
+ ),
1264
+ right_gate,
1265
+ )
1266
+
1267
+
1268
+
1269
+
1270
+ windows.append(
1271
+ left_gate
1272
+ *
1273
+ right_gate
1274
+ )
1275
+
1276
+
1277
+
1278
+
1279
+ windows = torch.stack(
1280
+ windows,
1281
+ dim=0,
1282
+ )
1283
+
1284
+
1285
+
1286
+
1287
+ windows = (
1288
+ windows
1289
+ /
1290
+ torch.sqrt(
1291
+
1292
+
1293
+ windows.pow(2).sum(
1294
+ dim=0,
1295
+ keepdim=True,
1296
+ )
1297
+ +
1298
+ 1e-12
1299
+ )
1300
+ )
1301
+
1302
+
1303
+
1304
+
1305
+ degree = (
1306
+ controls
1307
+ -
1308
+ 1
1309
+ )
1310
+
1311
+
1312
+
1313
+
1314
+ basis = []
1315
+
1316
+
1317
+
1318
+
1319
+ for j in range(
1320
+ bands
1321
+ ):
1322
+
1323
+
1324
+ left = edges[j]
1325
+
1326
+
1327
+
1328
+
1329
+ right = edges[j + 1]
1330
+
1331
+
1332
+
1333
+
1334
+ u = (
1335
+ (
1336
+ f
1337
+ -
1338
+ left
1339
+ )
1340
+ /
1341
+ (
1342
+ right
1343
+ -
1344
+ left
1345
+ +
1346
+ 1e-12
1347
+ )
1348
+ ).clamp(
1349
+ 0.0,
1350
+ 1.0,
1351
+ )
1352
+
1353
+
1354
+
1355
+
1356
+ row = []
1357
+
1358
+
1359
+
1360
+
1361
+ for m in range(
1362
+ controls
1363
+ ):
1364
+
1365
+
1366
+ bern = (
1367
+
1368
+
1369
+ math.comb(
1370
+ degree,
1371
+ m,
1372
+ )
1373
+
1374
+
1375
+ *
1376
+
1377
+
1378
+ u.pow(
1379
+ m
1380
+ )
1381
+
1382
+
1383
+ *
1384
+
1385
+
1386
+ (
1387
+ 1.0
1388
+ -
1389
+ u
1390
+ ).pow(
1391
+ degree
1392
+ -
1393
+ m
1394
+ )
1395
+ )
1396
+
1397
+
1398
+
1399
+
1400
+ row.append(
1401
+ windows[j]
1402
+ *
1403
+ bern
1404
+ )
1405
+
1406
+
1407
+
1408
+
1409
+ basis.append(
1410
+
1411
+
1412
+ torch.stack(
1413
+ row,
1414
+ dim=0,
1415
+ )
1416
+ )
1417
+
1418
+
1419
+
1420
+
1421
+ return torch.stack(
1422
+ basis,
1423
+ dim=0,
1424
+ )
1425
+
1426
+
1427
+
1428
+
1429
+ # =============================================================================
1430
+ # SAME-TIME FULL 8x8 SCALE MIXING
1431
+ # =============================================================================
1432
+
1433
+
1434
+ class CTWScaleMixer(
1435
+ nn.Module
1436
+ ):
1437
+
1438
+
1439
+ def __init__(
1440
+ self,
1441
+ ):
1442
+
1443
+
1444
+ super().__init__()
1445
+
1446
+
1447
+
1448
+
1449
+ eye = torch.eye(
1450
+ N_SCALES
1451
+ )
1452
+
1453
+
1454
+
1455
+
1456
+ self.weight = nn.Parameter(
1457
+
1458
+
1459
+ eye
1460
+ .unsqueeze(
1461
+ 0
1462
+ )
1463
+ .repeat(
1464
+ N_GROUPS,
1465
+ 1,
1466
+ 1,
1467
+ )
1468
+ )
1469
+
1470
+
1471
+
1472
+
1473
+ def forward(
1474
+ self,
1475
+ x,
1476
+ ):
1477
+
1478
+
1479
+ b, l, s, c = x.shape
1480
+
1481
+
1482
+
1483
+
1484
+ xg = x.reshape(
1485
+ b,
1486
+ l,
1487
+ s,
1488
+ N_GROUPS,
1489
+ CHANNELS_PER_GROUP,
1490
+ )
1491
+
1492
+
1493
+
1494
+
1495
+ y = torch.einsum(
1496
+ "blsgc,gts->bltgc",
1497
+ xg,
1498
+ self.weight,
1499
+ )
1500
+
1501
+
1502
+
1503
+
1504
+ return y.reshape(
1505
+ b,
1506
+ l,
1507
+ s,
1508
+ c,
1509
+ )
1510
+
1511
+
1512
+
1513
+
1514
+ # =============================================================================
1515
+ # STRICTLY CAUSAL MEYER FIR
1516
+ #
1517
+ # h[k] is a nonnegative lag:
1518
+ #
1519
+ # y[t] = SUM_{k=0}^{K-1} h[k] x[t-k]
1520
+ #
1521
+ # FFT only implements this zero-padded LINEAR convolution efficiently.
1522
+ # =============================================================================
1523
+
1524
+
1525
+ class CTWCausalMeyerFIR(
1526
+ nn.Module
1527
+ ):
1528
+
1529
+
1530
+ def __init__(
1531
+ self,
1532
+ ):
1533
+
1534
+
1535
+ super().__init__()
1536
+
1537
+
1538
+
1539
+
1540
+ basis = ctw_build_meyer_basis(
1541
+ MEYER_KERNEL,
1542
+ N_MEYER_BANDS,
1543
+ N_BAND_CONTROLS,
1544
+ )
1545
+
1546
+
1547
+
1548
+
1549
+ self.register_buffer(
1550
+ "basis",
1551
+ basis,
1552
+ persistent=False,
1553
+ )
1554
+
1555
+
1556
+
1557
+
1558
+ imag_mask = torch.ones(
1559
+ MEYER_KERNEL
1560
+ //
1561
+ 2
1562
+ +
1563
+ 1,
1564
+ dtype=torch.float32,
1565
+ )
1566
+
1567
+
1568
+
1569
+
1570
+ imag_mask[0] = 0.0
1571
+
1572
+
1573
+
1574
+
1575
+ if (
1576
+ MEYER_KERNEL
1577
+ %
1578
+ 2
1579
+ ==
1580
+ 0
1581
+ ):
1582
+
1583
+
1584
+ imag_mask[-1] = 0.0
1585
+
1586
+
1587
+
1588
+
1589
+ self.register_buffer(
1590
+ "imag_mask",
1591
+ imag_mask,
1592
+ persistent=False,
1593
+ )
1594
+
1595
+
1596
+
1597
+
1598
+ shape = (
1599
+ N_GROUPS,
1600
+ N_SCALES,
1601
+ N_MEYER_BANDS,
1602
+ N_BAND_CONTROLS,
1603
+ )
1604
+
1605
+
1606
+
1607
+
1608
+ self.coeff_re = nn.Parameter(
1609
+ torch.empty(
1610
+ shape
1611
+ )
1612
+ )
1613
+
1614
+
1615
+
1616
+
1617
+ self.coeff_im = nn.Parameter(
1618
+ torch.empty(
1619
+ shape
1620
+ )
1621
+ )
1622
+
1623
+
1624
+
1625
+
1626
+ nn.init.normal_(
1627
+ self.coeff_re,
1628
+ mean=0.0,
1629
+ std=1e-3,
1630
+ )
1631
+
1632
+
1633
+
1634
+
1635
+ nn.init.normal_(
1636
+ self.coeff_im,
1637
+ mean=0.0,
1638
+ std=1e-3,
1639
+ )
1640
+
1641
+
1642
+
1643
+
1644
+ def causal_kernel(
1645
+ self,
1646
+ ):
1647
+
1648
+
1649
+ with torch.autocast(
1650
+ device_type=self.coeff_re.device.type,
1651
+ enabled=False,
1652
+ ):
1653
+
1654
+
1655
+ basis = self.basis.float()
1656
+
1657
+
1658
+
1659
+
1660
+ re = torch.einsum(
1661
+ "gsbm,bmf->gsf",
1662
+ self.coeff_re.float(),
1663
+ basis,
1664
+ )
1665
+
1666
+
1667
+
1668
+
1669
+ im = torch.einsum(
1670
+ "gsbm,bmf->gsf",
1671
+ self.coeff_im.float(),
1672
+ basis,
1673
+ )
1674
+
1675
+
1676
+
1677
+
1678
+ im = (
1679
+ im
1680
+ *
1681
+ self.imag_mask[
1682
+ None,
1683
+ None,
1684
+ :
1685
+ ]
1686
+ )
1687
+
1688
+
1689
+
1690
+
1691
+ spectrum = torch.complex(
1692
+ re,
1693
+ im,
1694
+ )
1695
+
1696
+
1697
+
1698
+
1699
+ h = torch.fft.irfft(
1700
+ spectrum,
1701
+ n=MEYER_KERNEL,
1702
+ dim=-1,
1703
+ )
1704
+
1705
+
1706
+
1707
+
1708
+ return h
1709
+
1710
+
1711
+
1712
+
1713
+ def forward(
1714
+ self,
1715
+ x,
1716
+ ):
1717
+
1718
+
1719
+ # [B,L,S,96]
1720
+
1721
+
1722
+ b, l, s, c = x.shape
1723
+
1724
+
1725
+
1726
+
1727
+ # [B,G,S,Cg,L]
1728
+
1729
+
1730
+ xg = (
1731
+ x
1732
+ .reshape(
1733
+ b,
1734
+ l,
1735
+ s,
1736
+ N_GROUPS,
1737
+ CHANNELS_PER_GROUP,
1738
+ )
1739
+ .permute(
1740
+ 0,
1741
+ 3,
1742
+ 2,
1743
+ 4,
1744
+ 1,
1745
+ )
1746
+ .contiguous()
1747
+ )
1748
+
1749
+
1750
+
1751
+
1752
+ linear_length = (
1753
+ l
1754
+ +
1755
+ MEYER_KERNEL
1756
+ -
1757
+ 1
1758
+ )
1759
+
1760
+
1761
+
1762
+
1763
+ nfft = (
1764
+ 1
1765
+ <<
1766
+ (
1767
+ linear_length
1768
+ -
1769
+ 1
1770
+ ).bit_length()
1771
+ )
1772
+
1773
+
1774
+
1775
+
1776
+ with torch.autocast(
1777
+ device_type=self.coeff_re.device.type,
1778
+ enabled=False,
1779
+ ):
1780
+
1781
+
1782
+ xf = xg.float()
1783
+
1784
+
1785
+
1786
+
1787
+ h = self.causal_kernel()
1788
+
1789
+
1790
+
1791
+
1792
+ X = torch.fft.rfft(
1793
+ xf,
1794
+ n=nfft,
1795
+ dim=-1,
1796
+ )
1797
+
1798
+
1799
+
1800
+
1801
+ H = torch.fft.rfft(
1802
+ h,
1803
+ n=nfft,
1804
+ dim=-1,
1805
+ )
1806
+
1807
+
1808
+
1809
+
1810
+ Y = torch.fft.irfft(
1811
+
1812
+
1813
+ X
1814
+ *
1815
+ H[
1816
+ None,
1817
+ :,
1818
+ :,
1819
+ None,
1820
+ :
1821
+ ],
1822
+
1823
+
1824
+ n=nfft,
1825
+ dim=-1,
1826
+ )
1827
+
1828
+
1829
+
1830
+
1831
+ # First L outputs of LINEAR convolution.
1832
+
1833
+
1834
+ Y = Y[
1835
+ ...,
1836
+ :l
1837
+ ]
1838
+
1839
+
1840
+
1841
+
1842
+ return (
1843
+
1844
+
1845
+ Y
1846
+ .permute(
1847
+ 0,
1848
+ 4,
1849
+ 2,
1850
+ 1,
1851
+ 3,
1852
+ )
1853
+ .contiguous()
1854
+ .reshape(
1855
+ b,
1856
+ l,
1857
+ s,
1858
+ c,
1859
+ )
1860
+ .to(
1861
+ x.dtype
1862
+ )
1863
+ )
1864
+
1865
+
1866
+
1867
+
1868
+ # =============================================================================
1869
+ # STRICTLY LEFT-CAUSAL LOCAL CONVOLUTION
1870
+ # =============================================================================
1871
+
1872
+
1873
+ class CTWCausalLocalConv(
1874
+ nn.Module
1875
+ ):
1876
+
1877
+
1878
+ def __init__(
1879
+ self,
1880
+ ):
1881
+
1882
+
1883
+ super().__init__()
1884
+
1885
+
1886
+
1887
+
1888
+ self.conv = nn.Conv1d(
1889
+ MODEL_DIM,
1890
+ MODEL_DIM,
1891
+ kernel_size=LOCAL_KERNEL,
1892
+ groups=MODEL_DIM,
1893
+ bias=True,
1894
+ )
1895
+
1896
+
1897
+
1898
+
1899
+ nn.init.normal_(
1900
+ self.conv.weight,
1901
+ mean=0.0,
1902
+ std=0.02,
1903
+ )
1904
+
1905
+
1906
+
1907
+
1908
+ nn.init.zeros_(
1909
+ self.conv.bias
1910
+ )
1911
+
1912
+
1913
+
1914
+
1915
+ def forward(
1916
+ self,
1917
+ x,
1918
+ ):
1919
+
1920
+
1921
+ xt = x.transpose(
1922
+ 1,
1923
+ 2,
1924
+ )
1925
+
1926
+
1927
+
1928
+
1929
+ xt = F.pad(
1930
+ xt,
1931
+ (
1932
+ LOCAL_KERNEL
1933
+ -
1934
+ 1,
1935
+ 0,
1936
+ ),
1937
+ )
1938
+
1939
+
1940
+
1941
+
1942
+ return (
1943
+ self.conv(
1944
+ xt
1945
+ )
1946
+ .transpose(
1947
+ 1,
1948
+ 2,
1949
+ )
1950
+ )
1951
+
1952
+
1953
+
1954
+
1955
+ # =============================================================================
1956
+ # ONE CAUSAL TRANSWAVE LAYER
1957
+ # =============================================================================
1958
+
1959
+
1960
+ class CTWLayer(
1961
+ nn.Module
1962
+ ):
1963
+
1964
+
1965
+ def __init__(
1966
+ self,
1967
+ ):
1968
+
1969
+
1970
+ super().__init__()
1971
+
1972
+
1973
+
1974
+
1975
+ self.norm1 = CTWRMSNorm(
1976
+ MODEL_DIM
1977
+ )
1978
+
1979
+
1980
+
1981
+
1982
+ self.input_gate = nn.Linear(
1983
+ MODEL_DIM,
1984
+ MODEL_DIM,
1985
+ )
1986
+
1987
+
1988
+
1989
+
1990
+ self.output_gate = nn.Linear(
1991
+ MODEL_DIM,
1992
+ MODEL_DIM,
1993
+ )
1994
+
1995
+
1996
+
1997
+
1998
+ nn.init.zeros_(
1999
+ self.input_gate.weight
2000
+ )
2001
+
2002
+
2003
+
2004
+
2005
+ nn.init.constant_(
2006
+ self.input_gate.bias,
2007
+ 2.0,
2008
+ )
2009
+
2010
+
2011
+
2012
+
2013
+ nn.init.zeros_(
2014
+ self.output_gate.weight
2015
+ )
2016
+
2017
+
2018
+
2019
+
2020
+ nn.init.constant_(
2021
+ self.output_gate.bias,
2022
+ 2.0,
2023
+ )
2024
+
2025
+
2026
+
2027
+
2028
+ self.scale_in = (
2029
+ CTWScaleMixer()
2030
+ )
2031
+
2032
+
2033
+
2034
+
2035
+ self.meyer = (
2036
+ CTWCausalMeyerFIR()
2037
+ )
2038
+
2039
+
2040
+
2041
+
2042
+ self.scale_out = (
2043
+ CTWScaleMixer()
2044
+ )
2045
+
2046
+
2047
+
2048
+
2049
+ self.local = (
2050
+ CTWCausalLocalConv()
2051
+ )
2052
+
2053
+
2054
+
2055
+
2056
+ self.alpha_meyer = nn.Parameter(
2057
+
2058
+
2059
+ torch.tensor(
2060
+ 0.10,
2061
+ dtype=torch.float32,
2062
+ )
2063
+ )
2064
+
2065
+
2066
+
2067
+
2068
+ self.alpha_local = nn.Parameter(
2069
+
2070
+
2071
+ torch.tensor(
2072
+ 0.10,
2073
+ dtype=torch.float32,
2074
+ )
2075
+ )
2076
+
2077
+
2078
+
2079
+
2080
+ self.norm2 = CTWRMSNorm(
2081
+ MODEL_DIM
2082
+ )
2083
+
2084
+
2085
+
2086
+
2087
+ self.ffn = CTWSwiGLU(
2088
+ MODEL_DIM,
2089
+ FFN_DIM,
2090
+ )
2091
+
2092
+
2093
+
2094
+
2095
+ def forward(
2096
+ self,
2097
+ x,
2098
+ ):
2099
+
2100
+
2101
+ b, l, s, c = x.shape
2102
+
2103
+
2104
+
2105
+
2106
+ flat = x.reshape(
2107
+ b,
2108
+ l,
2109
+ MODEL_DIM,
2110
+ )
2111
+
2112
+
2113
+
2114
+
2115
+ n = self.norm1(
2116
+ flat
2117
+ )
2118
+
2119
+
2120
+
2121
+
2122
+ gate_in = torch.sigmoid(
2123
+
2124
+
2125
+ self.input_gate(
2126
+ n
2127
+ )
2128
+
2129
+
2130
+ ).reshape(
2131
+ b,
2132
+ l,
2133
+ s,
2134
+ c,
2135
+ )
2136
+
2137
+
2138
+
2139
+
2140
+ gate_out = torch.sigmoid(
2141
+
2142
+
2143
+ self.output_gate(
2144
+ n
2145
+ )
2146
+
2147
+
2148
+ ).reshape(
2149
+ b,
2150
+ l,
2151
+ s,
2152
+ c,
2153
+ )
2154
+
2155
+
2156
+
2157
+
2158
+ spectral = self.meyer(
2159
+
2160
+
2161
+ self.scale_in(
2162
+ x
2163
+ *
2164
+ gate_in
2165
+ )
2166
+ )
2167
+
2168
+
2169
+
2170
+
2171
+ spectral = self.scale_out(
2172
+ spectral
2173
+ )
2174
+
2175
+
2176
+
2177
+
2178
+ local = self.local(
2179
+ n
2180
+ ).reshape(
2181
+ b,
2182
+ l,
2183
+ s,
2184
+ c,
2185
+ )
2186
+
2187
+
2188
+
2189
+
2190
+ x = (
2191
+
2192
+
2193
+ x
2194
+
2195
+
2196
+ +
2197
+
2198
+
2199
+ self.alpha_meyer.to(
2200
+ x.dtype
2201
+ )
2202
+ *
2203
+ spectral
2204
+ *
2205
+ gate_out
2206
+
2207
+
2208
+ +
2209
+
2210
+
2211
+ self.alpha_local.to(
2212
+ x.dtype
2213
+ )
2214
+ *
2215
+ local
2216
+ )
2217
+
2218
+
2219
+
2220
+
2221
+ flat = x.reshape(
2222
+ b,
2223
+ l,
2224
+ MODEL_DIM,
2225
+ )
2226
+
2227
+
2228
+
2229
+
2230
+ flat = (
2231
+
2232
+
2233
+ flat
2234
+
2235
+
2236
+ +
2237
+
2238
+
2239
+ self.ffn(
2240
+ self.norm2(
2241
+ flat
2242
+ )
2243
+ )
2244
+ )
2245
+
2246
+
2247
+
2248
+
2249
+ return flat.reshape(
2250
+ b,
2251
+ l,
2252
+ s,
2253
+ c,
2254
+ )
2255
+
2256
+
2257
+
2258
+
2259
+ # =============================================================================
2260
+ # EXACT EIGHT-BYTE AUTOREGRESSIVE DECODER
2261
+ # =============================================================================
2262
+
2263
+
2264
+ class CTWByteDecoder(
2265
+ nn.Module
2266
+ ):
2267
+
2268
+
2269
+ def __init__(
2270
+ self,
2271
+ shared_embedding,
2272
+ ):
2273
+
2274
+
2275
+ super().__init__()
2276
+
2277
+
2278
+
2279
+
2280
+ self.shared_embedding = (
2281
+ shared_embedding
2282
+ )
2283
+
2284
+
2285
+
2286
+
2287
+ self.context_proj = nn.Linear(
2288
+ MODEL_DIM,
2289
+ BYTE_DECODER_DIM,
2290
+ )
2291
+
2292
+
2293
+
2294
+
2295
+ self.gru = nn.GRUCell(
2296
+ BYTE_DIM,
2297
+ BYTE_DECODER_DIM,
2298
+ )
2299
+
2300
+
2301
+
2302
+
2303
+ self.norm = CTWRMSNorm(
2304
+ BYTE_DECODER_DIM
2305
+ )
2306
+
2307
+
2308
+
2309
+
2310
+ self.to_byte_space = nn.Linear(
2311
+ BYTE_DECODER_DIM,
2312
+ BYTE_DIM,
2313
+ )
2314
+
2315
+
2316
+
2317
+
2318
+ self.bos = nn.Parameter(
2319
+ torch.zeros(
2320
+ BYTE_DIM
2321
+ )
2322
+ )
2323
+
2324
+
2325
+
2326
+
2327
+ self.byte_position = nn.Parameter(
2328
+
2329
+
2330
+ torch.zeros(
2331
+ BYTES_PER_BLOCK,
2332
+ BYTE_DIM,
2333
+ )
2334
+ )
2335
+
2336
+
2337
+
2338
+
2339
+ nn.init.normal_(
2340
+ self.bos,
2341
+ mean=0.0,
2342
+ std=0.02,
2343
+ )
2344
+
2345
+
2346
+
2347
+
2348
+ nn.init.normal_(
2349
+ self.byte_position,
2350
+ mean=0.0,
2351
+ std=0.01,
2352
+ )
2353
+
2354
+
2355
+
2356
+
2357
+ def nll(
2358
+ self,
2359
+ context,
2360
+ target_blocks,
2361
+ ):
2362
+
2363
+
2364
+ b, l, _ = context.shape
2365
+
2366
+
2367
+
2368
+
2369
+ n = (
2370
+ b
2371
+ *
2372
+ l
2373
+ )
2374
+
2375
+
2376
+
2377
+
2378
+ hidden = torch.tanh(
2379
+
2380
+
2381
+ self.context_proj(
2382
+ context
2383
+ )
2384
+
2385
+
2386
+ ).reshape(
2387
+ n,
2388
+ BYTE_DECODER_DIM,
2389
+ )
2390
+
2391
+
2392
+
2393
+
2394
+ previous = (
2395
+ self.bos[
2396
+ None,
2397
+ :
2398
+ ]
2399
+ .expand(
2400
+ n,
2401
+ -1,
2402
+ )
2403
+ )
2404
+
2405
+
2406
+
2407
+
2408
+ total_loss = None
2409
+
2410
+
2411
+
2412
+
2413
+ for r in range(
2414
+ BYTES_PER_BLOCK
2415
+ ):
2416
+
2417
+
2418
+ decoder_input = (
2419
+
2420
+
2421
+ previous
2422
+
2423
+
2424
+ +
2425
+
2426
+
2427
+ self.byte_position[
2428
+ r
2429
+ ][
2430
+ None,
2431
+ :
2432
+ ]
2433
+ )
2434
+
2435
+
2436
+
2437
+
2438
+ hidden = self.gru(
2439
+ decoder_input,
2440
+ hidden,
2441
+ )
2442
+
2443
+
2444
+
2445
+
2446
+ z = self.to_byte_space(
2447
+ self.norm(
2448
+ hidden
2449
+ )
2450
+ )
2451
+
2452
+
2453
+
2454
+
2455
+ target = (
2456
+ target_blocks[
2457
+ :,
2458
+ :,
2459
+ r
2460
+ ]
2461
+ .reshape(
2462
+ -1
2463
+ )
2464
+ .long()
2465
+ )
2466
+
2467
+
2468
+
2469
+
2470
+ position_loss = None
2471
+
2472
+
2473
+
2474
+
2475
+ for start in range(
2476
+ 0,
2477
+ n,
2478
+ HEAD_CHUNK,
2479
+ ):
2480
+
2481
+
2482
+ end = min(
2483
+ start
2484
+ +
2485
+ HEAD_CHUNK,
2486
+ n,
2487
+ )
2488
+
2489
+
2490
+
2491
+
2492
+ logits = F.linear(
2493
+ z[
2494
+ start:end
2495
+ ],
2496
+ self.shared_embedding.weight,
2497
+ )
2498
+
2499
+
2500
+
2501
+
2502
+ piece = F.cross_entropy(
2503
+ logits.float(),
2504
+ target[
2505
+ start:end
2506
+ ],
2507
+ reduction="sum",
2508
+ )
2509
+
2510
+
2511
+
2512
+
2513
+ position_loss = (
2514
+ piece
2515
+ if position_loss is None
2516
+ else
2517
+ position_loss
2518
+ +
2519
+ piece
2520
+ )
2521
+
2522
+
2523
+
2524
+
2525
+ total_loss = (
2526
+ position_loss
2527
+ if total_loss is None
2528
+ else
2529
+ total_loss
2530
+ +
2531
+ position_loss
2532
+ )
2533
+
2534
+
2535
+
2536
+
2537
+ # Exact teacher forcing:
2538
+ # byte r+1 may condition on true byte r.
2539
+
2540
+
2541
+ previous = self.shared_embedding(
2542
+ target
2543
+ )
2544
+
2545
+
2546
+
2547
+
2548
+ return (
2549
+ total_loss
2550
+ /
2551
+ float(
2552
+ n
2553
+ *
2554
+ BYTES_PER_BLOCK
2555
+ )
2556
+ )
2557
+
2558
+
2559
+
2560
+
2561
+ # =============================================================================
2562
+ # COMPLETE CAUSAL MODEL
2563
+ # =============================================================================
2564
+
2565
+
2566
+ class CTWModel(
2567
+ nn.Module
2568
+ ):
2569
+
2570
+
2571
+ def __init__(
2572
+ self,
2573
+ ):
2574
+
2575
+
2576
+ super().__init__()
2577
+
2578
+
2579
+
2580
+
2581
+ self.tokenizer = (
2582
+ CTWBlockLiftingTokenizer()
2583
+ )
2584
+
2585
+
2586
+
2587
+
2588
+ self.position = nn.Parameter(
2589
+
2590
+
2591
+ torch.zeros(
2592
+ 1,
2593
+ MODEL_CONTEXT,
2594
+ MODEL_DIM,
2595
+ )
2596
+ )
2597
+
2598
+
2599
+
2600
+
2601
+ nn.init.normal_(
2602
+ self.position,
2603
+ mean=0.0,
2604
+ std=0.01,
2605
+ )
2606
+
2607
+
2608
+
2609
+
2610
+ self.layers = nn.ModuleList(
2611
+
2612
+
2613
+ [
2614
+
2615
+
2616
+ CTWLayer()
2617
+
2618
+
2619
+ for _ in range(
2620
+ N_LAYERS
2621
+ )
2622
+ ]
2623
+ )
2624
+
2625
+
2626
+
2627
+
2628
+ self.final_norm = CTWRMSNorm(
2629
+ MODEL_DIM
2630
+ )
2631
+
2632
+
2633
+
2634
+
2635
+ self.bos_context = nn.Parameter(
2636
+ torch.zeros(
2637
+ MODEL_DIM
2638
+ )
2639
+ )
2640
+
2641
+
2642
+
2643
+
2644
+ nn.init.normal_(
2645
+ self.bos_context,
2646
+ mean=0.0,
2647
+ std=0.02,
2648
+ )
2649
+
2650
+
2651
+
2652
+
2653
+ self.decoder = CTWByteDecoder(
2654
+ self.tokenizer.byte_embedding
2655
+ )
2656
+
2657
+
2658
+
2659
+
2660
+ def encode_completed_blocks(
2661
+ self,
2662
+ raw_bytes,
2663
+ checkpoint_layers,
2664
+ ):
2665
+
2666
+
2667
+ if (
2668
+ raw_bytes.ndim
2669
+ !=
2670
+ 2
2671
+ ):
2672
+
2673
+
2674
+ raise ValueError(
2675
+ "Expected raw byte IDs [B,T]."
2676
+ )
2677
+
2678
+
2679
+
2680
+
2681
+ b, t = raw_bytes.shape
2682
+
2683
+
2684
+
2685
+
2686
+ if (
2687
+ t
2688
+ %
2689
+ BYTES_PER_BLOCK
2690
+ !=
2691
+ 0
2692
+ ):
2693
+
2694
+
2695
+ raise ValueError(
2696
+ "Raw byte length must be divisible by 8."
2697
+ )
2698
+
2699
+
2700
+
2701
+
2702
+ l = (
2703
+ t
2704
+ //
2705
+ BYTES_PER_BLOCK
2706
+ )
2707
+
2708
+
2709
+
2710
+
2711
+ self.alpha_meyer = nn.Parameter(
2712
+
2713
+
2714
+ torch.tensor(
2715
+ 0.10,
2716
+ dtype=torch.float32,
2717
+ )
2718
+ )
2719
+
2720
+
2721
+
2722
+
2723
+ self.alpha_local = nn.Parameter(
2724
+
2725
+
2726
+ torch.tensor(
2727
+ 0.10,
2728
+ dtype=torch.float32,
2729
+ )
2730
+ )
2731
+
2732
+
2733
+
2734
+
2735
+ self.norm2 = CTWRMSNorm(
2736
+ MODEL_DIM
2737
+ )
2738
+
2739
+
2740
+
2741
+
2742
+ self.ffn = CTWSwiGLU(
2743
+ MODEL_DIM,
2744
+ FFN_DIM,
2745
+ )
2746
+
2747
+
2748
+
2749
+
2750
+ def forward(
2751
+ self,
2752
+ x,
2753
+ ):
2754
+
2755
+
2756
+ b, l, s, c = x.shape
2757
+
2758
+
2759
+
2760
+
2761
+ flat = x.reshape(
2762
+ b,
2763
+ l,
2764
+ MODEL_DIM,
2765
+ )
2766
+
2767
+
2768
+
2769
+
2770
+ n = self.norm1(
2771
+ flat
2772
+ )
2773
+
2774
+
2775
+
2776
+
2777
+ gate_in = torch.sigmoid(
2778
+
2779
+
2780
+ self.input_gate(
2781
+ n
2782
+ )
2783
+
2784
+
2785
+ ).reshape(
2786
+ b,
2787
+ l,
2788
+ s,
2789
+ c,
2790
+ )
2791
+
2792
+
2793
+
2794
+
2795
+ gate_out = torch.sigmoid(
2796
+
2797
+
2798
+ self.output_gate(
2799
+ n
2800
+ )
2801
+
2802
+
2803
+ ).reshape(
2804
+ b,
2805
+ l,
2806
+ s,
2807
+ c,
2808
+ )
2809
+
2810
+
2811
+
2812
+
2813
+ spectral = self.meyer(
2814
+
2815
+
2816
+ self.scale_in(
2817
+ x
2818
+ *
2819
+ gate_in
2820
+ )
2821
+ )
2822
+
2823
+
2824
+
2825
+
2826
+ spectral = self.scale_out(
2827
+ spectral
2828
+ )
2829
+
2830
+
2831
+
2832
+
2833
+ local = self.local(
2834
+ n
2835
+ ).reshape(
2836
+ b,
2837
+ l,
2838
+ s,
2839
+ c,
2840
+ )
2841
+
2842
+
2843
+
2844
+
2845
+ x = (
2846
+
2847
+
2848
+ x
2849
+
2850
+
2851
+ +
2852
+
2853
+
2854
+ self.alpha_meyer.to(
2855
+ x.dtype
2856
+ )
2857
+ *
2858
+ spectral
2859
+ *
2860
+ gate_out
2861
+
2862
+
2863
+ +
2864
+
2865
+
2866
+ self.alpha_local.to(
2867
+ x.dtype
2868
+ )
2869
+ *
2870
+ local
2871
+ )
2872
+
2873
+
2874
+
2875
+
2876
+ flat = x.reshape(
2877
+ b,
2878
+ l,
2879
+ MODEL_DIM,
2880
+ )
2881
+
2882
+
2883
+
2884
+
2885
+ flat = (
2886
+
2887
+
2888
+ flat
2889
+
2890
+
2891
+ +
2892
+
2893
+
2894
+ self.ffn(
2895
+ self.norm2(
2896
+ flat
2897
+ )
2898
+ )
2899
+ )
2900
+
2901
+
2902
+
2903
+
2904
+ return flat.reshape(
2905
+ b,
2906
+ l,
2907
+ s,
2908
+ c,
2909
+ )
2910
+
2911
+
2912
+
2913
+
2914
+ # =============================================================================
2915
+ # EXACT EIGHT-BYTE AUTOREGRESSIVE DECODER
2916
+ # =============================================================================
2917
+
2918
+
2919
+ class CTWByteDecoder(
2920
+ nn.Module
2921
+ ):
2922
+
2923
+
2924
+ def __init__(
2925
+ self,
2926
+ shared_embedding,
2927
+ ):
2928
+
2929
+
2930
+ super().__init__()
2931
+
2932
+
2933
+
2934
+
2935
+ self.shared_embedding = (
2936
+ shared_embedding
2937
+ )
2938
+
2939
+
2940
+
2941
+
2942
+ self.context_proj = nn.Linear(
2943
+ MODEL_DIM,
2944
+ BYTE_DECODER_DIM,
2945
+ )
2946
+
2947
+
2948
+
2949
+
2950
+ self.gru = nn.GRUCell(
2951
+ BYTE_DIM,
2952
+ BYTE_DECODER_DIM,
2953
+ )
2954
+
2955
+
2956
+
2957
+
2958
+ self.norm = CTWRMSNorm(
2959
+ BYTE_DECODER_DIM
2960
+ )
2961
+
2962
+
2963
+
2964
+
2965
+ self.to_byte_space = nn.Linear(
2966
+ BYTE_DECODER_DIM,
2967
+ BYTE_DIM,
2968
+ )
2969
+
2970
+
2971
+
2972
+
2973
+ self.bos = nn.Parameter(
2974
+ torch.zeros(
2975
+ BYTE_DIM
2976
+ )
2977
+ )
2978
+
2979
+
2980
+
2981
+
2982
+ self.byte_position = nn.Parameter(
2983
+
2984
+
2985
+ torch.zeros(
2986
+ BYTES_PER_BLOCK,
2987
+ BYTE_DIM,
2988
+ )
2989
+ )
2990
+
2991
+
2992
+
2993
+
2994
+ nn.init.normal_(
2995
+ self.bos,
2996
+ mean=0.0,
2997
+ std=0.02,
2998
+ )
2999
+
3000
+
3001
+
3002
+
3003
+ nn.init.normal_(
3004
+ self.byte_position,
3005
+ mean=0.0,
3006
+ std=0.01,
3007
+ )
3008
+
3009
+
3010
+
3011
+
3012
+ def nll(
3013
+ self,
3014
+ context,
3015
+ target_blocks,
3016
+ ):
3017
+
3018
+
3019
+ b, l, _ = context.shape
3020
+
3021
+
3022
+
3023
+
3024
+ n = (
3025
+ b
3026
+ *
3027
+ l
3028
+ )
3029
+
3030
+
3031
+
3032
+
3033
+ hidden = torch.tanh(
3034
+
3035
+
3036
+ self.context_proj(
3037
+ context
3038
+ )
3039
+
3040
+
3041
+ ).reshape(
3042
+ n,
3043
+ BYTE_DECODER_DIM,
3044
+ )
3045
+
3046
+
3047
+
3048
+
3049
+ previous = (
3050
+ self.bos[
3051
+ None,
3052
+ :
3053
+ ]
3054
+ .expand(
3055
+ n,
3056
+ -1,
3057
+ )
3058
+ )
3059
+
3060
+
3061
+
3062
+
3063
+ total_loss = None
3064
+
3065
+
3066
+
3067
+
3068
+ for r in range(
3069
+ BYTES_PER_BLOCK
3070
+ ):
3071
+
3072
+
3073
+ decoder_input = (
3074
+
3075
+
3076
+ previous
3077
+
3078
+
3079
+ +
3080
+
3081
+
3082
+ self.byte_position[
3083
+ r
3084
+ ][
3085
+ None,
3086
+ :
3087
+ ]
3088
+ )
3089
+
3090
+
3091
+
3092
+
3093
+ hidden = self.gru(
3094
+ decoder_input,
3095
+ hidden,
3096
+ )
3097
+
3098
+
3099
+
3100
+
3101
+ z = self.to_byte_space(
3102
+ self.norm(
3103
+ hidden
3104
+ )
3105
+ )
3106
+
3107
+
3108
+
3109
+
3110
+ target = (
3111
+ target_blocks[
3112
+ :,
3113
+ :,
3114
+ r
3115
+ ]
3116
+ .reshape(
3117
+ -1
3118
+ )
3119
+ .long()
3120
+ )
3121
+
3122
+
3123
+
3124
+
3125
+ position_loss = None
3126
+
3127
+
3128
+
3129
+
3130
+ for start in range(
3131
+ 0,
3132
+ n,
3133
+ HEAD_CHUNK,
3134
+ ):
3135
+
3136
+
3137
+ end = min(
3138
+ start
3139
+ +
3140
+ HEAD_CHUNK,
3141
+ n,
3142
+ )
3143
+
3144
+
3145
+
3146
+
3147
+ logits = F.linear(
3148
+ z[
3149
+ start:end
3150
+ ],
3151
+ self.shared_embedding.weight,
3152
+ )
3153
+
3154
+
3155
+
3156
+
3157
+ piece = F.cross_entropy(
3158
+ logits.float(),
3159
+ target[
3160
+ start:end
3161
+ ],
3162
+ reduction="sum",
3163
+ )
3164
+
3165
+
3166
+
3167
+
3168
+ position_loss = (
3169
+ piece
3170
+ if position_loss is None
3171
+ else
3172
+ position_loss
3173
+ +
3174
+ piece
3175
+ )
3176
+
3177
+
3178
+
3179
+
3180
+ total_loss = (
3181
+ position_loss
3182
+ if total_loss is None
3183
+ else
3184
+ total_loss
3185
+ +
3186
+ position_loss
3187
+ )
3188
+
3189
+
3190
+
3191
+
3192
+ # Exact teacher forcing:
3193
+ # byte r+1 may condition on true byte r.
3194
+
3195
+
3196
+ previous = self.shared_embedding(
3197
+ target
3198
+ )
3199
+
3200
+
3201
+
3202
+
3203
+ return (
3204
+ total_loss
3205
+ /
3206
+ float(
3207
+ n
3208
+ *
3209
+ BYTES_PER_BLOCK
3210
+ )
3211
+ )
3212
+
3213
+
3214
+
3215
+
3216
+ # =============================================================================
3217
+ # COMPLETE CAUSAL MODEL
3218
+ # =============================================================================
3219
+
3220
+
3221
+ class CTWModel(
3222
+ nn.Module
3223
+ ):
3224
+
3225
+
3226
+ def __init__(
3227
+ self,
3228
+ ):
3229
+
3230
+
3231
+ super().__init__()
3232
+
3233
+
3234
+
3235
+
3236
+ self.tokenizer = (
3237
+ CTWBlockLiftingTokenizer()
3238
+ )
3239
+
3240
+
3241
+
3242
+
3243
+ self.position = nn.Parameter(
3244
+
3245
+
3246
+ torch.zeros(
3247
+ 1,
3248
+ MODEL_CONTEXT,
3249
+ MODEL_DIM,
3250
+ )
3251
+ )
3252
+
3253
+
3254
+
3255
+
3256
+ nn.init.normal_(
3257
+ self.position,
3258
+ mean=0.0,
3259
+ std=0.01,
3260
+ )
3261
+
3262
+
3263
+
3264
+
3265
+ self.layers = nn.ModuleList(
3266
+
3267
+
3268
+ [
3269
+
3270
+
3271
+ CTWLayer()
3272
+
3273
+
3274
+ for _ in range(
3275
+ N_LAYERS
3276
+ )
3277
+ ]
3278
+ )
3279
+
3280
+
3281
+
3282
+
3283
+ self.final_norm = CTWRMSNorm(
3284
+ MODEL_DIM
3285
+ )
3286
+
3287
+
3288
+
3289
+
3290
+ self.bos_context = nn.Parameter(
3291
+ torch.zeros(
3292
+ MODEL_DIM
3293
+ )
3294
+ )
3295
+
3296
+
3297
+
3298
+
3299
+ nn.init.normal_(
3300
+ self.bos_context,
3301
+ mean=0.0,
3302
+ std=0.02,
3303
+ )
3304
+
3305
+
3306
+
3307
+
3308
+ self.decoder = CTWByteDecoder(
3309
+ self.tokenizer.byte_embedding
3310
+ )
3311
+
3312
+
3313
+
3314
+
3315
+ def encode_completed_blocks(
3316
+ self,
3317
+ raw_bytes,
3318
+ checkpoint_layers,
3319
+ ):
3320
+
3321
+
3322
+ if (
3323
+ raw_bytes.ndim
3324
+ !=
3325
+ 2
3326
+ ):
3327
+
3328
+
3329
+ raise ValueError(
3330
+ "Expected raw byte IDs [B,T]."
3331
+ )
3332
+
3333
+
3334
+
3335
+
3336
+ b, t = raw_bytes.shape
3337
+
3338
+
3339
+
3340
+
3341
+ if (
3342
+ t
3343
+ %
3344
+ BYTES_PER_BLOCK
3345
+ !=
3346
+ 0
3347
+ ):
3348
+
3349
+
3350
+ raise ValueError(
3351
+ "Raw byte length must be divisible by 8."
3352
+ )
3353
+
3354
+
3355
+
3356
+
3357
+ l = (
3358
+ t
3359
+ //
3360
+ BYTES_PER_BLOCK
3361
+ )
3362
+
3363
+
3364
+
3365
+
3366
+ if (
3367
+ l
3368
+ >
3369
+ MODEL_CONTEXT
3370
+ ):
3371
+
3372
+
3373
+ raise ValueError(
3374
+
3375
+
3376
+ f"Context {l} exceeds "
3377
+ f"MODEL_CONTEXT={MODEL_CONTEXT}."
3378
+ )
3379
+
3380
+
3381
+
3382
+
3383
+ x = self.tokenizer(
3384
+ raw_bytes.long()
3385
+ )
3386
+
3387
+
3388
+
3389
+
3390
+ pos = (
3391
+ self.position[
3392
+ :,
3393
+ :l,
3394
+ :
3395
+ ]
3396
+ .reshape(
3397
+ 1,
3398
+ l,
3399
+ N_SCALES,
3400
+ BYTE_DIM,
3401
+ )
3402
+ )
3403
+
3404
+
3405
+
3406
+
3407
+ x = (
3408
+ x
3409
+ +
3410
+ pos.to(
3411
+ x.dtype
3412
+ )
3413
+ )
3414
+
3415
+
3416
+
3417
+
3418
+ for layer in self.layers:
3419
+
3420
+
3421
+ if (
3422
+ checkpoint_layers
3423
+ and
3424
+ self.training
3425
+ ):
3426
+
3427
+
3428
+ x = torch_checkpoint(
3429
+ layer,
3430
+ x,
3431
+ use_reentrant=False,
3432
+ preserve_rng_state=False,
3433
+ )
3434
+
3435
+
3436
+ else:
3437
+
3438
+
3439
+ x = layer(
3440
+ x
3441
+ )
3442
+
3443
+
3444
+
3445
+
3446
+ h = self.final_norm(
3447
+
3448
+
3449
+ x.reshape(
3450
+ b,
3451
+ l,
3452
+ MODEL_DIM,
3453
+ )
3454
+ )
3455
+
3456
+
3457
+
3458
+
3459
+ blocks = (
3460
+ raw_bytes
3461
+ .long()
3462
+ .reshape(
3463
+ b,
3464
+ l,
3465
+ BYTES_PER_BLOCK,
3466
+ )
3467
+ )
3468
+
3469
+
3470
+
3471
+
3472
+ return (
3473
+ h,
3474
+ blocks,
3475
+ )
3476
+
3477
+
3478
+
3479
+
3480
+ def contexts(
3481
+ self,
3482
+ raw_bytes,
3483
+ checkpoint_layers=False,
3484
+ ):
3485
+
3486
+
3487
+ (
3488
+ h,
3489
+ blocks,
3490
+ ) = self.encode_completed_blocks(
3491
+ raw_bytes,
3492
+ checkpoint_layers,
3493
+ )
3494
+
3495
+
3496
+
3497
+
3498
+ b, l, _ = h.shape
3499
+
3500
+
3501
+
3502
+
3503
+ context = torch.empty_like(
3504
+ h
3505
+ )
3506
+
3507
+
3508
+
3509
+
3510
+ # First block has no preceding block.
3511
+
3512
+
3513
+ context[
3514
+ :,
3515
+ 0,
3516
+ :
3517
+ ] = self.bos_context.to(
3518
+ h.dtype
3519
+ )
3520
+
3521
+
3522
+
3523
+
3524
+ # -------------------------------------------------------------
3525
+ # CRITICAL CAUSAL SHIFT
3526
+ #
3527
+ # prediction for block b receives h[b-1], never h[b].
3528
+ # -------------------------------------------------------------
3529
+
3530
+
3531
+ if l > 1:
3532
+
3533
+
3534
+ context[
3535
+ :,
3536
+ 1:,
3537
+ :
3538
+ ] = h[
3539
+ :,
3540
+ :-1,
3541
+ :
3542
+ ]
3543
+
3544
+
3545
+
3546
+
3547
+ return (
3548
+ context,
3549
+ blocks,
3550
+ )
3551
+
3552
+
3553
+
3554
+
3555
+ def nll(
3556
+ self,
3557
+ raw_bytes,
3558
+ checkpoint_layers=True,
3559
+ ):
3560
+
3561
+
3562
+ (
3563
+ context,
3564
+ blocks,
3565
+ ) = self.contexts(
3566
+ raw_bytes,
3567
+ checkpoint_layers,
3568
+ )
3569
+
3570
+
3571
+
3572
+
3573
+ return self.decoder.nll(
3574
+ context,
3575
+ blocks,
3576
+ )
vocab.json ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "<0x00>": 0,
3
+ "<0x01>": 1,
4
+ "<0x02>": 2,
5
+ "<0x03>": 3,
6
+ "<0x04>": 4,
7
+ "<0x05>": 5,
8
+ "<0x06>": 6,
9
+ "<0x07>": 7,
10
+ "<0x08>": 8,
11
+ "<0x09>": 9,
12
+ "<0x0A>": 10,
13
+ "<0x0B>": 11,
14
+ "<0x0C>": 12,
15
+ "<0x0D>": 13,
16
+ "<0x0E>": 14,
17
+ "<0x0F>": 15,
18
+ "<0x10>": 16,
19
+ "<0x11>": 17,
20
+ "<0x12>": 18,
21
+ "<0x13>": 19,
22
+ "<0x14>": 20,
23
+ "<0x15>": 21,
24
+ "<0x16>": 22,
25
+ "<0x17>": 23,
26
+ "<0x18>": 24,
27
+ "<0x19>": 25,
28
+ "<0x1A>": 26,
29
+ "<0x1B>": 27,
30
+ "<0x1C>": 28,
31
+ "<0x1D>": 29,
32
+ "<0x1E>": 30,
33
+ "<0x1F>": 31,
34
+ "<0x20>": 32,
35
+ "<0x21>": 33,
36
+ "<0x22>": 34,
37
+ "<0x23>": 35,
38
+ "<0x24>": 36,
39
+ "<0x25>": 37,
40
+ "<0x26>": 38,
41
+ "<0x27>": 39,
42
+ "<0x28>": 40,
43
+ "<0x29>": 41,
44
+ "<0x2A>": 42,
45
+ "<0x2B>": 43,
46
+ "<0x2C>": 44,
47
+ "<0x2D>": 45,
48
+ "<0x2E>": 46,
49
+ "<0x2F>": 47,
50
+ "<0x30>": 48,
51
+ "<0x31>": 49,
52
+ "<0x32>": 50,
53
+ "<0x33>": 51,
54
+ "<0x34>": 52,
55
+ "<0x35>": 53,
56
+ "<0x36>": 54,
57
+ "<0x37>": 55,
58
+ "<0x38>": 56,
59
+ "<0x39>": 57,
60
+ "<0x3A>": 58,
61
+ "<0x3B>": 59,
62
+ "<0x3C>": 60,
63
+ "<0x3D>": 61,
64
+ "<0x3E>": 62,
65
+ "<0x3F>": 63,
66
+ "<0x40>": 64,
67
+ "<0x41>": 65,
68
+ "<0x42>": 66,
69
+ "<0x43>": 67,
70
+ "<0x44>": 68,
71
+ "<0x45>": 69,
72
+ "<0x46>": 70,
73
+ "<0x47>": 71,
74
+ "<0x48>": 72,
75
+ "<0x49>": 73,
76
+ "<0x4A>": 74,
77
+ "<0x4B>": 75,
78
+ "<0x4C>": 76,
79
+ "<0x4D>": 77,
80
+ "<0x4E>": 78,
81
+ "<0x4F>": 79,
82
+ "<0x50>": 80,
83
+ "<0x51>": 81,
84
+ "<0x52>": 82,
85
+ "<0x53>": 83,
86
+ "<0x54>": 84,
87
+ "<0x55>": 85,
88
+ "<0x56>": 86,
89
+ "<0x57>": 87,
90
+ "<0x58>": 88,
91
+ "<0x59>": 89,
92
+ "<0x5A>": 90,
93
+ "<0x5B>": 91,
94
+ "<0x5C>": 92,
95
+ "<0x5D>": 93,
96
+ "<0x5E>": 94,
97
+ "<0x5F>": 95,
98
+ "<0x60>": 96,
99
+ "<0x61>": 97,
100
+ "<0x62>": 98,
101
+ "<0x63>": 99,
102
+ "<0x64>": 100,
103
+ "<0x65>": 101,
104
+ "<0x66>": 102,
105
+ "<0x67>": 103,
106
+ "<0x68>": 104,
107
+ "<0x69>": 105,
108
+ "<0x6A>": 106,
109
+ "<0x6B>": 107,
110
+ "<0x6C>": 108,
111
+ "<0x6D>": 109,
112
+ "<0x6E>": 110,
113
+ "<0x6F>": 111,
114
+ "<0x70>": 112,
115
+ "<0x71>": 113,
116
+ "<0x72>": 114,
117
+ "<0x73>": 115,
118
+ "<0x74>": 116,
119
+ "<0x75>": 117,
120
+ "<0x76>": 118,
121
+ "<0x77>": 119,
122
+ "<0x78>": 120,
123
+ "<0x79>": 121,
124
+ "<0x7A>": 122,
125
+ "<0x7B>": 123,
126
+ "<0x7C>": 124,
127
+ "<0x7D>": 125,
128
+ "<0x7E>": 126,
129
+ "<0x7F>": 127,
130
+ "<0x80>": 128,
131
+ "<0x81>": 129,
132
+ "<0x82>": 130,
133
+ "<0x83>": 131,
134
+ "<0x84>": 132,
135
+ "<0x85>": 133,
136
+ "<0x86>": 134,
137
+ "<0x87>": 135,
138
+ "<0x88>": 136,
139
+ "<0x89>": 137,
140
+ "<0x8A>": 138,
141
+ "<0x8B>": 139,
142
+ "<0x8C>": 140,
143
+ "<0x8D>": 141,
144
+ "<0x8E>": 142,
145
+ "<0x8F>": 143,
146
+ "<0x90>": 144,
147
+ "<0x91>": 145,
148
+ "<0x92>": 146,
149
+ "<0x93>": 147,
150
+ "<0x94>": 148,
151
+ "<0x95>": 149,
152
+ "<0x96>": 150,
153
+ "<0x97>": 151,
154
+ "<0x98>": 152,
155
+ "<0x99>": 153,
156
+ "<0x9A>": 154,
157
+ "<0x9B>": 155,
158
+ "<0x9C>": 156,
159
+ "<0x9D>": 157,
160
+ "<0x9E>": 158,
161
+ "<0x9F>": 159,
162
+ "<0xA0>": 160,
163
+ "<0xA1>": 161,
164
+ "<0xA2>": 162,
165
+ "<0xA3>": 163,
166
+ "<0xA4>": 164,
167
+ "<0xA5>": 165,
168
+ "<0xA6>": 166,
169
+ "<0xA7>": 167,
170
+ "<0xA8>": 168,
171
+ "<0xA9>": 169,
172
+ "<0xAA>": 170,
173
+ "<0xAB>": 171,
174
+ "<0xAC>": 172,
175
+ "<0xAD>": 173,
176
+ "<0xAE>": 174,
177
+ "<0xAF>": 175,
178
+ "<0xB0>": 176,
179
+ "<0xB1>": 177,
180
+ "<0xB2>": 178,
181
+ "<0xB3>": 179,
182
+ "<0xB4>": 180,
183
+ "<0xB5>": 181,
184
+ "<0xB6>": 182,
185
+ "<0xB7>": 183,
186
+ "<0xB8>": 184,
187
+ "<0xB9>": 185,
188
+ "<0xBA>": 186,
189
+ "<0xBB>": 187,
190
+ "<0xBC>": 188,
191
+ "<0xBD>": 189,
192
+ "<0xBE>": 190,
193
+ "<0xBF>": 191,
194
+ "<0xC0>": 192,
195
+ "<0xC1>": 193,
196
+ "<0xC2>": 194,
197
+ "<0xC3>": 195,
198
+ "<0xC4>": 196,
199
+ "<0xC5>": 197,
200
+ "<0xC6>": 198,
201
+ "<0xC7>": 199,
202
+ "<0xC8>": 200,
203
+ "<0xC9>": 201,
204
+ "<0xCA>": 202,
205
+ "<0xCB>": 203,
206
+ "<0xCC>": 204,
207
+ "<0xCD>": 205,
208
+ "<0xCE>": 206,
209
+ "<0xCF>": 207,
210
+ "<0xD0>": 208,
211
+ "<0xD1>": 209,
212
+ "<0xD2>": 210,
213
+ "<0xD3>": 211,
214
+ "<0xD4>": 212,
215
+ "<0xD5>": 213,
216
+ "<0xD6>": 214,
217
+ "<0xD7>": 215,
218
+ "<0xD8>": 216,
219
+ "<0xD9>": 217,
220
+ "<0xDA>": 218,
221
+ "<0xDB>": 219,
222
+ "<0xDC>": 220,
223
+ "<0xDD>": 221,
224
+ "<0xDE>": 222,
225
+ "<0xDF>": 223,
226
+ "<0xE0>": 224,
227
+ "<0xE1>": 225,
228
+ "<0xE2>": 226,
229
+ "<0xE3>": 227,
230
+ "<0xE4>": 228,
231
+ "<0xE5>": 229,
232
+ "<0xE6>": 230,
233
+ "<0xE7>": 231,
234
+ "<0xE8>": 232,
235
+ "<0xE9>": 233,
236
+ "<0xEA>": 234,
237
+ "<0xEB>": 235,
238
+ "<0xEC>": 236,
239
+ "<0xED>": 237,
240
+ "<0xEE>": 238,
241
+ "<0xEF>": 239,
242
+ "<0xF0>": 240,
243
+ "<0xF1>": 241,
244
+ "<0xF2>": 242,
245
+ "<0xF3>": 243,
246
+ "<0xF4>": 244,
247
+ "<0xF5>": 245,
248
+ "<0xF6>": 246,
249
+ "<0xF7>": 247,
250
+ "<0xF8>": 248,
251
+ "<0xF9>": 249,
252
+ "<0xFA>": 250,
253
+ "<0xFB>": 251,
254
+ "<0xFC>": 252,
255
+ "<0xFD>": 253,
256
+ "<0xFE>": 254,
257
+ "<0xFF>": 255
258
+ }