YifeiZuo commited on
Commit
9ae45c7
·
verified ·
1 Parent(s): 8edebbc

Upload AdamW-WSD attention 0.6B step 1000

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ 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
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ language:
4
+ - en
5
+ base_model: Qwen/Qwen3-0.6B
6
+ tags:
7
+ - parallax
8
+ - qwen3
9
+ - attention
10
+ - wsd
11
+ - 0.6b
12
+ - pretraining-checkpoint
13
+ ---
14
+
15
+ # Attention 0.6B AdamW-WSD - step 1000
16
+
17
+ Intermediate checkpoint at optimizer step **1000** (of 20000) of the 0.6B
18
+ Qwen3-style softmax-attention baseline used in the Parallax mechanism
19
+ analysis.
20
+
21
+ - **Architecture**: Qwen3-0.6B (28 layers, d_model=1024, 16 Q-heads, 8 KV-heads, GQA, RoPE theta 1e6)
22
+ - **Optimizer**: AdamW (lr=3e-4, weight decay=0.1, betas=(0.9, 0.95))
23
+ - **Scheduler**: WSD (warmup=0, last 20% linearly decayed)
24
+ - **Tokens seen at this step**: ~3930.0M sequences * 4096 tokens = ~15.7B tokens
25
+ - **Dataset**: Ultra-FineWeb (English split)
26
+ - **Tokenizer**: Qwen3-0.6B (vocab 151936)
27
+ - **Total steps in run**: 20000 (~80B tokens)
28
+
29
+ The full training trajectory (every 500 steps) lives in the [Attention 0.6B
30
+ AdamW-WSD training trajectory](https://huggingface.co/collections/YifeiZuo)
31
+ collection.
32
+
33
+ ## Loading
34
+
35
+ ```python
36
+ from transformers import AutoModelForCausalLM, AutoTokenizer
37
+
38
+ model = AutoModelForCausalLM.from_pretrained(
39
+ "YifeiZuo/attention-0.6b-adamw-wsd-step1000",
40
+ trust_remote_code=True,
41
+ )
42
+ tokenizer = AutoTokenizer.from_pretrained("YifeiZuo/attention-0.6b-adamw-wsd-step1000")
43
+ ```
configuration_parallax.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Parallax HF config, modular-style (inherits Qwen3Config).
2
+
3
+ This is a second, separate HF interface for the Parallax model family. Unlike
4
+ the self-contained ``torchtitan.hf_modeling.parallax`` package, this version
5
+ inherits from ``transformers.models.qwen3.configuration_qwen3.Qwen3Config``
6
+ so it picks up all of Qwen3's modern conventions for free (strict dataclass,
7
+ ``rope_parameters``, ``layer_types``, tp/pp plans, etc.).
8
+
9
+ The only Parallax-specific additions are the four fields at the bottom that
10
+ control the centered amortized local linear attention op. When
11
+ ``attn_type == "sdpa"`` this config describes a plain Qwen3-equivalent model.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from transformers.models.qwen3.configuration_qwen3 import Qwen3Config
17
+
18
+
19
+ class ParallaxConfig(Qwen3Config):
20
+ r"""Config for the Parallax model (Qwen3-derived).
21
+
22
+ Args:
23
+ attn_type (`str`, *optional*, defaults to `"parallax"`):
24
+ Attention implementation. Must be one of ``"sdpa"`` or
25
+ ``"parallax"``. ``"sdpa"`` uses the plain Qwen3 causal attention
26
+ path (softmax attention). ``"parallax"`` uses the centered
27
+ amortized local linear attention op and requires the extra
28
+ ``r_proj`` / ``r_norm`` per-layer weights.
29
+ use_centering (`bool`, *optional*, defaults to `True`):
30
+ Whether the amortized-LLA math uses the centered variant
31
+ (``s + c*s - r_term``). Currently only the centered variant is
32
+ implemented; kept for config-roundtrip parity with the training
33
+ code, which also has a non-centered path.
34
+ amortized_rho_scale (`float`, *optional*, defaults to `1.0`):
35
+ Multiplicative scale applied to the ``r`` tensor after its
36
+ rotary embedding, mirroring the training-time
37
+ ``amortized_rho_scale`` hyperparameter.
38
+ learn_amortized_rho_scale (`bool`, *optional*, defaults to `False`):
39
+ Whether the model learns a per-head scalar ``a_proj`` modulating
40
+ ``r``. When enabled, adds an ``a_proj: Linear(hidden, n_heads)``
41
+ whose sigmoid output gates ``r`` per head, mirroring the
42
+ training-time ``wa`` module in torchtitan.
43
+ rope_r (`str`, *optional*, defaults to `"correct"`):
44
+ How to apply rotary positional embeddings to R.
45
+ ``"correct"`` — standard RoPE on R (matches fixed torchtitan code).
46
+ ``"none"`` — skip RoPE on R entirely.
47
+ ``"buggy"`` — reproduce the old torchtitan bug where transpose
48
+ was applied before RoPE, causing positions 0..H-1 to be applied
49
+ along the heads axis instead of the sequence axis. Use this to
50
+ faithfully evaluate checkpoints trained with the buggy code.
51
+ """
52
+
53
+ model_type = "parallax"
54
+
55
+ # ---- Parallax-specific extras ----
56
+ # "sdpa" : plain causal self-attention (identical to Qwen3).
57
+ # "parallax": centered amortized local linear attention (adds r_proj + r_norm
58
+ # and replaces softmax attention with the centered LLA op).
59
+ attn_type: str = "parallax"
60
+ use_centering: bool = True
61
+ amortized_rho_scale: float = 1.0
62
+ learn_amortized_rho_scale: bool = False
63
+ rope_r: str = "correct"
64
+
65
+ def __post_init__(self, **kwargs):
66
+ if self.attn_type not in ("sdpa", "parallax"):
67
+ raise ValueError(
68
+ f"attn_type must be 'sdpa' or 'parallax', got {self.attn_type!r}"
69
+ )
70
+ if self.rope_r not in ("correct", "none", "buggy"):
71
+ raise ValueError(
72
+ f"rope_r must be 'correct', 'none', or 'buggy', got {self.rope_r!r}"
73
+ )
74
+ super().__post_init__(**kwargs)
75
+
76
+
77
+ __all__ = ["ParallaxConfig"]
merges.txt ADDED
The diff for this file is too large to render. See raw diff
 
