Dragonhead commited on
Commit
e37cf48
·
verified ·
1 Parent(s): ea262c4

Release full-precision weights: bf16 safetensors + Transformers code under transformers/ (Qwen3-ASR arch, trust_remote_code)

Browse files
transformers/__init__.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2026 The Alibaba Qwen team.
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ from .configuration_audar_asr import Qwen3ASRConfig
17
+ from .modeling_audar_asr import Qwen3ASRForConditionalGeneration
18
+ from .processing_audar_asr import Qwen3ASRProcessor
transformers/added_tokens.json ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "</think>": 151668,
3
+ "</tool_call>": 151658,
4
+ "</tool_response>": 151666,
5
+ "<asr_text>": 151704,
6
+ "<blank10>": 151686,
7
+ "<blank11>": 151687,
8
+ "<blank12>": 151688,
9
+ "<blank13>": 151689,
10
+ "<blank14>": 151690,
11
+ "<blank15>": 151691,
12
+ "<blank16>": 151692,
13
+ "<blank17>": 151693,
14
+ "<blank18>": 151694,
15
+ "<blank19>": 151695,
16
+ "<blank1>": 151677,
17
+ "<blank20>": 151696,
18
+ "<blank21>": 151697,
19
+ "<blank22>": 151698,
20
+ "<blank23>": 151699,
21
+ "<blank24>": 151700,
22
+ "<blank25>": 151701,
23
+ "<blank26>": 151702,
24
+ "<blank27>": 151703,
25
+ "<blank2>": 151678,
26
+ "<blank3>": 151679,
27
+ "<blank4>": 151680,
28
+ "<blank5>": 151681,
29
+ "<blank6>": 151682,
30
+ "<blank7>": 151683,
31
+ "<blank8>": 151684,
32
+ "<blank9>": 151685,
33
+ "<non_speech>": 151675,
34
+ "<think>": 151667,
35
+ "<tool_call>": 151657,
36
+ "<tool_response>": 151665,
37
+ "<tts_pad>": 151671,
38
+ "<tts_text_bos>": 151672,
39
+ "<tts_text_bos_single>": 151674,
40
+ "<tts_text_eod>": 151673,
41
+ "<|acm|>": 151710,
42
+ "<|aeb|>": 151711,
43
+ "<|apc|>": 151709,
44
+ "<|arb|>": 151705,
45
+ "<|arq|>": 151712,
46
+ "<|ars|>": 151707,
47
+ "<|ary|>": 151706,
48
+ "<|arz|>": 151708,
49
+ "<|audio_end|>": 151670,
50
+ "<|audio_pad|>": 151676,
51
+ "<|audio_start|>": 151669,
52
+ "<|box_end|>": 151649,
53
+ "<|box_start|>": 151648,
54
+ "<|endoftext|>": 151643,
55
+ "<|file_sep|>": 151664,
56
+ "<|fim_middle|>": 151660,
57
+ "<|fim_pad|>": 151662,
58
+ "<|fim_prefix|>": 151659,
59
+ "<|fim_suffix|>": 151661,
60
+ "<|im_end|>": 151645,
61
+ "<|im_start|>": 151644,
62
+ "<|image_pad|>": 151655,
63
+ "<|object_ref_end|>": 151647,
64
+ "<|object_ref_start|>": 151646,
65
+ "<|quad_end|>": 151651,
66
+ "<|quad_start|>": 151650,
67
+ "<|repo_name|>": 151663,
68
+ "<|video_pad|>": 151656,
69
+ "<|vision_end|>": 151653,
70
+ "<|vision_pad|>": 151654,
71
+ "<|vision_start|>": 151652
72
+ }
transformers/chat_template.jinja ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- set ns = namespace(system_text="") -%}
2
+ {%- for m in messages -%}
3
+ {%- if m.role == 'system' -%}
4
+ {%- if m.content is string -%}
5
+ {%- set ns.system_text = ns.system_text + m.content -%}
6
+ {%- else -%}
7
+ {%- for c in m.content -%}
8
+ {%- if c.type == 'text' and (c.text is defined) -%}
9
+ {%- set ns.system_text = ns.system_text + c.text -%}
10
+ {%- endif -%}
11
+ {%- endfor -%}
12
+ {%- endif -%}
13
+ {%- endif -%}
14
+ {%- endfor -%}
15
+
16
+ {%- set ns2 = namespace(audio_tokens="") -%}
17
+ {%- for m in messages -%}
18
+ {%- if m.content is not string -%}
19
+ {%- for c in m.content -%}
20
+ {%- if c.type == 'audio' or ('audio' in c) or ('audio_url' in c) -%}
21
+ {%- set ns2.audio_tokens = ns2.audio_tokens + "<|audio_start|><|audio_pad|><|audio_end|>" -%}
22
+ {%- endif -%}
23
+ {%- endfor -%}
24
+ {%- endif -%}
25
+ {%- endfor -%}
26
+
27
+ {{- '<|im_start|>system\n' + (ns.system_text if ns.system_text is string else '') + '<|im_end|>\n' -}}
28
+ {{- '<|im_start|>user\n' + ns2.audio_tokens + '<|im_end|>\n' -}}
29
+ {%- if add_generation_prompt -%}
30
+ {{- '<|im_start|>assistant\n' -}}
31
+ {%- endif -%}
transformers/chat_template.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"chat_template": "{%- set ns = namespace(system_text=\"\") -%}\n{%- for m in messages -%}\n {%- if m.role == 'system' -%}\n {%- if m.content is string -%}\n {%- set ns.system_text = ns.system_text + m.content -%}\n {%- else -%}\n {%- for c in m.content -%}\n {%- if c.type == 'text' and (c.text is defined) -%}\n {%- set ns.system_text = ns.system_text + c.text -%}\n {%- endif -%}\n {%- endfor -%}\n {%- endif -%}\n {%- endif -%}\n{%- endfor -%}\n\n{%- set ns2 = namespace(audio_tokens=\"\") -%}\n{%- for m in messages -%}\n {%- if m.content is not string -%}\n {%- for c in m.content -%}\n {%- if c.type == 'audio' or ('audio' in c) or ('audio_url' in c) -%}\n {%- set ns2.audio_tokens = ns2.audio_tokens + \"<|audio_start|><|audio_pad|><|audio_end|>\" -%}\n {%- endif -%}\n {%- endfor -%}\n {%- endif -%}\n{%- endfor -%}\n\n{{- '<|im_start|>system\\n' + (ns.system_text if ns.system_text is string else '') + '<|im_end|>\\n' -}}\n{{- '<|im_start|>user\\n' + ns2.audio_tokens + '<|im_end|>\\n' -}}\n{%- if add_generation_prompt -%}\n{{- '<|im_start|>assistant\\n' -}}\n{%- endif -%}"}
transformers/config.json ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Qwen3ASRForConditionalGeneration"
4
+ ],
5
+ "dtype": "bfloat16",
6
+ "eos_token_id": 151645,
7
+ "hidden_size": 2048,
8
+ "keys_to_ignore_at_inference": [
9
+ "past_key_values"
10
+ ],
11
+ "model_type": "qwen3_asr",
12
+ "pad_token_id": 151643,
13
+ "support_languages": [
14
+ "Chinese",
15
+ "English",
16
+ "Cantonese",
17
+ "Arabic",
18
+ "German",
19
+ "French",
20
+ "Spanish",
21
+ "Portuguese",
22
+ "Indonesian",
23
+ "Italian",
24
+ "Korean",
25
+ "Russian",
26
+ "Thai",
27
+ "Vietnamese",
28
+ "Japanese",
29
+ "Turkish",
30
+ "Hindi",
31
+ "Malay",
32
+ "Dutch",
33
+ "Swedish",
34
+ "Danish",
35
+ "Finnish",
36
+ "Polish",
37
+ "Czech",
38
+ "Filipino",
39
+ "Persian",
40
+ "Greek",
41
+ "Romanian",
42
+ "Hungarian",
43
+ "Macedonian"
44
+ ],
45
+ "thinker_config": {
46
+ "architectures": [
47
+ "Qwen3ASRForConditionalGeneration"
48
+ ],
49
+ "audio_config": {
50
+ "_name_or_path": "",
51
+ "activation_dropout": 0,
52
+ "activation_function": "gelu",
53
+ "add_cross_attention": false,
54
+ "architectures": null,
55
+ "attention_dropout": 0,
56
+ "bad_words_ids": null,
57
+ "begin_suppress_tokens": null,
58
+ "bos_token_id": null,
59
+ "chunk_size_feed_forward": 0,
60
+ "conv_chunksize": 500,
61
+ "cross_attention_hidden_size": null,
62
+ "d_model": 1024,
63
+ "decoder_start_token_id": null,
64
+ "diversity_penalty": 0.0,
65
+ "do_sample": false,
66
+ "downsample_hidden_size": 480,
67
+ "dropout": 0,
68
+ "dtype": "bfloat16",
69
+ "early_stopping": false,
70
+ "encoder_attention_heads": 16,
71
+ "encoder_ffn_dim": 4096,
72
+ "encoder_layers": 24,
73
+ "encoder_no_repeat_ngram_size": 0,
74
+ "eos_token_id": null,
75
+ "exponential_decay_length_penalty": null,
76
+ "finetuning_task": null,
77
+ "forced_bos_token_id": null,
78
+ "forced_eos_token_id": null,
79
+ "id2label": {
80
+ "0": "LABEL_0",
81
+ "1": "LABEL_1"
82
+ },
83
+ "initializer_range": 0.02,
84
+ "is_decoder": false,
85
+ "is_encoder_decoder": false,
86
+ "label2id": {
87
+ "LABEL_0": 0,
88
+ "LABEL_1": 1
89
+ },
90
+ "length_penalty": 1.0,
91
+ "max_length": 20,
92
+ "max_source_positions": 1500,
93
+ "min_length": 0,
94
+ "model_type": "qwen3_asr_audio_encoder",
95
+ "n_window": 50,
96
+ "n_window_infer": 800,
97
+ "no_repeat_ngram_size": 0,
98
+ "num_beam_groups": 1,
99
+ "num_beams": 1,
100
+ "num_hidden_layers": 24,
101
+ "num_mel_bins": 128,
102
+ "num_return_sequences": 1,
103
+ "output_attentions": false,
104
+ "output_dim": 2048,
105
+ "output_hidden_states": false,
106
+ "output_scores": false,
107
+ "pad_token_id": null,
108
+ "prefix": null,
109
+ "problem_type": null,
110
+ "pruned_heads": {},
111
+ "remove_invalid_values": false,
112
+ "repetition_penalty": 1.0,
113
+ "return_dict": true,
114
+ "return_dict_in_generate": false,
115
+ "scale_embedding": false,
116
+ "sep_token_id": null,
117
+ "suppress_tokens": null,
118
+ "task_specific_params": null,
119
+ "temperature": 1.0,
120
+ "tf_legacy_loss": false,
121
+ "tie_encoder_decoder": false,
122
+ "tie_word_embeddings": false,
123
+ "tokenizer_class": null,
124
+ "top_k": 50,
125
+ "top_p": 1.0,
126
+ "torchscript": false,
127
+ "typical_p": 1.0,
128
+ "use_bfloat16": false
129
+ },
130
+ "audio_end_token_id": 151670,
131
+ "audio_start_token_id": 151669,
132
+ "audio_token_id": 151676,
133
+ "dtype": "bfloat16",
134
+ "initializer_range": 0.02,
135
+ "model_type": "qwen3_asr_thinker",
136
+ "text_config": {
137
+ "_name_or_path": "",
138
+ "add_cross_attention": false,
139
+ "architectures": null,
140
+ "attention_bias": false,
141
+ "attention_dropout": 0.0,
142
+ "bad_words_ids": null,
143
+ "begin_suppress_tokens": null,
144
+ "bos_token_id": null,
145
+ "chunk_size_feed_forward": 0,
146
+ "cross_attention_hidden_size": null,
147
+ "decoder_start_token_id": null,
148
+ "diversity_penalty": 0.0,
149
+ "do_sample": false,
150
+ "dtype": "bfloat16",
151
+ "early_stopping": false,
152
+ "encoder_no_repeat_ngram_size": 0,
153
+ "eos_token_id": null,
154
+ "exponential_decay_length_penalty": null,
155
+ "finetuning_task": null,
156
+ "forced_bos_token_id": null,
157
+ "forced_eos_token_id": null,
158
+ "head_dim": 128,
159
+ "hidden_act": "silu",
160
+ "hidden_size": 2048,
161
+ "id2label": {
162
+ "0": "LABEL_0",
163
+ "1": "LABEL_1"
164
+ },
165
+ "initializer_range": 0.02,
166
+ "intermediate_size": 6144,
167
+ "is_decoder": false,
168
+ "is_encoder_decoder": false,
169
+ "label2id": {
170
+ "LABEL_0": 0,
171
+ "LABEL_1": 1
172
+ },
173
+ "length_penalty": 1.0,
174
+ "max_length": 20,
175
+ "max_position_embeddings": 65536,
176
+ "min_length": 0,
177
+ "model_type": "qwen3_asr_text",
178
+ "no_repeat_ngram_size": 0,
179
+ "num_attention_heads": 16,
180
+ "num_beam_groups": 1,
181
+ "num_beams": 1,
182
+ "num_hidden_layers": 28,
183
+ "num_key_value_heads": 8,
184
+ "num_return_sequences": 1,
185
+ "output_attentions": false,
186
+ "output_hidden_states": false,
187
+ "output_scores": false,
188
+ "pad_token_id": 151643,
189
+ "prefix": null,
190
+ "problem_type": null,
191
+ "pruned_heads": {},
192
+ "remove_invalid_values": false,
193
+ "repetition_penalty": 1.0,
194
+ "return_dict": true,
195
+ "return_dict_in_generate": false,
196
+ "rms_norm_eps": 1e-06,
197
+ "rope_scaling": {
198
+ "interleaved": true,
199
+ "mrope_interleaved": true,
200
+ "mrope_section": [
201
+ 24,
202
+ 20,
203
+ 20
204
+ ],
205
+ "rope_type": "default",
206
+ "type": "default"
207
+ },
208
+ "rope_theta": 1000000,
209
+ "sep_token_id": null,
210
+ "suppress_tokens": null,
211
+ "task_specific_params": null,
212
+ "temperature": 1.0,
213
+ "tf_legacy_loss": false,
214
+ "tie_encoder_decoder": false,
215
+ "tie_word_embeddings": false,
216
+ "tokenizer_class": null,
217
+ "top_k": 50,
218
+ "top_p": 1.0,
219
+ "torchscript": false,
220
+ "typical_p": 1.0,
221
+ "use_bfloat16": false,
222
+ "use_cache": true,
223
+ "vocab_size": 151936
224
+ },
225
+ "user_token_id": 872
226
+ },
227
+ "transformers_version": "4.57.6",
228
+ "auto_map": {
229
+ "AutoConfig": "configuration_audar_asr.Qwen3ASRConfig",
230
+ "AutoModel": "modeling_audar_asr.Qwen3ASRForConditionalGeneration",
231
+ "AutoModelForCausalLM": "modeling_audar_asr.Qwen3ASRForConditionalGeneration",
232
+ "AutoProcessor": "processing_audar_asr.Qwen3ASRProcessor"
233
+ }
234
+ }
transformers/configuration_audar_asr.py ADDED
@@ -0,0 +1,425 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2026 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
+ from transformers.configuration_utils import PretrainedConfig
16
+ from transformers.utils import logging
17
+
18
+
19
+ logger = logging.get_logger(__name__)
20
+
21
+
22
+ class Qwen3ASRAudioEncoderConfig(PretrainedConfig):
23
+ r"""
24
+ This is the configuration class to store the configuration of a [`Qwen3ASRAudioEncoder`]. It is used to instantiate a
25
+ Qwen3-ASR audio encoder according to the specified arguments, defining the model architecture. Instantiating a
26
+ configuration with the defaults will yield a similar configuration to that of the audio encoder of the Qwen2-Audio
27
+ architecture.
28
+
29
+ e.g. [Qwen/Qwen3-ASR-1.7B](https://huggingface.co/Qwen/Qwen3-ASR-1.7B)
30
+
31
+ Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
32
+ documentation from [`PretrainedConfig`] for more information.
33
+
34
+ Args:
35
+ num_mel_bins (`int`, *optional*, defaults to 128):
36
+ Number of mel features used per input features. Should correspond to the value used in the
37
+ `Qwen3ASRProcessor` class.
38
+ encoder_layers (`int`, *optional*, defaults to 32):
39
+ Number of encoder layers.
40
+ encoder_attention_heads (`int`, *optional*, defaults to 20):
41
+ Number of attention heads for each attention layer in the Transformer encoder.
42
+ encoder_ffn_dim (`int`, *optional*, defaults to 5120):
43
+ Dimensionality of the "intermediate" (often named feed-forward) layer in encoder.
44
+ d_model (`int`, *optional*, defaults to 1280):
45
+ Dimensionality of the layers.
46
+ dropout (`float`, *optional*, defaults to 0.0):
47
+ The dropout probability for all fully connected layers in the embeddings, encoder, and pooler.
48
+ attention_dropout (`float`, *optional*, defaults to 0.0):
49
+ The dropout ratio for the attention probabilities.
50
+ activation_function (`str`, *optional*, defaults to `"gelu"`):
51
+ The non-linear activation function (function or string) in the encoder and pooler. If string, `"gelu"`,
52
+ `"relu"`, `"silu"` and `"gelu_new"` are supported.
53
+ activation_dropout (`float`, *optional*, defaults to 0.0):
54
+ The dropout ratio for activations inside the fully connected layer.
55
+ scale_embedding (`bool`, *optional*, defaults to `False`):
56
+ Scale embeddings by diving by sqrt(d_model).
57
+ initializer_range (`float`, *optional*, defaults to 0.02):
58
+ The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
59
+ max_source_positions (`int`, *optional*, defaults to 1500):
60
+ The maximum sequence length of log-mel filter-bank features that this model might ever be used with.
61
+ n_window (`int`, *optional*, defaults to 100):
62
+ The chunk for conv and flash attn in AudioEncoder.
63
+ output_dim (`int`, *optional*, defaults to 3584):
64
+ The output dimension of AudioEncoder.
65
+
66
+ Example:
67
+
68
+ ```python
69
+ >>> from transformers import Qwen3ASRAudioEncoderConfig, Qwen3ASRAudioEncoder
70
+
71
+ >>> # Initializing a Qwen3ASRAudioEncoderConfig
72
+ >>> configuration = Qwen3ASRAudioEncoderConfig()
73
+
74
+ >>> # Initializing a Qwen3ASRAudioEncoder (with random weights)
75
+ >>> model = Qwen3ASRAudioEncoder(configuration)
76
+
77
+ >>> # Accessing the model configuration
78
+ >>> configuration = model.config
79
+ ```"""
80
+
81
+ model_type = "qwen3_asr_audio_encoder"
82
+
83
+ def __init__(
84
+ self,
85
+ num_mel_bins=128,
86
+ encoder_layers=32,
87
+ encoder_attention_heads=20,
88
+ encoder_ffn_dim=5120,
89
+ d_model=1280,
90
+ dropout=0,
91
+ attention_dropout=0,
92
+ activation_function="gelu",
93
+ activation_dropout=0,
94
+ scale_embedding=False,
95
+ initializer_range=0.02,
96
+ max_source_positions=1500,
97
+ n_window=100,
98
+ output_dim=3584,
99
+ n_window_infer=400,
100
+ conv_chunksize=500,
101
+ downsample_hidden_size=480,
102
+ **kwargs,
103
+ ):
104
+ super().__init__(**kwargs)
105
+
106
+ self.num_mel_bins = num_mel_bins
107
+ self.d_model = d_model
108
+ self.encoder_layers = encoder_layers
109
+ self.encoder_attention_heads = encoder_attention_heads
110
+ self.encoder_ffn_dim = encoder_ffn_dim
111
+ self.dropout = dropout
112
+ self.attention_dropout = attention_dropout
113
+ self.activation_function = activation_function
114
+ self.activation_dropout = activation_dropout
115
+ self.num_hidden_layers = encoder_layers
116
+ self.initializer_range = initializer_range
117
+ self.scale_embedding = scale_embedding # scale factor will be sqrt(d_model) if True
118
+ self.max_source_positions = max_source_positions
119
+ self.n_window = n_window
120
+ self.output_dim = output_dim
121
+ self.n_window_infer = n_window_infer
122
+ self.conv_chunksize = conv_chunksize
123
+ self.downsample_hidden_size = downsample_hidden_size
124
+
125
+
126
+ class Qwen3ASRTextConfig(PretrainedConfig):
127
+ r"""
128
+ This is the configuration class to store the configuration of a [`Qwen3ASRTextModel`]. It is used to instantiate a
129
+ Qwen3-ASR model according to the specified arguments, defining the model architecture. Instantiating a configuration
130
+ with the defaults will yield a similar configuration to that of
131
+ Qwen3-ASR-1.7B [Qwen/Qwen3-ASR-1.7B](https://huggingface.co/Qwen/Qwen3-ASR-1.7B)
132
+
133
+ Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
134
+ documentation from [`PretrainedConfig`] for more information.
135
+
136
+ Args:
137
+ vocab_size (`int`, *optional*, defaults to 151936):
138
+ Vocabulary size of the Qwen3ASR model. Defines the number of different tokens that can be represented by the
139
+ `inputs_ids` passed when calling [`Qwen3ASRModel`]
140
+ hidden_size (`int`, *optional*, defaults to 4096):
141
+ Dimension of the hidden representations.
142
+ intermediate_size (`int`, *optional*, defaults to 22016):
143
+ Dimension of the MLP representations.
144
+ num_hidden_layers (`int`, *optional*, defaults to 32):
145
+ Number of hidden layers in the Transformer encoder.
146
+ num_attention_heads (`int`, *optional*, defaults to 32):
147
+ Number of attention heads for each attention layer in the Transformer encoder.
148
+ num_key_value_heads (`int`, *optional*, defaults to 32):
149
+ This is the number of key_value heads that should be used to implement Grouped Query Attention. If
150
+ `num_key_value_heads=num_attention_heads`, the model will use Multi Head Attention (MHA), if
151
+ `num_key_value_heads=1` the model will use Multi Query Attention (MQA) otherwise GQA is used. When
152
+ converting a multi-head checkpoint to a GQA checkpoint, each group key and value head should be constructed
153
+ by meanpooling all the original heads within that group. For more details, check out [this
154
+ paper](https://huggingface.co/papers/2305.13245). If it is not specified, will default to `32`.
155
+ head_dim (`int`, *optional*, defaults to 128):
156
+ The dimension of the head. If not specified, will default to `hidden_size // num_attention_heads`.
157
+ hidden_act (`str` or `function`, *optional*, defaults to `"silu"`):
158
+ The non-linear activation function (function or string) in the decoder.
159
+ max_position_embeddings (`int`, *optional*, defaults to 128000):
160
+ The maximum sequence length that this model might ever be used with.
161
+ initializer_range (`float`, *optional*, defaults to 0.02):
162
+ The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
163
+ rms_norm_eps (`float`, *optional*, defaults to 1e-06):
164
+ The epsilon used by the rms normalization layers.
165
+ use_cache (`bool`, *optional*, defaults to `True`):
166
+ Whether or not the model should return the last key/values attentions (not used by all models). Only
167
+ relevant if `config.is_decoder=True`.
168
+ tie_word_embeddings (`bool`, *optional*, defaults to `False`):
169
+ Whether the model's input and output word embeddings should be tied.
170
+ rope_theta (`float`, *optional*, defaults to 5000000.0):
171
+ The base period of the RoPE embeddings.
172
+ rope_scaling (`Dict`, *optional*):
173
+ Dictionary containing the scaling configuration for the RoPE embeddings. NOTE: if you apply new rope type
174
+ and you expect the model to work on longer `max_position_embeddings`, we recommend you to update this value
175
+ accordingly.
176
+ Expected contents:
177
+ `rope_type` (`str`):
178
+ The sub-variant of RoPE to use. Can be one of ['default', 'linear', 'dynamic', 'yarn', 'longrope',
179
+ 'llama3'], with 'default' being the original RoPE implementation.
180
+ `factor` (`float`, *optional*):
181
+ Used with all rope types except 'default'. The scaling factor to apply to the RoPE embeddings. In
182
+ most scaling types, a `factor` of x will enable the model to handle sequences of length x *
183
+ original maximum pre-trained length.
184
+ `original_max_position_embeddings` (`int`, *optional*):
185
+ Used with 'dynamic', 'longrope' and 'llama3'. The original max position embeddings used during
186
+ pretraining.
187
+ `attention_factor` (`float`, *optional*):
188
+ Used with 'yarn' and 'longrope'. The scaling factor to be applied on the attention
189
+ computation. If unspecified, it defaults to value recommended by the implementation, using the
190
+ `factor` field to infer the suggested value.
191
+ `beta_fast` (`float`, *optional*):
192
+ Only used with 'yarn'. Parameter to set the boundary for extrapolation (only) in the linear
193
+ ramp function. If unspecified, it defaults to 32.
194
+ `beta_slow` (`float`, *optional*):
195
+ Only used with 'yarn'. Parameter to set the boundary for interpolation (only) in the linear
196
+ ramp function. If unspecified, it defaults to 1.
197
+ `short_factor` (`list[float]`, *optional*):
198
+ Only used with 'longrope'. The scaling factor to be applied to short contexts (<
199
+ `original_max_position_embeddings`). Must be a list of numbers with the same length as the hidden
200
+ size divided by the number of attention heads divided by 2
201
+ `long_factor` (`list[float]`, *optional*):
202
+ Only used with 'longrope'. The scaling factor to be applied to long contexts (<
203
+ `original_max_position_embeddings`). Must be a list of numbers with the same length as the hidden
204
+ size divided by the number of attention heads divided by 2
205
+ `low_freq_factor` (`float`, *optional*):
206
+ Only used with 'llama3'. Scaling factor applied to low frequency components of the RoPE
207
+ `high_freq_factor` (`float`, *optional*):
208
+ Only used with 'llama3'. Scaling factor applied to high frequency components of the RoPE
209
+ attention_bias (`bool`, defaults to `False`, *optional*, defaults to `False`):
210
+ Whether to use a bias in the query, key, value and output projection layers during self-attention.
211
+ attention_dropout (`float`, *optional*, defaults to 0.0):
212
+ The dropout ratio for the attention probabilities.
213
+
214
+ ```python
215
+ >>> from transformers import Qwen3ASRTextModel, Qwen3ASRTextConfig
216
+
217
+ >>> # Initializing a Qwen3ASR style configuration
218
+ >>> configuration = Qwen3ASRTextConfig()
219
+
220
+ >>> # Initializing a model from the Qwen3-VL-7B style configuration
221
+ >>> model = Qwen3ASRTextModel(configuration)
222
+
223
+ >>> # Accessing the model configuration
224
+ >>> configuration = model.config
225
+ ```"""
226
+
227
+ model_type = "qwen3_asr_text"
228
+ base_config_key = "text_config"
229
+
230
+ def __init__(
231
+ self,
232
+ vocab_size=151936,
233
+ hidden_size=4096,
234
+ intermediate_size=22016,
235
+ num_hidden_layers=32,
236
+ num_attention_heads=32,
237
+ num_key_value_heads=32,
238
+ head_dim=128,
239
+ hidden_act="silu",
240
+ max_position_embeddings=128000,
241
+ initializer_range=0.02,
242
+ rms_norm_eps=1e-6,
243
+ use_cache=True,
244
+ tie_word_embeddings=False,
245
+ rope_theta=5000000.0,
246
+ rope_scaling=None,
247
+ attention_bias=False,
248
+ attention_dropout=0.0,
249
+ **kwargs,
250
+ ):
251
+ self.vocab_size = vocab_size
252
+ self.max_position_embeddings = max_position_embeddings
253
+ self.hidden_size = hidden_size
254
+ self.intermediate_size = intermediate_size
255
+ self.num_hidden_layers = num_hidden_layers
256
+ self.num_attention_heads = num_attention_heads
257
+
258
+ # for backward compatibility
259
+ if num_key_value_heads is None:
260
+ num_key_value_heads = num_attention_heads
261
+
262
+ self.num_key_value_heads = num_key_value_heads
263
+ self.head_dim = head_dim
264
+ self.hidden_act = hidden_act
265
+ self.initializer_range = initializer_range
266
+ self.rms_norm_eps = rms_norm_eps
267
+ self.use_cache = use_cache
268
+ self.rope_theta = rope_theta
269
+ self.rope_scaling = rope_scaling
270
+ self.attention_bias = attention_bias
271
+ self.attention_dropout = attention_dropout
272
+ # Validate the correctness of rotary position embeddings parameters
273
+ # BC: if there is a 'type' field, move it to 'rope_type'.
274
+ if self.rope_scaling is not None and "type" in self.rope_scaling:
275
+ self.rope_scaling["rope_type"] = self.rope_scaling["type"]
276
+
277
+ super().__init__(tie_word_embeddings=tie_word_embeddings, **kwargs)
278
+
279
+
280
+ class Qwen3ASRThinkerConfig(PretrainedConfig):
281
+ r"""
282
+ This is the configuration class to store the configuration of a [`Qwen3ASRThinker`]. It is used to instantiate a
283
+ Qwen3-ASR-Thinker model according to the specified arguments, defining the model architecture. Instantiating a
284
+ configuration with the defaults will yield a similar configuration to that of the thinker component of the Qwen3-Omni
285
+ architecture.
286
+
287
+ e.g. [Qwen/Qwen3-ASR-1.7B](https://huggingface.co/Qwen/Qwen3-ASR-1.7B)
288
+
289
+ Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
290
+ documentation from [`PretrainedConfig`] for more information.
291
+
292
+ Args:
293
+ audio_config (`dict`, *optional*):
294
+ The config dictionary of the audio backbone.
295
+ text_config (`dict`, *optional*):
296
+ The config dictionary of the text backbone.
297
+ audio_token_id (`int`, *optional*, defaults to 151646):
298
+ The audio token id to encode the audio prompt.
299
+ audio_start_token_id (`int`, *optional*, defaults to 151647):
300
+ The audio start token id to encode the audio prompt.
301
+ user_token_id (`int`, *optional*, defaults to 872):
302
+ The user token id to encode the user token.
303
+ initializer_range (`float`, *optional*, defaults to 0.02):
304
+ The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
305
+
306
+ Example:
307
+
308
+ ```python
309
+ >>> from transformers import Qwen3ASRThinkerModel, Qwen3ASRThinkerConfig
310
+
311
+ >>> # Initializing a default Qwen3ASRThinkerConfig
312
+ >>> configuration = Qwen3ASRThinkerConfig()
313
+
314
+ >>> # Initializing a model (with random weights) from the default configuration
315
+ >>> model = Qwen3ASRThinkerModel(configuration)
316
+
317
+ >>> # Accessing the model configuration
318
+ >>> configuration = model.config
319
+ ```"""
320
+
321
+ model_type = "qwen3_asr_thinker"
322
+
323
+ attribute_map = {}
324
+ sub_configs = {
325
+ "audio_config": Qwen3ASRAudioEncoderConfig,
326
+ "text_config": Qwen3ASRTextConfig,
327
+ }
328
+
329
+ def __init__(
330
+ self,
331
+ audio_config=None,
332
+ text_config=None,
333
+ audio_token_id=151646,
334
+ audio_start_token_id=151647,
335
+ user_token_id=872,
336
+ initializer_range=0.02,
337
+ **kwargs,
338
+ ):
339
+ super().__init__(**kwargs)
340
+ self.user_token_id = user_token_id
341
+ self.audio_start_token_id = audio_start_token_id
342
+ self.initializer_range = initializer_range
343
+
344
+ if isinstance(audio_config, dict):
345
+ audio_config = Qwen3ASRAudioEncoderConfig(**audio_config)
346
+ elif audio_config is None:
347
+ audio_config = Qwen3ASRAudioEncoderConfig()
348
+ self.audio_config = audio_config
349
+
350
+ if isinstance(text_config, dict):
351
+ text_config = Qwen3ASRTextConfig(**text_config)
352
+ elif text_config is None:
353
+ text_config = Qwen3ASRTextConfig()
354
+ self.text_config = text_config
355
+ self.audio_token_id = audio_token_id
356
+
357
+
358
+ class Qwen3ASRConfig(PretrainedConfig):
359
+ """
360
+ This is the configuration class to store the configuration of a [`Qwen3ASRForConditionalGeneration`]. It is used to instantiate a Qwen3ASR
361
+ model according to the specified sub-models configurations, defining the model architecture.
362
+
363
+ Instantiating a configuration with the defaults will yield a similar configuration to that of the
364
+ [Qwen/Qwen3-ASR-1.7B](https://huggingface.co/Qwen/Qwen3-ASR-1.7B) architecture.
365
+
366
+ Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
367
+ documentation from [`PretrainedConfig`] for more information.
368
+
369
+ Args:
370
+ thinker_config (`dict`, *optional*): Configuration of the underlying thinker sub-model.
371
+ support_languages (`List[str]`, *optional*): The languages supported by the model.
372
+
373
+ Example:
374
+
375
+ ```python
376
+ >>> from transformers import (
377
+ ... Qwen3ASRThinkerConfig,
378
+ ... Qwen3ASRForConditionalGeneration,
379
+ ... Qwen3ASRConfig,
380
+ ... )
381
+
382
+ >>> # Initializing a Qwen3ASR style configuration
383
+ >>> configuration = Qwen3ASRConfig()
384
+
385
+ >>> # Initializing a model from the configuration
386
+ >>> model = Qwen3ASRForConditionalGeneration(configuration)
387
+
388
+ >>> # Accessing the model configuration
389
+ >>> configuration = model.config
390
+ ```"""
391
+
392
+ model_type = "qwen3_asr"
393
+ sub_configs = {
394
+ "thinker_config": Qwen3ASRThinkerConfig,
395
+ }
396
+
397
+ def __init__(
398
+ self,
399
+ thinker_config=None,
400
+ support_languages=None,
401
+ **kwargs,
402
+ ):
403
+ super().__init__(**kwargs)
404
+ if thinker_config is None:
405
+ thinker_config = {}
406
+
407
+ self.thinker_config = Qwen3ASRThinkerConfig(**thinker_config)
408
+ self.support_languages = support_languages
409
+
410
+ def get_text_config(self, decoder=False) -> "PretrainedConfig":
411
+ """
412
+ Returns the config that is meant to be used with text IO. On most models, it is the original config instance
413
+ itself. On specific composite models, it is under a set of valid names.
414
+
415
+ Args:
416
+ decoder (`Optional[bool]`, *optional*, defaults to `False`):
417
+ If set to `True`, then only search for decoder config names.
418
+ """
419
+ # Overridden for deeply nested config like Qwen2.5-Omni. We don't have any omni model
420
+ # except for Qwen yet. This has to be generalized if more deeply nested configs are
421
+ # added. NOTE: currently method used only by vLLM
422
+ return self.thinker_config.get_text_config()
423
+
424
+
425
+ __all__ = ["Qwen3ASRConfig", "Qwen3ASRThinkerConfig", "Qwen3ASRAudioEncoderConfig"]
transformers/generation_config.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "eos_token_id": [
4
+ 151645
5
+ ],
6
+ "pad_token_id": 151643,
7
+ "transformers_version": "4.57.6"
8
+ }
transformers/merges.txt ADDED
The diff for this file is too large to render. See raw diff
 
