ToastyPigeon commited on
Commit
9711198
·
verified ·
1 Parent(s): f63e4de

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ cache/models--Qwen--Qwen3-30B-A3B-Instruct-2507/blobs/afe775cbdefb257e1bf1d8551fb930bd4b78d74da0b10bbb651f6b6a6f67c325 filter=lfs diff=lfs merge=lfs -text
37
+ cache/models--Qwen--Qwen3-30B-A3B-Instruct-2507/blobs/c2bc4101cde6b7c9dda36bbdff815c2ff19541d7732e94d306d87a0806c133b3 filter=lfs diff=lfs merge=lfs -text
38
+ cache/models--Qwen--Qwen3-30B-A3B-Instruct-2507/blobs/fa5623e55641935f938894cc91090732452ef22da12596e857c8dff4fa71627b filter=lfs diff=lfs merge=lfs -text
39
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
__pycache__/modeling_scatterbrain.cpython-312.pyc ADDED
Binary file (34.4 kB). View file
 
config.json ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "ScatterbrainForCausalLM"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "configuration_scatterbrain.ScatterbrainConfig",
7
+ "AutoModelForCausalLM": "modeling_scatterbrain.ScatterbrainForCausalLM"
8
+ },
9
+ "model_type": "scatterbrain",
10
+ "attention_bias": false,
11
+ "attention_dropout": 0.0,
12
+ "bos_token_id": 151643,
13
+ "decoder_sparse_step": 1,
14
+ "eos_token_id": 151645,
15
+ "head_dim": 128,
16
+ "hidden_act": "silu",
17
+ "hidden_size": 2048,
18
+ "initializer_range": 0.02,
19
+ "intermediate_size": 6144,
20
+ "max_position_embeddings": 262144,
21
+ "max_window_layers": 48,
22
+ "mlp_only_layers": [],
23
+ "moe_intermediate_size": 768,
24
+ "norm_topk_prob": true,
25
+ "num_attention_heads": 32,
26
+ "num_experts": 128,
27
+ "num_experts_per_tok": 16,
28
+ "num_hidden_layers": 1,
29
+ "num_loop_iterations": 30,
30
+ "num_key_value_heads": 4,
31
+ "output_router_logits": false,
32
+ "rms_norm_eps": 1e-06,
33
+ "rope_scaling": null,
34
+ "rope_theta": 10000000,
35
+ "router_aux_loss_coef": 0.001,
36
+ "sliding_window": null,
37
+ "tie_word_embeddings": false,
38
+ "torch_dtype": "bfloat16",
39
+ "transformers_version": "4.51.0",
40
+ "use_cache": true,
41
+ "use_sliding_window": false,
42
+ "vocab_size": 151936,
43
+ "_original_num_hidden_layers": 48,
44
+ "_extracted_from_layer": 30,
45
+ "_source_model": "Qwen/Qwen3-30B-A3B-Instruct-2507"
46
+ }
config.json.bak ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Qwen3MoeForCausalLM"
4
+ ],
5
+ "model_type": "qwen3_moe",
6
+ "attention_bias": false,
7
+ "attention_dropout": 0.0,
8
+ "bos_token_id": 151643,
9
+ "decoder_sparse_step": 1,
10
+ "eos_token_id": 151645,
11
+ "head_dim": 128,
12
+ "hidden_act": "silu",
13
+ "hidden_size": 2048,
14
+ "initializer_range": 0.02,
15
+ "intermediate_size": 6144,
16
+ "max_position_embeddings": 262144,
17
+ "max_window_layers": 48,
18
+ "mlp_only_layers": [],
19
+ "moe_intermediate_size": 768,
20
+ "norm_topk_prob": true,
21
+ "num_attention_heads": 32,
22
+ "num_experts": 128,
23
+ "num_experts_per_tok": 8,
24
+ "num_hidden_layers": 1,
25
+ "num_key_value_heads": 4,
26
+ "output_router_logits": false,
27
+ "rms_norm_eps": 1e-06,
28
+ "rope_scaling": null,
29
+ "rope_theta": 10000000,
30
+ "router_aux_loss_coef": 0.001,
31
+ "sliding_window": null,
32
+ "tie_word_embeddings": false,
33
+ "torch_dtype": "bfloat16",
34
+ "transformers_version": "4.51.0",
35
+ "use_cache": true,
36
+ "use_sliding_window": false,
37
+ "vocab_size": 151936,
38
+ "_original_num_hidden_layers": 48,
39
+ "_extracted_from_layer": 30,
40
+ "_source_model": "Qwen/Qwen3-30B-A3B-Instruct-2507"
41
+ }
configuration_scatterbrain.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Configuration for Scatterbrain - a single MoE layer looped multiple times
2
+ #
3
+ # Based on Qwen3MoeConfig
4
+
5
+ from transformers.configuration_utils import PretrainedConfig
6
+
7
+
8
+ class ScatterbrainConfig(PretrainedConfig):
9
+ r"""
10
+ Configuration class for Scatterbrain - a model that loops a single MoE layer multiple times.
11
+
12
+ Args:
13
+ vocab_size (`int`, *optional*, defaults to 151936):
14
+ Vocabulary size of the model.
15
+ hidden_size (`int`, *optional*, defaults to 2048):
16
+ Dimension of the hidden representations.
17
+ intermediate_size (`int`, *optional*, defaults to 6144):
18
+ Dimension of the MLP intermediate representations (for dense layers).
19
+ moe_intermediate_size (`int`, *optional*, defaults to 768):
20
+ Dimension of the MLP intermediate representations for each expert.
21
+ num_hidden_layers (`int`, *optional*, defaults to 1):
22
+ Number of physical decoder layers. For Scatterbrain this is always 1.
23
+ num_loop_iterations (`int`, *optional*, defaults to 30):
24
+ Number of times to loop through the single layer.
25
+ num_attention_heads (`int`, *optional*, defaults to 32):
26
+ Number of attention heads for each attention layer.
27
+ num_key_value_heads (`int`, *optional*, defaults to 4):
28
+ Number of key_value heads for Grouped Query Attention.
29
+ head_dim (`int`, *optional*, defaults to 128):
30
+ Dimension of each attention head.
31
+ hidden_act (`str`, *optional*, defaults to `"silu"`):
32
+ Activation function in the MLP.
33
+ max_position_embeddings (`int`, *optional*, defaults to 262144):
34
+ Maximum sequence length.
35
+ initializer_range (`float`, *optional*, defaults to 0.02):
36
+ Standard deviation for weight initialization.
37
+ rms_norm_eps (`float`, *optional*, defaults to 1e-6):
38
+ Epsilon for RMS normalization.
39
+ use_cache (`bool`, *optional*, defaults to `True`):
40
+ Whether to use KV cache.
41
+ tie_word_embeddings (`bool`, *optional*, defaults to `False`):
42
+ Whether to tie input and output embeddings.
43
+ rope_theta (`float`, *optional*, defaults to 10000000.0):
44
+ Base period for rotary embeddings.
45
+ attention_dropout (`float`, *optional*, defaults to 0.0):
46
+ Dropout ratio for attention weights.
47
+ num_experts (`int`, *optional*, defaults to 128):
48
+ Number of experts in the MoE layer.
49
+ num_experts_per_tok (`int`, *optional*, defaults to 8):
50
+ Number of experts activated per token.
51
+ norm_topk_prob (`bool`, *optional*, defaults to `True`):
52
+ Whether to normalize top-k routing probabilities.
53
+ router_aux_loss_coef (`float`, *optional*, defaults to 0.001):
54
+ Coefficient for router auxiliary loss.
55
+ """
56
+
57
+ model_type = "scatterbrain"
58
+ keys_to_ignore_at_inference = ["past_key_values"]
59
+
60
+ def __init__(
61
+ self,
62
+ vocab_size=151936,
63
+ hidden_size=2048,
64
+ intermediate_size=6144,
65
+ moe_intermediate_size=768,
66
+ num_hidden_layers=1,
67
+ num_loop_iterations=30,
68
+ num_attention_heads=32,
69
+ num_key_value_heads=4,
70
+ head_dim=128,
71
+ hidden_act="silu",
72
+ max_position_embeddings=262144,
73
+ initializer_range=0.02,
74
+ rms_norm_eps=1e-6,
75
+ use_cache=True,
76
+ tie_word_embeddings=False,
77
+ rope_theta=10000000.0,
78
+ rope_scaling=None,
79
+ attention_dropout=0.0,
80
+ attention_bias=False,
81
+ num_experts=128,
82
+ num_experts_per_tok=8,
83
+ norm_topk_prob=True,
84
+ output_router_logits=False,
85
+ router_aux_loss_coef=0.001,
86
+ decoder_sparse_step=1,
87
+ mlp_only_layers=None,
88
+ sliding_window=None,
89
+ use_sliding_window=False,
90
+ max_window_layers=48,
91
+ pad_token_id=None,
92
+ bos_token_id=151643,
93
+ eos_token_id=151645,
94
+ **kwargs,
95
+ ):
96
+ self.vocab_size = vocab_size
97
+ self.hidden_size = hidden_size
98
+ self.intermediate_size = intermediate_size
99
+ self.moe_intermediate_size = moe_intermediate_size
100
+ self.num_hidden_layers = num_hidden_layers
101
+ self.num_loop_iterations = num_loop_iterations
102
+ self.num_attention_heads = num_attention_heads
103
+ self.num_key_value_heads = num_key_value_heads
104
+ self.head_dim = head_dim
105
+ self.hidden_act = hidden_act
106
+ self.max_position_embeddings = max_position_embeddings
107
+ self.initializer_range = initializer_range
108
+ self.rms_norm_eps = rms_norm_eps
109
+ self.use_cache = use_cache
110
+ self.rope_theta = rope_theta
111
+ self.rope_scaling = rope_scaling
112
+ self.attention_dropout = attention_dropout
113
+ self.attention_bias = attention_bias
114
+ self.num_experts = num_experts
115
+ self.num_experts_per_tok = num_experts_per_tok
116
+ self.norm_topk_prob = norm_topk_prob
117
+ self.output_router_logits = output_router_logits
118
+ self.router_aux_loss_coef = router_aux_loss_coef
119
+ self.decoder_sparse_step = decoder_sparse_step
120
+ self.mlp_only_layers = mlp_only_layers if mlp_only_layers is not None else []
121
+ self.sliding_window = sliding_window
122
+ self.use_sliding_window = use_sliding_window
123
+ self.max_window_layers = max_window_layers
124
+
125
+ super().__init__(
126
+ pad_token_id=pad_token_id,
127
+ bos_token_id=bos_token_id,
128
+ eos_token_id=eos_token_id,
129
+ tie_word_embeddings=tie_word_embeddings,
130
+ **kwargs,
131
+ )
convert_to_stacked.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Convert Scatterbrain checkpoint from individual expert weights to stacked format.
4
+
5
+ This converts:
6
+ model.layers.0.mlp.experts.{i}.gate_proj.weight -> model.layers.0.mlp.expert_gate_proj
7
+ model.layers.0.mlp.experts.{i}.up_proj.weight -> model.layers.0.mlp.expert_up_proj
8
+ model.layers.0.mlp.experts.{i}.down_proj.weight -> model.layers.0.mlp.expert_down_proj
9
+ """
10
+
11
+ import json
12
+ import os
13
+ import re
14
+ import torch
15
+ from safetensors.torch import load_file, save_file
16
+ from collections import defaultdict
17
+
18
+
19
+ def convert_checkpoint(model_dir: str, output_dir: str = None):
20
+ """Convert checkpoint from individual experts to stacked format."""
21
+ if output_dir is None:
22
+ output_dir = model_dir
23
+
24
+ # Load config to get num_experts
25
+ config_path = os.path.join(model_dir, "config.json")
26
+ with open(config_path) as f:
27
+ config = json.load(f)
28
+
29
+ num_experts = config["num_experts"]
30
+ print(f"Converting {num_experts} experts to stacked format...")
31
+
32
+ # Find all safetensor files
33
+ safetensor_files = sorted([f for f in os.listdir(model_dir) if f.endswith('.safetensors')])
34
+
35
+ if not safetensor_files:
36
+ raise ValueError(f"No safetensor files found in {model_dir}")
37
+
38
+ # Load all weights
39
+ all_weights = {}
40
+ for sf_file in safetensor_files:
41
+ path = os.path.join(model_dir, sf_file)
42
+ print(f"Loading {sf_file}...")
43
+ weights = load_file(path)
44
+ all_weights.update(weights)
45
+
46
+ # Pattern to match expert weights
47
+ expert_pattern = re.compile(r'(.+\.mlp)\.experts\.(\d+)\.(gate_proj|up_proj|down_proj)\.weight')
48
+
49
+ # Group expert weights by layer and projection type
50
+ expert_groups = defaultdict(lambda: defaultdict(dict))
51
+ other_weights = {}
52
+
53
+ for key, value in all_weights.items():
54
+ match = expert_pattern.match(key)
55
+ if match:
56
+ layer_prefix = match.group(1) # e.g., "model.layers.0.mlp"
57
+ expert_idx = int(match.group(2))
58
+ proj_type = match.group(3) # gate_proj, up_proj, down_proj
59
+ expert_groups[layer_prefix][proj_type][expert_idx] = value
60
+ else:
61
+ other_weights[key] = value
62
+
63
+ # Stack expert weights
64
+ new_weights = dict(other_weights)
65
+
66
+ for layer_prefix, proj_types in expert_groups.items():
67
+ for proj_type, expert_weights in proj_types.items():
68
+ # Sort by expert index and stack
69
+ sorted_weights = [expert_weights[i] for i in range(num_experts)]
70
+ stacked = torch.stack(sorted_weights, dim=0)
71
+
72
+ new_key = f"{layer_prefix}.expert_{proj_type}"
73
+ new_weights[new_key] = stacked
74
+ print(f" {new_key}: {stacked.shape}")
75
+
76
+ # Save to single safetensor file
77
+ os.makedirs(output_dir, exist_ok=True)
78
+ output_path = os.path.join(output_dir, "model.safetensors")
79
+
80
+ print(f"\nSaving to {output_path}...")
81
+ save_file(new_weights, output_path)
82
+
83
+ # Remove old safetensor files if output_dir == model_dir
84
+ if output_dir == model_dir:
85
+ for sf_file in safetensor_files:
86
+ if sf_file != "model.safetensors":
87
+ old_path = os.path.join(model_dir, sf_file)
88
+ print(f"Removing old file: {sf_file}")
89
+ os.remove(old_path)
90
+
91
+ # Update index file if it exists
92
+ index_path = os.path.join(model_dir, "model.safetensors.index.json")
93
+ if os.path.exists(index_path):
94
+ print("Removing old index file...")
95
+ os.remove(index_path)
96
+
97
+ print("\nConversion complete!")
98
+ print(f"New weights saved to: {output_path}")
99
+
100
+ # Print summary
101
+ total_params = sum(p.numel() for p in new_weights.values())
102
+ print(f"Total parameters: {total_params:,}")
103
+
104
+
105
+ if __name__ == "__main__":
106
+ import sys
107
+
108
+ if len(sys.argv) < 2:
109
+ model_dir = "/home/aibox/training/scatterbrain-small-experimental"
110
+ else:
111
+ model_dir = sys.argv[1]
112
+
113
+ output_dir = sys.argv[2] if len(sys.argv) > 2 else None
114
+
115
+ convert_checkpoint(model_dir, output_dir)
generation_config.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token_id": 151643,
3
+ "do_sample": true,
4
+ "eos_token_id": [
5
+ 151645,
6
+ 151643
7
+ ],
8
+ "pad_token_id": 151643,
9
+ "temperature": 0.7,
10
+ "top_k": 20,
11
+ "top_p": 0.8,
12
+ "transformers_version": "4.51.0"
13
+ }
merges.txt ADDED
The diff for this file is too large to render. See raw diff
 
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:45fb88364e2e510bacdd175533ce9540ea31458d2c75ae11fcf83ec66e0714ac
3
+ size 2490906760
modeling_scatterbrain.py ADDED
@@ -0,0 +1,683 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Scatterbrain - A single MoE layer looped multiple times
2
+ #
3
+ # Based on Qwen3MoeForCausalLM architecture with looping logic from Loopstral
4
+
5
+ import copy
6
+ from typing import Callable, Optional, Union
7
+
8
+ import torch
9
+ import torch.nn.functional as F
10
+ from torch import nn
11
+
12
+ from transformers.activations import ACT2FN
13
+ from transformers.cache_utils import Cache, DynamicCache, DynamicLayer
14
+
15
+ # Try to import Liger kernels for optimized operations
16
+ try:
17
+ from liger_kernel.transformers import LigerRMSNorm, LigerSwiGLUMLP
18
+ LIGER_AVAILABLE = True
19
+ except ImportError:
20
+ LIGER_AVAILABLE = False
21
+
22
+ # Try to import ScatterMoE for optimized MoE computation
23
+ try:
24
+ from scattermoe import flatten_sort_count, parallel_linear
25
+ SCATTERMOE_AVAILABLE = True
26
+ except ImportError:
27
+ SCATTERMOE_AVAILABLE = False
28
+ from transformers.generation import GenerationMixin
29
+ from transformers.integrations import use_kernel_forward_from_hub
30
+ from transformers.masking_utils import create_causal_mask, create_sliding_window_causal_mask
31
+ from transformers.modeling_flash_attention_utils import FlashAttentionKwargs
32
+ from transformers.modeling_layers import GradientCheckpointingLayer
33
+ from transformers.modeling_outputs import MoeCausalLMOutputWithPast, MoeModelOutputWithPast
34
+ from transformers.modeling_rope_utils import ROPE_INIT_FUNCTIONS, dynamic_rope_update
35
+ from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
36
+ from transformers.processing_utils import Unpack
37
+ from transformers.utils import TransformersKwargs, auto_docstring, can_return_tuple
38
+ from transformers.utils.deprecation import deprecate_kwarg
39
+
40
+ from .configuration_scatterbrain import ScatterbrainConfig
41
+
42
+
43
+ def rotate_half(x):
44
+ """Rotates half the hidden dims of the input."""
45
+ x1 = x[..., : x.shape[-1] // 2]
46
+ x2 = x[..., x.shape[-1] // 2 :]
47
+ return torch.cat((-x2, x1), dim=-1)
48
+
49
+
50
+ def apply_rotary_pos_emb(q, k, cos, sin, position_ids=None, unsqueeze_dim=1):
51
+ """Applies Rotary Position Embedding to the query and key tensors."""
52
+ cos = cos.unsqueeze(unsqueeze_dim)
53
+ sin = sin.unsqueeze(unsqueeze_dim)
54
+ q_embed = (q * cos) + (rotate_half(q) * sin)
55
+ k_embed = (k * cos) + (rotate_half(k) * sin)
56
+ return q_embed, k_embed
57
+
58
+
59
+ def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
60
+ """Repeat KV heads for GQA."""
61
+ batch, num_key_value_heads, slen, head_dim = hidden_states.shape
62
+ if n_rep == 1:
63
+ return hidden_states
64
+ hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
65
+ return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
66
+
67
+
68
+ def eager_attention_forward(
69
+ module: nn.Module,
70
+ query: torch.Tensor,
71
+ key: torch.Tensor,
72
+ value: torch.Tensor,
73
+ attention_mask: Optional[torch.Tensor],
74
+ scaling: float,
75
+ dropout: float = 0.0,
76
+ **kwargs: Unpack[TransformersKwargs],
77
+ ):
78
+ key_states = repeat_kv(key, module.num_key_value_groups)
79
+ value_states = repeat_kv(value, module.num_key_value_groups)
80
+
81
+ attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
82
+ if attention_mask is not None:
83
+ causal_mask = attention_mask[:, :, :, : key_states.shape[-2]]
84
+ attn_weights = attn_weights + causal_mask
85
+
86
+ attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
87
+ attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
88
+ attn_output = torch.matmul(attn_weights, value_states)
89
+ attn_output = attn_output.transpose(1, 2).contiguous()
90
+
91
+ return attn_output, attn_weights
92
+
93
+
94
+ class ScatterbrainAttention(nn.Module):
95
+ """Multi-headed attention with QK normalization."""
96
+
97
+ def __init__(self, config: ScatterbrainConfig, layer_idx: int):
98
+ super().__init__()
99
+ self.config = config
100
+ self.layer_idx = layer_idx
101
+ self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
102
+ self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
103
+ self.scaling = self.head_dim**-0.5
104
+ self.attention_dropout = config.attention_dropout
105
+ self.is_causal = True
106
+
107
+ self.q_proj = nn.Linear(
108
+ config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.attention_bias
109
+ )
110
+ self.k_proj = nn.Linear(
111
+ config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
112
+ )
113
+ self.v_proj = nn.Linear(
114
+ config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
115
+ )
116
+ self.o_proj = nn.Linear(
117
+ config.num_attention_heads * self.head_dim, config.hidden_size, bias=config.attention_bias
118
+ )
119
+ self.q_norm = ScatterbrainRMSNorm(self.head_dim, eps=config.rms_norm_eps)
120
+ self.k_norm = ScatterbrainRMSNorm(self.head_dim, eps=config.rms_norm_eps)
121
+ self.sliding_window = getattr(config, "sliding_window", None)
122
+
123
+ @deprecate_kwarg("past_key_value", new_name="past_key_values", version="4.58")
124
+ def forward(
125
+ self,
126
+ hidden_states: torch.Tensor,
127
+ position_embeddings: tuple[torch.Tensor, torch.Tensor],
128
+ attention_mask: Optional[torch.Tensor],
129
+ past_key_values: Optional[Cache] = None,
130
+ cache_position: Optional[torch.LongTensor] = None,
131
+ cache_slot_idx: Optional[int] = None,
132
+ **kwargs: Unpack[FlashAttentionKwargs],
133
+ ) -> tuple[torch.Tensor, Optional[torch.Tensor]]:
134
+ input_shape = hidden_states.shape[:-1]
135
+ hidden_shape = (*input_shape, -1, self.head_dim)
136
+
137
+ query_states = self.q_norm(self.q_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
138
+ key_states = self.k_norm(self.k_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
139
+ value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
140
+
141
+ cos, sin = position_embeddings
142
+ query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
143
+
144
+ if past_key_values is not None:
145
+ cache_kwargs = {"sin": sin, "cos": cos, "cache_position": cache_position}
146
+ # Use cache_slot_idx for looped layers - each iteration gets its own cache slot
147
+ slot_idx = cache_slot_idx if cache_slot_idx is not None else self.layer_idx
148
+ key_states, value_states = past_key_values.update(key_states, value_states, slot_idx, cache_kwargs)
149
+
150
+ attention_interface: Callable = eager_attention_forward
151
+ if self.config._attn_implementation != "eager":
152
+ attention_interface = ALL_ATTENTION_FUNCTIONS[self.config._attn_implementation]
153
+
154
+ attn_output, attn_weights = attention_interface(
155
+ self,
156
+ query_states,
157
+ key_states,
158
+ value_states,
159
+ attention_mask,
160
+ dropout=0.0 if not self.training else self.attention_dropout,
161
+ scaling=self.scaling,
162
+ sliding_window=self.sliding_window,
163
+ **kwargs,
164
+ )
165
+
166
+ attn_output = attn_output.reshape(*input_shape, -1).contiguous()
167
+ attn_output = self.o_proj(attn_output)
168
+ return attn_output, attn_weights
169
+
170
+
171
+ class ScatterbrainMLP(nn.Module):
172
+ def __init__(self, config, intermediate_size=None):
173
+ super().__init__()
174
+ self.config = config
175
+ self.hidden_size = config.hidden_size
176
+ self.intermediate_size = intermediate_size if intermediate_size is not None else config.intermediate_size
177
+ self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
178
+ self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
179
+ self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
180
+ self.act_fn = ACT2FN[config.hidden_act]
181
+
182
+ def forward(self, x):
183
+ # Fused SwiGLU: down(act(gate(x)) * up(x))
184
+ return self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
185
+
186
+
187
+ class ScatterbrainSparseMoeBlock(nn.Module):
188
+ """
189
+ MoE block with optimized expert computation using ScatterMoE Triton kernels.
190
+
191
+ When ScatterMoE is available, uses fused Triton kernels for massive speedup.
192
+ Falls back to Python loop implementation when ScatterMoE is not available.
193
+
194
+ Key optimizations with ScatterMoE:
195
+ 1. Fused scatter-gather operations in Triton
196
+ 2. All experts processed in parallel on GPU
197
+ 3. Efficient memory access patterns
198
+ """
199
+ def __init__(self, config):
200
+ super().__init__()
201
+ self.num_experts = config.num_experts
202
+ self.top_k = config.num_experts_per_tok
203
+ self.norm_topk_prob = config.norm_topk_prob
204
+ self.hidden_size = config.hidden_size
205
+ self.moe_intermediate_size = config.moe_intermediate_size
206
+
207
+ self.gate = nn.Linear(config.hidden_size, config.num_experts, bias=False)
208
+
209
+ # Stacked expert weights as Parameters
210
+ # Shape: [num_experts, out_features, in_features]
211
+ self.expert_gate_proj = nn.Parameter(
212
+ torch.empty(config.num_experts, config.moe_intermediate_size, config.hidden_size)
213
+ )
214
+ self.expert_up_proj = nn.Parameter(
215
+ torch.empty(config.num_experts, config.moe_intermediate_size, config.hidden_size)
216
+ )
217
+ self.expert_down_proj = nn.Parameter(
218
+ torch.empty(config.num_experts, config.hidden_size, config.moe_intermediate_size)
219
+ )
220
+
221
+ # Initialize weights
222
+ for param in [self.expert_gate_proj, self.expert_up_proj, self.expert_down_proj]:
223
+ nn.init.kaiming_uniform_(param, a=5**0.5)
224
+
225
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
226
+ batch_size, sequence_length, hidden_dim = hidden_states.shape
227
+ hidden_states_flat = hidden_states.view(-1, hidden_dim)
228
+ num_tokens = hidden_states_flat.shape[0]
229
+
230
+ # Router
231
+ router_logits = self.gate(hidden_states_flat)
232
+ routing_weights = F.softmax(router_logits, dim=1, dtype=torch.float)
233
+ routing_weights, selected_experts = torch.topk(routing_weights, self.top_k, dim=-1)
234
+
235
+ if self.norm_topk_prob:
236
+ routing_weights = routing_weights / routing_weights.sum(dim=-1, keepdim=True)
237
+ routing_weights = routing_weights.to(hidden_states_flat.dtype)
238
+
239
+ if SCATTERMOE_AVAILABLE:
240
+ # Use ScatterMoE's optimized Triton kernels
241
+ final_hidden_states = self._forward_scattermoe(
242
+ hidden_states_flat, selected_experts, routing_weights
243
+ )
244
+ else:
245
+ # Fallback to Python loop
246
+ final_hidden_states = self._forward_loop(
247
+ hidden_states_flat, selected_experts, routing_weights
248
+ )
249
+
250
+ final_hidden_states = final_hidden_states.reshape(batch_size, sequence_length, hidden_dim)
251
+ return final_hidden_states, router_logits
252
+
253
+ def _forward_scattermoe(
254
+ self,
255
+ hidden_states: torch.Tensor,
256
+ selected_experts: torch.Tensor,
257
+ routing_weights: torch.Tensor,
258
+ ) -> torch.Tensor:
259
+ """Forward pass using ScatterMoE Triton kernels."""
260
+ # Get sorting indices and expert offsets from ScatterMoE
261
+ sorted_expert_idxs, sorted_scattered_idxs, expert_offsets = flatten_sort_count(
262
+ selected_experts, num_experts=self.num_experts
263
+ )
264
+
265
+ # ScatterMoE parallel_linear expects weights in [E, in, out] format
266
+ # Our weights are stored as [E, out, in], so we need to permute them
267
+ # This matches what ParallelExperts.forward() does internally
268
+
269
+ # First pass: gate and up projections (hidden -> intermediate)
270
+ # We need to do gate and up separately, then combine with SiLU
271
+ gate_out = parallel_linear(
272
+ inputs=hidden_states,
273
+ expert_weights=self.expert_gate_proj.permute(0, 2, 1), # [E, hidden, intermediate]
274
+ k=self.top_k,
275
+ sorted_expert_idxs=sorted_expert_idxs,
276
+ sorted_scattered_idxs=sorted_scattered_idxs,
277
+ expert_offsets=expert_offsets,
278
+ grouped_out=True, # Keep output grouped by expert (size: num_tokens * k)
279
+ )
280
+
281
+ up_out = parallel_linear(
282
+ inputs=hidden_states,
283
+ expert_weights=self.expert_up_proj.permute(0, 2, 1), # [E, hidden, intermediate]
284
+ k=self.top_k,
285
+ sorted_expert_idxs=sorted_expert_idxs,
286
+ sorted_scattered_idxs=sorted_scattered_idxs,
287
+ expert_offsets=expert_offsets,
288
+ grouped_out=True, # Keep output grouped by expert (size: num_tokens * k)
289
+ )
290
+
291
+ # Apply SwiGLU activation
292
+ activated = F.silu(gate_out) * up_out
293
+
294
+ # Second pass: down projection (intermediate -> hidden) with gates for weighted sum
295
+ # When grouped_in=True, use k=1 since input is already expanded to num_tokens * top_k
296
+ output = parallel_linear(
297
+ inputs=activated,
298
+ expert_weights=self.expert_down_proj.permute(0, 2, 1), # [E, intermediate, hidden]
299
+ k=1, # k=1 because input is already grouped/expanded
300
+ sorted_expert_idxs=sorted_expert_idxs,
301
+ sorted_scattered_idxs=sorted_scattered_idxs,
302
+ expert_offsets=expert_offsets,
303
+ gates=routing_weights, # Apply routing weights during scatter
304
+ grouped_in=True, # Input is grouped by expert
305
+ grouped_out=False, # Output ungrouped (back to token order)
306
+ )
307
+
308
+ return output
309
+
310
+ def _forward_loop(
311
+ self,
312
+ hidden_states: torch.Tensor,
313
+ selected_experts: torch.Tensor,
314
+ routing_weights: torch.Tensor,
315
+ ) -> torch.Tensor:
316
+ """Fallback forward pass using Python loop."""
317
+ num_tokens = hidden_states.shape[0]
318
+
319
+ # Flatten token-expert assignments
320
+ flat_expert_indices = selected_experts.view(-1)
321
+ flat_token_indices = torch.arange(num_tokens, device=hidden_states.device).unsqueeze(1).expand(-1, self.top_k).reshape(-1)
322
+ flat_routing_weights = routing_weights.view(-1)
323
+
324
+ # Sort by expert for contiguous memory access
325
+ sorted_indices = torch.argsort(flat_expert_indices, stable=True)
326
+ sorted_expert_indices = flat_expert_indices[sorted_indices]
327
+ sorted_token_indices = flat_token_indices[sorted_indices]
328
+ sorted_routing_weights = flat_routing_weights[sorted_indices]
329
+ sorted_hidden = hidden_states[sorted_token_indices]
330
+
331
+ # Compute expert boundaries
332
+ expert_counts = torch.bincount(sorted_expert_indices, minlength=self.num_experts)
333
+ expert_offsets = torch.zeros(self.num_experts + 1, dtype=torch.long, device=hidden_states.device)
334
+ expert_offsets[1:] = torch.cumsum(expert_counts, dim=0)
335
+
336
+ final_hidden_states = torch.zeros_like(hidden_states)
337
+
338
+ # Pre-fetch to lists to avoid repeated tensor->scalar conversions
339
+ counts_list = expert_counts.tolist()
340
+ offsets_list = expert_offsets.tolist()
341
+
342
+ # Process each expert
343
+ for expert_idx in range(self.num_experts):
344
+ count = counts_list[expert_idx]
345
+ if count == 0:
346
+ continue
347
+
348
+ start_idx = offsets_list[expert_idx]
349
+ end_idx = offsets_list[expert_idx + 1]
350
+
351
+ # Get tokens for this expert
352
+ expert_tokens = sorted_hidden[start_idx:end_idx]
353
+ expert_weights = sorted_routing_weights[start_idx:end_idx]
354
+ token_indices = sorted_token_indices[start_idx:end_idx]
355
+
356
+ # Get this expert's weight matrices
357
+ gate_w = self.expert_gate_proj[expert_idx]
358
+ up_w = self.expert_up_proj[expert_idx]
359
+ down_w = self.expert_down_proj[expert_idx]
360
+
361
+ # SwiGLU computation: down(silu(gate(x)) * up(x))
362
+ gate_out = F.linear(expert_tokens, gate_w)
363
+ up_out = F.linear(expert_tokens, up_w)
364
+ activated = F.silu(gate_out) * up_out
365
+ expert_out = F.linear(activated, down_w)
366
+
367
+ # Weight and accumulate
368
+ weighted_out = expert_out * expert_weights.unsqueeze(-1)
369
+ final_hidden_states.index_add_(0, token_indices, weighted_out)
370
+
371
+ return final_hidden_states
372
+
373
+
374
+ class _ScatterbrainRMSNormFallback(nn.Module):
375
+ """Fallback RMSNorm when Liger is not available."""
376
+ def __init__(self, hidden_size, eps=1e-6):
377
+ super().__init__()
378
+ self.weight = nn.Parameter(torch.ones(hidden_size))
379
+ self.variance_epsilon = eps
380
+
381
+ def forward(self, hidden_states):
382
+ input_dtype = hidden_states.dtype
383
+ hidden_states = hidden_states.to(torch.float32)
384
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
385
+ hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
386
+ return self.weight * hidden_states.to(input_dtype)
387
+
388
+ def extra_repr(self):
389
+ return f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}"
390
+
391
+
392
+ # Use Liger RMSNorm if available, otherwise fallback
393
+ ScatterbrainRMSNorm = LigerRMSNorm if LIGER_AVAILABLE else _ScatterbrainRMSNormFallback
394
+
395
+
396
+ class ScatterbrainDecoderLayer(GradientCheckpointingLayer):
397
+ def __init__(self, config: ScatterbrainConfig, layer_idx: int):
398
+ super().__init__()
399
+ self.hidden_size = config.hidden_size
400
+
401
+ self.self_attn = ScatterbrainAttention(config, layer_idx)
402
+
403
+ # MoE layer
404
+ if config.num_experts > 0:
405
+ self.mlp = ScatterbrainSparseMoeBlock(config)
406
+ else:
407
+ self.mlp = ScatterbrainMLP(config, intermediate_size=config.intermediate_size)
408
+
409
+ self.input_layernorm = ScatterbrainRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
410
+ self.post_attention_layernorm = ScatterbrainRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
411
+
412
+ @deprecate_kwarg("past_key_value", new_name="past_key_values", version="4.58")
413
+ def forward(
414
+ self,
415
+ hidden_states: torch.Tensor,
416
+ position_embeddings: tuple[torch.Tensor, torch.Tensor],
417
+ attention_mask: Optional[torch.Tensor] = None,
418
+ position_ids: Optional[torch.LongTensor] = None,
419
+ past_key_values: Optional[Cache] = None,
420
+ cache_position: Optional[torch.LongTensor] = None,
421
+ cache_slot_idx: Optional[int] = None,
422
+ **kwargs: Unpack[FlashAttentionKwargs],
423
+ ) -> torch.FloatTensor:
424
+ residual = hidden_states
425
+ hidden_states = self.input_layernorm(hidden_states)
426
+
427
+ # Self Attention
428
+ hidden_states, _ = self.self_attn(
429
+ hidden_states=hidden_states,
430
+ position_embeddings=position_embeddings,
431
+ attention_mask=attention_mask,
432
+ position_ids=position_ids,
433
+ past_key_values=past_key_values,
434
+ cache_position=cache_position,
435
+ cache_slot_idx=cache_slot_idx,
436
+ **kwargs,
437
+ )
438
+ hidden_states = residual + hidden_states
439
+
440
+ # MLP / MoE
441
+ residual = hidden_states
442
+ hidden_states = self.post_attention_layernorm(hidden_states)
443
+ hidden_states = self.mlp(hidden_states)
444
+
445
+ # Unpack MoE output
446
+ if isinstance(hidden_states, tuple):
447
+ hidden_states, _ = hidden_states
448
+ hidden_states = residual + hidden_states
449
+
450
+ return hidden_states
451
+
452
+
453
+ class ScatterbrainRotaryEmbedding(nn.Module):
454
+ inv_freq: torch.Tensor
455
+
456
+ def __init__(self, config: ScatterbrainConfig, device=None):
457
+ super().__init__()
458
+ if hasattr(config, "rope_scaling") and isinstance(config.rope_scaling, dict):
459
+ self.rope_type = config.rope_scaling.get("rope_type", config.rope_scaling.get("type"))
460
+ else:
461
+ self.rope_type = "default"
462
+ self.max_seq_len_cached = config.max_position_embeddings
463
+ self.original_max_seq_len = config.max_position_embeddings
464
+
465
+ self.config = config
466
+ self.rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
467
+
468
+ inv_freq, self.attention_scaling = self.rope_init_fn(self.config, device)
469
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
470
+ self.original_inv_freq = self.inv_freq
471
+
472
+ @torch.no_grad()
473
+ @dynamic_rope_update
474
+ def forward(self, x, position_ids):
475
+ inv_freq_expanded = self.inv_freq[None, :, None].float().expand(position_ids.shape[0], -1, 1).to(x.device)
476
+ position_ids_expanded = position_ids[:, None, :].float()
477
+
478
+ device_type = x.device.type if isinstance(x.device.type, str) and x.device.type != "mps" else "cpu"
479
+ with torch.autocast(device_type=device_type, enabled=False):
480
+ freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(1, 2)
481
+ emb = torch.cat((freqs, freqs), dim=-1)
482
+ cos = emb.cos() * self.attention_scaling
483
+ sin = emb.sin() * self.attention_scaling
484
+
485
+ return cos.to(dtype=x.dtype), sin.to(dtype=x.dtype)
486
+
487
+
488
+ @auto_docstring
489
+ class ScatterbrainPreTrainedModel(PreTrainedModel):
490
+ config_class = ScatterbrainConfig
491
+ base_model_prefix = "model"
492
+ supports_gradient_checkpointing = True
493
+ _no_split_modules = ["ScatterbrainDecoderLayer"]
494
+ _skip_keys_device_placement = ["past_key_values"]
495
+ _supports_flash_attn = True
496
+ _supports_sdpa = True
497
+ _supports_flex_attn = True
498
+ _can_compile_fullgraph = False # MoE models don't work with torch.compile
499
+ _supports_attention_backend = True
500
+
501
+
502
+ @auto_docstring
503
+ class ScatterbrainModel(ScatterbrainPreTrainedModel):
504
+ def __init__(self, config: ScatterbrainConfig):
505
+ super().__init__(config)
506
+ self.padding_idx = config.pad_token_id
507
+ self.vocab_size = config.vocab_size
508
+
509
+ self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
510
+ # Only one physical layer
511
+ self.layers = nn.ModuleList(
512
+ [ScatterbrainDecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
513
+ )
514
+ self.norm = ScatterbrainRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
515
+ self.rotary_emb = ScatterbrainRotaryEmbedding(config=config)
516
+ self.gradient_checkpointing = False
517
+
518
+ # Number of loop iterations and cache slots
519
+ self._num_loop_iterations = config.num_loop_iterations
520
+ self._num_cache_slots = config.num_loop_iterations
521
+
522
+ # Initialize weights and apply final processing
523
+ self.post_init()
524
+
525
+ @auto_docstring
526
+ def forward(
527
+ self,
528
+ input_ids: Optional[torch.LongTensor] = None,
529
+ attention_mask: Optional[torch.Tensor] = None,
530
+ position_ids: Optional[torch.LongTensor] = None,
531
+ past_key_values: Optional[Cache] = None,
532
+ inputs_embeds: Optional[torch.FloatTensor] = None,
533
+ use_cache: Optional[bool] = None,
534
+ cache_position: Optional[torch.LongTensor] = None,
535
+ **kwargs: Unpack[TransformersKwargs],
536
+ ) -> MoeModelOutputWithPast:
537
+ if (input_ids is None) ^ (inputs_embeds is not None):
538
+ raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
539
+
540
+ if inputs_embeds is None:
541
+ inputs_embeds = self.embed_tokens(input_ids)
542
+
543
+ # Handle cache creation/extension for looping
544
+ if use_cache:
545
+ if past_key_values is None:
546
+ # Create cache with enough slots for all loop iterations
547
+ cache_config = copy.copy(self.config)
548
+ cache_config.num_hidden_layers = self._num_cache_slots
549
+ past_key_values = DynamicCache(config=cache_config)
550
+ elif isinstance(past_key_values, DynamicCache) and len(past_key_values.layers) < self._num_cache_slots:
551
+ # Extend cache if created externally with fewer slots
552
+ while len(past_key_values.layers) < self._num_cache_slots:
553
+ past_key_values.layers.append(DynamicLayer())
554
+
555
+ if cache_position is None:
556
+ past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
557
+ cache_position = torch.arange(
558
+ past_seen_tokens, past_seen_tokens + inputs_embeds.shape[1], device=inputs_embeds.device
559
+ )
560
+ if position_ids is None:
561
+ position_ids = cache_position.unsqueeze(0)
562
+
563
+ mask_function = create_causal_mask if self.config.sliding_window is None else create_sliding_window_causal_mask
564
+ causal_mask = mask_function(
565
+ config=self.config,
566
+ input_embeds=inputs_embeds,
567
+ attention_mask=attention_mask,
568
+ cache_position=cache_position,
569
+ past_key_values=past_key_values,
570
+ position_ids=position_ids,
571
+ )
572
+
573
+ hidden_states = inputs_embeds
574
+ position_embeddings = self.rotary_emb(hidden_states, position_ids)
575
+
576
+ # Loop through the single layer multiple times
577
+ # Each iteration gets its own cache slot
578
+ decoder_layer = self.layers[0]
579
+ for loop_idx in range(self._num_loop_iterations):
580
+ hidden_states = decoder_layer(
581
+ hidden_states,
582
+ position_embeddings=position_embeddings,
583
+ attention_mask=causal_mask,
584
+ position_ids=position_ids,
585
+ past_key_values=past_key_values,
586
+ use_cache=use_cache,
587
+ cache_position=cache_position,
588
+ cache_slot_idx=loop_idx,
589
+ **kwargs,
590
+ )
591
+
592
+ hidden_states = self.norm(hidden_states)
593
+
594
+ return MoeModelOutputWithPast(
595
+ last_hidden_state=hidden_states,
596
+ past_key_values=past_key_values,
597
+ )
598
+
599
+
600
+ @auto_docstring
601
+ class ScatterbrainForCausalLM(ScatterbrainPreTrainedModel, GenerationMixin):
602
+ _tied_weights_keys = ["lm_head.weight"]
603
+
604
+ def __init__(self, config):
605
+ super().__init__(config)
606
+ self.model = ScatterbrainModel(config)
607
+ self.vocab_size = config.vocab_size
608
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
609
+ self.router_aux_loss_coef = config.router_aux_loss_coef
610
+ self.num_experts = config.num_experts
611
+ self.num_experts_per_tok = config.num_experts_per_tok
612
+
613
+ # Initialize weights and apply final processing
614
+ self.post_init()
615
+
616
+ def get_input_embeddings(self):
617
+ return self.model.embed_tokens
618
+
619
+ def set_input_embeddings(self, value):
620
+ self.model.embed_tokens = value
621
+
622
+ def get_output_embeddings(self):
623
+ return self.lm_head
624
+
625
+ def set_output_embeddings(self, new_embeddings):
626
+ self.lm_head = new_embeddings
627
+
628
+ @can_return_tuple
629
+ @auto_docstring
630
+ def forward(
631
+ self,
632
+ input_ids: Optional[torch.LongTensor] = None,
633
+ attention_mask: Optional[torch.Tensor] = None,
634
+ position_ids: Optional[torch.LongTensor] = None,
635
+ past_key_values: Optional[Cache] = None,
636
+ inputs_embeds: Optional[torch.FloatTensor] = None,
637
+ labels: Optional[torch.LongTensor] = None,
638
+ use_cache: Optional[bool] = None,
639
+ output_router_logits: Optional[bool] = None,
640
+ cache_position: Optional[torch.LongTensor] = None,
641
+ logits_to_keep: Union[int, torch.Tensor] = 0,
642
+ **kwargs: Unpack[TransformersKwargs],
643
+ ) -> MoeCausalLMOutputWithPast:
644
+ output_router_logits = (
645
+ output_router_logits if output_router_logits is not None else self.config.output_router_logits
646
+ )
647
+
648
+ outputs: MoeModelOutputWithPast = self.model(
649
+ input_ids=input_ids,
650
+ attention_mask=attention_mask,
651
+ position_ids=position_ids,
652
+ past_key_values=past_key_values,
653
+ inputs_embeds=inputs_embeds,
654
+ use_cache=use_cache,
655
+ output_router_logits=output_router_logits,
656
+ cache_position=cache_position,
657
+ **kwargs,
658
+ )
659
+
660
+ hidden_states = outputs.last_hidden_state
661
+ slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
662
+ logits = self.lm_head(hidden_states[:, slice_indices, :])
663
+
664
+ loss = None
665
+ if labels is not None:
666
+ loss = self.loss_function(logits, labels, self.vocab_size, **kwargs)
667
+
668
+ return MoeCausalLMOutputWithPast(
669
+ loss=loss,
670
+ logits=logits,
671
+ past_key_values=outputs.past_key_values,
672
+ hidden_states=outputs.hidden_states,
673
+ attentions=outputs.attentions,
674
+ router_logits=outputs.router_logits,
675
+ )
676
+
677
+
678
+ __all__ = [
679
+ "ScatterbrainConfig",
680
+ "ScatterbrainForCausalLM",
681
+ "ScatterbrainModel",
682
+ "ScatterbrainPreTrainedModel",
683
+ ]
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:aeb13307a71acd8fe81861d94ad54ab689df773318809eed3cbe794b4492dae4
3
+ size 11422654
tokenizer_config.json ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "added_tokens_decoder": {
4
+ "151643": {
5
+ "content": "<|endoftext|>",
6
+ "lstrip": false,
7
+ "normalized": false,
8
+ "rstrip": false,
9
+ "single_word": false,
10
+ "special": true
11
+ },
12
+ "151644": {
13
+ "content": "<|im_start|>",
14
+ "lstrip": false,
15
+ "normalized": false,
16
+ "rstrip": false,
17
+ "single_word": false,
18
+ "special": true
19
+ },
20
+ "151645": {
21
+ "content": "<|im_end|>",
22
+ "lstrip": false,
23
+ "normalized": false,
24
+ "rstrip": false,
25
+ "single_word": false,
26
+ "special": true
27
+ },
28
+ "151646": {
29
+ "content": "<|object_ref_start|>",
30
+ "lstrip": false,
31
+ "normalized": false,
32
+ "rstrip": false,
33
+ "single_word": false,
34
+ "special": true
35
+ },
36
+ "151647": {
37
+ "content": "<|object_ref_end|>",
38
+ "lstrip": false,
39
+ "normalized": false,
40
+ "rstrip": false,
41
+ "single_word": false,
42
+ "special": true
43
+ },
44
+ "151648": {
45
+ "content": "<|box_start|>",
46
+ "lstrip": false,
47
+ "normalized": false,
48
+ "rstrip": false,
49
+ "single_word": false,
50
+ "special": true
51
+ },
52
+ "151649": {
53
+ "content": "<|box_end|>",
54
+ "lstrip": false,
55
+ "normalized": false,
56
+ "rstrip": false,
57
+ "single_word": false,
58
+ "special": true
59
+ },
60
+ "151650": {
61
+ "content": "<|quad_start|>",
62
+ "lstrip": false,
63
+ "normalized": false,
64
+ "rstrip": false,
65
+ "single_word": false,
66
+ "special": true
67
+ },
68
+ "151651": {
69
+ "content": "<|quad_end|>",
70
+ "lstrip": false,
71
+ "normalized": false,
72
+ "rstrip": false,
73
+ "single_word": false,
74
+ "special": true
75
+ },
76
+ "151652": {
77
+ "content": "<|vision_start|>",
78
+ "lstrip": false,
79
+ "normalized": false,
80
+ "rstrip": false,
81
+ "single_word": false,
82
+ "special": true
83
+ },
84
+ "151653": {
85
+ "content": "<|vision_end|>",
86
+ "lstrip": false,
87
+ "normalized": false,
88
+ "rstrip": false,
89
+ "single_word": false,
90
+ "special": true
91
+ },
92
+ "151654": {
93
+ "content": "<|vision_pad|>",
94
+ "lstrip": false,
95
+ "normalized": false,
96
+ "rstrip": false,
97
+ "single_word": false,
98
+ "special": true
99
+ },
100
+ "151655": {
101
+ "content": "<|image_pad|>",
102
+ "lstrip": false,
103
+ "normalized": false,
104
+ "rstrip": false,
105
+ "single_word": false,
106
+ "special": true
107
+ },
108
+ "151656": {
109
+ "content": "<|video_pad|>",
110
+ "lstrip": false,
111
+ "normalized": false,
112
+ "rstrip": false,
113
+ "single_word": false,
114
+ "special": true
115
+ },
116
+ "151657": {
117
+ "content": "<tool_call>",
118
+ "lstrip": false,
119
+ "normalized": false,
120
+ "rstrip": false,
121
+ "single_word": false,
122
+ "special": false
123
+ },
124
+ "151658": {
125
+ "content": "</tool_call>",
126
+ "lstrip": false,
127
+ "normalized": false,
128
+ "rstrip": false,
129
+ "single_word": false,
130
+ "special": false
131
+ },
132
+ "151659": {
133
+ "content": "<|fim_prefix|>",
134
+ "lstrip": false,
135
+ "normalized": false,
136
+ "rstrip": false,
137
+ "single_word": false,
138
+ "special": false
139
+ },
140
+ "151660": {
141
+ "content": "<|fim_middle|>",
142
+ "lstrip": false,
143
+ "normalized": false,
144
+ "rstrip": false,
145
+ "single_word": false,
146
+ "special": false
147
+ },
148
+ "151661": {
149
+ "content": "<|fim_suffix|>",
150
+ "lstrip": false,
151
+ "normalized": false,
152
+ "rstrip": false,
153
+ "single_word": false,
154
+ "special": false
155
+ },
156
+ "151662": {
157
+ "content": "<|fim_pad|>",
158
+ "lstrip": false,
159
+ "normalized": false,
160
+ "rstrip": false,
161
+ "single_word": false,
162
+ "special": false
163
+ },
164
+ "151663": {
165
+ "content": "<|repo_name|>",
166
+ "lstrip": false,
167
+ "normalized": false,
168
+ "rstrip": false,
169
+ "single_word": false,
170
+ "special": false
171
+ },
172
+ "151664": {
173
+ "content": "<|file_sep|>",
174
+ "lstrip": false,
175
+ "normalized": false,
176
+ "rstrip": false,
177
+ "single_word": false,
178
+ "special": false
179
+ },
180
+ "151665": {
181
+ "content": "<tool_response>",
182
+ "lstrip": false,
183
+ "normalized": false,
184
+ "rstrip": false,
185
+ "single_word": false,
186
+ "special": false
187
+ },
188
+ "151666": {
189
+ "content": "</tool_response>",
190
+ "lstrip": false,
191
+ "normalized": false,
192
+ "rstrip": false,
193
+ "single_word": false,
194
+ "special": false
195
+ },
196
+ "151667": {
197
+ "content": "<think>",
198
+ "lstrip": false,
199
+ "normalized": false,
200
+ "rstrip": false,
201
+ "single_word": false,
202
+ "special": false
203
+ },
204
+ "151668": {
205
+ "content": "</think>",
206
+ "lstrip": false,
207
+ "normalized": false,
208
+ "rstrip": false,
209
+ "single_word": false,
210
+ "special": false
211
+ }
212
+ },
213
+ "additional_special_tokens": [
214
+ "<|im_start|>",
215
+ "<|im_end|>",
216
+ "<|object_ref_start|>",
217
+ "<|object_ref_end|>",
218
+ "<|box_start|>",
219
+ "<|box_end|>",
220
+ "<|quad_start|>",
221
+ "<|quad_end|>",
222
+ "<|vision_start|>",
223
+ "<|vision_end|>",
224
+ "<|vision_pad|>",
225
+ "<|image_pad|>",
226
+ "<|video_pad|>"
227
+ ],
228
+ "bos_token": null,
229
+ "chat_template": "{%- if tools %}\n {{- '<|im_start|>system\\n' }}\n {%- if messages[0].role == 'system' %}\n {{- messages[0].content + '\\n\\n' }}\n {%- endif %}\n {{- \"# Tools\\n\\nYou may call one or more functions to assist with the user query.\\n\\nYou are provided with function signatures within <tools></tools> XML tags:\\n<tools>\" }}\n {%- for tool in tools %}\n {{- \"\\n\" }}\n {{- tool | tojson }}\n {%- endfor %}\n {{- \"\\n</tools>\\n\\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\\n<tool_call>\\n{\\\"name\\\": <function-name>, \\\"arguments\\\": <args-json-object>}\\n</tool_call><|im_end|>\\n\" }}\n{%- else %}\n {%- if messages[0].role == 'system' %}\n {{- '<|im_start|>system\\n' + messages[0].content + '<|im_end|>\\n' }}\n {%- endif %}\n{%- endif %}\n{%- for message in messages %}\n {%- if message.content is string %}\n {%- set content = message.content %}\n {%- else %}\n {%- set content = '' %}\n {%- endif %}\n {%- if (message.role == \"user\") or (message.role == \"system\" and not loop.first) %}\n {{- '<|im_start|>' + message.role + '\\n' + content + '<|im_end|>' + '\\n' }}\n {%- elif message.role == \"assistant\" %}\n {{- '<|im_start|>' + message.role + '\\n' + content }}\n {%- if message.tool_calls %}\n {%- for tool_call in message.tool_calls %}\n {%- if (loop.first and content) or (not loop.first) %}\n {{- '\\n' }}\n {%- endif %}\n {%- if tool_call.function %}\n {%- set tool_call = tool_call.function %}\n {%- endif %}\n {{- '<tool_call>\\n{\"name\": \"' }}\n {{- tool_call.name }}\n {{- '\", \"arguments\": ' }}\n {%- if tool_call.arguments is string %}\n {{- tool_call.arguments }}\n {%- else %}\n {{- tool_call.arguments | tojson }}\n {%- endif %}\n {{- '}\\n</tool_call>' }}\n {%- endfor %}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n {%- elif message.role == \"tool\" %}\n {%- if loop.first or (messages[loop.index0 - 1].role != \"tool\") %}\n {{- '<|im_start|>user' }}\n {%- endif %}\n {{- '\\n<tool_response>\\n' }}\n {{- content }}\n {{- '\\n</tool_response>' }}\n {%- if loop.last or (messages[loop.index0 + 1].role != \"tool\") %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n {%- endif %}\n{%- endfor %}\n{%- if add_generation_prompt %}\n {{- '<|im_start|>assistant\\n' }}\n{%- endif %}",
230
+ "clean_up_tokenization_spaces": false,
231
+ "eos_token": "<|im_end|>",
232
+ "errors": "replace",
233
+ "model_max_length": 1010000,
234
+ "pad_token": "<|endoftext|>",
235
+ "split_special_tokens": false,
236
+ "tokenizer_class": "Qwen2Tokenizer",
237
+ "unk_token": null,
238
+ "add_bos_token": false
239
+ }
vocab.json ADDED
The diff for this file is too large to render. See raw diff