model-00001-of-00001.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b1a03efffcd26ef4ad15dff829444e3c5928fa163c40a55ba766b5d107f0001c
3
+ size 1192137739
model.safetensors.index.json ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "metadata": {
3
+ "total_size": 1192099840
4
+ },
5
+ "weight_map": {
6
+ "model.embed_tokens.weight": "model-00001-of-00001.safetensors",
7
+ "model.layers.0.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
8
+ "model.layers.0.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
9
+ "model.layers.0.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
10
+ "model.layers.0.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
11
+ "model.layers.0.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
12
+ "model.layers.0.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
13
+ "model.layers.0.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
14
+ "model.layers.0.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
15
+ "model.layers.0.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
16
+ "model.layers.0.input_layernorm.weight": "model-00001-of-00001.safetensors",
17
+ "model.layers.0.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
18
+ "model.layers.1.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
19
+ "model.layers.1.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
20
+ "model.layers.1.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
21
+ "model.layers.1.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
22
+ "model.layers.1.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
23
+ "model.layers.1.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
24
+ "model.layers.1.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
25
+ "model.layers.1.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
26
+ "model.layers.1.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
27
+ "model.layers.1.input_layernorm.weight": "model-00001-of-00001.safetensors",
28
+ "model.layers.1.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
29
+ "model.layers.2.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
30
+ "model.layers.2.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
31
+ "model.layers.2.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
32
+ "model.layers.2.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
33
+ "model.layers.2.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
34
+ "model.layers.2.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
35
+ "model.layers.2.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
36
+ "model.layers.2.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
37
+ "model.layers.2.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
38
+ "model.layers.2.input_layernorm.weight": "model-00001-of-00001.safetensors",
39
+ "model.layers.2.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
40
+ "model.layers.3.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
41
+ "model.layers.3.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
42
+ "model.layers.3.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
43
+ "model.layers.3.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
44
+ "model.layers.3.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
45
+ "model.layers.3.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
46
+ "model.layers.3.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
47
+ "model.layers.3.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
48
+ "model.layers.3.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
49
+ "model.layers.3.input_layernorm.weight": "model-00001-of-00001.safetensors",
50
+ "model.layers.3.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
51
+ "model.layers.4.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
52
+ "model.layers.4.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
53
+ "model.layers.4.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
54
+ "model.layers.4.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
55
+ "model.layers.4.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
56
+ "model.layers.4.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
57
+ "model.layers.4.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
58
+ "model.layers.4.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
59
+ "model.layers.4.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
60
+ "model.layers.4.input_layernorm.weight": "model-00001-of-00001.safetensors",
61
+ "model.layers.4.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
62
+ "model.layers.5.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
63
+ "model.layers.5.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
64
+ "model.layers.5.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
65
+ "model.layers.5.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
66
+ "model.layers.5.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
67
+ "model.layers.5.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
68
+ "model.layers.5.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
69
+ "model.layers.5.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
70
+ "model.layers.5.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
71
+ "model.layers.5.input_layernorm.weight": "model-00001-of-00001.safetensors",
72
+ "model.layers.5.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
73
+ "model.layers.6.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
74
+ "model.layers.6.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
75
+ "model.layers.6.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
76
+ "model.layers.6.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
77
+ "model.layers.6.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
78
+ "model.layers.6.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
79
+ "model.layers.6.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
80
+ "model.layers.6.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
81
+ "model.layers.6.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
82
+ "model.layers.6.input_layernorm.weight": "model-00001-of-00001.safetensors",
83
+ "model.layers.6.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
84
+ "model.layers.7.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
85
+ "model.layers.7.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
86
+ "model.layers.7.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
87
+ "model.layers.7.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
88
+ "model.layers.7.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
89
+ "model.layers.7.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
90
+ "model.layers.7.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
91
+ "model.layers.7.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
92
+ "model.layers.7.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
93
+ "model.layers.7.input_layernorm.weight": "model-00001-of-00001.safetensors",
94
+ "model.layers.7.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
95
+ "model.layers.8.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
96
+ "model.layers.8.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
97
+ "model.layers.8.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
98
+ "model.layers.8.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
99
+ "model.layers.8.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
100
+ "model.layers.8.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
101
+ "model.layers.8.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
102
+ "model.layers.8.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
103
+ "model.layers.8.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
104
+ "model.layers.8.input_layernorm.weight": "model-00001-of-00001.safetensors",
105
+ "model.layers.8.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
106
+ "model.layers.9.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
107
+ "model.layers.9.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
108
+ "model.layers.9.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
109
+ "model.layers.9.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
110
+ "model.layers.9.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
111
+ "model.layers.9.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
112
+ "model.layers.9.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
113
+ "model.layers.9.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
114
+ "model.layers.9.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
115
+ "model.layers.9.input_layernorm.weight": "model-00001-of-00001.safetensors",
116
+ "model.layers.9.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
117
+ "model.layers.10.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
118
+ "model.layers.10.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
119
+ "model.layers.10.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
120
+ "model.layers.10.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
121
+ "model.layers.10.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
122
+ "model.layers.10.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
123
+ "model.layers.10.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
124
+ "model.layers.10.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
125
+ "model.layers.10.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
126
+ "model.layers.10.input_layernorm.weight": "model-00001-of-00001.safetensors",
127
+ "model.layers.10.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
128
+ "model.layers.11.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
129
+ "model.layers.11.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
130
+ "model.layers.11.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
131
+ "model.layers.11.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
132
+ "model.layers.11.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
133
+ "model.layers.11.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
134
+ "model.layers.11.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
135
+ "model.layers.11.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
136
+ "model.layers.11.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
137
+ "model.layers.11.input_layernorm.weight": "model-00001-of-00001.safetensors",
138
+ "model.layers.11.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
139
+ "model.layers.12.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
140
+ "model.layers.12.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
141
+ "model.layers.12.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
142
+ "model.layers.12.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
143
+ "model.layers.12.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
144
+ "model.layers.12.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
145
+ "model.layers.12.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
146
+ "model.layers.12.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
147
+ "model.layers.12.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
148
+ "model.layers.12.input_layernorm.weight": "model-00001-of-00001.safetensors",
149
+ "model.layers.12.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
150
+ "model.layers.13.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
151
+ "model.layers.13.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
152
+ "model.layers.13.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
153
+ "model.layers.13.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
154
+ "model.layers.13.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
155
+ "model.layers.13.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
156
+ "model.layers.13.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
157
+ "model.layers.13.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
158
+ "model.layers.13.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
159
+ "model.layers.13.input_layernorm.weight": "model-00001-of-00001.safetensors",
160
+ "model.layers.13.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
161
+ "model.layers.14.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
162
+ "model.layers.14.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
163
+ "model.layers.14.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
164
+ "model.layers.14.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
165
+ "model.layers.14.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
166
+ "model.layers.14.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
167
+ "model.layers.14.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
168
+ "model.layers.14.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
169
+ "model.layers.14.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
170
+ "model.layers.14.input_layernorm.weight": "model-00001-of-00001.safetensors",
171
+ "model.layers.14.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
172
+ "model.layers.15.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
173
+ "model.layers.15.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
174
+ "model.layers.15.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
175
+ "model.layers.15.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
176
+ "model.layers.15.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
177
+ "model.layers.15.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
178
+ "model.layers.15.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
179
+ "model.layers.15.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
180
+ "model.layers.15.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
181
+ "model.layers.15.input_layernorm.weight": "model-00001-of-00001.safetensors",
182
+ "model.layers.15.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
183
+ "model.layers.16.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
184
+ "model.layers.16.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
185
+ "model.layers.16.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
186
+ "model.layers.16.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
187
+ "model.layers.16.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
188
+ "model.layers.16.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
189
+ "model.layers.16.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
190
+ "model.layers.16.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
191
+ "model.layers.16.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
192
+ "model.layers.16.input_layernorm.weight": "model-00001-of-00001.safetensors",
193
+ "model.layers.16.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
194
+ "model.layers.17.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
195
+ "model.layers.17.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
196
+ "model.layers.17.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
197
+ "model.layers.17.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
198
+ "model.layers.17.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
199
+ "model.layers.17.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
200
+ "model.layers.17.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
201
+ "model.layers.17.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
202
+ "model.layers.17.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
203
+ "model.layers.17.input_layernorm.weight": "model-00001-of-00001.safetensors",
204
+ "model.layers.17.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
205
+ "model.layers.18.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
206
+ "model.layers.18.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
207
+ "model.layers.18.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
208
+ "model.layers.18.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
209
+ "model.layers.18.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
210
+ "model.layers.18.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
211
+ "model.layers.18.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
212
+ "model.layers.18.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
213
+ "model.layers.18.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
214
+ "model.layers.18.input_layernorm.weight": "model-00001-of-00001.safetensors",
215
+ "model.layers.18.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
216
+ "model.layers.19.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
217
+ "model.layers.19.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
218
+ "model.layers.19.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
219
+ "model.layers.19.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
220
+ "model.layers.19.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
221
+ "model.layers.19.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
222
+ "model.layers.19.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
223
+ "model.layers.19.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
224
+ "model.layers.19.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
225
+ "model.layers.19.input_layernorm.weight": "model-00001-of-00001.safetensors",
226
+ "model.layers.19.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
227
+ "model.layers.20.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
228
+ "model.layers.20.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
229
+ "model.layers.20.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
230
+ "model.layers.20.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
231
+ "model.layers.20.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
232
+ "model.layers.20.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
233
+ "model.layers.20.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
234
+ "model.layers.20.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
235
+ "model.layers.20.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
236
+ "model.layers.20.input_layernorm.weight": "model-00001-of-00001.safetensors",
237
+ "model.layers.20.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
238
+ "model.layers.21.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
239
+ "model.layers.21.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
240
+ "model.layers.21.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
241
+ "model.layers.21.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
242
+ "model.layers.21.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
243
+ "model.layers.21.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
244
+ "model.layers.21.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
245
+ "model.layers.21.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
246
+ "model.layers.21.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
247
+ "model.layers.21.input_layernorm.weight": "model-00001-of-00001.safetensors",
248
+ "model.layers.21.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
249
+ "model.layers.22.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
250
+ "model.layers.22.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
251
+ "model.layers.22.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
252
+ "model.layers.22.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
253
+ "model.layers.22.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
254
+ "model.layers.22.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
255
+ "model.layers.22.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
256
+ "model.layers.22.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
257
+ "model.layers.22.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
258
+ "model.layers.22.input_layernorm.weight": "model-00001-of-00001.safetensors",
259
+ "model.layers.22.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
260
+ "model.layers.23.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
261
+ "model.layers.23.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
262
+ "model.layers.23.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
263
+ "model.layers.23.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
264
+ "model.layers.23.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
265
+ "model.layers.23.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
266
+ "model.layers.23.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
267
+ "model.layers.23.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
268
+ "model.layers.23.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
269
+ "model.layers.23.input_layernorm.weight": "model-00001-of-00001.safetensors",
270
+ "model.layers.23.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
271
+ "model.layers.24.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
272
+ "model.layers.24.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
273
+ "model.layers.24.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
274
+ "model.layers.24.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
275
+ "model.layers.24.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
276
+ "model.layers.24.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
277
+ "model.layers.24.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
278
+ "model.layers.24.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
279
+ "model.layers.24.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
280
+ "model.layers.24.input_layernorm.weight": "model-00001-of-00001.safetensors",
281
+ "model.layers.24.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
282
+ "model.layers.25.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
283
+ "model.layers.25.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
284
+ "model.layers.25.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
285
+ "model.layers.25.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
286
+ "model.layers.25.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
287
+ "model.layers.25.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
288
+ "model.layers.25.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
289
+ "model.layers.25.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
290
+ "model.layers.25.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
291
+ "model.layers.25.input_layernorm.weight": "model-00001-of-00001.safetensors",
292
+ "model.layers.25.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
293
+ "model.layers.26.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
294
+ "model.layers.26.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
295
+ "model.layers.26.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
296
+ "model.layers.26.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
297
+ "model.layers.26.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
298
+ "model.layers.26.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
299
+ "model.layers.26.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
300
+ "model.layers.26.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
301
+ "model.layers.26.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
302
+ "model.layers.26.input_layernorm.weight": "model-00001-of-00001.safetensors",
303
+ "model.layers.26.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
304
+ "model.layers.27.self_attn.q_norm.weight": "model-00001-of-00001.safetensors",
305
+ "model.layers.27.self_attn.k_norm.weight": "model-00001-of-00001.safetensors",
306
+ "model.layers.27.self_attn.q_proj.weight": "model-00001-of-00001.safetensors",
307
+ "model.layers.27.self_attn.k_proj.weight": "model-00001-of-00001.safetensors",
308
+ "model.layers.27.self_attn.v_proj.weight": "model-00001-of-00001.safetensors",
309
+ "model.layers.27.self_attn.o_proj.weight": "model-00001-of-00001.safetensors",
310
+ "model.layers.27.mlp.gate_proj.weight": "model-00001-of-00001.safetensors",
311
+ "model.layers.27.mlp.down_proj.weight": "model-00001-of-00001.safetensors",
312
+ "model.layers.27.mlp.up_proj.weight": "model-00001-of-00001.safetensors",
313
+ "model.layers.27.input_layernorm.weight": "model-00001-of-00001.safetensors",
314
+ "model.layers.27.post_attention_layernorm.weight": "model-00001-of-00001.safetensors",
315
+ "model.norm.weight": "model-00001-of-00001.safetensors"
316
+ }
317
+ }
modeling_parallax.py ADDED
@@ -0,0 +1,367 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Parallax HF modeling file, modular-style (inherits from Qwen3).
2
+
3
+ This module is the second, separate HF interface for the Parallax family.
4
+ It inherits almost everything from ``transformers.models.qwen3`` and only
5
+ overrides the attention class to add the centered amortized local linear
6
+ attention op (``attn_type="parallax"``).
7
+
8
+ Design notes
9
+ ------------
10
+ * All boilerplate — RMSNorm, MLP, rotary embeddings, decoder-layer scaffolding,
11
+ the base ``PreTrainedModel`` class, ``Qwen3Model``, ``Qwen3ForCausalLM``,
12
+ mask preparation, cache handling, ``GenerationMixin`` integration, etc. —
13
+ is inherited from ``transformers.models.qwen3``.
14
+ * The only new code is:
15
+ - ``parallax_centered_attention_forward``: a pure-PyTorch attention kernel
16
+ matching the math of ``torchtitan/models/flashlla/dev_ops/reference.py``
17
+ (``centered_dense_reference``), but batched over heads and taking an
18
+ additive attention mask in the HF shape ``(B, 1, q_len, kv_len)``.
19
+ - ``ParallaxAttention``: inherits from ``Qwen3Attention``, adds an
20
+ ``r_proj`` / ``r_norm`` pair when ``config.attn_type == "parallax"``,
21
+ and overrides ``forward`` to dispatch to the parallax kernel in that
22
+ case. For ``attn_type == "sdpa"`` the forward simply delegates to
23
+ ``Qwen3Attention.forward`` unchanged, so all modern HF attention
24
+ backends (sdpa, flash_attention_2, flex_attention, eager) remain
25
+ available for that path.
26
+ - ``ParallaxDecoderLayer``, ``ParallaxModel``, ``ParallaxPreTrainedModel``,
27
+ ``ParallaxForCausalLM``: thin subclasses that rewire parent classes to
28
+ the ``ParallaxAttention`` / ``ParallaxConfig`` below.
29
+
30
+ Why this file exists alongside ``torchtitan/hf_modeling/parallax/``
31
+ -------------------------------------------------------------------
32
+ The older ``torchtitan.hf_modeling.parallax`` package is fully self-contained
33
+ (no imports from ``transformers.models.qwen3``). That makes it robust across
34
+ transformers versions but also duplicates a lot of boilerplate that drifts
35
+ from HF conventions. This ``parallax_qwen3`` package takes the opposite
36
+ tradeoff: minimal code, surgical diffs from Qwen3, tracks HF updates for
37
+ free, at the cost of depending on a stable ``transformers.models.qwen3`` API.
38
+
39
+ Both produce numerically equivalent outputs on the same Parallax checkpoint
40
+ weights; a parity test verifies this.
41
+ """
42
+
43
+ from __future__ import annotations
44
+
45
+ from typing import Optional
46
+
47
+ import torch
48
+ import torch.nn as nn
49
+ from transformers.cache_utils import Cache
50
+ from transformers.modeling_outputs import CausalLMOutputWithPast
51
+ from transformers.models.qwen3.modeling_qwen3 import (
52
+ Qwen3Attention,
53
+ Qwen3DecoderLayer,
54
+ Qwen3ForCausalLM,
55
+ Qwen3Model,
56
+ Qwen3PreTrainedModel,
57
+ Qwen3RMSNorm,
58
+ apply_rotary_pos_emb,
59
+ repeat_kv,
60
+ rotate_half,
61
+ )
62
+
63
+ from .configuration_parallax import ParallaxConfig
64
+
65
+
66
+ # ---------------------------------------------------------------------------
67
+ # Parallax centered attention kernel (pure PyTorch reference)
68
+ # ---------------------------------------------------------------------------
69
+
70
+
71
+ def parallax_centered_attention_forward(
72
+ module: nn.Module,
73
+ query: torch.Tensor,
74
+ r: torch.Tensor,
75
+ key: torch.Tensor,
76
+ value: torch.Tensor,
77
+ attention_mask: Optional[torch.Tensor],
78
+ scaling: float,
79
+ dropout: float = 0.0,
80
+ **kwargs,
81
+ ) -> tuple[torch.Tensor, None]:
82
+ """Centered amortized local linear attention.
83
+
84
+ This is a batched generalization of ``centered_dense_reference`` from
85
+ ``torchtitan/models/flashlla/dev_ops/reference.py``:
86
+
87
+ p = softmax((Q Kᵀ) * scale + mask)
88
+ rk = R Kᵀ
89
+ s = p V
90
+ c = sum(p * rk, -1, keepdim=True)
91
+ r_term = (p * rk) V
92
+ out = s + c * s - r_term
93
+
94
+ Shapes
95
+ ------
96
+ query : (B, H, q_len, D)
97
+ r : (B, H, q_len, D) — Parallax-specific extra projection
98
+ key : (B, H_kv, kv_len, D) — GQA-compressed, expanded internally
99
+ value : (B, H_kv, kv_len, D)
100
+ attention_mask : (B, 1, q_len, kv_len) additive, 0 or -inf (HF convention)
101
+
102
+ Returns
103
+ -------
104
+ attn_output : (B, q_len, H, D) — transposed to match Qwen3 eager impl
105
+ attn_weights : None — not exposed (centered attention has no
106
+ meaningful "attention matrix" per head)
107
+ """
108
+ # Expand GQA-compressed k/v to match q heads
109
+ key = repeat_kv(key, module.num_key_value_groups)
110
+ value = repeat_kv(value, module.num_key_value_groups)
111
+
112
+ # Upcast to float32 for numerical stability (matches the training kernel,
113
+ # which uses bfloat16 for math but accumulates in fp32 within the softmax).
114
+ out_dtype = query.dtype
115
+ qf = query.float()
116
+ rf = r.float()
117
+ kf = key.float()
118
+ vf = value.float()
119
+
120
+ qk = torch.einsum("bhqd,bhkd->bhqk", qf, kf) * scaling
121
+ q_len = qk.shape[-2]
122
+ kv_len = qk.shape[-1]
123
+ if attention_mask is not None:
124
+ # HF causal masks may cover a larger key span than our current
125
+ # kv_len during decode; slice to match.
126
+ qk = qk + attention_mask[..., :q_len, :kv_len].to(qk.dtype)
127
+ elif q_len > 1:
128
+ # HF's `create_causal_mask` returns None when the model's default
129
+ # attention backend (e.g. sdpa) handles causality implicitly. Our
130
+ # parallax kernel is hand-written and needs the explicit additive
131
+ # mask, so build one here. Decode (q_len == 1) is naturally
132
+ # unmasked: the single query can attend to every cached key.
133
+ offset = kv_len - q_len
134
+ row = torch.arange(q_len, device=qk.device)[:, None] + offset
135
+ col = torch.arange(kv_len, device=qk.device)[None, :]
136
+ causal = row >= col
137
+ bias = torch.zeros(q_len, kv_len, dtype=qk.dtype, device=qk.device)
138
+ bias = bias.masked_fill(~causal, float("-inf"))
139
+ qk = qk + bias
140
+
141
+ p = torch.softmax(qk, dim=-1)
142
+ rk = torch.einsum("bhqd,bhkd->bhqk", rf, kf)
143
+
144
+ s = torch.einsum("bhqk,bhkd->bhqd", p, vf)
145
+ c = (p * rk).sum(dim=-1, keepdim=True)
146
+ r_term = torch.einsum("bhqk,bhkd->bhqd", p * rk, vf)
147
+
148
+ attn_output = (s + c * s - r_term).to(out_dtype)
149
+ # Match Qwen3 eager_attention_forward: return transposed (B, q_len, H, D)
150
+ attn_output = attn_output.transpose(1, 2).contiguous()
151
+ return attn_output, None
152
+
153
+
154
+ # ---------------------------------------------------------------------------
155
+ # Attention / DecoderLayer / Model / ForCausalLM
156
+ # ---------------------------------------------------------------------------
157
+
158
+
159
+ class ParallaxAttention(Qwen3Attention):
160
+ """Qwen3 attention plus an optional Parallax (centered amortized LLA) path."""
161
+
162
+ def __init__(self, config: ParallaxConfig, layer_idx: int) -> None:
163
+ super().__init__(config, layer_idx)
164
+ self.attn_type = config.attn_type
165
+ self.amortized_rho_scale = config.amortized_rho_scale
166
+ self.learn_amortized_rho_scale = config.learn_amortized_rho_scale
167
+ self.rope_r = getattr(config, "rope_r", "correct")
168
+ self._buggy_rope_cos: torch.Tensor | None = None
169
+ self._buggy_rope_sin: torch.Tensor | None = None
170
+ if self.attn_type == "parallax":
171
+ # Extra projection + RMSNorm for the amortized local linear attn
172
+ self.r_proj = nn.Linear(
173
+ config.hidden_size,
174
+ config.num_attention_heads * self.head_dim,
175
+ bias=config.attention_bias,
176
+ )
177
+ self.r_norm = Qwen3RMSNorm(self.head_dim, eps=config.rms_norm_eps)
178
+ # Learned per-head gate on r (sigmoid), mirroring torchtitan `wa`.
179
+ if self.learn_amortized_rho_scale:
180
+ self.a_proj = nn.Linear(
181
+ config.hidden_size,
182
+ config.num_attention_heads,
183
+ bias=False,
184
+ )
185
+ else:
186
+ self.a_proj = None
187
+
188
+ def forward(
189
+ self,
190
+ hidden_states: torch.Tensor,
191
+ position_embeddings: tuple[torch.Tensor, torch.Tensor],
192
+ attention_mask: Optional[torch.Tensor],
193
+ past_key_values: Optional[Cache] = None,
194
+ **kwargs,
195
+ ) -> tuple[torch.Tensor, Optional[torch.Tensor]]:
196
+ if self.attn_type != "parallax":
197
+ # Plain Qwen3 attention — delegate to the parent, which supports
198
+ # sdpa / flash_attention_2 / flex_attention / eager backends.
199
+ return super().forward(
200
+ hidden_states=hidden_states,
201
+ position_embeddings=position_embeddings,
202
+ attention_mask=attention_mask,
203
+ past_key_values=past_key_values,
204
+ **kwargs,
205
+ )
206
+
207
+ # ---- Parallax path ----
208
+ input_shape = hidden_states.shape[:-1]
209
+ hidden_shape = (*input_shape, -1, self.head_dim)
210
+
211
+ query_states = self.q_norm(
212
+ self.q_proj(hidden_states).view(hidden_shape)
213
+ ).transpose(1, 2)
214
+ key_states = self.k_norm(
215
+ self.k_proj(hidden_states).view(hidden_shape)
216
+ ).transpose(1, 2)
217
+ value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
218
+
219
+ # r: same num_heads as q (not num_key_value_heads), rope applied.
220
+ # Note hidden_shape uses -1 for the heads dim, so r_proj (which produces
221
+ # num_attention_heads*head_dim) will correctly view as (..., n_heads, D).
222
+ r_states = self.r_norm(
223
+ self.r_proj(hidden_states).view(hidden_shape)
224
+ ).transpose(1, 2)
225
+
226
+ cos, sin = position_embeddings
227
+ query_states, key_states = apply_rotary_pos_emb(
228
+ query_states, key_states, cos, sin
229
+ )
230
+ # Apply rope to r according to rope_r mode.
231
+ if self.rope_r == "correct":
232
+ r_states, _ = apply_rotary_pos_emb(r_states, r_states, cos, sin)
233
+ elif self.rope_r == "buggy":
234
+ # Reproduce the old torchtitan bug: reshape_for_broadcast read
235
+ # (B, H, S, D) as (bz, seqlen=H, _, head_dim=D), so it applied
236
+ # positions 0..H-1 along the heads axis. Every token in the
237
+ # sequence got the SAME rotation (the one for position h, where
238
+ # h is the head index). This is a fixed per-head rotation that
239
+ # does not vary with sequence position.
240
+ #
241
+ # We lazily compute cos/sin for positions 0..H-1 and cache them.
242
+ # Shape: (1, H, 1, D) so head h gets rotation for position h,
243
+ # broadcast across all sequence positions.
244
+ if self._buggy_rope_cos is None or self._buggy_rope_cos.device != r_states.device:
245
+ H = r_states.shape[1]
246
+ # Reuse the same RoPE frequencies: extract from cos/sin for
247
+ # positions 0..H-1. cos/sin are (B,1,T,D) during prefill
248
+ # (T >= H always since T >= 1 and H = num_heads).
249
+ # For robustness, recompute from config's rope_theta.
250
+ head_dim = r_states.shape[-1]
251
+ rope_theta = self.config.rope_parameters["rope_theta"]
252
+ inv_freq = 1.0 / (rope_theta ** (
253
+ torch.arange(0, head_dim, 2, device=r_states.device, dtype=torch.float32) / head_dim
254
+ ))
255
+ pos = torch.arange(H, device=r_states.device, dtype=torch.float32)
256
+ freqs = torch.outer(pos, inv_freq) # (H, D/2)
257
+ emb = torch.cat([freqs, freqs], dim=-1) # (H, D)
258
+ self._buggy_rope_cos = emb.cos().view(1, H, 1, head_dim).to(r_states.dtype)
259
+ self._buggy_rope_sin = emb.sin().view(1, H, 1, head_dim).to(r_states.dtype)
260
+ r_states = (r_states * self._buggy_rope_cos) + (rotate_half(r_states) * self._buggy_rope_sin)
261
+ # else: rope_r == "none", skip RoPE on R entirely
262
+ if self.a_proj is not None:
263
+ # a: (B, n_heads, q_len), sigmoid per-head gate
264
+ a = torch.sigmoid(self.a_proj(hidden_states)).transpose(1, 2).to(dtype=r_states.dtype)
265
+ r_states = r_states * (self.amortized_rho_scale * a.unsqueeze(-1))
266
+ elif self.amortized_rho_scale != 1.0:
267
+ r_states = r_states * self.amortized_rho_scale
268
+
269
+ if past_key_values is not None:
270
+ key_states, value_states = past_key_values.update(
271
+ key_states, value_states, self.layer_idx
272
+ )
273
+
274
+ attn_output, attn_weights = parallax_centered_attention_forward(
275
+ self,
276
+ query_states,
277
+ r_states,
278
+ key_states,
279
+ value_states,
280
+ attention_mask,
281
+ dropout=0.0 if not self.training else self.attention_dropout,
282
+ scaling=self.scaling,
283
+ )
284
+
285
+ attn_output = attn_output.reshape(*input_shape, -1).contiguous()
286
+ attn_output = self.o_proj(attn_output)
287
+ return attn_output, attn_weights
288
+
289
+
290
+ class ParallaxDecoderLayer(Qwen3DecoderLayer):
291
+ def __init__(self, config: ParallaxConfig, layer_idx: int) -> None:
292
+ # Call the grandparent (nn.Module) init to avoid Qwen3DecoderLayer
293
+ # building a Qwen3Attention we'd immediately replace.
294
+ nn.Module.__init__(self)
295
+ self.hidden_size = config.hidden_size
296
+ self.attention_type = config.layer_types[layer_idx]
297
+ self.self_attn = ParallaxAttention(config=config, layer_idx=layer_idx)
298
+ # Reuse the MLP + norms from Qwen3 via its own constructor logic.
299
+ # Easiest is to rebuild them directly here to match Qwen3DecoderLayer.
300
+ from transformers.models.qwen3.modeling_qwen3 import Qwen3MLP
301
+
302
+ self.mlp = Qwen3MLP(config)
303
+ self.input_layernorm = Qwen3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
304
+ self.post_attention_layernorm = Qwen3RMSNorm(
305
+ config.hidden_size, eps=config.rms_norm_eps
306
+ )
307
+
308
+
309
+ class ParallaxPreTrainedModel(Qwen3PreTrainedModel):
310
+ config: ParallaxConfig # type: ignore[assignment]
311
+ config_class = ParallaxConfig
312
+ base_model_prefix = "model"
313
+ _no_split_modules = ["ParallaxDecoderLayer"]
314
+ # Parallax path is hand-written and does not plug into ALL_ATTENTION_FUNCTIONS.
315
+ # The sdpa path (delegated to super) supports the standard backends.
316
+ _supports_flash_attn = True
317
+ _supports_sdpa = True
318
+ _supports_flex_attn = True
319
+
320
+
321
+ class ParallaxModel(ParallaxPreTrainedModel, Qwen3Model):
322
+ def __init__(self, config: ParallaxConfig) -> None:
323
+ # Bypass Qwen3Model.__init__ (which builds Qwen3DecoderLayers) and
324
+ # rebuild the module tree with ParallaxDecoderLayers.
325
+ Qwen3PreTrainedModel.__init__(self, config)
326
+ self.padding_idx = config.pad_token_id
327
+ self.vocab_size = config.vocab_size
328
+ self.embed_tokens = nn.Embedding(
329
+ config.vocab_size, config.hidden_size, self.padding_idx
330
+ )
331
+ self.layers = nn.ModuleList(
332
+ [
333
+ ParallaxDecoderLayer(config, layer_idx)
334
+ for layer_idx in range(config.num_hidden_layers)
335
+ ]
336
+ )
337
+ self.norm = Qwen3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
338
+ # Qwen3Model constructs its rotary embedding from the config; reuse.
339
+ from transformers.models.qwen3.modeling_qwen3 import Qwen3RotaryEmbedding
340
+
341
+ self.rotary_emb = Qwen3RotaryEmbedding(config=config)
342
+ self.gradient_checkpointing = False
343
+ self.has_sliding_layers = "sliding_attention" in (config.layer_types or [])
344
+ self.post_init()
345
+
346
+
347
+ class ParallaxForCausalLM(ParallaxPreTrainedModel, Qwen3ForCausalLM):
348
+ _tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
349
+
350
+ def __init__(self, config: ParallaxConfig) -> None:
351
+ # Bypass Qwen3ForCausalLM.__init__ (which builds a Qwen3Model) and
352
+ # rebuild with ParallaxModel.
353
+ Qwen3PreTrainedModel.__init__(self, config)
354
+ self.model = ParallaxModel(config)
355
+ self.vocab_size = config.vocab_size
356
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
357
+ self.post_init()
358
+
359
+
360
+ __all__ = [
361
+ "ParallaxAttention",
362
+ "ParallaxDecoderLayer",
363
+ "ParallaxForCausalLM",
364
+ "ParallaxModel",
365
+ "ParallaxPreTrainedModel",
366
+ "parallax_centered_attention_forward",
367
+ ]
sharded/shard-00001-model-00001-of-00001.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:86cbf2242cae2269ee1f2faa0749f0fd7753232306b47668c30d8517183bddcf
3
+ size 1192157480
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_bos_token": false,
3
+ "add_prefix_space": false,
4
+ "added_tokens_decoder": {
5
+ "151643": {
6
+ "content": "<|endoftext|>",
7
+ "lstrip": false,
8
+ "normalized": false,
9
+ "rstrip": false,
10
+ "single_word": false,
11
+ "special": true
12
+ },
13
+ "151644": {
14
+ "content": "<|im_start|>",
15
+ "lstrip": false,
16
+ "normalized": false,
17
+ "rstrip": false,
18
+ "single_word": false,
19
+ "special": true
20
+ },
21
+ "151645": {
22
+ "content": "<|im_end|>",
23
+ "lstrip": false,
24
+ "normalized": false,
25
+ "rstrip": false,
26
+ "single_word": false,
27
+ "special": true
28
+ },
29
+ "151646": {
30
+ "content": "<|object_ref_start|>",
31
+ "lstrip": false,
32
+ "normalized": false,
33
+ "rstrip": false,
34
+ "single_word": false,
35
+ "special": true
36
+ },
37
+ "151647": {
38
+ "content": "<|object_ref_end|>",
39
+ "lstrip": false,
40
+ "normalized": false,
41
+ "rstrip": false,
42
+ "single_word": false,
43
+ "special": true
44
+ },
45
+ "151648": {
46
+ "content": "<|box_start|>",
47
+ "lstrip": false,
48
+ "normalized": false,
49
+ "rstrip": false,
50
+ "single_word": false,
51
+ "special": true
52
+ },
53
+ "151649": {
54
+ "content": "<|box_end|>",
55
+ "lstrip": false,
56
+ "normalized": false,
57
+ "rstrip": false,
58
+ "single_word": false,
59
+ "special": true
60
+ },
61
+ "151650": {
62
+ "content": "<|quad_start|>",
63
+ "lstrip": false,
64
+ "normalized": false,
65
+ "rstrip": false,
66
+ "single_word": false,
67
+ "special": true
68
+ },
69
+ "151651": {
70
+ "content": "<|quad_end|>",
71
+ "lstrip": false,
72
+ "normalized": false,
73
+ "rstrip": false,
74
+ "single_word": false,
75
+ "special": true
76
+ },
77
+ "151652": {
78
+ "content": "<|vision_start|>",
79
+ "lstrip": false,
80
+ "normalized": false,
81
+ "rstrip": false,
82
+ "single_word": false,
83
+ "special": true
84
+ },
85
+ "151653": {
86
+ "content": "<|vision_end|>",
87
+ "lstrip": false,
88
+ "normalized": false,
89
+ "rstrip": false,
90
+ "single_word": false,
91
+ "special": true
92
+ },
93
+ "151654": {
94
+ "content": "<|vision_pad|>",
95
+ "lstrip": false,
96
+ "normalized": false,
97
+ "rstrip": false,
98
+ "single_word": false,
99
+ "special": true
100
+ },
101
+ "151655": {
102
+ "content": "<|image_pad|>",
103
+ "lstrip": false,
104
+ "normalized": false,
105
+ "rstrip": false,
106
+ "single_word": false,
107
+ "special": true
108
+ },
109
+ "151656": {
110
+ "content": "<|video_pad|>",
111
+ "lstrip": false,
112
+ "normalized": false,
113
+ "rstrip": false,
114
+ "single_word": false,
115
+ "special": true
116
+ },
117
+ "151657": {
118
+ "content": "<tool_call>",
119
+ "lstrip": false,
120
+ "normalized": false,
121
+ "rstrip": false,
122
+ "single_word": false,
123
+ "special": false
124
+ },
125
+ "151658": {
126
+ "content": "</tool_call>",
127
+ "lstrip": false,
128
+ "normalized": false,
129
+ "rstrip": false,
130
+ "single_word": false,
131
+ "special": false
132
+ },
133
+ "151659": {
134
+ "content": "<|fim_prefix|>",
135
+ "lstrip": false,
136
+ "normalized": false,
137
+ "rstrip": false,
138
+ "single_word": false,
139
+ "special": false
140
+ },
141
+ "151660": {
142
+ "content": "<|fim_middle|>",
143
+ "lstrip": false,
144
+ "normalized": false,
145
+ "rstrip": false,
146
+ "single_word": false,
147
+ "special": false
148
+ },
149
+ "151661": {
150
+ "content": "<|fim_suffix|>",
151
+ "lstrip": false,
152
+ "normalized": false,
153
+ "rstrip": false,
154
+ "single_word": false,
155
+ "special": false
156
+ },
157
+ "151662": {
158
+ "content": "<|fim_pad|>",
159
+ "lstrip": false,
160
+ "normalized": false,
161
+ "rstrip": false,
162
+ "single_word": false,
163
+ "special": false
164
+ },
165
+ "151663": {
166
+ "content": "<|repo_name|>",
167
+ "lstrip": false,
168
+ "normalized": false,
169
+ "rstrip": false,
170
+ "single_word": false,
171
+ "special": false
172
+ },
173
+ "151664": {
174
+ "content": "<|file_sep|>",
175
+ "lstrip": false,
176
+ "normalized": false,
177
+ "rstrip": false,
178
+ "single_word": false,
179
+ "special": false
180
+ },
181
+ "151665": {
182
+ "content": "<tool_response>",
183
+ "lstrip": false,
184
+ "normalized": false,
185
+ "rstrip": false,
186
+ "single_word": false,
187
+ "special": false
188
+ },
189
+ "151666": {
190
+ "content": "</tool_response>",
191
+ "lstrip": false,
192
+ "normalized": false,
193
+ "rstrip": false,
194
+ "single_word": false,
195
+ "special": false
196
+ },
197
+ "151667": {
198
+ "content": "<think>",
199
+ "lstrip": false,
200
+ "normalized": false,
201
+ "rstrip": false,
202
+ "single_word": false,
203
+ "special": false
204
+ },
205
+ "151668": {
206
+ "content": "</think>",
207
+ "lstrip": false,
208
+ "normalized": false,
209
+ "rstrip": false,
210
+ "single_word": false,
211
+ "special": false
212
+ }
213
+ },
214
+ "additional_special_tokens": [
215
+ "<|im_start|>",
216
+ "<|im_end|>",
217
+ "<|object_ref_start|>",
218
+ "<|object_ref_end|>",
219
+ "<|box_start|>",
220
+ "<|box_end|>",
221
+ "<|quad_start|>",
222
+ "<|quad_end|>",
223
+ "<|vision_start|>",
224
+ "<|vision_end|>",
225
+ "<|vision_pad|>",
226
+ "<|image_pad|>",
227
+ "<|video_pad|>"
228
+ ],
229
+ "bos_token": "<|im_start|>",
230
+ "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{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}\n{%- for message in messages[::-1] %}\n {%- set index = (messages|length - 1) - loop.index0 %}\n {%- if ns.multi_step_tool and message.role == \"user\" and message.content is string and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}\n {%- set ns.multi_step_tool = false %}\n {%- set ns.last_query_index = index %}\n {%- endif %}\n{%- endfor %}\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 {%- set reasoning_content = '' %}\n {%- if message.reasoning_content is string %}\n {%- set reasoning_content = message.reasoning_content %}\n {%- else %}\n {%- if '</think>' in content %}\n {%- set reasoning_content = content.split('</think>')[0].rstrip('\\n').split('<think>')[-1].lstrip('\\n') %}\n {%- set content = content.split('</think>')[-1].lstrip('\\n') %}\n {%- endif %}\n {%- endif %}\n {%- if loop.index0 > ns.last_query_index %}\n {%- if loop.last or (not loop.last and reasoning_content) %}\n {{- '<|im_start|>' + message.role + '\\n<think>\\n' + reasoning_content.strip('\\n') + '\\n</think>\\n\\n' + content.lstrip('\\n') }}\n {%- else %}\n {{- '<|im_start|>' + message.role + '\\n' + content }}\n {%- endif %}\n {%- else %}\n {{- '<|im_start|>' + message.role + '\\n' + content }}\n {%- endif %}\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 {%- if enable_thinking is defined and enable_thinking is false %}\n {{- '<think>\\n\\n</think>\\n\\n' }}\n {%- endif %}\n{%- endif %}",
231
+ "clean_up_tokenization_spaces": false,
232
+ "eos_token": "<|im_end|>",
233
+ "errors": "replace",
234
+ "model_max_length": 131072,
235
+ "pad_token": "<|endoftext|>",
236
+ "split_special_tokens": false,
237
+ "tokenizer_class": "Qwen2Tokenizer",
238
+ "unk_token": null
239
+ }
vocab.json ADDED
The diff for this file is too large to render. See raw diff