Update to terminal-RL checkpoint (360 steps)

#2
by aagohary - opened
README.md CHANGED
@@ -19,7 +19,7 @@ tags:
19
 
20
  MagenticBrain is a 14B-parameter orchestration model from **Microsoft Research AI Frontiers**. It plans multi-step tasks, calls declared tools, and coordinates sub-agents. It does not execute actions itself — every real-world side effect happens inside a host harness.
21
 
22
- The model is supervised fine-tuned from [Qwen/Qwen3-14B](https://huggingface.co/Qwen/Qwen3-14B) on agentic data: function-calling corpora, file-system trajectories, terminal tasks, sub-agent delegation traces, and reasoning data. It's co-designed with **MagenticLite**, our agentic application and harness, and that's the configuration it has been most thoroughly evaluated in.
23
 
24
  We're releasing weights only. Inference code, training recipes, and the execution harness are part of MagenticLite.
25
 
@@ -144,7 +144,7 @@ MagenticBrain runs in non-thinking mode — keep `enable_thinking=False` in the
144
 
145
  ### Approach
146
 
147
- Post-training is Supervised Fine-Tuning on a heterogeneous agentic data mix. Reinforcement learning is in active exploration but not part of this release. Thinking tokens are disabled by default (`enable_thinking=False`) to control verbosity and reduce looping on long trajectories.
148
 
149
  ### Data sources
150
 
 
19
 
20
  MagenticBrain is a 14B-parameter orchestration model from **Microsoft Research AI Frontiers**. It plans multi-step tasks, calls declared tools, and coordinates sub-agents. It does not execute actions itself — every real-world side effect happens inside a host harness.
21
 
22
+ The model is supervised fine-tuned from [Qwen/Qwen3-14B](https://huggingface.co/Qwen/Qwen3-14B) on agentic data: function-calling corpora, file-system trajectories, terminal tasks, sub-agent delegation traces, and reasoning data. After supervised fine-tuning, it was further trained with reinforcement learning on in-house-constructed terminal tasks. It's co-designed with **MagenticLite**, our agentic application and harness, and that's the configuration it has been most thoroughly evaluated in.
23
 
24
  We're releasing weights only. Inference code, training recipes, and the execution harness are part of MagenticLite.
25
 
 
144
 
145
  ### Approach
146
 
147
+ Post-training has two stages. First, Supervised Fine-Tuning on a heterogeneous agentic data mix. Second, a reinforcement learning stage on in-house-constructed terminal tasks, further specializing the model for multi-step CLI execution. Thinking tokens are disabled by default (`enable_thinking=False`) to control verbosity and reduce looping on long trajectories.
148
 
149
  ### Data sources
150
 
config.json CHANGED
@@ -60,13 +60,14 @@
60
  "num_attention_heads": 40,
61
  "num_hidden_layers": 40,
62
  "num_key_value_heads": 8,
 
63
  "rms_norm_eps": 1e-06,
64
  "rope_scaling": null,
65
  "rope_theta": 1000000,
66
  "sliding_window": null,
67
  "tie_word_embeddings": false,
68
  "transformers_version": "4.57.6",
69
- "use_cache": false,
70
  "use_sliding_window": false,
71
  "vocab_size": 151936
72
  }
 
60
  "num_attention_heads": 40,
61
  "num_hidden_layers": 40,
62
  "num_key_value_heads": 8,
63
+ "pad_token_id": 151643,
64
  "rms_norm_eps": 1e-06,
65
  "rope_scaling": null,
66
  "rope_theta": 1000000,
67
  "sliding_window": null,
68
  "tie_word_embeddings": false,
69
  "transformers_version": "4.57.6",
70
+ "use_cache": true,
71
  "use_sliding_window": false,
72
  "vocab_size": 151936
73
  }
