anandselvadurai-techus commited on
Commit
28e7cfa
·
verified ·
1 Parent(s): f80ed61

Updated Files.

Browse files
Files changed (3) hide show
  1. model.safetensors +2 -2
  2. modeling_tokle.py +86 -1
  3. spab_table.safetensors +3 -0
model.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:082e3ae8de93edcbb4790e4917d089354ac79adc4acb937d41e3277ef8f59ec5
3
- size 45201124
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7161cefd6b1f5dfbf55b4c1ba5772327ccce5cab567865ed8ec43738eba44f25
3
+ size 11646604
modeling_tokle.py CHANGED
@@ -8,6 +8,7 @@ Works on Transformers 4.x and 5.x. The v5 differences are marked inline; they
8
  are not cosmetic, see the note above _M1.
9
  """
10
  import math
 
11
  from typing import Optional, Tuple, Union
12
 
13
  import torch
@@ -62,6 +63,12 @@ def apply_rope(x, cos, sin):
62
 
63
 
64
  # ----------------------------------------------------------------------------- spab
 
 
 
 
 
 
65
  # Mixing constants for the pair hash. Plain ints, not buffers, and that matters:
66
  # buffers here would be non-persistent, and Transformers 5 builds the model on
67
  # the meta device and fills only what the checkpoint contains. Non-persistent
@@ -96,9 +103,12 @@ class SPABBias(nn.Module):
96
  self.scale = nn.Parameter(torch.full((config.n_head,), init))
97
  if not config.spab_enabled:
98
  self.scale.requires_grad_(False)
 
 
99
  self.register_buffer("table",
100
  torch.zeros(config.spab_table_size, dtype=torch.float32),
101
- persistent=True)
 
102
 
103
  def hash(self, i, j):
104
  # Murmur-style mix. Relies on int64 overflow wrapping, so keep it in
@@ -113,6 +123,11 @@ class SPABBias(nn.Module):
113
  def forward(self, idx):
114
  if not self.enabled:
115
  return None
 
 
 
 
 
116
  # Materialises b*t*t int64 pairs, so this is the memory high-water mark
117
  # of a forward pass. Fine at t=512; watch it if max_seq_len ever grows.
118
  b, t = idx.shape
@@ -194,6 +209,48 @@ class ToklePreTrainedModel(PreTrainedModel):
194
  _no_split_modules = ["TokleDecoderLayer"]
195
  _supports_sdpa = True
196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  def _init_weights(self, module):
198
  if isinstance(module, nn.Linear):
199
  nn.init.normal_(module.weight, 0.0, 0.02)
@@ -213,6 +270,34 @@ class ToklePreTrainedModel(PreTrainedModel):
213
  nn.init.normal_(out.weight, 0.0, 0.02 / math.sqrt(2 * self.config.n_layer))
214
 
215
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  class TokleModel(ToklePreTrainedModel):
217
  def __init__(self, config: TokleConfig):
218
  super().__init__(config)
 
8
  are not cosmetic, see the note above _M1.
9
  """
10
  import math
11
+ import os
12
  from typing import Optional, Tuple, Union
13
 
14
  import torch
 
63
 
64
 
65
  # ----------------------------------------------------------------------------- spab
66
+ # The table lives outside model.safetensors. It is frozen data, not weights, and
67
+ # keeping it separate stops it being counted as trained parameters. Cost of that
68
+ # choice: it has to be fetched and installed by hand after the weights load, so
69
+ # every load path below goes through _install_spab_table.
70
+ SPAB_TABLE_FILE = "spab_table.safetensors"
71
+
72
  # Mixing constants for the pair hash. Plain ints, not buffers, and that matters:
73
  # buffers here would be non-persistent, and Transformers 5 builds the model on
74
  # the meta device and fills only what the checkpoint contains. Non-persistent
 
103
  self.scale = nn.Parameter(torch.full((config.n_head,), init))
104
  if not config.spab_enabled:
105
  self.scale.requires_grad_(False)
106
+ # persistent=False keeps it out of state_dict and therefore out of
107
+ # model.safetensors; `loaded` guards against using the zeros.
108
  self.register_buffer("table",
109
  torch.zeros(config.spab_table_size, dtype=torch.float32),
110
+ persistent=False)
111
+ self.loaded = not config.spab_enabled
112
 
113
  def hash(self, i, j):
114
  # Murmur-style mix. Relies on int64 overflow wrapping, so keep it in
 
123
  def forward(self, idx):
124
  if not self.enabled:
125
  return None