transformers/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:67343cdb57bff88118500135e9212595e0efe3a4eb6d9643dcdb9d132a1f5ad8
3
+ size 4698521568
transformers/modeling_audar_asr.py ADDED
@@ -0,0 +1,1365 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2026 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
+ import math
16
+ from dataclasses import dataclass
17
+ from typing import Callable, Optional, Union
18
+
19
+ import numpy as np
20
+ import torch
21
+ from torch import nn
22
+ from torch.nn import functional as F
23
+
24
+ from transformers.activations import ACT2FN
25
+ from transformers.cache_utils import Cache, DynamicCache
26
+ from transformers.generation import GenerationMixin
27
+ from transformers.integrations import use_kernel_forward_from_hub
28
+ from transformers.masking_utils import create_causal_mask
29
+ from transformers.modeling_flash_attention_utils import FlashAttentionKwargs
30
+ from transformers.modeling_layers import GradientCheckpointingLayer
31
+ from transformers.modeling_outputs import (
32
+ BaseModelOutput,
33
+ BaseModelOutputWithPast,
34
+ MoeCausalLMOutputWithPast,
35
+ )
36
+ from transformers.modeling_rope_utils import ROPE_INIT_FUNCTIONS, dynamic_rope_update
37
+ from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
38
+ from transformers.processing_utils import Unpack
39
+ from transformers.utils import auto_docstring, can_return_tuple
40
+ from transformers.utils.deprecation import deprecate_kwarg
41
+ from transformers.utils.generic import TransformersKwargs, check_model_inputs
42
+
43
+ from .configuration_audar_asr import (
44
+ Qwen3ASRAudioEncoderConfig,
45
+ Qwen3ASRConfig,
46
+ Qwen3ASRThinkerConfig,
47
+ )
48
+
49
+
50
+ @use_kernel_forward_from_hub("RMSNorm")
51
+ class Qwen3ASRTextRMSNorm(nn.Module):
52
+ def __init__(self, hidden_size, eps: float = 1e-6) -> None:
53
+ """
54
+ Qwen3ASRTextRMSNorm is equivalent to T5LayerNorm
55
+ """
56
+ super().__init__()
57
+ self.weight = nn.Parameter(torch.ones(hidden_size))
58
+ self.variance_epsilon = eps
59
+
60
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
61
+ input_dtype = hidden_states.dtype
62
+ hidden_states = hidden_states.to(torch.float32)
63
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
64
+ hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
65
+ return self.weight * hidden_states.to(input_dtype)
66
+
67
+ def extra_repr(self):
68
+ return f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}"
69
+
70
+
71
+ def rotate_half(x):
72
+ """Rotates half the hidden dims of the input."""
73
+ x1 = x[..., : x.shape[-1] // 2]
74
+ x2 = x[..., x.shape[-1] // 2 :]
75
+ return torch.cat((-x2, x1), dim=-1)
76
+
77
+
78
+ def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
79
+ """
80
+ This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
81
+ num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
82
+ """
83
+ batch, num_key_value_heads, slen, head_dim = hidden_states.shape
84
+ if n_rep == 1:
85
+ return hidden_states
86
+ hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
87
+ return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
88
+
89
+
90
+ def eager_attention_forward(
91
+ module: nn.Module,
92
+ query: torch.Tensor,
93
+ key: torch.Tensor,
94
+ value: torch.Tensor,
95
+ attention_mask: Optional[torch.Tensor],
96
+ scaling: float,
97
+ dropout: float = 0.0,
98
+ **kwargs: Unpack[TransformersKwargs],
99
+ ):
100
+ key_states = repeat_kv(key, module.num_key_value_groups)
101
+ value_states = repeat_kv(value, module.num_key_value_groups)
102
+
103
+ attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
104
+ if attention_mask is not None:
105
+ causal_mask = attention_mask[:, :, :, : key_states.shape[-2]]
106
+ attn_weights = attn_weights + causal_mask
107
+
108
+ attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
109
+ attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
110
+ attn_output = torch.matmul(attn_weights, value_states)
111
+ attn_output = attn_output.transpose(1, 2).contiguous()
112
+
113
+ return attn_output, attn_weights
114
+
115
+
116
+ def apply_rotary_pos_emb(q, k, cos, sin, position_ids=None, unsqueeze_dim=1):
117
+ """Applies Rotary Position Embedding to the query and key tensors.
118
+
119
+ Args:
120
+ q (`torch.Tensor`): The query tensor.
121
+ k (`torch.Tensor`): The key tensor.
122
+ cos (`torch.Tensor`): The cosine part of the rotary embedding.
123
+ sin (`torch.Tensor`): The sine part of the rotary embedding.
124
+ position_ids (`torch.Tensor`, *optional*):
125
+ Deprecated and unused.
126
+ unsqueeze_dim (`int`, *optional*, defaults to 1):
127
+ The 'unsqueeze_dim' argument specifies the dimension along which to unsqueeze cos[position_ids] and
128
+ sin[position_ids] so that they can be properly broadcasted to the dimensions of q and k. For example, note
129
+ that cos[position_ids] and sin[position_ids] have the shape [batch_size, seq_len, head_dim]. Then, if q and
130
+ k have the shape [batch_size, heads, seq_len, head_dim], then setting unsqueeze_dim=1 makes
131
+ cos[position_ids] and sin[position_ids] broadcastable to the shapes of q and k. Similarly, if q and k have
132
+ the shape [batch_size, seq_len, heads, head_dim], then set unsqueeze_dim=2.
133
+ Returns:
134
+ `tuple(torch.Tensor)` comprising of the query and key tensors rotated using the Rotary Position Embedding.
135
+ """
136
+ cos = cos.unsqueeze(unsqueeze_dim)
137
+ sin = sin.unsqueeze(unsqueeze_dim)
138
+ q_embed = (q * cos) + (rotate_half(q) * sin)
139
+ k_embed = (k * cos) + (rotate_half(k) * sin)
140
+ return q_embed, k_embed
141
+
142
+
143
+ class Qwen3ASRTextAttention(nn.Module):
144
+ """Multi-headed attention from 'Attention Is All You Need' paper"""
145
+
146
+ def __init__(self, config: Qwen3ASRConfig, layer_idx: int):
147
+ super().__init__()
148
+ self.config = config
149
+ self.layer_idx = layer_idx
150
+ self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
151
+ self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
152
+ self.scaling = self.head_dim**-0.5
153
+ self.attention_dropout = config.attention_dropout
154
+ self.is_causal = True
155
+
156
+ self.q_proj = nn.Linear(
157
+ config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.attention_bias
158
+ )
159
+ self.k_proj = nn.Linear(
160
+ config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
161
+ )
162
+ self.v_proj = nn.Linear(
163
+ config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
164
+ )
165
+ self.o_proj = nn.Linear(
166
+ config.num_attention_heads * self.head_dim, config.hidden_size, bias=config.attention_bias
167
+ )
168
+ self.q_norm = Qwen3ASRTextRMSNorm(
169
+ self.head_dim, eps=config.rms_norm_eps
170
+ ) # unlike olmo, only on the head dim!
171
+ self.k_norm = Qwen3ASRTextRMSNorm(
172
+ self.head_dim, eps=config.rms_norm_eps
173
+ ) # thus post q_norm does not need reshape
174
+
175
+ @deprecate_kwarg("past_key_value", new_name="past_key_values", version="4.58")
176
+ def forward(
177
+ self,
178
+ hidden_states: torch.Tensor,
179
+ position_embeddings: tuple[torch.Tensor, torch.Tensor],
180
+ attention_mask: Optional[torch.Tensor],
181
+ past_key_values: Optional[Cache] = None,
182
+ cache_position: Optional[torch.LongTensor] = None,
183
+ **kwargs: Unpack[FlashAttentionKwargs],
184
+ ) -> tuple[torch.Tensor, Optional[torch.Tensor]]:
185
+ input_shape = hidden_states.shape[:-1]
186
+ hidden_shape = (*input_shape, -1, self.head_dim)
187
+
188
+ query_states = self.q_norm(self.q_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
189
+ key_states = self.k_norm(self.k_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
190
+ value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
191
+
192
+ cos, sin = position_embeddings
193
+ query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
194
+
195
+ if past_key_values is not None:
196
+ # sin and cos are specific to RoPE models; cache_position needed for the static cache
197
+ cache_kwargs = {"sin": sin, "cos": cos, "cache_position": cache_position}
198
+ key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx, cache_kwargs)
199
+
200
+ attention_interface: Callable = eager_attention_forward
201
+ if self.config._attn_implementation != "eager":
202
+ attention_interface = ALL_ATTENTION_FUNCTIONS[self.config._attn_implementation]
203
+
204
+ attn_output, attn_weights = attention_interface(
205
+ self,
206
+ query_states,
207
+ key_states,
208
+ value_states,
209
+ attention_mask,
210
+ dropout=0.0 if not self.training else self.attention_dropout,
211
+ scaling=self.scaling,
212
+ **kwargs,
213
+ )
214
+
215
+ attn_output = attn_output.reshape(*input_shape, -1).contiguous()
216
+ attn_output = self.o_proj(attn_output)
217
+ return attn_output, attn_weights
218
+
219
+
220
+ class Qwen3ASRTextMLP(nn.Module):
221
+ def __init__(self, config):
222
+ super().__init__()
223
+ self.config = config
224
+ self.hidden_size = config.hidden_size
225
+ self.intermediate_size = config.intermediate_size
226
+ self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
227
+ self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
228
+ self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
229
+ self.act_fn = ACT2FN[config.hidden_act]
230
+
231
+ def forward(self, x):
232
+ down_proj = self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
233
+ return down_proj
234
+
235
+
236
+ class Qwen3ASRThinkerTextDecoderLayer(GradientCheckpointingLayer):
237
+ def __init__(self, config: Qwen3ASRConfig, layer_idx: int):
238
+ super().__init__()
239
+ self.hidden_size = config.hidden_size
240
+
241
+ self.self_attn = Qwen3ASRTextAttention(config=config, layer_idx=layer_idx)
242
+
243
+ self.mlp = Qwen3ASRTextMLP(config)
244
+ self.input_layernorm = Qwen3ASRTextRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
245
+ self.post_attention_layernorm = Qwen3ASRTextRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
246
+
247
+ @deprecate_kwarg("past_key_value", new_name="past_key_values", version="4.58")
248
+ def forward(
249
+ self,
250
+ hidden_states: torch.Tensor,
251
+ position_embeddings: tuple[torch.Tensor, torch.Tensor],
252
+ attention_mask: Optional[torch.Tensor] = None,
253
+ position_ids: Optional[torch.LongTensor] = None,
254
+ past_key_values: Optional[Cache] = None,
255
+ use_cache: Optional[bool] = False,
256
+ cache_position: Optional[torch.LongTensor] = None,
257
+ **kwargs: Unpack[TransformersKwargs],
258
+ ) -> torch.Tensor:
259
+ residual = hidden_states
260
+ hidden_states = self.input_layernorm(hidden_states)
261
+ # Self Attention
262
+ hidden_states, _ = self.self_attn(
263
+ hidden_states=hidden_states,
264
+ attention_mask=attention_mask,
265
+ position_ids=position_ids,
266
+ past_key_values=past_key_values,
267
+ use_cache=use_cache,
268
+ cache_position=cache_position,
269
+ position_embeddings=position_embeddings,
270
+ **kwargs,
271
+ )
272
+ hidden_states = residual + hidden_states
273
+
274
+ # Fully Connected
275
+ residual = hidden_states
276
+ hidden_states = self.post_attention_layernorm(hidden_states)
277
+ hidden_states = self.mlp(hidden_states)
278
+ hidden_states = residual + hidden_states
279
+ return hidden_states
280
+
281
+
282
+ @auto_docstring
283
+ class Qwen3ASRPreTrainedModel(PreTrainedModel):
284
+ config: Qwen3ASRConfig
285
+ base_model_prefix = "model"
286
+ supports_gradient_checkpointing = True
287
+ _skip_keys_device_placement = "past_key_values"
288
+ _supports_flash_attn = True
289
+ _supports_sdpa = True
290
+
291
+ _can_compile_fullgraph = True
292
+ _supports_attention_backend = True
293
+ _can_record_outputs = {
294
+ "attentions": Qwen3ASRTextAttention,
295
+ }
296
+
297
+
298
+ @dataclass
299
+ class Qwen3ASRThinkerCausalLMOutputWithPast(MoeCausalLMOutputWithPast):
300
+ r"""
301
+ Args:
302
+ rope_deltas (`torch.LongTensor` of shape `(batch_size, )`, *optional*):
303
+ The rope index difference between sequence length and multimodal rope.
304
+ """
305
+
306
+ rope_deltas: Optional[torch.LongTensor] = None
307
+
308
+
309
+ def _get_feat_extract_output_lengths(input_lengths):
310
+ """
311
+ Computes the output length of the convolutional layers and the output length of the audio encoder
312
+ """
313
+
314
+ input_lengths_leave = input_lengths % 100
315
+ feat_lengths = (input_lengths_leave - 1) // 2 + 1
316
+ output_lengths = ((feat_lengths - 1) // 2 + 1 - 1) // 2 + 1 + (input_lengths // 100) * 13
317
+ return output_lengths
318
+
319
+
320
+ class Qwen3ASRPreTrainedModelForConditionalGeneration(Qwen3ASRPreTrainedModel):
321
+ def _prepare_4d_causal_attention_mask_with_cache_position(
322
+ self,
323
+ attention_mask: torch.Tensor,
324
+ sequence_length: int,
325
+ target_length: int,
326
+ dtype: torch.dtype,
327
+ device: torch.device,
328
+ min_dtype: float,
329
+ cache_position: torch.Tensor,
330
+ batch_size: int,
331
+ ):
332
+ """
333
+ Creates a causal 4D mask of shape `(batch_size, 1, query_length, key_value_length)` from a 2D mask of shape
334
+ `(batch_size, key_value_length)`, or if the input `attention_mask` is already 4D, do nothing.
335
+
336
+ Args:
337
+ attention_mask (`torch.Tensor`):
338
+ A 2D attention mask of shape `(batch_size, key_value_length)` or a 4D attention mask of shape `(batch_size, 1, query_length, key_value_length)`.
339
+ sequence_length (`int`):
340
+ The sequence length being processed.
341
+ target_length (`int`):
342
+ The target length: when generating with static cache, the mask should be as long as the static cache, to account for the 0 padding, the part of the cache that is not filled yet.
343
+ dtype (`torch.dtype`):
344
+ The dtype to use for the 4D attention mask.
345
+ device (`torch.device`):
346
+ The device to place the 4D attention mask on.
347
+ min_dtype (`float`):
348
+ The minimum value representable with the dtype `dtype`.
349
+ cache_position (`torch.Tensor`):
350
+ Indices depicting the position of the input sequence tokens in the sequence.
351
+ batch_size (`torch.Tensor`):
352
+ Batch size.
353
+ """
354
+ if attention_mask is not None and attention_mask.dim() == 4:
355
+ # In this case we assume that the mask comes already in inverted form and requires no inversion or slicing.
356
+ causal_mask = attention_mask
357
+ else:
358
+ causal_mask = torch.full(
359
+ (sequence_length, target_length), fill_value=min_dtype, dtype=dtype, device=device
360
+ )
361
+ if sequence_length != 1:
362
+ causal_mask = torch.triu(causal_mask, diagonal=1)
363
+ causal_mask *= torch.arange(target_length, device=device) > cache_position.reshape(-1, 1)
364
+ causal_mask = causal_mask[None, None, :, :].expand(batch_size, 1, -1, -1)
365
+ if attention_mask is not None:
366
+ causal_mask = causal_mask.clone() # copy to contiguous memory for in-place edit
367
+ mask_length = attention_mask.shape[-1]
368
+ padding_mask = causal_mask[:, :, :, :mask_length] + attention_mask[:, None, None, :]
369
+ padding_mask = padding_mask == 0
370
+ causal_mask[:, :, :, :mask_length] = causal_mask[:, :, :, :mask_length].masked_fill(
371
+ padding_mask, min_dtype
372
+ )
373
+
374
+ return causal_mask
375
+
376
+
377
+ def get_chunked_index(
378
+ self, token_indices: torch.Tensor, tokens_per_chunk: int, remove_index: int
379
+ ) -> list[tuple[int, int]]:
380
+ """
381
+ Splits token index list into chunks based on token value ranges.
382
+
383
+ Given a list of token indices, returns a list of (start, end) index tuples representing
384
+ slices of the list where the token values fall within successive ranges of `t_ntoken_per_chunk`.
385
+
386
+ For example, if `t_ntoken_per_chunk` is 1000, the function will create chunks such that:
387
+ - the first chunk contains token values < 1000,
388
+ - the second chunk contains values >= 1000 and < 2000, and so on.
389
+
390
+ Parameters:
391
+ token_indices (`torch.Tensor` of shape `(seq_len, )`): A monotonically increasing list of
392
+ token index values.
393
+ t_ntoken_per_chunk (`int`): Number of tokens per chunk (used as the chunk size threshold).
394
+ remove_index (`int`) An index id to subtract from `token_indices` before chunking
395
+
396
+ Returns:
397
+ `list[tuple[int, int]]`: A list of tuples, each representing the start (inclusive)
398
+ and end (exclusive) indices of a chunk in `token_indices`.
399
+ """
400
+
401
+ def _iter():
402
+ i, start_idx = 0, 0 # skip bos token
403
+ current_chunk = 1
404
+ while i < len(token_indices): # skip eos token
405
+ if token_indices[i] - remove_index >= current_chunk * tokens_per_chunk:
406
+ yield (start_idx, i)
407
+ start_idx = i
408
+ current_chunk += 1
409
+ i += 1
410
+ yield (start_idx, len(token_indices))
411
+
412
+ return list(_iter())
413
+
414
+ def get_rope_index(
415
+ self,
416
+ attention_mask: Optional[torch.Tensor] = None,
417
+ ) -> tuple[torch.Tensor, torch.Tensor]:
418
+ """
419
+ Calculate the rope index in LLM.
420
+
421
+ Explanation:
422
+ Each embedding sequence contains text embedding.
423
+
424
+ Args:
425
+ input_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`):
426
+ Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you provide
427
+ it.
428
+ attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
429
+ Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
430
+
431
+ - 1 for tokens that are **not masked**,
432
+ - 0 for tokens that are **masked**.
433
+ audio_seqlens (`torch.LongTensor` of shape `(num_audios)`, *optional*):
434
+ The length of feature shape of each audio in LLM.
435
+
436
+ Returns:
437
+ position_ids (`torch.LongTensor` of shape `(3, batch_size, sequence_length)`)
438
+ mrope_position_deltas (`torch.Tensor` of shape `(batch_size)`)
439
+ """
440
+ mrope_position_deltas = []
441
+
442
+ position_ids = attention_mask.float().cumsum(-1) - 1
443
+ position_ids.masked_fill_(attention_mask == 0, 1)
444
+ position_ids = position_ids.unsqueeze(0).expand(3, -1, -1).to(attention_mask.device)
445
+ max_position_ids = position_ids.max(0, keepdim=False)[0].max(-1, keepdim=True)[0]
446
+ mrope_position_deltas = max_position_ids + 1 - torch.sum(attention_mask, dim=-1, keepdim=True)
447
+
448
+ return position_ids, mrope_position_deltas
449
+
450
+
451
+ class Qwen3ASRAudioAttention(nn.Module):
452
+ """Multi-headed attention from 'Attention Is All You Need' paper"""
453
+
454
+ def __init__(self, config):
455
+ super().__init__()
456
+ self.embed_dim = config.d_model
457
+ self.num_heads = config.encoder_attention_heads
458
+ self.dropout = config.attention_dropout
459
+ self.head_dim = self.embed_dim // self.num_heads
460
+ self.num_key_value_groups = 1 # needed for eager attention
461
+ self.config = config
462
+
463
+ if (self.head_dim * self.num_heads) != self.embed_dim:
464
+ raise ValueError(
465
+ f"embed_dim must be divisible by num_heads (got `embed_dim`: {self.embed_dim}"
466
+ f" and `num_heads`: {self.num_heads})."
467
+ )
468
+ self.scaling = self.head_dim**-0.5
469
+ self.attention_dropout = 0.0
470
+ self.is_decoder = False
471
+ self.is_causal = False
472
+ self.k_proj = nn.Linear(self.embed_dim, self.embed_dim, bias=True)
473
+ self.v_proj = nn.Linear(self.embed_dim, self.embed_dim, bias=True)
474
+ self.q_proj = nn.Linear(self.embed_dim, self.embed_dim, bias=True)
475
+ self.out_proj = nn.Linear(self.embed_dim, self.embed_dim, bias=True)
476
+
477
+ def forward(
478
+ self,
479
+ hidden_states: torch.Tensor,
480
+ cu_seqlens: Optional[torch.Tensor] = None,
481
+ attention_mask: Optional[torch.Tensor] = None,
482
+ **kwargs,
483
+ ) -> tuple[torch.Tensor, Optional[torch.Tensor], Optional[tuple[torch.Tensor]]]:
484
+ """Input shape: Batch x Time x Channel"""
485
+
486
+ seq_length, _ = hidden_states.size()
487
+
488
+ query_states = self.q_proj(hidden_states).reshape(seq_length, self.num_heads, -1)
489
+ key_states = self.k_proj(hidden_states).reshape(seq_length, self.num_heads, -1)
490
+ value_states = self.v_proj(hidden_states).reshape(seq_length, self.num_heads, -1)
491
+
492
+ query_states = query_states.transpose(0, 1).unsqueeze(0)
493
+ key_states = key_states.transpose(0, 1).unsqueeze(0)
494
+ value_states = value_states.transpose(0, 1).unsqueeze(0)
495
+ max_seqlen = (cu_seqlens[1:] - cu_seqlens[:-1]).max()
496
+
497
+ attention_interface: Callable = eager_attention_forward
498
+ if self.config._attn_implementation != "eager":
499
+ attention_interface = ALL_ATTENTION_FUNCTIONS[self.config._attn_implementation]
500
+
501
+ attn_output, _ = attention_interface(
502
+ self,
503
+ query_states,
504
+ key_states,
505
+ value_states,
506
+ attention_mask=attention_mask,
507
+ dropout=0.0 if not self.training else self.attention_dropout,
508
+ scaling=self.scaling,
509
+ cu_seq_lens_q=cu_seqlens, # pass cu seq lens for FA2
510
+ cu_seq_lens_k=cu_seqlens,
511
+ max_length_q=max_seqlen,
512
+ max_length_k=max_seqlen,
513
+ is_causal=False,
514
+ **kwargs,
515
+ )
516
+
517
+ attn_output = attn_output.reshape(seq_length, -1).contiguous()
518
+ attn_output = self.out_proj(attn_output)
519
+
520
+ return attn_output
521
+
522
+
523
+ class Qwen3ASRAudioEncoderLayer(GradientCheckpointingLayer):
524
+ def __init__(self, config: Qwen3ASRAudioEncoderConfig):
525
+ super().__init__()
526
+ self.embed_dim = config.d_model
527
+ self.self_attn = Qwen3ASRAudioAttention(config)
528
+ self.self_attn_layer_norm = nn.LayerNorm(self.embed_dim)
529
+ self.dropout = config.dropout
530
+ self.activation_fn = ACT2FN[config.activation_function]
531
+ self.activation_dropout = config.activation_dropout
532
+ self.fc1 = nn.Linear(self.embed_dim, config.encoder_ffn_dim)
533
+ self.fc2 = nn.Linear(config.encoder_ffn_dim, self.embed_dim)
534
+ self.final_layer_norm = nn.LayerNorm(self.embed_dim)
535
+
536
+ def forward(
537
+ self,
538
+ hidden_states: torch.Tensor,
539
+ cu_seqlens: torch.Tensor,
540
+ attention_mask: Optional[torch.Tensor] = None,
541
+ **kwargs,
542
+ ) -> torch.Tensor:
543
+ """
544
+ Args:
545
+ hidden_states (`torch.FloatTensor`): input to the layer of shape `(batch, seq_len, embed_dim)`
546
+ attention_mask (`torch.FloatTensor`): attention mask of size
547
+ `(batch, 1, tgt_len, src_len)` where padding elements are indicated by very large negative values.
548
+ layer_head_mask (`torch.FloatTensor`): mask for attention heads in a given layer of size
549
+ `(encoder_attention_heads,)`.
550
+ output_attentions (`bool`, *optional*):
551
+ Whether or not to return the attentions tensors of all attention layers. See `attentions` under
552
+ returned tensors for more detail.
553
+ """
554
+ residual = hidden_states
555
+ hidden_states = self.self_attn_layer_norm(hidden_states)
556
+ hidden_states = self.self_attn(
557
+ hidden_states=hidden_states,
558
+ cu_seqlens=cu_seqlens,
559
+ attention_mask=attention_mask,
560
+ **kwargs,
561
+ )
562
+ hidden_states = residual + hidden_states
563
+ residual = hidden_states
564
+ hidden_states = self.final_layer_norm(hidden_states)
565
+ hidden_states = self.fc1(hidden_states)
566
+ hidden_states = self.activation_fn(hidden_states)
567
+ hidden_states = self.fc2(hidden_states)
568
+ hidden_states = residual + hidden_states
569
+
570
+ if hidden_states.dtype == torch.float16:
571
+ clamp_value = torch.finfo(hidden_states.dtype).max - 1000
572
+ hidden_states = torch.clamp(hidden_states, min=-clamp_value, max=clamp_value)
573
+
574
+ outputs = (hidden_states,)
575
+
576
+ return outputs
577
+
578
+
579
+ class SinusoidsPositionEmbedding(nn.Module):
580
+ def __init__(self, length, channels, max_timescale=10000):
581
+ super().__init__()
582
+ if channels % 2 != 0:
583
+ raise ValueError("SinusoidsPositionEmbedding needs even channels input")
584
+ log_timescale_increment = np.log(max_timescale) / (channels // 2 - 1)
585
+ inv_timescales = torch.exp(-log_timescale_increment * torch.arange(channels // 2).float())
586
+ scaled_time = torch.arange(length)[:, np.newaxis] * inv_timescales[np.newaxis, :]
587
+ self.register_buffer(
588
+ "positional_embedding",
589
+ torch.cat([torch.sin(scaled_time), torch.cos(scaled_time)], dim=1),
590
+ persistent=False,
591
+ )
592
+
593
+ def forward(self, seqlen: int):
594
+ return self.positional_embedding[:seqlen, :]
595
+
596
+
597
+ @auto_docstring(
598
+ custom_intro="""
599
+ Transformer encoder consisting of *config.encoder_layers* self attention layers. Each layer is a
600
+ [`Qwen3ASRAudioEncoderLayer`].
601
+ """
602
+ )
603
+ class Qwen3ASRAudioEncoder(Qwen3ASRPreTrainedModel):
604
+ config: Qwen3ASRAudioEncoderConfig
605
+ main_input_name = "input_features"
606
+ _no_split_modules = ["Qwen3ASRAudioEncoderLayer"]
607
+ _supports_sdpa = True
608
+
609
+ def __init__(self, config: Qwen3ASRAudioEncoderConfig):
610
+ super().__init__(config)
611
+ self.dropout = config.dropout
612
+
613
+ embed_dim = config.d_model
614
+ self.num_mel_bins = config.num_mel_bins
615
+ self.max_source_positions = config.max_source_positions
616
+ self.embed_scale = math.sqrt(embed_dim) if config.scale_embedding else 1.0
617
+ self.n_window = config.n_window
618
+ self.positional_embedding = SinusoidsPositionEmbedding(self.max_source_positions, embed_dim)
619
+ self.layers = nn.ModuleList([Qwen3ASRAudioEncoderLayer(config) for _ in range(config.encoder_layers)])
620
+ self.ln_post = nn.LayerNorm(config.d_model)
621
+ self.gradient_checkpointing = False
622
+ self.conv2d1 = nn.Conv2d(1, config.downsample_hidden_size, 3, 2, padding=1)
623
+ self.conv2d2 = nn.Conv2d(config.downsample_hidden_size, config.downsample_hidden_size, 3, 2, padding=1)
624
+ self.conv2d3 = nn.Conv2d(config.downsample_hidden_size, config.downsample_hidden_size, 3, 2, padding=1)
625
+ self.conv_out = nn.Linear(
626
+ config.downsample_hidden_size * ((((config.num_mel_bins + 1) // 2 + 1) // 2 + 1) // 2),
627
+ config.d_model,
628
+ bias=False,
629
+ )
630
+ self.proj1 = nn.Linear(config.d_model, config.d_model)
631
+ self.act = ACT2FN[config.activation_function]
632
+ self.proj2 = nn.Linear(config.d_model, config.output_dim)
633
+ self.n_window_infer = self.config.n_window_infer
634
+ self.conv_chunksize = self.config.conv_chunksize
635
+ # Initialize weights and apply final processing
636
+ self.post_init()
637
+
638
+ def _freeze_parameters(self):
639
+ for param in self.parameters():
640
+ param.requires_grad = False
641
+ self._requires_grad = False
642
+
643
+ def get_input_embeddings(self) -> nn.Module:
644
+ return self.conv1
645
+
646
+ def set_input_embeddings(self, value: nn.Module):
647
+ self.conv1 = value
648
+
649
+ def _prepare_attention_mask(self, inputs_tensor: torch.Tensor, cu_seqlens: torch.Tensor) -> torch.Tensor:
650
+ # Flash Attention 2 doesn't need a 4D mask and relies on `cu_seqlens/max_seqlen`
651
+ # NOTE: the created attention masl only approximates the ragged FA2 attention by
652
+ # allowing bidirectional attention within `cu_seqlens` blocks, and not attending between
653
+ # blocks. Though it will not be a 100% match for FA2's `varlen` path
654
+ if self.config._attn_implementation == "flash_attention_2":
655
+ return None
656
+
657
+ seq_length = inputs_tensor.shape[0]
658
+ attention_mask = torch.full(
659
+ [1, 1, seq_length, seq_length],
660
+ torch.finfo(inputs_tensor.dtype).min,
661
+ device=inputs_tensor.device,
662
+ dtype=inputs_tensor.dtype,
663
+ )
664
+ for i in range(1, len(cu_seqlens)):
665
+ attention_mask[..., cu_seqlens[i - 1] : cu_seqlens[i], cu_seqlens[i - 1] : cu_seqlens[i]] = 0
666
+ return attention_mask
667
+
668
+ @auto_docstring
669
+ def forward(
670
+ self,
671
+ input_features,
672
+ feature_lens=None,
673
+ aftercnn_lens=None,
674
+ ):
675
+ r"""
676
+ feature_lens (`torch.LongTensor` of shape `(batch_size,)`):
677
+ mel length
678
+ aftercnn_lens (`torch.LongTensor` of shape `(batch_size,)`):
679
+ mel length after cnn
680
+ """
681
+ aftercnn_lens = _get_feat_extract_output_lengths(feature_lens)
682
+ chunk_num = torch.ceil(feature_lens / (self.n_window * 2)).long()
683
+
684
+ chunk_lengths = torch.tensor(
685
+ [self.n_window * 2] * chunk_num.sum(),
686
+ dtype=torch.long,
687
+ device=feature_lens.device,
688
+ )
689
+ tail_chunk_index = F.pad(chunk_num, (1, 0), value=-1).cumsum(0)[1:]
690
+ chunk_lengths[tail_chunk_index] = feature_lens % (self.n_window * 2)
691
+ chunk_lengths[chunk_lengths == 0] = self.n_window * 2
692
+
693
+ chunk_list = input_features.T.split(chunk_lengths.tolist(), dim=0)
694
+ padded_feature = nn.utils.rnn.pad_sequence(chunk_list, batch_first=True).transpose(1, 2)
695
+ feature_lens_after_cnn = _get_feat_extract_output_lengths(chunk_lengths)
696
+ padded_mask_after_cnn = nn.utils.rnn.pad_sequence(
697
+ [torch.ones(length, dtype=torch.bool, device=padded_feature.device) for length in feature_lens_after_cnn],
698
+ batch_first=True,
699
+ )
700
+ padded_feature = padded_feature.unsqueeze(1)
701
+ # Split to chunk to avoid OOM during convolution
702
+ padded_embeds = []
703
+ for chunk in padded_feature.split(self.conv_chunksize, dim=0):
704
+ padded_embed = F.gelu(self.conv2d1(chunk))
705
+ padded_embed = F.gelu(self.conv2d2(padded_embed))
706
+ padded_embed = F.gelu(self.conv2d3(padded_embed))
707
+ padded_embeds.append(padded_embed)
708
+ padded_embed = torch.cat(padded_embeds, dim=0)
709
+ b, c, f, t = padded_embed.size()
710
+ padded_embed = self.conv_out(padded_embed.permute(0, 3, 1, 2).contiguous().view(b, t, c * f))
711
+
712
+ positional_embedding = (
713
+ self.positional_embedding.positional_embedding[: padded_embed.shape[1], :]
714
+ .unsqueeze(0)
715
+ .to(padded_embed.dtype)
716
+ )
717
+ padded_embed = padded_embed + positional_embedding
718
+ hidden_states = padded_embed[padded_mask_after_cnn]
719
+ cu_chunk_lens = [0]
720
+ window_aftercnn = padded_mask_after_cnn.shape[-1] * (self.n_window_infer // (self.n_window * 2))
721
+ for cnn_len in aftercnn_lens:
722
+ cu_chunk_lens += [window_aftercnn] * (cnn_len // window_aftercnn)
723
+ remainder = cnn_len % window_aftercnn
724
+ if remainder != 0:
725
+ cu_chunk_lens += [remainder]
726
+ cu_seqlens = torch.tensor(cu_chunk_lens, device=aftercnn_lens.device).cumsum(-1, dtype=torch.int32)
727
+
728
+ for encoder_layer in self.layers:
729
+ layer_outputs = encoder_layer(
730
+ hidden_states,
731
+ cu_seqlens,
732
+ )
733
+
734
+ hidden_states = layer_outputs[0]
735
+
736
+ hidden_states = self.ln_post(hidden_states)
737
+ hidden_states = self.proj1(hidden_states)
738
+ hidden_states = self.act(hidden_states)
739
+ hidden_states = self.proj2(hidden_states)
740
+ return BaseModelOutput(last_hidden_state=hidden_states)
741
+
742
+ def padded_and_mask_function(self, tensor_list, tensor_len, padding_value=0, padding_side="right"):
743
+ """
744
+ Pads a sequence of tensors to their maximum length on indicated `padding_side`.
745
+ Then prepares a mask so that pad tokens are not attended to.
746
+ """
747
+ max_len = tensor_len.max()
748
+ dim = tensor_list[0].shape[0]
749
+ padded_tensor = torch.full(
750
+ size=(len(tensor_list), dim, max_len),
751
+ fill_value=padding_value,
752
+ dtype=self.dtype,
753
+ device=tensor_list[0].device,
754
+ )
755
+
756
+ batch_mask = torch.zeros(
757
+ (len(tensor_len), max_len),
758
+ dtype=torch.long,
759
+ device=padded_tensor.device,
760
+ )
761
+ for i, length in enumerate(tensor_len):
762
+ batch_mask[i, :length] = 1
763
+ padded_tensor[i, :, :length] = tensor_list[i]
764
+
765
+ feature_lens_after_cnn = (tensor_len - 1) // 2 + 1
766
+ max_len_after_cnn = feature_lens_after_cnn.max()
767
+ batch_mask_after_cnn = torch.zeros(
768
+ (len(tensor_len), max_len_after_cnn),
769
+ dtype=torch.long,
770
+ device=padded_tensor.device,
771
+ )
772
+ for i, length in enumerate(feature_lens_after_cnn):
773
+ batch_mask_after_cnn[i, :length] = 1
774
+ return (
775
+ padded_tensor,
776
+ batch_mask.unsqueeze(1),
777
+ batch_mask_after_cnn.bool(),
778
+ )
779
+
780
+
781
+ class Qwen3ASRThinkerTextRotaryEmbedding(nn.Module):
782
+ inv_freq: torch.Tensor # fix linting for `register_buffer`
783
+
784
+ def __init__(self, config: Qwen3ASRConfig, device=None):
785
+ super().__init__()
786
+ if hasattr(config, "rope_scaling") and config.rope_scaling is not None:
787
+ self.rope_type = config.rope_scaling.get("rope_type", "default")
788
+ else:
789
+ self.rope_type = "default"
790
+ self.max_seq_len_cached = config.max_position_embeddings
791
+ self.original_max_seq_len = config.max_position_embeddings
792
+
793
+ self.config = config
794
+ self.rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
795
+
796
+ inv_freq, self.attention_scaling = self.rope_init_fn(self.config, device)
797
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
798
+ self.original_inv_freq = self.inv_freq
799
+
800
+ self.mrope_section = config.rope_scaling.get("mrope_section", [24, 20, 20])
801
+
802
+ def apply_interleaved_mrope(self, freqs, mrope_section):
803
+ """Apply interleaved MRoPE to 3D rotary embeddings.
804
+ Reorganizes frequency layout from chunked [TTT...HHH...WWW] to
805
+ interleaved [THTHWHTHW...TT], preserving frequency continuity.
806
+ args:
807
+ x: (3, bs, seq_len, head_dim // 2)
808
+ mrope_section: (3,)
809
+ returns:
810
+ x_t: (bs, seq_len, head_dim // 2)
811
+ """
812
+ freqs_t = freqs[0] # just overwrite the first dimension T
813
+ for dim, offset in enumerate((1, 2), start=1): # H, W
814
+ length = mrope_section[dim] * 3
815
+ idx = slice(offset, length, 3)
816
+ freqs_t[..., idx] = freqs[dim, ..., idx]
817
+ return freqs_t
818
+
819
+ @torch.no_grad()
820
+ @dynamic_rope_update # power user: used with advanced RoPE types (e.g. dynamic rope)
821
+ def forward(self, x, position_ids):
822
+ # In contrast to other models, Qwen3ASRThinker has different position ids for the grids
823
+ # So we expand the inv_freq to shape (3, ...)
824
+ if position_ids.ndim == 2:
825
+ position_ids = position_ids[None, ...].expand(3, position_ids.shape[0], -1)
826
+ inv_freq_expanded = self.inv_freq[None, None, :, None].float().expand(3, position_ids.shape[1], -1, 1)
827
+ position_ids_expanded = position_ids[:, :, None, :].float() # shape (3, bs, 1, positions)
828
+
829
+ device_type = x.device.type if isinstance(x.device.type, str) and x.device.type != "mps" else "cpu"
830
+ with torch.autocast(device_type=device_type, enabled=False): # Force float32
831
+ freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(2, 3)
832
+ freqs = self.apply_interleaved_mrope(freqs, self.mrope_section)
833
+ emb = torch.cat((freqs, freqs), dim=-1)
834
+ cos = emb.cos() * self.attention_scaling
835
+ sin = emb.sin() * self.attention_scaling
836
+
837
+ return cos.to(dtype=x.dtype), sin.to(dtype=x.dtype)
838
+
839
+
840
+ class Qwen3ASRThinkerTextMLP(nn.Module):
841
+ def __init__(self, config, intermediate_size=None):
842
+ super().__init__()
843
+ self.config = config
844
+ self.hidden_size = config.hidden_size
845
+ self.intermediate_size = intermediate_size if intermediate_size is not None else config.intermediate_size
846
+ self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
847
+ self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
848
+ self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
849
+ self.act_fn = ACT2FN[config.hidden_act]
850
+
851
+ def forward(self, x):
852
+ down_proj = self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
853
+ return down_proj
854
+
855
+
856
+ @use_kernel_forward_from_hub("RMSNorm")
857
+ class Qwen3ASRThinkerTextRMSNorm(nn.Module):
858
+ def __init__(self, hidden_size, eps=1e-6):
859
+ """
860
+ Qwen3ASRThinkerTextRMSNorm is equivalent to T5LayerNorm
861
+ """
862
+ super().__init__()
863
+ self.weight = nn.Parameter(torch.ones(hidden_size))
864
+ self.variance_epsilon = eps
865
+
866
+ def forward(self, hidden_states):
867
+ input_dtype = hidden_states.dtype
868
+ hidden_states = hidden_states.to(torch.float32)
869
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
870
+ hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
871
+ return self.weight * hidden_states.to(input_dtype)
872
+
873
+ def extra_repr(self):
874
+ return f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}"
875
+
876
+
877
+ class Qwen3ASRThinkerTextAttention(nn.Module):
878
+ """Multi-headed attention from 'Attention Is All You Need' paper"""
879
+
880
+ def __init__(self, config, layer_idx):
881
+ super().__init__()
882
+ self.config = config
883
+ self.layer_idx = layer_idx
884
+ self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
885
+ self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
886
+ self.scaling = self.head_dim**-0.5
887
+ self.attention_dropout = config.attention_dropout
888
+ self.is_causal = True
889
+
890
+ self.q_proj = nn.Linear(
891
+ config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.attention_bias
892
+ )
893
+ self.k_proj = nn.Linear(
894
+ config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
895
+ )
896
+ self.v_proj = nn.Linear(
897
+ config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
898
+ )
899
+ self.o_proj = nn.Linear(
900
+ config.num_attention_heads * self.head_dim, config.hidden_size, bias=config.attention_bias
901
+ )
902
+ self.q_norm = Qwen3ASRThinkerTextRMSNorm(
903
+ self.head_dim, eps=config.rms_norm_eps
904
+ ) # unlike olmo, only on the head dim!
905
+ self.k_norm = Qwen3ASRThinkerTextRMSNorm(
906
+ self.head_dim, eps=config.rms_norm_eps
907
+ ) # thus post q_norm does not need reshape
908
+ self.sliding_window = None
909
+
910
+ @deprecate_kwarg("past_key_value", new_name="past_key_values", version="4.58")
911
+ def forward(
912
+ self,
913
+ hidden_states: torch.Tensor,
914
+ position_embeddings: tuple[torch.Tensor, torch.Tensor],
915
+ attention_mask: Optional[torch.Tensor],
916
+ past_key_values: Optional[Cache] = None,
917
+ cache_position: Optional[torch.LongTensor] = None,
918
+ **kwargs: Unpack[FlashAttentionKwargs],
919
+ ) -> tuple[torch.Tensor, Optional[torch.Tensor]]:
920
+ input_shape = hidden_states.shape[:-1]
921
+ hidden_shape = (*input_shape, -1, self.head_dim)
922
+
923
+ query_states = self.q_norm(self.q_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
924
+ key_states = self.k_norm(self.k_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
925
+ value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
926
+
927
+ cos, sin = position_embeddings
928
+ query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
929
+
930
+ if past_key_values is not None:
931
+ # sin and cos are specific to RoPE models; cache_position needed for the static cache
932
+ cache_kwargs = {"sin": sin, "cos": cos, "cache_position": cache_position}
933
+ key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx, cache_kwargs)
934
+
935
+ attention_interface: Callable = eager_attention_forward
936
+ if self.config._attn_implementation != "eager":
937
+ attention_interface = ALL_ATTENTION_FUNCTIONS[self.config._attn_implementation]
938
+
939
+ attn_output, attn_weights = attention_interface(
940
+ self,
941
+ query_states,
942
+ key_states,
943
+ value_states,
944
+ attention_mask,
945
+ dropout=0.0 if not self.training else self.attention_dropout,
946
+ scaling=self.scaling,
947
+ sliding_window=self.sliding_window, # diff with Llama
948
+ **kwargs,
949
+ )
950
+
951
+ attn_output = attn_output.reshape(*input_shape, -1).contiguous()
952
+ attn_output = self.o_proj(attn_output)
953
+ return attn_output, attn_weights
954
+
955
+
956
+ @auto_docstring(
957
+ custom_intro=(
958
+ "Text part of Qwen3ASRThinker, "
959
+ )
960
+ )
961
+ class Qwen3ASRThinkerTextModel(Qwen3ASRPreTrainedModel):
962
+ config: Qwen3ASRConfig
963
+ _no_split_modules = ["Qwen3ASRThinkerTextDecoderLayer"]
964
+ config_class = Qwen3ASRConfig
965
+ _can_record_outputs = {
966
+ "hidden_states": Qwen3ASRThinkerTextDecoderLayer,
967
+ "attentions": Qwen3ASRThinkerTextAttention,
968
+ }
969
+
970
+ def __init__(self, config: Qwen3ASRConfig):
971
+ super().__init__(config)
972
+ self.padding_idx = config.pad_token_id
973
+ self.vocab_size = config.vocab_size
974
+
975
+ self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
976
+ self.layers = nn.ModuleList(
977
+ [Qwen3ASRThinkerTextDecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
978
+ )
979
+ self.norm = Qwen3ASRTextRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
980
+ self.rotary_emb = Qwen3ASRThinkerTextRotaryEmbedding(config)
981
+ self.gradient_checkpointing = False
982
+
983
+ # Initialize weights and apply final processing
984
+ self.post_init()
985
+
986
+ @check_model_inputs()
987
+ @auto_docstring
988
+ def forward(
989
+ self,
990
+ input_ids: Optional[torch.LongTensor] = None,
991
+ attention_mask: Optional[torch.Tensor] = None,
992
+ position_ids: Optional[torch.LongTensor] = None,
993
+ past_key_values: Optional[Cache] = None,
994
+ inputs_embeds: Optional[torch.FloatTensor] = None,
995
+ use_cache: Optional[bool] = None,
996
+ cache_position: Optional[torch.LongTensor] = None,
997
+ **kwargs: Unpack[FlashAttentionKwargs],
998
+ ) -> Union[tuple, BaseModelOutputWithPast]:
999
+ if (input_ids is None) ^ (inputs_embeds is not None):
1000
+ raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
1001
+
1002
+ # torch.jit.trace() doesn't support cache objects in the output
1003
+ if use_cache and past_key_values is None and not torch.jit.is_tracing():
1004
+ past_key_values = DynamicCache(config=self.config)
1005
+
1006
+ if inputs_embeds is None:
1007
+ inputs_embeds = self.embed_tokens(input_ids)
1008
+
1009
+ if cache_position is None:
1010
+ past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
1011
+ cache_position = torch.arange(
1012
+ past_seen_tokens, past_seen_tokens + inputs_embeds.shape[1], device=inputs_embeds.device
1013
+ )
1014
+
1015
+ # the hard coded `3` is for temporal, height and width.
1016
+ if position_ids is None:
1017
+ position_ids = cache_position.view(1, 1, -1).expand(3, inputs_embeds.shape[0], -1)
1018
+ elif position_ids.ndim == 2:
1019
+ position_ids = position_ids[None, ...].expand(3, position_ids.shape[0], -1)
1020
+
1021
+ if position_ids.ndim == 3 and position_ids.shape[0] == 4:
1022
+ text_position_ids = position_ids[0]
1023
+ position_ids = position_ids[1:]
1024
+ else:
1025
+ text_position_ids = position_ids[0]
1026
+
1027
+ attention_mask = create_causal_mask(
1028
+ config=self.config,
1029
+ input_embeds=inputs_embeds,
1030
+ attention_mask=attention_mask,
1031
+ cache_position=cache_position,
1032
+ past_key_values=past_key_values,
1033
+ position_ids=text_position_ids,
1034
+ )
1035
+
1036
+ hidden_states = inputs_embeds
1037
+
1038
+ # create position embeddings to be shared across the decoder layers
1039
+ position_embeddings = self.rotary_emb(hidden_states, position_ids)
1040
+
1041
+ # decoder layers
1042
+ for layer_idx, decoder_layer in enumerate(self.layers):
1043
+ layer_outputs = decoder_layer(
1044
+ hidden_states,
1045
+ attention_mask=attention_mask,
1046
+ position_ids=text_position_ids,
1047
+ past_key_values=past_key_values,
1048
+ cache_position=cache_position,
1049
+ position_embeddings=position_embeddings,
1050
+ **kwargs,
1051
+ )
1052
+ hidden_states = layer_outputs
1053
+
1054
+ hidden_states = self.norm(hidden_states)
1055
+
1056
+ return BaseModelOutputWithPast(
1057
+ last_hidden_state=hidden_states,
1058
+ past_key_values=past_key_values,
1059
+ )
1060
+
1061
+
1062
+ @auto_docstring(
1063
+ custom_intro="""
1064
+ The Qwen3ASRThinker model which consists of a audio backbone and a language model.
1065
+ """
1066
+ )
1067
+ class Qwen3ASRThinkerForConditionalGeneration(Qwen3ASRPreTrainedModelForConditionalGeneration, GenerationMixin):
1068
+ config: Qwen3ASRThinkerConfig
1069
+ base_model_prefix = "thinker"
1070
+ _tied_weights_keys = ["model.embed_tokens.weight", "lm_head.weight"]
1071
+ _no_split_modules = [
1072
+ "Qwen3ASRAudioEncoderLayer",
1073
+ "Qwen3ASRThinkerTextDecoderLayer",
1074
+ ]
1075
+ _can_record_outputs = {
1076
+ "hidden_states": Qwen3ASRThinkerTextDecoderLayer,
1077
+ "attentions": Qwen3ASRThinkerTextAttention,
1078
+ }
1079
+
1080
+ def __init__(self, config):
1081
+ super().__init__(config)
1082
+ self.audio_tower = Qwen3ASRAudioEncoder._from_config(config.audio_config)
1083
+ self.vocab_size = config.text_config.vocab_size
1084
+ self.model = Qwen3ASRThinkerTextModel._from_config(config.text_config)
1085
+ if "forced_aligner" in config.model_type:
1086
+ self.lm_head = nn.Linear(config.text_config.hidden_size, config.classify_num, bias=False)
1087
+ else:
1088
+ self.lm_head = nn.Linear(config.text_config.hidden_size, config.text_config.vocab_size, bias=False)
1089
+ self.pad_token_id = self.config.pad_token_id if self.config.pad_token_id is not None else -1
1090
+ self.rope_deltas = None
1091
+ self.post_init()
1092
+
1093
+ def get_input_embeddings(self):
1094
+ return self.model.get_input_embeddings()
1095
+
1096
+ def set_input_embeddings(self, value):
1097
+ self.model.set_input_embeddings(value)
1098
+
1099
+ def get_audio_features(
1100
+ self,
1101
+ input_features: torch.FloatTensor,
1102
+ feature_attention_mask: Optional[torch.LongTensor] = None,
1103
+ audio_feature_lengths: Optional[torch.LongTensor] = None,
1104
+ ):
1105
+ """
1106
+ Encodes audios into continuous embeddings that can be forwarded to the language model.
1107
+
1108
+ Args:
1109
+ input_features (`torch.FloatTensor`):
1110
+ The tensors corresponding to the input audios.
1111
+ feature_attention_mask (`torch.LongTensor`, *optional*):
1112
+ Mask to avoid performing attention on padding feature indices. Mask values selected in `[0, 1]`:
1113
+ audio_feature_lengths (`torch.LongTensor` of shape `(num_audios)`, *optional*):
1114
+ The length of feature shape of each audio in LLM.
1115
+ """
1116
+ if feature_attention_mask is not None:
1117
+ audio_feature_lengths = torch.sum(feature_attention_mask, dim=1)
1118
+ else:
1119
+ audio_feature_lengths = None
1120
+ feature_lens = audio_feature_lengths if audio_feature_lengths is not None else feature_attention_mask.sum(-1)
1121
+
1122
+ # audio encoder do not support batch inference to keep precision
1123
+ audio_features = []
1124
+ for input_feature, feature_len in zip(input_features, feature_lens):
1125
+ audio_output = self.audio_tower(
1126
+ input_feature[:, :feature_len],
1127
+ feature_lens=feature_len.unsqueeze(0),
1128
+ )
1129
+ audio_feature = audio_output.last_hidden_state
1130
+ audio_features.append(audio_feature)
1131
+ audio_features = torch.cat(audio_features, dim=0)
1132
+
1133
+ return audio_features
1134
+
1135
+ def get_placeholder_mask(
1136
+ self,
1137
+ input_ids: torch.LongTensor,
1138
+ inputs_embeds: torch.FloatTensor,
1139
+ ):
1140
+ """
1141
+ Obtains multimodal placeholder mask from `input_ids` or `inputs_embeds`, and checks that the placeholder token count is
1142
+ equal to the length of multimodal features. If the lengths are different, an error is raised.
1143
+ """
1144
+ if input_ids is None:
1145
+ special_audio_mask = (
1146
+ inputs_embeds
1147
+ == self.get_input_embeddings()(
1148
+ torch.tensor(self.config.audio_token_id, dtype=torch.long, device=inputs_embeds.device)
1149
+ )
1150
+ ).all(-1)
1151
+ else:
1152
+ special_audio_mask = input_ids == self.config.audio_token_id
1153
+
1154
+ special_audio_mask = special_audio_mask.unsqueeze(-1).expand_as(inputs_embeds).to(inputs_embeds.device)
1155
+ return special_audio_mask
1156
+
1157
+ @can_return_tuple
1158
+ @auto_docstring
1159
+ def forward(
1160
+ self,
1161
+ input_ids=None,
1162
+ input_features=None,
1163
+ attention_mask=None,
1164
+ feature_attention_mask=None,
1165
+ audio_feature_lengths=None,
1166
+ position_ids=None,
1167
+ past_key_values=None,
1168
+ inputs_embeds=None,
1169
+ rope_deltas=None,
1170
+ labels=None,
1171
+ use_cache=None,
1172
+ cache_position=None,
1173
+ **kwargs,
1174
+ ) -> Union[tuple, Qwen3ASRThinkerCausalLMOutputWithPast]:
1175
+ r"""
1176
+ feature_attention_mask (`torch.Tensor` of shape `(batch_size, feature_sequence_length)`, *optional*):
1177
+ Mask to avoid performing attention on padding feature indices. Mask values selected in `[0, 1]`:
1178
+ - 1 for tokens that are **not masked**,
1179
+ - 0 for tokens that are **masked**.
1180
+ audio_feature_lengths (`torch.LongTensor` of shape `(num_audios)`, *optional*):
1181
+ The length of feature shape of each audio in LLM.
1182
+ rope_deltas (`torch.LongTensor` of shape `(batch_size, )`, *optional*):
1183
+ The rope index difference between sequence length and multimodal rope.
1184
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
1185
+ Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
1186
+ config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
1187
+ (masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
1188
+ """
1189
+
1190
+ if inputs_embeds is None:
1191
+ # 1. Extract the input embeddings
1192
+ inputs_embeds = self.get_input_embeddings()(input_ids)
1193
+
1194
+ # 2. Merge text, audios
1195
+ if input_features is not None:
1196
+ audio_features = self.get_audio_features(
1197
+ input_features,
1198
+ feature_attention_mask=feature_attention_mask,
1199
+ audio_feature_lengths=audio_feature_lengths,
1200
+ )
1201
+ audio_features = audio_features.to(inputs_embeds.device, inputs_embeds.dtype)
1202
+ audio_mask = self.get_placeholder_mask(input_ids, inputs_embeds=inputs_embeds)
1203
+ inputs_embeds = inputs_embeds.masked_scatter(audio_mask, audio_features)
1204
+
1205
+ if feature_attention_mask is not None:
1206
+ audio_feature_lengths = torch.sum(feature_attention_mask, dim=1)
1207
+ else:
1208
+ audio_feature_lengths = None
1209
+
1210
+ if attention_mask is not None and position_ids is None:
1211
+ if (
1212
+ cache_position is None
1213
+ or (cache_position is not None and cache_position[0] == 0)
1214
+ or self.rope_deltas is None
1215
+ ):
1216
+ delta0 = (1 - attention_mask).sum(dim=-1).unsqueeze(1)
1217
+ position_ids, rope_deltas = self.get_rope_index(
1218
+ attention_mask,
1219
+ )
1220
+ rope_deltas = rope_deltas - delta0
1221
+ self.rope_deltas = rope_deltas
1222
+ else:
1223
+ batch_size, seq_length = input_ids.shape
1224
+ delta = cache_position[0] + self.rope_deltas if cache_position is not None else 0
1225
+ position_ids = torch.arange(seq_length, device=input_ids.device)
1226
+ position_ids = position_ids.view(1, -1).expand(batch_size, -1)
1227
+ position_ids = position_ids.add(delta)
1228
+ position_ids = position_ids.unsqueeze(0).expand(3, -1, -1)
1229
+
1230
+ outputs = self.model(
1231
+ attention_mask=attention_mask,
1232
+ position_ids=position_ids,
1233
+ past_key_values=past_key_values,
1234
+ inputs_embeds=inputs_embeds,
1235
+ use_cache=use_cache,
1236
+ cache_position=cache_position,
1237
+ **kwargs,
1238
+ )
1239
+
1240
+ hidden_states = outputs[0]
1241
+ logits = self.lm_head(hidden_states)
1242
+
1243
+ loss = None
1244
+ if labels is not None:
1245
+ loss = self.loss_function(
1246
+ logits=logits, labels=labels, vocab_size=self.config.get_text_config().vocab_size
1247
+ )
1248
+
1249
+ return Qwen3ASRThinkerCausalLMOutputWithPast(
1250
+ loss=loss,
1251
+ logits=logits,
1252
+ hidden_states=outputs.hidden_states,
1253
+ attentions=outputs.attentions,
1254
+ past_key_values=outputs.past_key_values,
1255
+ rope_deltas=self.rope_deltas,
1256
+ )
1257
+
1258
+ def prepare_inputs_for_generation(
1259
+ self,
1260
+ input_ids,
1261
+ past_key_values=None,
1262
+ attention_mask=None,
1263
+ inputs_embeds=None,
1264
+ cache_position=None,
1265
+ position_ids=None,
1266
+ use_cache=True,
1267
+ input_features=None,
1268
+ feature_attention_mask=None,
1269
+ **kwargs,
1270
+ ):
1271
+ model_inputs = super().prepare_inputs_for_generation(
1272
+ input_ids,
1273
+ past_key_values=past_key_values,
1274
+ attention_mask=attention_mask,
1275
+ inputs_embeds=inputs_embeds,
1276
+ cache_position=cache_position,
1277
+ position_ids=position_ids,
1278
+ use_cache=use_cache,
1279
+ input_features=input_features,
1280
+ feature_attention_mask=feature_attention_mask,
1281
+ **kwargs,
1282
+ )
1283
+
1284
+ model_inputs["position_ids"] = None
1285
+
1286
+ if cache_position[0] != 0:
1287
+ model_inputs["input_features"] = None
1288
+
1289
+ return model_inputs
1290
+
1291
+
1292
+ @auto_docstring
1293
+ class Qwen3ASRThinkerTextPreTrainedModel(PreTrainedModel):
1294
+ config = Qwen3ASRConfig
1295
+ base_model_prefix = "model"
1296
+ supports_gradient_checkpointing = True
1297
+ _no_split_modules = ["Qwen3ASRThinkerTextDecoderLayer"]
1298
+ _skip_keys_device_placement = ["past_key_values"]
1299
+ _supports_flash_attn = True
1300
+ _supports_sdpa = True
1301
+ _supports_flex_attn = True
1302
+ _can_compile_fullgraph = False # MoE models don't work with torch.compile (`torch.where(condition)` not supported)
1303
+ _supports_attention_backend = True
1304
+ _can_record_outputs = {
1305
+ "hidden_states": Qwen3ASRThinkerTextDecoderLayer,
1306
+ "attentions": Qwen3ASRThinkerTextAttention,
1307
+ }
1308
+ config_class = Qwen3ASRConfig
1309
+
1310
+
1311
+ class Qwen3ASRForConditionalGeneration(Qwen3ASRPreTrainedModel, GenerationMixin):
1312
+ config_class = Qwen3ASRConfig
1313
+
1314
+ def __init__(self, config: Qwen3ASRConfig):
1315
+ super().__init__(config)
1316
+ self.config = config
1317
+
1318
+ self.thinker = Qwen3ASRThinkerForConditionalGeneration._from_config(config.thinker_config)
1319
+ self.post_init()
1320
+
1321
+ def get_support_languages(self):
1322
+ return self.config.support_languages
1323
+
1324
+ @torch.no_grad()
1325
+ def generate(
1326
+ self,
1327
+ input_ids: Optional[torch.Tensor] = None,
1328
+ max_new_tokens: int = 4096,
1329
+ eos_token_id: int | list[int] = [151645, 151643],
1330
+ **kwargs,
1331
+ ):
1332
+ shared_kwargs = {}
1333
+ thinker_kwargs = {
1334
+ "max_new_tokens": max_new_tokens,
1335
+ "eos_token_id": eos_token_id,
1336
+ }
1337
+
1338
+ for key, value in kwargs.items():
1339
+ # Process special input values
1340
+ if key == "feature_attention_mask":
1341
+ thinker_kwargs[key] = value
1342
+ elif key in ("input_features", "attention_mask"):
1343
+ thinker_kwargs[key] = value
1344
+ # Put other key to shared kwargs
1345
+ else:
1346
+ shared_kwargs[key] = value
1347
+
1348
+ # Merge kwargs
1349
+ for key, value in shared_kwargs.items():
1350
+ if key not in thinker_kwargs:
1351
+ thinker_kwargs[key] = value
1352
+
1353
+ thinker_result = self.thinker.generate(input_ids=input_ids, return_dict_in_generate=True, **thinker_kwargs)
1354
+
1355
+ return thinker_result
1356
+
1357
+
1358
+ __all__ = [
1359
+ "Qwen3ASRForConditionalGeneration",
1360
+ "Qwen3ASRThinkerTextModel",
1361
+ "Qwen3ASRThinkerForConditionalGeneration",
1362
+ "Qwen3ASRPreTrainedModel",
1363
+ "Qwen3ASRPreTrainedModelForConditionalGeneration",
1364
+ "Qwen3ASRThinkerTextPreTrainedModel",
1365
+ ]
transformers/preprocessor_config.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "chunk_length": 30,
3
+ "dither": 0.0,
4
+ "feature_extractor_type": "WhisperFeatureExtractor",
5
+ "feature_size": 128,
6
+ "hop_length": 160,
7
+ "n_fft": 400,
8
+ "n_samples": 480000,
9
+ "nb_max_frames": 3000,
10
+ "padding_side": "right",
11
+ "padding_value": 0.0,
12
+ "processor_class": "Qwen3ASRProcessor",
13
+ "return_attention_mask": true,
14
+ "sampling_rate": 16000,
15
+ "auto_map": {
16
+ "AutoProcessor": "processing_audar_asr.Qwen3ASRProcessor"
17
+ }
18
+ }
transformers/processing_audar_asr.py ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2026 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
+ import re
16
+
17
+ import numpy as np
18
+
19
+ from transformers.audio_utils import AudioInput
20
+ from transformers.feature_extraction_utils import BatchFeature
21
+ from transformers.processing_utils import ProcessingKwargs, ProcessorMixin
22
+ from transformers.tokenization_utils_base import TextInput
23
+
24
+
25
+ class Qwen3ASRProcessorKwargs(ProcessingKwargs, total=False):
26
+ _defaults = {
27
+ "text_kwargs": {
28
+ "padding": False,
29
+ "padding_side": "left",
30
+ },
31
+ "audio_kwargs": {
32
+ "sampling_rate": 16000,
33
+ "padding": True,
34
+ "return_attention_mask": True,
35
+ },
36
+ }
37
+
38
+
39
+ def _get_feat_extract_output_lengths(input_lengths):
40
+ """
41
+ Computes the output length of the convolutional layers and the output length of the audio encoder
42
+ """
43
+
44
+ input_lengths_leave = input_lengths % 100
45
+ feat_lengths = (input_lengths_leave - 1) // 2 + 1
46
+ output_lengths = ((feat_lengths - 1) // 2 + 1 - 1) // 2 + 1 + (input_lengths // 100) * 13
47
+ return output_lengths
48
+
49
+
50
+ class Qwen3ASRProcessor(ProcessorMixin):
51
+ r"""
52
+ Constructs a Qwen3ASR processor.
53
+ [`Qwen3ASRProcessor`] offers all the functionalities of [`WhisperFeatureExtractor`], and [`Qwen2TokenizerFast`]. See the
54
+ [`~Qwen3ASRProcessor.__call__`] and [`~Qwen3ASRProcessor.decode`] for more information.
55
+
56
+ Args:
57
+ feature_extractor ([`WhisperFeatureExtractor`], *optional*):
58
+ The audio feature extractor.
59
+ tokenizer ([`Qwen2TokenizerFast`], *optional*):
60
+ The text tokenizer.
61
+ chat_template (`Optional[str]`, *optional*):
62
+ The Jinja template to use for formatting the conversation. If not provided, the default chat template is used.
63
+ """
64
+
65
+ attributes = ["feature_extractor", "tokenizer"]
66
+ feature_extractor_class = "WhisperFeatureExtractor"
67
+ tokenizer_class = ("Qwen2Tokenizer", "Qwen2TokenizerFast")
68
+
69
+ def __init__(
70
+ self, feature_extractor=None, tokenizer=None, chat_template=None
71
+ ):
72
+ super().__init__(feature_extractor, tokenizer, chat_template=chat_template)
73
+ self.audio_token = self.tokenizer.audio_token
74
+ self.audio_bos_token = self.tokenizer.audio_bos_token
75
+ self.audio_eos_token = self.tokenizer.audio_eos_token
76
+
77
+ def __call__(
78
+ self,
79
+ text: TextInput = None,
80
+ audio: AudioInput = None,
81
+ **kwargs,
82
+ ) -> BatchFeature:
83
+ """
84
+ Main method to prepare for the model one or several sequences(s) and audio(s). This method forwards the `text`
85
+ and `kwargs` arguments to Qwen2TokenizerFast's [`~Qwen2TokenizerFast.__call__`] if `text` is not `None` to encode
86
+ the text. To prepare the audio(s), this method forwards the `audio` and `kwargs` arguments to
87
+ WhisperFeatureExtractor's [`~WhisperFeatureExtractor.__call__`] if `audio` is not `None`. Please refer to the doctsring
88
+ of the above two methods for more information.
89
+
90
+ Args:
91
+ text (`str`, `List[str]`, `List[List[str]]`):
92
+ The sequence or batch of sequences to be encoded. Each sequence can be a string or a list of strings
93
+ (pretokenized string). If the sequences are provided as list of strings (pretokenized), you must set
94
+ `is_split_into_words=True` (to lift the ambiguity with a batch of sequences).
95
+ audio (`np.ndarray`, `List[np.ndarray]`):
96
+ The audio or batch of audio to be prepared. Each audio can be a NumPy array.
97
+ """
98
+
99
+ if text is None:
100
+ raise ValueError("You need to specify either a `text` input to process.")
101
+
102
+ output_kwargs = self._merge_kwargs(
103
+ Qwen3ASRProcessorKwargs,
104
+ tokenizer_init_kwargs=self.tokenizer.init_kwargs,
105
+ **kwargs,
106
+ )
107
+
108
+ if audio is not None:
109
+ output_kwargs["audio_kwargs"]["padding"] = True
110
+ output_kwargs["audio_kwargs"]["truncation"] = False
111
+ audio_inputs = self.feature_extractor(audio, **output_kwargs["audio_kwargs"])
112
+ audio_inputs["feature_attention_mask"] = audio_inputs.pop(
113
+ "attention_mask"
114
+ ) # rename feature_attention_mask to prevent conflicts later on
115
+ audio_inputs["input_features"] = audio_inputs.pop(
116
+ "input_features"
117
+ ) # rename input_features to prevent conflicts later on
118
+ audio_lengths = iter(_get_feat_extract_output_lengths(audio_inputs["feature_attention_mask"].sum(-1)))
119
+ else:
120
+ audio_inputs = {}
121
+ audio_lengths = iter([])
122
+
123
+ if not isinstance(text, list):
124
+ text = [text]
125
+
126
+ text = self.replace_multimodal_special_tokens(
127
+ text,
128
+ audio_lengths,
129
+ )
130
+
131
+ texts_inputs = self.tokenizer(text, **output_kwargs["text_kwargs"])
132
+
133
+ return BatchFeature(
134
+ data={**texts_inputs, **audio_inputs},
135
+ tensor_type=kwargs.get("return_tensors"),
136
+ )
137
+
138
+ def replace_multimodal_special_tokens(
139
+ self,
140
+ text,
141
+ audio_lengths,
142
+ ):
143
+
144
+ processed_text = []
145
+ for sample in text:
146
+ positions = []
147
+ special_tokens = [re.escape(tok) for tok in [self.audio_token]]
148
+ pattern = "|".join(special_tokens)
149
+ positions = sorted([(match.start(), match.group()) for match in re.finditer(pattern, sample)])
150
+ positions.sort(key=lambda x: x[0])
151
+
152
+ for _, special_token in positions:
153
+ if special_token == self.audio_token:
154
+ sample = sample.replace(self.audio_token, "<|audio_placeholder|>" * next(audio_lengths), 1)
155
+
156
+ sample = sample.replace("<|audio_placeholder|>", self.audio_token)
157
+ processed_text.append(sample)
158
+ return processed_text
159
+
160
+ def get_chunked_index(self, token_indices: np.ndarray, tokens_per_chunk: int) -> list[tuple[int, int]]:
161
+ """
162
+ Splits token index list into chunks based on token value ranges.
163
+
164
+ Given a list of token indices, returns a list of (start, end) index tuples representing
165
+ slices of the list where the token values fall within successive ranges of `t_ntoken_per_chunk`.
166
+
167
+ For example, if `t_ntoken_per_chunk` is 1000, the function will create chunks such that:
168
+ - the first chunk contains token values < 1000,
169
+ - the second chunk contains values >= 1000 and < 2000, and so on.
170
+
171
+ Parameters:
172
+ token_indices (`np.ndarray`): A monotonically increasing list of token index values.
173
+ t_ntoken_per_chunk (`int`): Number of tokens per chunk (used as the chunk size threshold).
174
+
175
+ Returns:
176
+ `list[tuple[int, int]]`: A list of tuples, each representing the start (inclusive)
177
+ and end (exclusive) indices of a chunk in `token_indices`.
178
+ """
179
+
180
+ def _iter():
181
+ i, start_idx = 0, 0 # skip bos token
182
+ current_chunk = 1
183
+ while i < len(token_indices): # skip eos token
184
+ if token_indices[i] >= current_chunk * tokens_per_chunk:
185
+ yield (start_idx, i)
186
+ start_idx = i
187
+ current_chunk += 1
188
+ i += 1
189
+ yield (start_idx, len(token_indices))
190
+
191
+ return list(_iter())
192
+
193
+ def apply_chat_template(self, conversations, chat_template=None, **kwargs):
194
+ return super().apply_chat_template(conversations, chat_template, **kwargs)
195
+
196
+ @property
197
+ def model_input_names(self):
198
+ tokenizer_input_names = self.tokenizer.model_input_names
199
+ feature_extractor_input_names = self.feature_extractor.model_input_names
200
+ return list(
201
+ dict.fromkeys(
202
+ tokenizer_input_names
203
+ + feature_extractor_input_names
204
+ + ["feature_attention_mask"]
205
+ )
206
+ )
207
+
208
+
209
+ __all__ = ["Qwen3ASRProcessor"]
transformers/special_tokens_map.json ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "additional_special_tokens": [
3
+ {
4
+ "content": "<|arb|>",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false
9
+ },
10
+ {
11
+ "content": "<|ary|>",
12
+ "lstrip": false,
13
+ "normalized": false,
14
+ "rstrip": false,
15
+ "single_word": false
16
+ },
17
+ {
18
+ "content": "<|ars|>",
19
+ "lstrip": false,
20
+ "normalized": false,
21
+ "rstrip": false,
22
+ "single_word": false
23
+ },
24
+ {
25
+ "content": "<|arz|>",
26
+ "lstrip": false,
27
+ "normalized": false,
28
+ "rstrip": false,
29
+ "single_word": false
30
+ },
31
+ {
32
+ "content": "<|apc|>",
33
+ "lstrip": false,
34
+ "normalized": false,
35
+ "rstrip": false,
36
+ "single_word": false
37
+ },
38
+ {
39
+ "content": "<|acm|>",
40
+ "lstrip": false,
41
+ "normalized": false,
42
+ "rstrip": false,
43
+ "single_word": false
44
+ },
45
+ {
46
+ "content": "<|aeb|>",
47
+ "lstrip": false,
48
+ "normalized": false,
49
+ "rstrip": false,
50
+ "single_word": false
51
+ },
52
+ {
53
+ "content": "<|arq|>",
54
+ "lstrip": false,
55
+ "normalized": false,
56
+ "rstrip": false,
57
+ "single_word": false
58
+ }
59
+ ],
60
+ "audio_bos_token": "<|audio_start|>",
61
+ "audio_eos_token": "<|audio_end|>",
62
+ "audio_token": "<|audio_pad|>",
63
+ "eos_token": {
64
+ "content": "<|im_end|>",
65
+ "lstrip": false,
66
+ "normalized": false,
67
+ "rstrip": false,
68
+ "single_word": false
69
+ },
70
+ "image_token": "<|image_pad|>",
71
+ "pad_token": {
72
+ "content": "<|endoftext|>",
73
+ "lstrip": false,
74
+ "normalized": false,
75
+ "rstrip": false,
76
+ "single_word": false
77
+ },
78
+ "video_token": "<|video_pad|>",
79
+ "vision_bos_token": "<|vision_start|>",
80
+ "vision_eos_token": "<|vision_end|>"
81
+ }
transformers/tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:35d0c8e97867e3d560bef280b9bc00e8ea8d42f9150e27f6016d5cf7100bf5f9
3
+ size 11430971
transformers/tokenizer_config.json ADDED
@@ -0,0 +1,603 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ "151669": {
214
+ "content": "<|audio_start|>",
215
+ "lstrip": false,
216
+ "normalized": false,
217
+ "rstrip": false,
218
+ "single_word": false,
219
+ "special": true
220
+ },
221
+ "151670": {
222
+ "content": "<|audio_end|>",
223
+ "lstrip": false,
224
+ "normalized": false,
225
+ "rstrip": false,
226
+ "single_word": false,
227
+ "special": true
228
+ },
229
+ "151671": {
230
+ "content": "<tts_pad>",
231
+ "lstrip": false,
232
+ "normalized": false,
233
+ "rstrip": false,
234
+ "single_word": false,
235
+ "special": true
236
+ },
237
+ "151672": {
238
+ "content": "<tts_text_bos>",
239
+ "lstrip": false,
240
+ "normalized": false,
241
+ "rstrip": false,
242
+ "single_word": false,
243
+ "special": true
244
+ },
245
+ "151673": {
246
+ "content": "<tts_text_eod>",
247
+ "lstrip": false,
248
+ "normalized": false,
249
+ "rstrip": false,
250
+ "single_word": false,
251
+ "special": true
252
+ },
253
+ "151674": {
254
+ "content": "<tts_text_bos_single>",
255
+ "lstrip": false,
256
+ "normalized": false,
257
+ "rstrip": false,
258
+ "single_word": false,
259
+ "special": true
260
+ },
261
+ "151675": {
262
+ "content": "<non_speech>",
263
+ "lstrip": false,
264
+ "normalized": false,
265
+ "rstrip": false,
266
+ "single_word": false,
267
+ "special": false
268
+ },
269
+ "151676": {
270
+ "content": "<|audio_pad|>",
271
+ "lstrip": false,
272
+ "normalized": false,
273
+ "rstrip": false,
274
+ "single_word": false,
275
+ "special": true
276
+ },
277
+ "151677": {
278
+ "content": "<blank1>",
279
+ "lstrip": false,
280
+ "normalized": false,
281
+ "rstrip": false,
282
+ "single_word": false,
283
+ "special": true
284
+ },
285
+ "151678": {
286
+ "content": "<blank2>",
287
+ "lstrip": false,
288
+ "normalized": false,
289
+ "rstrip": false,
290
+ "single_word": false,
291
+ "special": true
292
+ },
293
+ "151679": {
294
+ "content": "<blank3>",
295
+ "lstrip": false,
296
+ "normalized": false,
297
+ "rstrip": false,
298
+ "single_word": false,
299
+ "special": true
300
+ },
301
+ "151680": {
302
+ "content": "<blank4>",
303
+ "lstrip": false,
304
+ "normalized": false,
305
+ "rstrip": false,
306
+ "single_word": false,
307
+ "special": true
308
+ },
309
+ "151681": {
310
+ "content": "<blank5>",
311
+ "lstrip": false,
312
+ "normalized": false,
313
+ "rstrip": false,
314
+ "single_word": false,
315
+ "special": true
316
+ },
317
+ "151682": {
318
+ "content": "<blank6>",
319
+ "lstrip": false,
320
+ "normalized": false,
321
+ "rstrip": false,
322
+ "single_word": false,
323
+ "special": true
324
+ },
325
+ "151683": {
326
+ "content": "<blank7>",
327
+ "lstrip": false,
328
+ "normalized": false,
329
+ "rstrip": false,
330
+ "single_word": false,
331
+ "special": true
332
+ },
333
+ "151684": {
334
+ "content": "<blank8>",
335
+ "lstrip": false,
336
+ "normalized": false,
337
+ "rstrip": false,
338
+ "single_word": false,
339
+ "special": true
340
+ },
341
+ "151685": {
342
+ "content": "<blank9>",
343
+ "lstrip": false,
344
+ "normalized": false,
345
+ "rstrip": false,
346
+ "single_word": false,
347
+ "special": true
348
+ },
349
+ "151686": {
350
+ "content": "<blank10>",
351
+ "lstrip": false,
352
+ "normalized": false,
353
+ "rstrip": false,
354
+ "single_word": false,
355
+ "special": true
356
+ },
357
+ "151687": {
358
+ "content": "<blank11>",
359
+ "lstrip": false,
360
+ "normalized": false,
361
+ "rstrip": false,
362
+ "single_word": false,
363
+ "special": true
364
+ },
365
+ "151688": {
366
+ "content": "<blank12>",
367
+ "lstrip": false,
368
+ "normalized": false,
369
+ "rstrip": false,
370
+ "single_word": false,
371
+ "special": true
372
+ },
373
+ "151689": {
374
+ "content": "<blank13>",
375
+ "lstrip": false,
376
+ "normalized": false,
377
+ "rstrip": false,
378
+ "single_word": false,
379
+ "special": true
380
+ },
381
+ "151690": {
382
+ "content": "<blank14>",
383
+ "lstrip": false,
384
+ "normalized": false,
385
+ "rstrip": false,
386
+ "single_word": false,
387
+ "special": true
388
+ },
389
+ "151691": {
390
+ "content": "<blank15>",
391
+ "lstrip": false,
392
+ "normalized": false,
393
+ "rstrip": false,
394
+ "single_word": false,
395
+ "special": true
396
+ },
397
+ "151692": {
398
+ "content": "<blank16>",
399
+ "lstrip": false,
400
+ "normalized": false,
401
+ "rstrip": false,
402
+ "single_word": false,
403
+ "special": true
404
+ },
405
+ "151693": {
406
+ "content": "<blank17>",
407
+ "lstrip": false,
408
+ "normalized": false,
409
+ "rstrip": false,
410
+ "single_word": false,
411
+ "special": true
412
+ },
413
+ "151694": {
414
+ "content": "<blank18>",
415
+ "lstrip": false,
416
+ "normalized": false,
417
+ "rstrip": false,
418
+ "single_word": false,
419
+ "special": true
420
+ },
421
+ "151695": {
422
+ "content": "<blank19>",
423
+ "lstrip": false,
424
+ "normalized": false,
425
+ "rstrip": false,
426
+ "single_word": false,
427
+ "special": true
428
+ },
429
+ "151696": {
430
+ "content": "<blank20>",
431
+ "lstrip": false,
432
+ "normalized": false,
433
+ "rstrip": false,
434
+ "single_word": false,
435
+ "special": true
436
+ },
437
+ "151697": {
438
+ "content": "<blank21>",
439
+ "lstrip": false,
440
+ "normalized": false,
441
+ "rstrip": false,
442
+ "single_word": false,
443
+ "special": true
444
+ },
445
+ "151698": {
446
+ "content": "<blank22>",
447
+ "lstrip": false,
448
+ "normalized": false,
449
+ "rstrip": false,
450
+ "single_word": false,
451
+ "special": true
452
+ },
453
+ "151699": {
454
+ "content": "<blank23>",
455
+ "lstrip": false,
456
+ "normalized": false,
457
+ "rstrip": false,
458
+ "single_word": false,
459
+ "special": true
460
+ },
461
+ "151700": {
462
+ "content": "<blank24>",
463
+ "lstrip": false,
464
+ "normalized": false,
465
+ "rstrip": false,
466
+ "single_word": false,
467
+ "special": true
468
+ },
469
+ "151701": {
470
+ "content": "<blank25>",
471
+ "lstrip": false,
472
+ "normalized": false,
473
+ "rstrip": false,
474
+ "single_word": false,
475
+ "special": true
476
+ },
477
+ "151702": {
478
+ "content": "<blank26>",
479
+ "lstrip": false,
480
+ "normalized": false,
481
+ "rstrip": false,
482
+ "single_word": false,
483
+ "special": true
484
+ },
485
+ "151703": {
486
+ "content": "<blank27>",
487
+ "lstrip": false,
488
+ "normalized": false,
489
+ "rstrip": false,
490
+ "single_word": false,
491
+ "special": true
492
+ },
493
+ "151704": {
494
+ "content": "<asr_text>",
495
+ "lstrip": false,
496
+ "normalized": false,
497
+ "rstrip": false,
498
+ "single_word": false,
499
+ "special": false
500
+ },
501
+ "151705": {
502
+ "content": "<|arb|>",
503
+ "lstrip": false,
504
+ "normalized": false,
505
+ "rstrip": false,
506
+ "single_word": false,
507
+ "special": true
508
+ },
509
+ "151706": {
510
+ "content": "<|ary|>",
511
+ "lstrip": false,
512
+ "normalized": false,
513
+ "rstrip": false,
514
+ "single_word": false,
515
+ "special": true
516
+ },
517
+ "151707": {
518
+ "content": "<|ars|>",
519
+ "lstrip": false,
520
+ "normalized": false,
521
+ "rstrip": false,
522
+ "single_word": false,
523
+ "special": true
524
+ },
525
+ "151708": {
526
+ "content": "<|arz|>",
527
+ "lstrip": false,
528
+ "normalized": false,
529
+ "rstrip": false,
530
+ "single_word": false,
531
+ "special": true
532
+ },
533
+ "151709": {
534
+ "content": "<|apc|>",
535
+ "lstrip": false,
536
+ "normalized": false,
537
+ "rstrip": false,
538
+ "single_word": false,
539
+ "special": true
540
+ },
541
+ "151710": {
542
+ "content": "<|acm|>",
543
+ "lstrip": false,
544
+ "normalized": false,
545
+ "rstrip": false,
546
+ "single_word": false,
547
+ "special": true
548
+ },
549
+ "151711": {
550
+ "content": "<|aeb|>",
551
+ "lstrip": false,
552
+ "normalized": false,
553
+ "rstrip": false,
554
+ "single_word": false,
555
+ "special": true
556
+ },
557
+ "151712": {
558
+ "content": "<|arq|>",
559
+ "lstrip": false,
560
+ "normalized": false,
561
+ "rstrip": false,
562
+ "single_word": false,
563
+ "special": true
564
+ }
565
+ },
566
+ "additional_special_tokens": [
567
+ "<|arb|>",
568
+ "<|ary|>",
569
+ "<|ars|>",
570
+ "<|arz|>",
571
+ "<|apc|>",
572
+ "<|acm|>",
573
+ "<|aeb|>",
574
+ "<|arq|>"
575
+ ],
576
+ "audio_bos_token": "<|audio_start|>",
577
+ "audio_eos_token": "<|audio_end|>",
578
+ "audio_token": "<|audio_pad|>",
579
+ "bos_token": null,
580
+ "clean_up_tokenization_spaces": false,
581
+ "eos_token": "<|im_end|>",
582
+ "errors": "replace",
583
+ "extra_special_tokens": {
584
+ "audio_bos_token": "<|audio_start|>",
585
+ "audio_eos_token": "<|audio_end|>",
586
+ "audio_token": "<|audio_pad|>",
587
+ "image_token": "<|image_pad|>",
588
+ "video_token": "<|video_pad|>",
589
+ "vision_bos_token": "<|vision_start|>",
590
+ "vision_eos_token": "<|vision_end|>"
591
+ },
592
+ "fix_mistral_regex": true,
593
+ "image_token": "<|image_pad|>",
594
+ "model_max_length": 131072,
595
+ "pad_token": "<|endoftext|>",
596
+ "processor_class": "Qwen3ASRProcessor",
597
+ "split_special_tokens": false,
598
+ "tokenizer_class": "Qwen2Tokenizer",
599
+ "unk_token": null,
600
+ "video_token": "<|video_pad|>",
601
+ "vision_bos_token": "<|vision_start|>",
602
+ "vision_eos_token": "<|vision_end|>"
603
+ }
transformers/vocab.json ADDED
The diff for this file is too large to render. See raw diff