configuration_qwen3.py DELETED
@@ -1,226 +0,0 @@
1
- # coding=utf-8
2
- # Copyright 2024 The Qwen team, Alibaba Group and the HuggingFace Inc. team. All rights reserved.
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- """Qwen3 model configuration"""
16
-
17
- from ...configuration_utils import PretrainedConfig, layer_type_validation
18
- from ...modeling_rope_utils import rope_config_validation
19
- from ...utils import logging
20
-
21
-
22
- logger = logging.get_logger(__name__)
23
-
24
-
25
- class Qwen3Config(PretrainedConfig):
26
- r"""
27
- This is the configuration class to store the configuration of a [`Qwen3Model`]. It is used to instantiate a
28
- Qwen3 model according to the specified arguments, defining the model architecture. Instantiating a configuration
29
- with the defaults will yield a similar configuration to that of
30
- Qwen3-8B [Qwen/Qwen3-8B](https://huggingface.co/Qwen/Qwen3-8B).
31
-
32
- Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
33
- documentation from [`PretrainedConfig`] for more information.
34
-
35
-
36
- Args:
37
- vocab_size (`int`, *optional*, defaults to 151936):
38
- Vocabulary size of the Qwen3 model. Defines the number of different tokens that can be represented by the
39
- `inputs_ids` passed when calling [`Qwen3Model`]
40
- hidden_size (`int`, *optional*, defaults to 4096):
41
- Dimension of the hidden representations.
42
- intermediate_size (`int`, *optional*, defaults to 22016):
43
- Dimension of the MLP representations.
44
- num_hidden_layers (`int`, *optional*, defaults to 32):
45
- Number of hidden layers in the Transformer encoder.
46
- num_attention_heads (`int`, *optional*, defaults to 32):
47
- Number of attention heads for each attention layer in the Transformer encoder.
48
- num_key_value_heads (`int`, *optional*, defaults to 32):
49
- This is the number of key_value heads that should be used to implement Grouped Query Attention. If
50
- `num_key_value_heads=num_attention_heads`, the model will use Multi Head Attention (MHA), if
51
- `num_key_value_heads=1` the model will use Multi Query Attention (MQA) otherwise GQA is used. When
52
- converting a multi-head checkpoint to a GQA checkpoint, each group key and value head should be constructed
53
- by meanpooling all the original heads within that group. For more details, check out [this
54
- paper](https://huggingface.co/papers/2305.13245). If it is not specified, will default to `32`.
55
- head_dim (`int`, *optional*, defaults to 128):
56
- The attention head dimension.
57
- hidden_act (`str` or `function`, *optional*, defaults to `"silu"`):
58
- The non-linear activation function (function or string) in the decoder.
59
- max_position_embeddings (`int`, *optional*, defaults to 32768):
60
- The maximum sequence length that this model might ever be used with.
61
- initializer_range (`float`, *optional*, defaults to 0.02):
62
- The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
63
- rms_norm_eps (`float`, *optional*, defaults to 1e-06):
64
- The epsilon used by the rms normalization layers.
65
- use_cache (`bool`, *optional*, defaults to `True`):
66
- Whether or not the model should return the last key/values attentions (not used by all models). Only
67
- relevant if `config.is_decoder=True`.
68
- tie_word_embeddings (`bool`, *optional*, defaults to `False`):
69
- Whether the model's input and output word embeddings should be tied.
70
- rope_theta (`float`, *optional*, defaults to 10000.0):
71
- The base period of the RoPE embeddings.
72
- rope_scaling (`Dict`, *optional*):
73
- Dictionary containing the scaling configuration for the RoPE embeddings. NOTE: if you apply new rope type
74
- and you expect the model to work on longer `max_position_embeddings`, we recommend you to update this value
75
- accordingly.
76
- Expected contents:
77
- `rope_type` (`str`):
78
- The sub-variant of RoPE to use. Can be one of ['default', 'linear', 'dynamic', 'yarn', 'longrope',
79
- 'llama3'], with 'default' being the original RoPE implementation.
80
- `factor` (`float`, *optional*):
81
- Used with all rope types except 'default'. The scaling factor to apply to the RoPE embeddings. In
82
- most scaling types, a `factor` of x will enable the model to handle sequences of length x *
83
- original maximum pre-trained length.
84
- `original_max_position_embeddings` (`int`, *optional*):
85
- Used with 'dynamic', 'longrope' and 'llama3'. The original max position embeddings used during
86
- pretraining.
87
- `attention_factor` (`float`, *optional*):
88
- Used with 'yarn' and 'longrope'. The scaling factor to be applied on the attention
89
- computation. If unspecified, it defaults to value recommended by the implementation, using the
90
- `factor` field to infer the suggested value.
91
- `beta_fast` (`float`, *optional*):
92
- Only used with 'yarn'. Parameter to set the boundary for extrapolation (only) in the linear
93
- ramp function. If unspecified, it defaults to 32.
94
- `beta_slow` (`float`, *optional*):
95
- Only used with 'yarn'. Parameter to set the boundary for interpolation (only) in the linear
96
- ramp function. If unspecified, it defaults to 1.
97
- `short_factor` (`list[float]`, *optional*):
98
- Only used with 'longrope'. The scaling factor to be applied to short contexts (<
99
- `original_max_position_embeddings`). Must be a list of numbers with the same length as the hidden
100
- size divided by the number of attention heads divided by 2
101
- `long_factor` (`list[float]`, *optional*):
102
- Only used with 'longrope'. The scaling factor to be applied to long contexts (<
103
- `original_max_position_embeddings`). Must be a list of numbers with the same length as the hidden
104
- size divided by the number of attention heads divided by 2
105
- `low_freq_factor` (`float`, *optional*):
106
- Only used with 'llama3'. Scaling factor applied to low frequency components of the RoPE
107
- `high_freq_factor` (`float`, *optional*):
108
- Only used with 'llama3'. Scaling factor applied to high frequency components of the RoPE
109
- attention_bias (`bool`, defaults to `False`, *optional*, defaults to `False`):
110
- Whether to use a bias in the query, key, value and output projection layers during self-attention.
111
- use_sliding_window (`bool`, *optional*, defaults to `False`):
112
- Whether to use sliding window attention.
113
- sliding_window (`int`, *optional*, defaults to 4096):
114
- Sliding window attention (SWA) window size. If not specified, will default to `4096`.
115
- max_window_layers (`int`, *optional*, defaults to 28):
116
- The number of layers using full attention. The first `max_window_layers` layers will use full attention, while any
117
- additional layer afterwards will use SWA (Sliding Window Attention).
118
- layer_types (`list`, *optional*):
119
- Attention pattern for each layer.
120
- attention_dropout (`float`, *optional*, defaults to 0.0):
121
- The dropout ratio for the attention probabilities.
122
-
123
- ```python
124
- >>> from transformers import Qwen3Model, Qwen3Config
125
-
126
- >>> # Initializing a Qwen3 style configuration
127
- >>> configuration = Qwen3Config()
128
-
129
- >>> # Initializing a model from the Qwen3-8B style configuration
130
- >>> model = Qwen3Model(configuration)
131
-
132
- >>> # Accessing the model configuration
133
- >>> configuration = model.config
134
- ```"""
135
-
136
- model_type = "qwen3"
137
- keys_to_ignore_at_inference = ["past_key_values"]
138
-
139
- # Default tensor parallel plan for base model `Qwen3`
140
- base_model_tp_plan = {
141
- "layers.*.self_attn.q_proj": "colwise",
142
- "layers.*.self_attn.k_proj": "colwise",
143
- "layers.*.self_attn.v_proj": "colwise",
144
- "layers.*.self_attn.o_proj": "rowwise",
145
- "layers.*.mlp.gate_proj": "colwise",
146
- "layers.*.mlp.up_proj": "colwise",
147
- "layers.*.mlp.down_proj": "rowwise",
148
- }
149
- base_model_pp_plan = {
150
- "embed_tokens": (["input_ids"], ["inputs_embeds"]),
151
- "layers": (["hidden_states", "attention_mask"], ["hidden_states"]),
152
- "norm": (["hidden_states"], ["hidden_states"]),
153
- }
154
-
155
- def __init__(
156
- self,
157
- vocab_size=151936,
158
- hidden_size=4096,
159
- intermediate_size=22016,
160
- num_hidden_layers=32,
161
- num_attention_heads=32,
162
- num_key_value_heads=32,
163
- head_dim=128,
164
- hidden_act="silu",
165
- max_position_embeddings=32768,
166
- initializer_range=0.02,
167
- rms_norm_eps=1e-6,
168
- use_cache=True,
169
- tie_word_embeddings=False,
170
- rope_theta=10000.0,
171
- rope_scaling=None,
172
- attention_bias=False,
173
- use_sliding_window=False,
174
- sliding_window=4096,
175
- max_window_layers=28,
176
- layer_types=None,
177
- attention_dropout=0.0,
178
- **kwargs,
179
- ):
180
- self.vocab_size = vocab_size
181
- self.max_position_embeddings = max_position_embeddings
182
- self.hidden_size = hidden_size
183
- self.intermediate_size = intermediate_size
184
- self.num_hidden_layers = num_hidden_layers
185
- self.num_attention_heads = num_attention_heads
186
- self.use_sliding_window = use_sliding_window
187
- self.sliding_window = sliding_window if self.use_sliding_window else None
188
- self.max_window_layers = max_window_layers
189
-
190
- # for backward compatibility
191
- if num_key_value_heads is None:
192
- num_key_value_heads = num_attention_heads
193
-
194
- self.num_key_value_heads = num_key_value_heads
195
- self.head_dim = head_dim
196
- self.hidden_act = hidden_act
197
- self.initializer_range = initializer_range
198
- self.rms_norm_eps = rms_norm_eps
199
- self.use_cache = use_cache
200
- self.rope_theta = rope_theta
201
- self.rope_scaling = rope_scaling
202
- self.attention_bias = attention_bias
203
- self.attention_dropout = attention_dropout
204
- # Validate the correctness of rotary position embeddings parameters
205
- # BC: if there is a 'type' field, move it to 'rope_type'.
206
- if self.rope_scaling is not None and "type" in self.rope_scaling:
207
- self.rope_scaling["rope_type"] = self.rope_scaling["type"]
208
- rope_config_validation(self)
209
-
210
- self.layer_types = layer_types
211
- if self.layer_types is None:
212
- self.layer_types = [
213
- "sliding_attention"
214
- if self.sliding_window is not None and i >= self.max_window_layers
215
- else "full_attention"
216
- for i in range(self.num_hidden_layers)
217
- ]
218
- layer_type_validation(self.layer_types, self.num_hidden_layers)
219
-
220
- super().__init__(
221
- tie_word_embeddings=tie_word_embeddings,
222
- **kwargs,
223
- )
224
-
225
-
226
- __all__ = ["Qwen3Config"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
generation_config.json CHANGED
@@ -2,6 +2,7 @@
2
  "_from_model_config": true,
3
  "bos_token_id": 151643,
4
  "eos_token_id": 151645,
 
5
  "transformers_version": "4.57.6",
6
  "use_cache": false
7
  }
 