126
+ if not self.loaded:
127
+ raise RuntimeError(
128
+ f"the SPAB table was never loaded -- {SPAB_TABLE_FILE} is missing "
129
+ f"or was not installed. Load the model with from_pretrained(), "
130
+ f"which fetches it; an all-zero table silently ruins every output.")
131
  # Materialises b*t*t int64 pairs, so this is the memory high-water mark
132
  # of a forward pass. Fine at t=512; watch it if max_seq_len ever grows.
133
  b, t = idx.shape
 
209
  _no_split_modules = ["TokleDecoderLayer"]
210
  _supports_sdpa = True
211
 
212
+ def _spab(self):
213
+ for m in self.modules():
214
+ if getattr(m, "is_spab", False):
215
+ return m
216
+ return None
217
+
218
+ def install_spab_table(self, table):
219
+ """Copy the frozen table in. Accepts a tensor or a .safetensors path."""
220
+ spab = self._spab()
221
+ if spab is None:
222
+ return self
223
+ if isinstance(table, (str, os.PathLike)):
224
+ from safetensors.torch import load_file
225
+ table = load_file(str(table))["table"]
226
+ table = table.reshape(-1)
227
+ if table.numel() != spab.table_size:
228
+ raise ValueError(f"SPAB table has {table.numel()} entries, "
229
+ f"expected {spab.table_size}")
230
+ # Match the existing buffer's device and dtype so a model already moved
231
+ # to cuda/fp16 keeps behaving the way it did before the split.
232
+ ref = spab.table
233
+ spab.table = table.to(device=ref.device, dtype=ref.dtype)
234
+ spab.loaded = True
235
+ return self
236
+
237
+ @classmethod
238
+ def from_pretrained(cls, pretrained_model_name_or_path, *args, **kwargs):
239
+ model = super().from_pretrained(pretrained_model_name_or_path, *args, **kwargs)
240
+ if getattr(model.config, "spab_enabled", False):
241
+ model.install_spab_table(
242
+ _resolve_table(pretrained_model_name_or_path, **kwargs))
243
+ return model
244
+
245
+ def save_pretrained(self, save_directory, *args, **kwargs):
246
+ out = super().save_pretrained(save_directory, *args, **kwargs)
247
+ spab = self._spab()
248
+ if spab is not None and spab.enabled and spab.loaded:
249
+ from safetensors.torch import save_file
250
+ save_file({"table": spab.table.detach().cpu().to(torch.float32).contiguous()},
251
+ os.path.join(save_directory, SPAB_TABLE_FILE))
252
+ return out
253
+
254
  def _init_weights(self, module):
255
  if isinstance(module, nn.Linear):
256
  nn.init.normal_(module.weight, 0.0, 0.02)
 
270
  nn.init.normal_(out.weight, 0.0, 0.02 / math.sqrt(2 * self.config.n_layer))
271
 
272
 
273
+ def _resolve_table(repo, **kwargs):
274
+ """Find spab_table.safetensors in a local dir, the HF cache, or the Hub."""
275
+ local = os.path.join(str(repo), SPAB_TABLE_FILE)
276
+ if os.path.isfile(local):
277
+ return local
278
+ try:
279
+ from transformers.utils import cached_file
280
+ return cached_file(str(repo), SPAB_TABLE_FILE,
281
+ **{k: kwargs[k] for k in
282
+ ("revision", "token", "cache_dir", "local_files_only",
283
+ "subfolder") if k in kwargs})
284
+ except Exception:
285
+ pass
286
+ try:
287
+ from huggingface_hub import hf_hub_download
288
+ return hf_hub_download(str(repo), SPAB_TABLE_FILE,
289
+ revision=kwargs.get("revision"),
290
+ token=kwargs.get("token"))
291
+ except Exception as e:
292
+ # Worth a clear message: without the table the model loads happily and
293
+ # then produces nonsense, which is a miserable thing to debug.
294
+ raise FileNotFoundError(
295
+ f"{SPAB_TABLE_FILE} was not found in '{repo}'. Tokle ships its frozen "
296
+ f"SPAB table beside model.safetensors and cannot run without it; copy "
297
+ f"the whole repo, not just the weights. ({type(e).__name__}: {e})"
298
+ ) from e
299
+
300
+
301
  class TokleModel(ToklePreTrainedModel):
302
  def __init__(self, config: TokleConfig):
303
  super().__init__(config)
spab_table.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9b7c75290ad59adb2551d2db9bbc6bd8b2ff6f72e18d037c6ce8d741a1a596ba
3
+ size 33554512