2
  "_from_model_config": true,
3
  "bos_token_id": 151643,
4
  "eos_token_id": 151645,
5
+ "pad_token_id": 151643,
6
  "transformers_version": "4.57.6",
7
  "use_cache": false
8
  }
model-00001-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:c41d4c2a7d12df552b0b6c008d4350f34fb9b483cac2d32b12dea3ddd7d7cb84
3
  size 4684558368
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4539bad45017af50ca104d690cc8bb779cbcfabc29dd5843a7861af703671072
3
  size 4684558368
model-00002-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:db4f3f3ce12ab3ac811d4c4103fc1bcb86340dd5225a83424c9b9423d9ab363f
3
  size 4676778920
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1b35c5a3da42800f17eee81a2626d88490bb7e81bf30fcec7c62678cd5a27ff6
3
  size 4676778920
model-00003-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:680e13b01f4c429060aefcda5194e14e79ffb687dd878913159a5bfe60702b77
3
  size 4928480056
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d858ff790cc462a2647430711b4b28602cda466102f9073ad9a2f4edfba9f182
3
  size 4928480056
model-00004-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:8bf6c64ab66efb63de5a6ff9f7facf661f1dd825cd183be4de7310b319b8d60a
3
  size 4928480080
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8ff3c4079bb4dd7450729b415f4d9e21e964c2fc735085938b052116c0a82858
3
  size 4928480080
model-00005-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:41f00d23ab24cebd72c591f8be4a3a367eb2a46f45dbd7be5aef12641432e3a2
3
  size 4676778952
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:85f22ea7bd6ee2f19178333983bec5a2c2047a0bc6eb3d7910ca7dbf050a1764
3
  size 4676778952
model-00006-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:1dc926fd9b835b0cbed4ebca5eafa7b7f69a7c236c0773d002f2fd7004e99bf3
3
  size 4928480096
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3773651bd385eef4305e37b9fe0825ed6566826b74ba32ecd9c7fc99ca09ca7c
3
  size 4928480096
model-00007-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:d7efff67976230015688e2b854b87932345675e4b340467370465d6aa0817e52
3
  size 4928480096
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:762e386b26919290f4cf03ac6d071845c07aee21b166d26edeb6ad2bd4b076e3
3
  size 4928480096
model-00008-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:4b370aad0cbe94d3a9cb3b42971c9f00c0058e1e514cfcb2fcca419b4e649dd1
3
  size 4676778952
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:85eacd56fe4c99fe54e3f201fa9c41e206659b56d45bcfdc108e88541062759f
3
  size 4676778952
model-00009-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:12c72d4ee22bc432fbf2f32032ea71dbada4eaa3f36fbf9ec3a3ca3d72ccced2
3
  size 4928480096
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f85278f128f53ed06e234bdc049aa5eb3c7ea68d57976ea95d6a7e2495b0daa8
3
  size 4928480096
model-00010-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:3bf9cef18d5f41d5f56be374ccc0c12110886d17d9b8d4423b320a7faa0380df
3
  size 4928480096
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a3031b64f838672dbdf568b9a3f814592eb3cd4a2977de4340cfb0d85658e5d0
3
  size 4928480096
model-00011-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:9e05ebd14a039b27715283a306dbfebd750e7acfe120d29b1da515fb3d5fd134
3
  size 4676778952
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d709ea6ead46134675a22b96828799e9199fd7a5d0273edb8b146f22bbcef820
3
  size 4676778952
model-00012-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:39c13a73c28635b672877792189116d1c3e5574d535a0780f86fe47938361f6e
3
  size 2999075752
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:20266e24d359a471095e722dbc3886eb20458978b36dcf92002d3037b17066c9
3
  size 2999075752
model-00013-of-00013.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:c1e0c36f33095be599be50ecd9ce74dceceefe0b778e95c4a6c19e2587d8dda6
3
  size 3111649408
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:20e0498e852182d5c5357f2cc32e2ed72618b6aee98eb9c6d76d62fbe641baf5
3
  size 3111649408
modeling_qwen3.py DELETED
@@ -1,528 +0,0 @@
1
- # 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
2
- # This file was automatically generated from src/transformers/models/qwen3/modular_qwen3.py.
3
- # Do NOT edit this file manually as any edits will be overwritten by the generation of
4
- # the file from the modular. If any change should be done, please apply the change to the
5
- # modular_qwen3.py file directly. One of our CI enforces this.
6
- # 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
7
- # coding=utf-8
8
- # Copyright 2025 The Qwen team, Alibaba Group and the HuggingFace Inc. team. All rights reserved.
9
- #
10
- # Licensed under the Apache License, Version 2.0 (the "License");
11
- # you may not use this file except in compliance with the License.
12
- # You may obtain a copy of the License at
13
- #
14
- # http://www.apache.org/licenses/LICENSE-2.0
15
- #
16
- # Unless required by applicable law or agreed to in writing, software
17
- # distributed under the License is distributed on an "AS IS" BASIS,
18
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
- # See the License for the specific language governing permissions and
20
- # limitations under the License.
21
-
22
- from typing import Callable, Optional, Union
23
-
24
- import torch
25
- from torch import nn
26
-
27
- from ...activations import ACT2FN
28
- from ...cache_utils import Cache, DynamicCache
29
- from ...generation import GenerationMixin
30
- from ...integrations import use_kernel_forward_from_hub
31
- from ...masking_utils import create_causal_mask, create_sliding_window_causal_mask
32
- from ...modeling_flash_attention_utils import FlashAttentionKwargs
33
- from ...modeling_layers import (
34
- GenericForQuestionAnswering,
35
- GenericForSequenceClassification,
36
- GenericForTokenClassification,
37
- GradientCheckpointingLayer,
38
- )
39
- from ...modeling_outputs import BaseModelOutputWithPast, CausalLMOutputWithPast
40
- from ...modeling_rope_utils import ROPE_INIT_FUNCTIONS, dynamic_rope_update
41
- from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
42
- from ...processing_utils import Unpack
43
- from ...utils import TransformersKwargs, auto_docstring, can_return_tuple
44
- from ...utils.deprecation import deprecate_kwarg
45
- from ...utils.generic import check_model_inputs
46
- from .configuration_qwen3 import Qwen3Config
47
-
48
-
49
- @use_kernel_forward_from_hub("RMSNorm")
50
- class Qwen3RMSNorm(nn.Module):
51
- def __init__(self, hidden_size, eps: float = 1e-6) -> None:
52
- """
53
- Qwen3RMSNorm is equivalent to T5LayerNorm
54
- """
55
- super().__init__()
56
- self.weight = nn.Parameter(torch.ones(hidden_size))
57
- self.variance_epsilon = eps
58
-
59
- def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
60
- input_dtype = hidden_states.dtype
61
- hidden_states = hidden_states.to(torch.float32)
62
- variance = hidden_states.pow(2).mean(-1, keepdim=True)
63
- hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
64
- return self.weight * hidden_states.to(input_dtype)
65
-
66
- def extra_repr(self):
67
- return f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}"
68
-
69
-
70
- class Qwen3MLP(nn.Module):
71
- def __init__(self, config):
72
- super().__init__()
73
- self.config = config
74
- self.hidden_size = config.hidden_size
75
- self.intermediate_size = config.intermediate_size
76
- self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
77
- self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
78
- self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
79
- self.act_fn = ACT2FN[config.hidden_act]
80
-
81
- def forward(self, x):
82
- down_proj = self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
83
- return down_proj
84
-
85
-
86
- def rotate_half(x):
87
- """Rotates half the hidden dims of the input."""
88
- x1 = x[..., : x.shape[-1] // 2]
89
- x2 = x[..., x.shape[-1] // 2 :]
90
- return torch.cat((-x2, x1), dim=-1)
91
-
92
-
93
- def apply_rotary_pos_emb(q, k, cos, sin, position_ids=None, unsqueeze_dim=1):
94
- """Applies Rotary Position Embedding to the query and key tensors.
95
-
96
- Args:
97
- q (`torch.Tensor`): The query tensor.
98
- k (`torch.Tensor`): The key tensor.
99
- cos (`torch.Tensor`): The cosine part of the rotary embedding.
100
- sin (`torch.Tensor`): The sine part of the rotary embedding.
101
- position_ids (`torch.Tensor`, *optional*):
102
- Deprecated and unused.
103
- unsqueeze_dim (`int`, *optional*, defaults to 1):
104
- The 'unsqueeze_dim' argument specifies the dimension along which to unsqueeze cos[position_ids] and
105
- sin[position_ids] so that they can be properly broadcasted to the dimensions of q and k. For example, note
106
- that cos[position_ids] and sin[position_ids] have the shape [batch_size, seq_len, head_dim]. Then, if q and
107
- k have the shape [batch_size, heads, seq_len, head_dim], then setting unsqueeze_dim=1 makes
108
- cos[position_ids] and sin[position_ids] broadcastable to the shapes of q and k. Similarly, if q and k have
109
- the shape [batch_size, seq_len, heads, head_dim], then set unsqueeze_dim=2.
110
- Returns:
111
- `tuple(torch.Tensor)` comprising of the query and key tensors rotated using the Rotary Position Embedding.
112
- """
113
- cos = cos.unsqueeze(unsqueeze_dim)
114
- sin = sin.unsqueeze(unsqueeze_dim)
115
- q_embed = (q * cos) + (rotate_half(q) * sin)
116
- k_embed = (k * cos) + (rotate_half(k) * sin)
117
- return q_embed, k_embed
118
-
119
-
120
- def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
121
- """
122
- This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
123
- num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
124
- """
125
- batch, num_key_value_heads, slen, head_dim = hidden_states.shape
126
- if n_rep == 1:
127
- return hidden_states
128
- hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
129
- return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
130
-
131
-
132
- def eager_attention_forward(
133
- module: nn.Module,
134
- query: torch.Tensor,
135
- key: torch.Tensor,
136
- value: torch.Tensor,
137
- attention_mask: Optional[torch.Tensor],
138
- scaling: float,
139
- dropout: float = 0.0,
140
- **kwargs: Unpack[TransformersKwargs],
141
- ):
142
- key_states = repeat_kv(key, module.num_key_value_groups)
143
- value_states = repeat_kv(value, module.num_key_value_groups)
144
-
145
- attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
146
- if attention_mask is not None:
147
- causal_mask = attention_mask[:, :, :, : key_states.shape[-2]]
148
- attn_weights = attn_weights + causal_mask
149
-
150
- attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
151
- attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
152
- attn_output = torch.matmul(attn_weights, value_states)
153
- attn_output = attn_output.transpose(1, 2).contiguous()
154
-
155
- return attn_output, attn_weights
156
-
157
-
158
- class Qwen3Attention(nn.Module):
159
- """Multi-headed attention from 'Attention Is All You Need' paper"""
160
-
161
- def __init__(self, config: Qwen3Config, layer_idx: int):
162
- super().__init__()
163
- self.config = config
164
- self.layer_idx = layer_idx
165
- self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
166
- self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
167
- self.scaling = self.head_dim**-0.5
168
- self.attention_dropout = config.attention_dropout
169
- self.is_causal = True
170
-
171
- self.q_proj = nn.Linear(
172
- config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.attention_bias
173
- )
174
- self.k_proj = nn.Linear(
175
- config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
176
- )
177
- self.v_proj = nn.Linear(
178
- config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
179
- )
180
- self.o_proj = nn.Linear(
181
- config.num_attention_heads * self.head_dim, config.hidden_size, bias=config.attention_bias
182
- )
183
- self.q_norm = Qwen3RMSNorm(self.head_dim, eps=config.rms_norm_eps) # unlike olmo, only on the head dim!
184
- self.k_norm = Qwen3RMSNorm(self.head_dim, eps=config.rms_norm_eps) # thus post q_norm does not need reshape
185
- self.sliding_window = config.sliding_window if config.layer_types[layer_idx] == "sliding_attention" else None
186
-
187
- @deprecate_kwarg("past_key_value", new_name="past_key_values", version="4.58")
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
- cache_position: Optional[torch.LongTensor] = None,
195
- **kwargs: Unpack[FlashAttentionKwargs],
196
- ) -> tuple[torch.Tensor, Optional[torch.Tensor]]:
197
- input_shape = hidden_states.shape[:-1]
198
- hidden_shape = (*input_shape, -1, self.head_dim)
199
-
200
- query_states = self.q_norm(self.q_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
201
- key_states = self.k_norm(self.k_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
202
- value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
203
-
204
- cos, sin = position_embeddings
205
- query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
206
-
207
- if past_key_values is not None:
208
- # sin and cos are specific to RoPE models; cache_position needed for the static cache
209
- cache_kwargs = {"sin": sin, "cos": cos, "cache_position": cache_position}
210
- key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx, cache_kwargs)
211
-
212
- attention_interface: Callable = eager_attention_forward
213
- if self.config._attn_implementation != "eager":
214
- attention_interface = ALL_ATTENTION_FUNCTIONS[self.config._attn_implementation]
215
-
216
- attn_output, attn_weights = attention_interface(
217
- self,
218
- query_states,
219
- key_states,
220
- value_states,
221
- attention_mask,
222
- dropout=0.0 if not self.training else self.attention_dropout,
223
- scaling=self.scaling,
224
- sliding_window=self.sliding_window, # diff with Llama
225
- **kwargs,
226
- )
227
-
228
- attn_output = attn_output.reshape(*input_shape, -1).contiguous()
229
- attn_output = self.o_proj(attn_output)
230
- return attn_output, attn_weights
231
-
232
-
233
- class Qwen3DecoderLayer(GradientCheckpointingLayer):
234
- def __init__(self, config: Qwen3Config, layer_idx: int):
235
- super().__init__()
236
- self.hidden_size = config.hidden_size
237
-
238
- self.self_attn = Qwen3Attention(config=config, layer_idx=layer_idx)
239
-
240
- self.mlp = Qwen3MLP(config)
241
- self.input_layernorm = Qwen3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
242
- self.post_attention_layernorm = Qwen3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
243
- self.attention_type = config.layer_types[layer_idx]
244
-
245
- @deprecate_kwarg("past_key_value", new_name="past_key_values", version="4.58")
246
- def forward(
247
- self,
248
- hidden_states: torch.Tensor,
249
- attention_mask: Optional[torch.Tensor] = None,
250
- position_ids: Optional[torch.LongTensor] = None,
251
- past_key_values: Optional[Cache] = None,
252
- use_cache: Optional[bool] = False,
253
- cache_position: Optional[torch.LongTensor] = None,
254
- position_embeddings: Optional[tuple[torch.Tensor, torch.Tensor]] = None, # necessary, but kept here for BC
255
- **kwargs: Unpack[TransformersKwargs],
256
- ) -> torch.Tensor:
257
- residual = hidden_states
258
- hidden_states = self.input_layernorm(hidden_states)
259
- # Self Attention
260
- hidden_states, _ = self.self_attn(
261
- hidden_states=hidden_states,
262
- attention_mask=attention_mask,
263
- position_ids=position_ids,
264
- past_key_values=past_key_values,
265
- use_cache=use_cache,
266
- cache_position=cache_position,
267
- position_embeddings=position_embeddings,
268
- **kwargs,
269
- )
270
- hidden_states = residual + hidden_states
271
-
272
- # Fully Connected
273
- residual = hidden_states
274
- hidden_states = self.post_attention_layernorm(hidden_states)
275
- hidden_states = self.mlp(hidden_states)
276
- hidden_states = residual + hidden_states
277
- return hidden_states
278
-
279
-
280
- @auto_docstring
281
- class Qwen3PreTrainedModel(PreTrainedModel):
282
- config: Qwen3Config
283
- base_model_prefix = "model"
284
- supports_gradient_checkpointing = True
285
- _no_split_modules = ["Qwen3DecoderLayer"]
286
- _skip_keys_device_placement = ["past_key_values"]
287
- _supports_flash_attn = True
288
- _supports_sdpa = True
289
- _supports_flex_attn = True
290
-
291
- _can_compile_fullgraph = True
292
- _supports_attention_backend = True
293
- _can_record_outputs = {
294
- "hidden_states": Qwen3DecoderLayer,
295
- "attentions": Qwen3Attention,
296
- }
297
-
298
-
299
- class Qwen3RotaryEmbedding(nn.Module):
300
- inv_freq: torch.Tensor # fix linting for `register_buffer`
301
-
302
- def __init__(self, config: Qwen3Config, device=None):
303
- super().__init__()
304
- # BC: "rope_type" was originally "type"
305
- if hasattr(config, "rope_scaling") and isinstance(config.rope_scaling, dict):
306
- self.rope_type = config.rope_scaling.get("rope_type", config.rope_scaling.get("type"))
307
- else:
308
- self.rope_type = "default"
309
- self.max_seq_len_cached = config.max_position_embeddings
310
- self.original_max_seq_len = config.max_position_embeddings
311
-
312
- self.config = config
313
- self.rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
314
-
315
- inv_freq, self.attention_scaling = self.rope_init_fn(self.config, device)
316
- self.register_buffer("inv_freq", inv_freq, persistent=False)
317
- self.original_inv_freq = self.inv_freq
318
-
319
- @torch.no_grad()
320
- @dynamic_rope_update # power user: used with advanced RoPE types (e.g. dynamic rope)
321
- def forward(self, x, position_ids):
322
- inv_freq_expanded = self.inv_freq[None, :, None].float().expand(position_ids.shape[0], -1, 1).to(x.device)
323
- position_ids_expanded = position_ids[:, None, :].float()
324
-
325
- device_type = x.device.type if isinstance(x.device.type, str) and x.device.type != "mps" else "cpu"
326
- with torch.autocast(device_type=device_type, enabled=False): # Force float32
327
- freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(1, 2)
328
- emb = torch.cat((freqs, freqs), dim=-1)
329
- cos = emb.cos() * self.attention_scaling
330
- sin = emb.sin() * self.attention_scaling
331
-
332
- return cos.to(dtype=x.dtype), sin.to(dtype=x.dtype)
333
-
334
-
335
- @auto_docstring
336
- class Qwen3Model(Qwen3PreTrainedModel):
337
- def __init__(self, config: Qwen3Config):
338
- super().__init__(config)
339
- self.padding_idx = config.pad_token_id
340
- self.vocab_size = config.vocab_size
341
-
342
- self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
343
- self.layers = nn.ModuleList(
344
- [Qwen3DecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
345
- )
346
- self.norm = Qwen3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
347
- self.rotary_emb = Qwen3RotaryEmbedding(config=config)
348
- self.gradient_checkpointing = False
349
- self.has_sliding_layers = "sliding_attention" in self.config.layer_types
350
-
351
- # Initialize weights and apply final processing
352
- self.post_init()
353
-
354
- @check_model_inputs
355
- @auto_docstring
356
- def forward(
357
- self,
358
- input_ids: Optional[torch.LongTensor] = None,
359
- attention_mask: Optional[torch.Tensor] = None,
360
- position_ids: Optional[torch.LongTensor] = None,
361
- past_key_values: Optional[Cache] = None,
362
- inputs_embeds: Optional[torch.FloatTensor] = None,
363
- use_cache: Optional[bool] = None,
364
- cache_position: Optional[torch.LongTensor] = None,
365
- **kwargs: Unpack[TransformersKwargs],
366
- ) -> BaseModelOutputWithPast:
367
- if (input_ids is None) ^ (inputs_embeds is not None):
368
- raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
369
-
370
- if inputs_embeds is None:
371
- inputs_embeds = self.embed_tokens(input_ids)
372
-
373
- if use_cache and past_key_values is None:
374
- past_key_values = DynamicCache(config=self.config)
375
-
376
- if cache_position is None:
377
- past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
378
- cache_position = torch.arange(
379
- past_seen_tokens, past_seen_tokens + inputs_embeds.shape[1], device=inputs_embeds.device
380
- )
381
-
382
- if position_ids is None:
383
- position_ids = cache_position.unsqueeze(0)
384
-
385
- # It may already have been prepared by e.g. `generate`
386
- if not isinstance(causal_mask_mapping := attention_mask, dict):
387
- # Prepare mask arguments
388
- mask_kwargs = {
389
- "config": self.config,
390
- "input_embeds": inputs_embeds,
391
- "attention_mask": attention_mask,
392
- "cache_position": cache_position,
393
- "past_key_values": past_key_values,
394
- "position_ids": position_ids,
395
- }
396
- # Create the masks
397
- causal_mask_mapping = {
398
- "full_attention": create_causal_mask(**mask_kwargs),
399
- }
400
- # The sliding window alternating layers are not always activated depending on the config
401
- if self.has_sliding_layers:
402
- causal_mask_mapping["sliding_attention"] = create_sliding_window_causal_mask(**mask_kwargs)
403
-
404
- hidden_states = inputs_embeds
405
-
406
- # create position embeddings to be shared across the decoder layers
407
- position_embeddings = self.rotary_emb(hidden_states, position_ids)
408
-
409
- for decoder_layer in self.layers[: self.config.num_hidden_layers]:
410
- hidden_states = decoder_layer(
411
- hidden_states,
412
- attention_mask=causal_mask_mapping[decoder_layer.attention_type],
413
- position_ids=position_ids,
414
- past_key_values=past_key_values,
415
- use_cache=use_cache,
416
- cache_position=cache_position,
417
- position_embeddings=position_embeddings,
418
- **kwargs,
419
- )
420
-
421
- hidden_states = self.norm(hidden_states)
422
- return BaseModelOutputWithPast(
423
- last_hidden_state=hidden_states,
424
- past_key_values=past_key_values if use_cache else None,
425
- )
426
-
427
-
428
- @auto_docstring
429
- class Qwen3ForCausalLM(Qwen3PreTrainedModel, GenerationMixin):
430
- _tied_weights_keys = ["lm_head.weight"]
431
- _tp_plan = {"lm_head": "colwise_rep"}
432
- _pp_plan = {"lm_head": (["hidden_states"], ["logits"])}
433
-
434
- def __init__(self, config):
435
- super().__init__(config)
436
- self.model = Qwen3Model(config)
437
- self.vocab_size = config.vocab_size
438
- self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
439
-
440
- # Initialize weights and apply final processing
441
- self.post_init()
442
-
443
- @can_return_tuple
444
- @auto_docstring
445
- def forward(
446
- self,
447
- input_ids: Optional[torch.LongTensor] = None,
448
- attention_mask: Optional[torch.Tensor] = None,
449
- position_ids: Optional[torch.LongTensor] = None,
450
- past_key_values: Optional[Cache] = None,
451
- inputs_embeds: Optional[torch.FloatTensor] = None,
452
- labels: Optional[torch.LongTensor] = None,
453
- use_cache: Optional[bool] = None,
454
- cache_position: Optional[torch.LongTensor] = None,
455
- logits_to_keep: Union[int, torch.Tensor] = 0,
456
- **kwargs: Unpack[TransformersKwargs],
457
- ) -> CausalLMOutputWithPast:
458
- r"""
459
- labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
460
- Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
461
- config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
462
- (masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
463
-
464
- Example:
465
-
466
- ```python
467
- >>> from transformers import AutoTokenizer, Qwen3ForCausalLM
468
-
469
- >>> model = Qwen3ForCausalLM.from_pretrained("Qwen/Qwen3-8B")
470
- >>> tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-8B")
471
-
472
- >>> prompt = "Hey, are you conscious? Can you talk to me?"
473
- >>> inputs = tokenizer(prompt, return_tensors="pt")
474
-
475
- >>> # Generate
476
- >>> generate_ids = model.generate(inputs.input_ids, max_length=30)
477
- >>> tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
478
- "Hey, are you conscious? Can you talk to me?\nI'm not conscious, but I can talk to you."
479
- ```"""
480
- outputs: BaseModelOutputWithPast = self.model(
481
- input_ids=input_ids,
482
- attention_mask=attention_mask,
483
- position_ids=position_ids,
484
- past_key_values=past_key_values,
485
- inputs_embeds=inputs_embeds,
486
- use_cache=use_cache,
487
- cache_position=cache_position,
488
- **kwargs,
489
- )
490
-
491
- hidden_states = outputs.last_hidden_state
492
- # Only compute necessary logits, and do not upcast them to float if we are not computing the loss
493
- slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
494
- logits = self.lm_head(hidden_states[:, slice_indices, :])
495
-
496
- loss = None
497
- if labels is not None:
498
- loss = self.loss_function(logits=logits, labels=labels, vocab_size=self.config.vocab_size, **kwargs)
499
-
500
- return CausalLMOutputWithPast(
501
- loss=loss,
502
- logits=logits,
503
- past_key_values=outputs.past_key_values,
504
- hidden_states=outputs.hidden_states,
505
- attentions=outputs.attentions,
506
- )
507
-
508
-
509
- class Qwen3ForSequenceClassification(GenericForSequenceClassification, Qwen3PreTrainedModel):
510
- pass
511
-
512
-
513
- class Qwen3ForTokenClassification(GenericForTokenClassification, Qwen3PreTrainedModel):
514
- pass
515
-
516
-
517
- class Qwen3ForQuestionAnswering(GenericForQuestionAnswering, Qwen3PreTrainedModel):
518
- base_model_prefix = "transformer" # For BC, where `transformer` was used instead of `model`
519
-
520
-
521
- __all__ = [
522
- "Qwen3ForCausalLM",
523
- "Qwen3ForQuestionAnswering",
524
- "Qwen3PreTrainedModel",
525
- "Qwen3Model",
526
- "Qwen3ForSequenceClassification",
527
- "Qwen3ForTokenClassification",
528
- ]