yangwang825 commited on
Commit
f14099b
·
verified ·
1 Parent(s): 0166738

End of training

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ step_*
2
+ epoch_*
README.md ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - en
4
+ tags:
5
+ - token-classification
6
+ - ner
7
+ - pytorch
8
+ - custom-model
9
+ library_name: transformers
10
+ ---
11
+
12
+ # UnmaskingQwen3 for Token Classification
13
+
14
+ This model is a fine-tuned version of a custom UnmaskingQwen3ForTokenClassification model for token classification tasks.
15
+
16
+ ## Model Details
17
+
18
+ - **Model Type**: Custom UnmaskingQwen3ForTokenClassification
19
+ - **Task**: Token Classification (NER/POS/Chunking)
20
+ - **Training Framework**: Transformers + Accelerate
21
+
22
+ ## Usage
23
+
24
+ ```python
25
+ from transformers import AutoTokenizer, AutoModelForTokenClassification
26
+
27
+ # Load the model and tokenizer
28
+ tokenizer = AutoTokenizer.from_pretrained("your-username/your-model-name", trust_remote_code=True)
29
+ model = AutoModelForTokenClassification.from_pretrained("your-username/your-model-name", trust_remote_code=True)
30
+
31
+ # Use for inference
32
+ inputs = tokenizer(["Your text here"], return_tensors="pt", is_split_into_words=False)
33
+ outputs = model(**inputs)
34
+ predictions = outputs.logits.argmax(dim=-1)
35
+ ```
36
+
37
+ ## Training Details
38
+
39
+ - **Training Data**: ['automated-analytics/ai4privacy-pii-masking-en-v1-ner', 'automated-analytics/gretel-pii-masking-en-v1-ner']
40
+ - **Learning Rate**: 5e-05
41
+ - **Batch Size**: 128
42
+ - **Epochs**: 3
43
+ - **Max Length**: 128
44
+
45
+ ## Evaluation Results
46
+
47
+ ### Overall Metrics
48
+
49
+ - Precision: 0.0000
50
+ - Recall: 0.0000
51
+ - F1 Score: 0.0000
52
+ - Accuracy: 0.0000
53
+
54
+ ### Entity-level Performance
55
+
56
+ | Entity Type | Precision | Recall | F1-Score | Support |
57
+ | ----------- | --------- | ------ | -------- | ------- |
58
+
59
+
60
+ ## Important Note
61
+
62
+ This model uses a custom model class. Make sure to use `trust_remote_code=True` when loading the model.
__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .modeling_unmasking_qwen import UnmaskingQwen2ForTokenClassification, UnmaskingQwen3ForTokenClassification
added_tokens.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "</tool_call>": 151658,
3
+ "<tool_call>": 151657,
4
+ "<|box_end|>": 151649,
5
+ "<|box_start|>": 151648,
6
+ "<|endoftext|>": 151643,
7
+ "<|file_sep|>": 151664,
8
+ "<|fim_middle|>": 151660,
9
+ "<|fim_pad|>": 151662,
10
+ "<|fim_prefix|>": 151659,
11
+ "<|fim_suffix|>": 151661,
12
+ "<|im_end|>": 151645,
13
+ "<|im_start|>": 151644,
14
+ "<|image_pad|>": 151655,
15
+ "<|object_ref_end|>": 151647,
16
+ "<|object_ref_start|>": 151646,
17
+ "<|quad_end|>": 151651,
18
+ "<|quad_start|>": 151650,
19
+ "<|repo_name|>": 151663,
20
+ "<|video_pad|>": 151656,
21
+ "<|vision_end|>": 151653,
22
+ "<|vision_pad|>": 151654,
23
+ "<|vision_start|>": 151652
24
+ }
config.json ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "UnmaskingQwen2ForTokenClassification"
4
+ ],
5
+ "attention_dropout": 0.0,
6
+ "bos_token_id": 151643,
7
+ "eos_token_id": 151645,
8
+ "hidden_act": "silu",
9
+ "hidden_size": 896,
10
+ "id2label": {
11
+ "0": "O",
12
+ "1": "B-medical_record_number",
13
+ "2": "I-medical_record_number",
14
+ "3": "B-date_of_birth",
15
+ "4": "I-date_of_birth",
16
+ "5": "B-ssn",
17
+ "6": "I-ssn",
18
+ "7": "B-date",
19
+ "8": "I-date",
20
+ "9": "B-first_name",
21
+ "10": "I-first_name",
22
+ "11": "B-email",
23
+ "12": "I-email",
24
+ "13": "B-last_name",
25
+ "14": "I-last_name",
26
+ "15": "B-customer_id",
27
+ "16": "I-customer_id",
28
+ "17": "B-employee_id",
29
+ "18": "I-employee_id",
30
+ "19": "B-name",
31
+ "20": "I-name",
32
+ "21": "B-street_address",
33
+ "22": "I-street_address",
34
+ "23": "B-phone_number",
35
+ "24": "I-phone_number",
36
+ "25": "B-ipv4",
37
+ "26": "I-ipv4",
38
+ "27": "B-credit_card_number",
39
+ "28": "I-credit_card_number",
40
+ "29": "B-license_plate",
41
+ "30": "I-license_plate",
42
+ "31": "B-address",
43
+ "32": "I-address",
44
+ "33": "B-user_name",
45
+ "34": "I-user_name",
46
+ "35": "B-device_identifier",
47
+ "36": "I-device_identifier",
48
+ "37": "B-bank_routing_number",
49
+ "38": "I-bank_routing_number",
50
+ "39": "B-date_time",
51
+ "40": "I-date_time",
52
+ "41": "B-company_name",
53
+ "42": "I-company_name",
54
+ "43": "B-unique_identifier",
55
+ "44": "I-unique_identifier",
56
+ "45": "B-biometric_identifier",
57
+ "46": "I-biometric_identifier",
58
+ "47": "B-account_number",
59
+ "48": "I-account_number",
60
+ "49": "B-city",
61
+ "50": "I-city",
62
+ "51": "B-certificate_license_number",
63
+ "52": "I-certificate_license_number",
64
+ "53": "B-time",
65
+ "54": "I-time",
66
+ "55": "B-postcode",
67
+ "56": "I-postcode",
68
+ "57": "B-vehicle_identifier",
69
+ "58": "I-vehicle_identifier",
70
+ "59": "B-coordinate",
71
+ "60": "I-coordinate",
72
+ "61": "B-country",
73
+ "62": "I-country",
74
+ "63": "B-api_key",
75
+ "64": "I-api_key",
76
+ "65": "B-ipv6",
77
+ "66": "I-ipv6",
78
+ "67": "B-password",
79
+ "68": "I-password",
80
+ "69": "B-health_plan_beneficiary_number",
81
+ "70": "I-health_plan_beneficiary_number",
82
+ "71": "B-national_id",
83
+ "72": "I-national_id",
84
+ "73": "B-tax_id",
85
+ "74": "I-tax_id",
86
+ "75": "B-url",
87
+ "76": "I-url",
88
+ "77": "B-state",
89
+ "78": "I-state",
90
+ "79": "B-swift_bic",
91
+ "80": "I-swift_bic",
92
+ "81": "B-cvv",
93
+ "82": "I-cvv",
94
+ "83": "B-pin",
95
+ "84": "I-pin"
96
+ },
97
+ "initializer_range": 0.02,
98
+ "intermediate_size": 4864,
99
+ "label2id": {
100
+ "B-account_number": 47,
101
+ "B-address": 31,
102
+ "B-api_key": 63,
103
+ "B-bank_routing_number": 37,
104
+ "B-biometric_identifier": 45,
105
+ "B-certificate_license_number": 51,
106
+ "B-city": 49,
107
+ "B-company_name": 41,
108
+ "B-coordinate": 59,
109
+ "B-country": 61,
110
+ "B-credit_card_number": 27,
111
+ "B-customer_id": 15,
112
+ "B-cvv": 81,
113
+ "B-date": 7,
114
+ "B-date_of_birth": 3,
115
+ "B-date_time": 39,
116
+ "B-device_identifier": 35,
117
+ "B-email": 11,
118
+ "B-employee_id": 17,
119
+ "B-first_name": 9,
120
+ "B-health_plan_beneficiary_number": 69,
121
+ "B-ipv4": 25,
122
+ "B-ipv6": 65,
123
+ "B-last_name": 13,
124
+ "B-license_plate": 29,
125
+ "B-medical_record_number": 1,
126
+ "B-name": 19,
127
+ "B-national_id": 71,
128
+ "B-password": 67,
129
+ "B-phone_number": 23,
130
+ "B-pin": 83,
131
+ "B-postcode": 55,
132
+ "B-ssn": 5,
133
+ "B-state": 77,
134
+ "B-street_address": 21,
135
+ "B-swift_bic": 79,
136
+ "B-tax_id": 73,
137
+ "B-time": 53,
138
+ "B-unique_identifier": 43,
139
+ "B-url": 75,
140
+ "B-user_name": 33,
141
+ "B-vehicle_identifier": 57,
142
+ "I-account_number": 48,
143
+ "I-address": 32,
144
+ "I-api_key": 64,
145
+ "I-bank_routing_number": 38,
146
+ "I-biometric_identifier": 46,
147
+ "I-certificate_license_number": 52,
148
+ "I-city": 50,
149
+ "I-company_name": 42,
150
+ "I-coordinate": 60,
151
+ "I-country": 62,
152
+ "I-credit_card_number": 28,
153
+ "I-customer_id": 16,
154
+ "I-cvv": 82,
155
+ "I-date": 8,
156
+ "I-date_of_birth": 4,
157
+ "I-date_time": 40,
158
+ "I-device_identifier": 36,
159
+ "I-email": 12,
160
+ "I-employee_id": 18,
161
+ "I-first_name": 10,
162
+ "I-health_plan_beneficiary_number": 70,
163
+ "I-ipv4": 26,
164
+ "I-ipv6": 66,
165
+ "I-last_name": 14,
166
+ "I-license_plate": 30,
167
+ "I-medical_record_number": 2,
168
+ "I-name": 20,
169
+ "I-national_id": 72,
170
+ "I-password": 68,
171
+ "I-phone_number": 24,
172
+ "I-pin": 84,
173
+ "I-postcode": 56,
174
+ "I-ssn": 6,
175
+ "I-state": 78,
176
+ "I-street_address": 22,
177
+ "I-swift_bic": 80,
178
+ "I-tax_id": 74,
179
+ "I-time": 54,
180
+ "I-unique_identifier": 44,
181
+ "I-url": 76,
182
+ "I-user_name": 34,
183
+ "I-vehicle_identifier": 58,
184
+ "O": 0
185
+ },
186
+ "max_position_embeddings": 32768,
187
+ "max_window_layers": 21,
188
+ "model_type": "qwen2",
189
+ "num_attention_heads": 14,
190
+ "num_hidden_layers": 24,
191
+ "num_key_value_heads": 2,
192
+ "rms_norm_eps": 1e-06,
193
+ "rope_scaling": null,
194
+ "rope_theta": 1000000.0,
195
+ "sliding_window": 32768,
196
+ "tie_word_embeddings": true,
197
+ "torch_dtype": "float32",
198
+ "transformers_version": "4.51.3",
199
+ "use_cache": true,
200
+ "use_sliding_window": false,
201
+ "vocab_size": 151936,
202
+ "auto_map": {
203
+ "AutoModelForTokenClassification": "modeling_unmasking_qwen.UnmaskingQwen3ForTokenClassification"
204
+ }
205
+ }
configuration_unmasking_qwen.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+
2
+ from transformers.configuration_utils import PretrainedConfig
3
+
4
+ class UnmaskingQwenConfig(PretrainedConfig):
5
+ model_type = "unmasking_qwen"
merges.txt ADDED
The diff for this file is too large to render. See raw diff
 
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a794f6e3e7c5ad34ec15ddb9fd27c18ee491a588c9981fbe23454b24fddc97fa
3
+ size 1976468620
modeling_unmasking_qwen.py ADDED
@@ -0,0 +1,1051 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # Unmasking Qwen Token Classification Models
3
+ # Automatically generated file for model use with trust_remote_code=True
4
+
5
+ import torch
6
+ import torch.nn as nn
7
+ from transformers import PreTrainedModel
8
+ from transformers.modeling_outputs import TokenClassifierOutput
9
+
10
+ from typing import Optional, Tuple, Union, List, Dict, Callable
11
+
12
+ import torch
13
+ import torch.nn as nn
14
+
15
+ from transformers.modeling_outputs import TokenClassifierOutput
16
+ from transformers.models.bert import (
17
+ BertConfig, BertModel, BertPreTrainedModel
18
+ )
19
+ from transformers.models.roberta import (
20
+ RobertaConfig, RobertaModel, RobertaPreTrainedModel
21
+ )
22
+ from transformers.models.deberta_v2 import (
23
+ DebertaV2Config, DebertaV2Model, DebertaV2PreTrainedModel
24
+ )
25
+ from transformers.models.modernbert.modeling_modernbert import (
26
+ ModernBertConfig, ModernBertModel, ModernBertPreTrainedModel, ModernBertPredictionHead
27
+ )
28
+ from transformers import Qwen2Config
29
+ from transformers.modeling_outputs import TokenClassifierOutput, BaseModelOutputWithPast
30
+ from transformers.cache_utils import Cache
31
+ from transformers.modeling_flash_attention_utils import FlashAttentionKwargs
32
+ from transformers.processing_utils import Unpack
33
+ from transformers.models.qwen2.modeling_qwen2 import (
34
+ Qwen2PreTrainedModel,
35
+ Qwen2Model,
36
+ SlidingWindowCache,
37
+ StaticCache
38
+ )
39
+
40
+ from transformers.models.qwen3.modeling_qwen3 import (
41
+ Qwen3PreTrainedModel,
42
+ Qwen3Config,
43
+ Qwen3Model,
44
+ Qwen3RMSNorm,
45
+ Qwen3DecoderLayer,
46
+ Qwen3Attention,
47
+ BaseModelOutputWithPast,
48
+ TokenClassifierOutput,
49
+ Cache,
50
+ FlashAttentionKwargs,
51
+ Unpack,
52
+ Qwen3RotaryEmbedding,
53
+ Qwen3MLP,
54
+ apply_rotary_pos_emb,
55
+ can_return_tuple,
56
+ eager_attention_forward
57
+ )
58
+
59
+
60
+ def fixed_cross_entropy(
61
+ source: torch.Tensor,
62
+ target: torch.Tensor,
63
+ num_items_in_batch: Optional[int] = None,
64
+ ignore_index: int = -100,
65
+ **kwargs,
66
+ ) -> torch.Tensor:
67
+ reduction = "sum" if num_items_in_batch is not None else "mean"
68
+ loss = nn.functional.cross_entropy(source, target, ignore_index=ignore_index, reduction=reduction)
69
+ if reduction == "sum":
70
+ if not isinstance(num_items_in_batch, torch.Tensor):
71
+ num_items_in_batch = torch.tensor(num_items_in_batch, device=loss.device, dtype=loss.dtype)
72
+ elif num_items_in_batch.device != loss.device:
73
+ num_items_in_batch = num_items_in_batch.to(loss.device)
74
+ loss = loss / num_items_in_batch
75
+ return loss
76
+
77
+
78
+ class BertForTokenClassification(BertPreTrainedModel):
79
+
80
+ def __init__(self, config: BertConfig):
81
+ super().__init__(config)
82
+ self.num_labels = config.num_labels
83
+
84
+ self.bert = BertModel(config, add_pooling_layer=False)
85
+ classifier_dropout = (
86
+ config.classifier_dropout if config.classifier_dropout is not None else config.hidden_dropout_prob
87
+ )
88
+ self.dropout = nn.Dropout(classifier_dropout)
89
+ self.classifier = nn.Linear(config.hidden_size, config.num_labels)
90
+
91
+ # Initialize weights and apply final processing
92
+ self.post_init()
93
+
94
+ def forward(
95
+ self,
96
+ input_ids: Optional[torch.Tensor] = None,
97
+ attention_mask: Optional[torch.Tensor] = None,
98
+ token_type_ids: Optional[torch.Tensor] = None,
99
+ position_ids: Optional[torch.Tensor] = None,
100
+ head_mask: Optional[torch.Tensor] = None,
101
+ inputs_embeds: Optional[torch.Tensor] = None,
102
+ labels: Optional[torch.Tensor] = None,
103
+ output_attentions: Optional[bool] = None,
104
+ output_hidden_states: Optional[bool] = None,
105
+ return_dict: Optional[bool] = None,
106
+ num_items_in_batch: Optional[torch.Tensor] = None,
107
+ ignore_index: int = -100,
108
+ **kwargs,
109
+ ) -> Union[Tuple[torch.Tensor], TokenClassifierOutput]:
110
+ r"""
111
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
112
+ Labels for computing the token classification loss. Indices should be in `[0, ..., config.num_labels - 1]`.
113
+ """
114
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
115
+
116
+ outputs = self.bert(
117
+ input_ids,
118
+ attention_mask=attention_mask,
119
+ token_type_ids=token_type_ids,
120
+ position_ids=position_ids,
121
+ head_mask=head_mask,
122
+ inputs_embeds=inputs_embeds,
123
+ output_attentions=output_attentions,
124
+ output_hidden_states=output_hidden_states,
125
+ return_dict=return_dict,
126
+ )
127
+
128
+ sequence_output = outputs[0]
129
+
130
+ sequence_output = self.dropout(sequence_output)
131
+ logits = self.classifier(sequence_output)
132
+
133
+ loss = None
134
+ if labels is not None:
135
+ logits = logits.view(-1, self.num_labels)
136
+ labels = labels.view(-1).to(logits.device)
137
+ logits = logits.float()
138
+ loss = fixed_cross_entropy(logits, labels, num_items_in_batch, ignore_index)
139
+
140
+ if not return_dict:
141
+ output = (logits,) + outputs[2:]
142
+ return ((loss,) + output) if loss is not None else output
143
+
144
+ return TokenClassifierOutput(
145
+ loss=loss,
146
+ logits=logits,
147
+ hidden_states=outputs.hidden_states,
148
+ attentions=outputs.attentions,
149
+ )
150
+
151
+
152
+ class CRF(nn.Module):
153
+ """條件隨機場(CRF)層,基於更穩定的實現"""
154
+
155
+ def __init__(self, num_labels: int):
156
+ super().__init__()
157
+ self.num_labels = num_labels
158
+
159
+ # 轉移矩陣和起始/結束轉移參數
160
+ self.start_transitions = nn.Parameter(torch.empty(num_labels))
161
+ self.end_transitions = nn.Parameter(torch.empty(num_labels))
162
+ self.transitions = nn.Parameter(torch.empty(num_labels, num_labels))
163
+
164
+ # 用均勻分布初始化參數
165
+ nn.init.uniform_(self.start_transitions, -0.1, 0.1)
166
+ nn.init.uniform_(self.end_transitions, -0.1, 0.1)
167
+ nn.init.uniform_(self.transitions, -0.1, 0.1)
168
+
169
+ def _compute_log_denominator(self, features: torch.Tensor, mask: torch.Tensor) -> torch.Tensor:
170
+ """計算配分函數的對數(log of the partition function)"""
171
+ seq_len, batch_size, _ = features.shape
172
+
173
+ # 初始化得分為起始轉移得分 + 第一個時間步的特征
174
+ log_score = self.start_transitions + features[0] # [batch_size, num_labels]
175
+
176
+ # 逐時間步計算得分
177
+ for i in range(1, seq_len):
178
+ # 計算所有可能的轉移得分:前一時間步得分 + 轉移得分 + 當前時間步特征
179
+ # [batch_size, num_labels, 1] + [num_labels, num_labels] + [batch_size, 1, num_labels]
180
+ # -> [batch_size, num_labels, num_labels]
181
+ next_score = (
182
+ log_score.unsqueeze(2) + # [batch_size, num_labels, 1]
183
+ self.transitions + # [num_labels, num_labels]
184
+ features[i].unsqueeze(1) # [batch_size, 1, num_labels]
185
+ )
186
+
187
+ # 對所有可能的前一個標籤取logsumexp
188
+ next_score = torch.logsumexp(next_score, dim=1)
189
+
190
+ # 根據mask更新得分
191
+ log_score = torch.where(mask[i].unsqueeze(1), next_score, log_score)
192
+
193
+ # 加上到結束標籤的轉移得分
194
+ log_score += self.end_transitions
195
+
196
+ # 對所有可能的最終標籤取logsumexp
197
+ return torch.logsumexp(log_score, dim=1)
198
+
199
+ def _compute_log_numerator(self, features: torch.Tensor, labels: torch.Tensor, mask: torch.Tensor) -> torch.Tensor:
200
+ """計算給定標籤序列的得分"""
201
+ seq_len, batch_size, _ = features.shape
202
+
203
+ # 初始化得分
204
+ score = self.start_transitions[labels[0]] + features[0, torch.arange(batch_size), labels[0]]
205
+
206
+ # 逐時間步累加得分
207
+ for i in range(1, seq_len):
208
+ # 計算轉移得分和發射得分
209
+ score += (
210
+ self.transitions[labels[i-1], labels[i]] + # 轉移得分
211
+ features[i, torch.arange(batch_size), labels[i]] # 發射得分
212
+ ) * mask[i] # 只對有效位置計算
213
+
214
+ # 計算序列長度(減去1是因為索引從0開始)
215
+ seq_lens = mask.sum(dim=0) - 1
216
+
217
+ # 獲取每個序列的最後一個有效標籤
218
+ last_tags = labels[seq_lens.long(), torch.arange(batch_size)]
219
+
220
+ # 加上到結束標籤的轉移得分
221
+ score += self.end_transitions[last_tags]
222
+
223
+ return score
224
+
225
+ def forward(self, emissions: torch.Tensor, tags: torch.Tensor, mask: torch.Tensor) -> torch.Tensor:
226
+ """
227
+ 計算CRF負對數似然損失
228
+
229
+ 參數:
230
+ emissions: (seq_len, batch_size, num_labels) 發射得分
231
+ tags: (seq_len, batch_size) 真實標籤
232
+ mask: (seq_len, batch_size) 用於處理變長序列的遮罩
233
+
234
+ 返回:
235
+ CRF負對數似然損失
236
+ """
237
+ # 計算分子(numerator)和分母(denominator)的對數
238
+ log_numerator = self._compute_log_numerator(emissions, tags, mask)
239
+ log_denominator = self._compute_log_denominator(emissions, mask)
240
+
241
+ # 損失是分母減分子
242
+ loss = torch.mean(log_denominator - log_numerator)
243
+
244
+ return loss
245
+
246
+ def _viterbi_decode(self, features: torch.Tensor, mask: torch.Tensor) -> List[List[int]]:
247
+ """Viterbi算法解碼,找出最可能的標籤序列"""
248
+ seq_len, batch_size, _ = features.shape
249
+
250
+ # 初始化Viterbi變量
251
+ log_score = self.start_transitions + features[0] # [batch_size, num_labels]
252
+ backpointers = torch.zeros((seq_len, batch_size, self.num_labels), dtype=torch.long, device=features.device)
253
+
254
+ # 逐時間步填充
255
+ for i in range(1, seq_len):
256
+ # 計算所有可能的轉移得分
257
+ next_score = log_score.unsqueeze(2) + self.transitions + features[i].unsqueeze(1)
258
+
259
+ # 找出每個當前標籤的最佳前一個標籤
260
+ next_score, indices = next_score.max(dim=1)
261
+
262
+ # 記錄回溯指針
263
+ backpointers[i] = indices
264
+
265
+ # 根據mask更新得分
266
+ log_score = torch.where(mask[i].unsqueeze(1), next_score, log_score)
267
+
268
+ # 加上到結束標籤的轉移得分
269
+ log_score += self.end_transitions
270
+
271
+ # 找出每個序列的最後一個標籤
272
+ seq_lens = mask.sum(dim=0).long() - 1 # 序列長度
273
+
274
+ # 回溯獲取最佳路徑
275
+ best_paths = []
276
+ for seq_idx in range(batch_size):
277
+ # 找出得分最高的最終標籤
278
+ best_label = torch.argmax(log_score[seq_idx]).item()
279
+ best_path = [best_label]
280
+
281
+ # 從後向前回溯
282
+ for i in range(seq_lens[seq_idx], 0, -1):
283
+ best_label = backpointers[i, seq_idx, best_label].item()
284
+ best_path.insert(0, best_label)
285
+
286
+ best_paths.append(best_path)
287
+
288
+ return best_paths
289
+
290
+ def decode(self, emissions: torch.Tensor, mask: torch.Tensor) -> List[List[int]]:
291
+ """使用Viterbi解碼找出最可能的標籤序列"""
292
+ # 確保mask是bool類型
293
+ if mask.dtype != torch.bool:
294
+ mask = mask.bool()
295
+
296
+ with torch.no_grad():
297
+ return self._viterbi_decode(emissions, mask)
298
+
299
+
300
+ class BertCRFForTokenClassification(BertPreTrainedModel):
301
+ """BERT模型與CRF層結合用於token分類"""
302
+
303
+ def __init__(self, config: BertConfig):
304
+ super().__init__(config)
305
+ self.num_labels = config.num_labels
306
+
307
+ # BERT層
308
+ self.bert = BertModel(config, add_pooling_layer=False)
309
+
310
+ # Dropout和分類器
311
+ classifier_dropout = (
312
+ config.classifier_dropout if config.classifier_dropout is not None else config.hidden_dropout_prob
313
+ )
314
+ self.dropout = nn.Dropout(classifier_dropout)
315
+ self.classifier = nn.Linear(config.hidden_size, config.num_labels)
316
+
317
+ # CRF層
318
+ self.crf = CRF(config.num_labels)
319
+
320
+ # 初始化權重
321
+ self.post_init()
322
+
323
+ def forward(
324
+ self,
325
+ input_ids: Optional[torch.Tensor] = None,
326
+ attention_mask: Optional[torch.Tensor] = None,
327
+ token_type_ids: Optional[torch.Tensor] = None,
328
+ position_ids: Optional[torch.Tensor] = None,
329
+ head_mask: Optional[torch.Tensor] = None,
330
+ inputs_embeds: Optional[torch.Tensor] = None,
331
+ labels: Optional[torch.Tensor] = None,
332
+ output_attentions: Optional[bool] = None,
333
+ output_hidden_states: Optional[bool] = None,
334
+ return_dict: Optional[bool] = None,
335
+ ignore_index: int = -100,
336
+ **kwargs,
337
+ ) -> Union[Tuple[torch.Tensor], Dict[str, torch.Tensor]]:
338
+ """
339
+ 使用CRF進行序列標注的前向傳播
340
+
341
+ 參數:
342
+ labels: 標籤序列,用於計算損失
343
+ ignore_index: 忽略的標籤值,通常為-100
344
+ """
345
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
346
+
347
+ # BERT前向傳播
348
+ outputs = self.bert(
349
+ input_ids=input_ids,
350
+ attention_mask=attention_mask,
351
+ token_type_ids=token_type_ids,
352
+ position_ids=position_ids,
353
+ head_mask=head_mask,
354
+ inputs_embeds=inputs_embeds,
355
+ output_attentions=output_attentions,
356
+ output_hidden_states=output_hidden_states,
357
+ return_dict=return_dict,
358
+ )
359
+
360
+ sequence_output = outputs[0]
361
+ sequence_output = self.dropout(sequence_output)
362
+
363
+ # 獲取發射分數
364
+ logits = self.classifier(sequence_output) # [batch_size, seq_len, num_labels]
365
+
366
+ loss = None
367
+ if labels is not None:
368
+ # 準備CRF所需的輸入格式
369
+ # 交換維度:[batch_size, seq_len, num_labels] -> [seq_len, batch_size, num_labels]
370
+ emissions = logits.transpose(0, 1)
371
+
372
+ # 交換維度:[batch_size, seq_len] -> [seq_len, batch_size]
373
+ if attention_mask is not None:
374
+ attention_mask_t = attention_mask.transpose(0, 1).bool()
375
+ else:
376
+ attention_mask_t = torch.ones(emissions.shape[:2], dtype=torch.bool, device=emissions.device)
377
+
378
+ # 處理ignore_index
379
+ if ignore_index is not None:
380
+ labels_mask = (labels != ignore_index)
381
+ attention_mask_t = attention_mask_t & labels_mask.transpose(0, 1)
382
+
383
+ # 創建一個不包含ignore_index的標籤tensor
384
+ crf_labels = labels.clone()
385
+ crf_labels[~labels_mask] = 0 # 將ignore的位置臨時設為0,��免其影響CRF計算
386
+ crf_labels_t = crf_labels.transpose(0, 1)
387
+ else:
388
+ crf_labels_t = labels.transpose(0, 1)
389
+
390
+ # 計算CRF損失
391
+ loss = self.crf(
392
+ emissions=emissions,
393
+ tags=crf_labels_t,
394
+ mask=attention_mask_t
395
+ )
396
+
397
+ if not return_dict:
398
+ output = (logits,) + outputs[2:]
399
+ return ((loss,) + output) if loss is not None else output
400
+
401
+ return TokenClassifierOutput(
402
+ loss=loss,
403
+ logits=logits,
404
+ hidden_states=outputs.hidden_states,
405
+ attentions=outputs.attentions,
406
+ )
407
+
408
+ def decode(
409
+ self,
410
+ input_ids: Optional[torch.Tensor] = None,
411
+ attention_mask: Optional[torch.Tensor] = None,
412
+ token_type_ids: Optional[torch.Tensor] = None,
413
+ **kwargs,
414
+ ) -> List[List[int]]:
415
+ """
416
+ 解碼最可能的標籤序列
417
+ """
418
+ # 不計算梯度
419
+ with torch.no_grad():
420
+ # BERT前向傳播
421
+ outputs = self.bert(
422
+ input_ids=input_ids,
423
+ attention_mask=attention_mask,
424
+ token_type_ids=token_type_ids,
425
+ return_dict=True,
426
+ **kwargs,
427
+ )
428
+
429
+ sequence_output = outputs[0]
430
+ sequence_output = self.dropout(sequence_output)
431
+
432
+ # 獲取發射分數
433
+ logits = self.classifier(sequence_output) # [batch_size, seq_len, num_labels]
434
+
435
+ # 交換維度:[batch_size, seq_len, num_labels] -> [seq_len, batch_size, num_labels]
436
+ emissions = logits.transpose(0, 1)
437
+
438
+ # 準備遮罩
439
+ if attention_mask is not None:
440
+ mask = attention_mask.transpose(0, 1).bool()
441
+ else:
442
+ mask = torch.ones(emissions.shape[:2], dtype=torch.bool, device=emissions.device)
443
+
444
+ # 使用Viterbi算法解碼
445
+ best_tags = self.crf.decode(emissions, mask)
446
+
447
+ return best_tags
448
+
449
+
450
+ class RobertaForTokenClassification(RobertaPreTrainedModel):
451
+
452
+ def __init__(self, config: RobertaConfig):
453
+ super().__init__(config)
454
+ self.num_labels = config.num_labels
455
+
456
+ self.roberta = RobertaModel(config, add_pooling_layer=False)
457
+ classifier_dropout = (
458
+ config.classifier_dropout if config.classifier_dropout is not None else config.hidden_dropout_prob
459
+ )
460
+ self.dropout = nn.Dropout(classifier_dropout)
461
+ self.classifier = nn.Linear(config.hidden_size, config.num_labels)
462
+
463
+ # Initialize weights and apply final processing
464
+ self.post_init()
465
+
466
+ def forward(
467
+ self,
468
+ input_ids: Optional[torch.LongTensor] = None,
469
+ attention_mask: Optional[torch.FloatTensor] = None,
470
+ token_type_ids: Optional[torch.LongTensor] = None,
471
+ position_ids: Optional[torch.LongTensor] = None,
472
+ head_mask: Optional[torch.FloatTensor] = None,
473
+ inputs_embeds: Optional[torch.FloatTensor] = None,
474
+ labels: Optional[torch.LongTensor] = None,
475
+ output_attentions: Optional[bool] = None,
476
+ output_hidden_states: Optional[bool] = None,
477
+ return_dict: Optional[bool] = None,
478
+ num_items_in_batch: Optional[torch.Tensor] = None,
479
+ ignore_index: int = -100,
480
+ **kwargs,
481
+ ) -> Union[Tuple[torch.Tensor], TokenClassifierOutput]:
482
+ r"""
483
+ token_type_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
484
+ Segment token indices to indicate first and second portions of the inputs. Indices are selected in `[0,1]`:
485
+
486
+ - 0 corresponds to a *sentence A* token,
487
+ - 1 corresponds to a *sentence B* token.
488
+ This parameter can only be used when the model is initialized with `type_vocab_size` parameter with value
489
+ >= 2. All the value in this tensor should be always < type_vocab_size.
490
+
491
+ [What are token type IDs?](../glossary#token-type-ids)
492
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
493
+ Labels for computing the token classification loss. Indices should be in `[0, ..., config.num_labels - 1]`.
494
+ """
495
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
496
+
497
+ outputs = self.roberta(
498
+ input_ids,
499
+ attention_mask=attention_mask,
500
+ token_type_ids=token_type_ids,
501
+ position_ids=position_ids,
502
+ head_mask=head_mask,
503
+ inputs_embeds=inputs_embeds,
504
+ output_attentions=output_attentions,
505
+ output_hidden_states=output_hidden_states,
506
+ return_dict=return_dict,
507
+ )
508
+
509
+ sequence_output = outputs[0]
510
+
511
+ sequence_output = self.dropout(sequence_output)
512
+ logits = self.classifier(sequence_output)
513
+
514
+ loss = None
515
+ if labels is not None:
516
+ # Upcast to float if we need to compute the loss to avoid potential precision issues
517
+ logits = logits.view(-1, self.num_labels)
518
+ labels = labels.view(-1).to(logits.device)
519
+ logits = logits.float()
520
+ loss = fixed_cross_entropy(logits, labels, num_items_in_batch, ignore_index)
521
+
522
+ if not return_dict:
523
+ output = (logits,) + outputs[2:]
524
+ return ((loss,) + output) if loss is not None else output
525
+
526
+ return TokenClassifierOutput(
527
+ loss=loss,
528
+ logits=logits,
529
+ hidden_states=outputs.hidden_states,
530
+ attentions=outputs.attentions,
531
+ )
532
+
533
+
534
+ class DebertaV2ForTokenClassification(DebertaV2PreTrainedModel):
535
+
536
+ def __init__(self, config: DebertaV2Config):
537
+ super().__init__(config)
538
+ self.num_labels = config.num_labels
539
+
540
+ self.deberta = DebertaV2Model(config)
541
+ self.dropout = nn.Dropout(config.hidden_dropout_prob)
542
+ self.classifier = nn.Linear(config.hidden_size, config.num_labels)
543
+
544
+ # Initialize weights and apply final processing
545
+ self.post_init()
546
+
547
+ def forward(
548
+ self,
549
+ input_ids: Optional[torch.Tensor] = None,
550
+ attention_mask: Optional[torch.Tensor] = None,
551
+ token_type_ids: Optional[torch.Tensor] = None,
552
+ position_ids: Optional[torch.Tensor] = None,
553
+ inputs_embeds: Optional[torch.Tensor] = None,
554
+ labels: Optional[torch.Tensor] = None,
555
+ output_attentions: Optional[bool] = None,
556
+ output_hidden_states: Optional[bool] = None,
557
+ return_dict: Optional[bool] = None,
558
+ num_items_in_batch: Optional[torch.Tensor] = None,
559
+ ignore_index: int = -100,
560
+ **kwargs,
561
+ ) -> Union[Tuple, TokenClassifierOutput]:
562
+ r"""
563
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
564
+ Labels for computing the token classification loss. Indices should be in `[0, ..., config.num_labels - 1]`.
565
+ """
566
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
567
+
568
+ outputs = self.deberta(
569
+ input_ids,
570
+ attention_mask=attention_mask,
571
+ token_type_ids=token_type_ids,
572
+ position_ids=position_ids,
573
+ inputs_embeds=inputs_embeds,
574
+ output_attentions=output_attentions,
575
+ output_hidden_states=output_hidden_states,
576
+ return_dict=return_dict,
577
+ )
578
+
579
+ sequence_output = outputs[0]
580
+
581
+ sequence_output = self.dropout(sequence_output)
582
+ logits = self.classifier(sequence_output)
583
+
584
+ loss = None
585
+ if labels is not None:
586
+ # Upcast to float if we need to compute the loss to avoid potential precision issues
587
+ logits = logits.view(-1, self.num_labels)
588
+ labels = labels.view(-1).to(logits.device)
589
+ logits = logits.float()
590
+ loss = fixed_cross_entropy(logits, labels, num_items_in_batch, ignore_index)
591
+
592
+ if not return_dict:
593
+ output = (logits,) + outputs[1:]
594
+ return ((loss,) + output) if loss is not None else output
595
+
596
+ return TokenClassifierOutput(
597
+ loss=loss, logits=logits, hidden_states=outputs.hidden_states, attentions=outputs.attentions
598
+ )
599
+
600
+
601
+ class ModernBertForTokenClassification(ModernBertPreTrainedModel):
602
+
603
+ def __init__(self, config: ModernBertConfig):
604
+ super().__init__(config)
605
+ self.num_labels = config.num_labels
606
+
607
+ self.model = ModernBertModel(config)
608
+ self.head = ModernBertPredictionHead(config)
609
+ self.drop = torch.nn.Dropout(config.classifier_dropout)
610
+ self.classifier = nn.Linear(config.hidden_size, config.num_labels)
611
+
612
+ # Initialize weights and apply final processing
613
+ self.post_init()
614
+
615
+ def forward(
616
+ self,
617
+ input_ids: Optional[torch.LongTensor] = None,
618
+ attention_mask: Optional[torch.Tensor] = None,
619
+ sliding_window_mask: Optional[torch.Tensor] = None,
620
+ position_ids: Optional[torch.Tensor] = None,
621
+ inputs_embeds: Optional[torch.Tensor] = None,
622
+ labels: Optional[torch.Tensor] = None,
623
+ indices: Optional[torch.Tensor] = None,
624
+ cu_seqlens: Optional[torch.Tensor] = None,
625
+ max_seqlen: Optional[int] = None,
626
+ batch_size: Optional[int] = None,
627
+ seq_len: Optional[int] = None,
628
+ output_attentions: Optional[bool] = None,
629
+ output_hidden_states: Optional[bool] = None,
630
+ return_dict: Optional[bool] = None,
631
+ num_items_in_batch: Optional[torch.Tensor] = None,
632
+ ignore_index: int = -100,
633
+ **kwargs,
634
+ ) -> Union[Tuple[torch.Tensor], TokenClassifierOutput]:
635
+ r"""
636
+ sliding_window_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
637
+ Mask to avoid performing attention on padding or far-away tokens. In ModernBert, only every few layers
638
+ perform global attention, while the rest perform local attention. This mask is used to avoid attending to
639
+ far-away tokens in the local attention layers when not using Flash Attention.
640
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
641
+ Labels for computing the token classification loss. Indices should be in `[0, ..., config.num_labels - 1]`.
642
+ indices (`torch.Tensor` of shape `(total_unpadded_tokens,)`, *optional*):
643
+ Indices of the non-padding tokens in the input sequence. Used for unpadding the output.
644
+ cu_seqlens (`torch.Tensor` of shape `(batch + 1,)`, *optional*):
645
+ Cumulative sequence lengths of the input sequences. Used to index the unpadded tensors.
646
+ max_seqlen (`int`, *optional*):
647
+ Maximum sequence length in the batch excluding padding tokens. Used to unpad input_ids and pad output tensors.
648
+ batch_size (`int`, *optional*):
649
+ Batch size of the input sequences. Used to pad the output tensors.
650
+ seq_len (`int`, *optional*):
651
+ Sequence length of the input sequences including padding tokens. Used to pad the output tensors.
652
+ """
653
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
654
+ self._maybe_set_compile()
655
+
656
+ outputs = self.model(
657
+ input_ids=input_ids,
658
+ attention_mask=attention_mask,
659
+ sliding_window_mask=sliding_window_mask,
660
+ position_ids=position_ids,
661
+ inputs_embeds=inputs_embeds,
662
+ indices=indices,
663
+ cu_seqlens=cu_seqlens,
664
+ max_seqlen=max_seqlen,
665
+ batch_size=batch_size,
666
+ seq_len=seq_len,
667
+ output_attentions=output_attentions,
668
+ output_hidden_states=output_hidden_states,
669
+ return_dict=return_dict,
670
+ )
671
+ last_hidden_state = outputs[0]
672
+
673
+ last_hidden_state = self.head(last_hidden_state)
674
+ last_hidden_state = self.drop(last_hidden_state)
675
+ logits = self.classifier(last_hidden_state)
676
+
677
+ loss = None
678
+ if labels is not None:
679
+ # Upcast to float if we need to compute the loss to avoid potential precision issues
680
+ logits = logits.view(-1, self.num_labels)
681
+ labels = labels.view(-1).to(logits.device)
682
+ logits = logits.float()
683
+ loss = fixed_cross_entropy(logits, labels, num_items_in_batch, ignore_index)
684
+
685
+ if not return_dict:
686
+ output = (logits,) + outputs[1:]
687
+ return ((loss,) + output) if loss is not None else output
688
+
689
+ return TokenClassifierOutput(
690
+ loss=loss,
691
+ logits=logits,
692
+ hidden_states=outputs.hidden_states,
693
+ attentions=outputs.attentions,
694
+ )
695
+
696
+
697
+ class UnmaskingQwen3Attention(Qwen3Attention):
698
+ """Multi-headed attention without causal mask for bidirectional attention"""
699
+
700
+ def forward(
701
+ self,
702
+ hidden_states: torch.Tensor,
703
+ position_embeddings: Tuple[torch.Tensor, torch.Tensor],
704
+ attention_mask: Optional[torch.Tensor],
705
+ past_key_value: Optional[Cache] = None,
706
+ cache_position: Optional[torch.LongTensor] = None,
707
+ **kwargs: Unpack[FlashAttentionKwargs],
708
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
709
+ input_shape = hidden_states.shape[:-1]
710
+ hidden_shape = (*input_shape, -1, self.head_dim)
711
+
712
+ query_states = self.q_norm(self.q_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
713
+ key_states = self.k_norm(self.k_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
714
+ value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
715
+
716
+ cos, sin = position_embeddings
717
+ query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
718
+
719
+ if past_key_value is not None:
720
+ # sin and cos are specific to RoPE models; cache_position needed for the static cache
721
+ cache_kwargs = {"sin": sin, "cos": cos, "cache_position": cache_position}
722
+ key_states, value_states = past_key_value.update(key_states, value_states, self.layer_idx, cache_kwargs)
723
+
724
+ # Use eager attention as default
725
+ attention_interface: Callable = eager_attention_forward
726
+
727
+ # Remove causal mask by setting attention_mask to None or creating a non-causal mask
728
+ # For bidirectional attention, we don't want any masking except padding
729
+ if attention_mask is not None and 0.0 in attention_mask:
730
+ # Keep only padding mask if it exists, remove causal part
731
+ # This allows tokens to attend to future tokens
732
+ pass
733
+ else:
734
+ # If there's no padding, we can set attention_mask to None for full attention
735
+ attention_mask = None
736
+
737
+ attn_output, attn_weights = attention_interface(
738
+ self,
739
+ query_states,
740
+ key_states,
741
+ value_states,
742
+ attention_mask,
743
+ dropout=0.0 if not self.training else self.attention_dropout,
744
+ scaling=self.scaling,
745
+ sliding_window=self.sliding_window,
746
+ **kwargs,
747
+ )
748
+
749
+ attn_output = attn_output.reshape(*input_shape, -1).contiguous()
750
+ attn_output = self.o_proj(attn_output)
751
+ return attn_output, attn_weights
752
+
753
+
754
+ class UnmaskingQwen3DecoderLayer(Qwen3DecoderLayer):
755
+
756
+ def __init__(self, config: Qwen3Config, layer_idx: int):
757
+ super(Qwen3DecoderLayer, self).__init__()
758
+ self.hidden_size = config.hidden_size
759
+ self.self_attn = UnmaskingQwen3Attention(config=config, layer_idx=layer_idx)
760
+ self.mlp = Qwen3MLP(config)
761
+ self.input_layernorm = Qwen3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
762
+ self.post_attention_layernorm = Qwen3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
763
+
764
+
765
+ class UnmaskingQwen3Model(Qwen3Model):
766
+
767
+ def __init__(self, config: Qwen3Config):
768
+ super(Qwen3PreTrainedModel, self).__init__(config)
769
+ self.padding_idx = config.pad_token_id
770
+ self.vocab_size = config.vocab_size
771
+
772
+ self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
773
+ self.layers = nn.ModuleList(
774
+ [UnmaskingQwen3DecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
775
+ )
776
+ self.norm = Qwen3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
777
+ self.rotary_emb = Qwen3RotaryEmbedding(config=config)
778
+ self.gradient_checkpointing = False
779
+
780
+ # Initialize weights and apply final processing
781
+ self.post_init()
782
+
783
+ def _update_causal_mask(
784
+ self,
785
+ attention_mask: torch.Tensor,
786
+ input_tensor: torch.Tensor,
787
+ cache_position: torch.Tensor,
788
+ past_key_values: Cache,
789
+ output_attentions: bool = False,
790
+ ):
791
+ # Override the causal mask creation to create a non-causal mask
792
+ # This allows bidirectional attention
793
+ if attention_mask is None:
794
+ # If no attention mask is provided, return None to allow full attention
795
+ return None
796
+
797
+ # If attention_mask is provided, it's likely for padding
798
+ # Convert it to the right format but without the causal constraint
799
+ dtype = input_tensor.dtype
800
+ min_dtype = torch.finfo(dtype).min
801
+ batch_size = input_tensor.shape[0]
802
+ sequence_length = input_tensor.shape[1]
803
+
804
+ if isinstance(attention_mask, torch.Tensor) and attention_mask.dim() == 2:
805
+ # Convert 2D padding mask to 4D attention mask
806
+ expanded_attn_mask = attention_mask[:, None, None, :]
807
+ expanded_attn_mask = expanded_attn_mask.to(dtype=dtype)
808
+ expanded_attn_mask = (1.0 - expanded_attn_mask) * min_dtype
809
+ return expanded_attn_mask
810
+
811
+ # If it's already 4D, return as is
812
+ return attention_mask
813
+
814
+
815
+ class UnmaskingQwen3ForTokenClassification(Qwen3PreTrainedModel):
816
+
817
+ def __init__(self, config):
818
+ super().__init__(config)
819
+ self.num_labels = config.num_labels
820
+ self.model = UnmaskingQwen3Model(config)
821
+ if getattr(config, "classifier_dropout", None) is not None:
822
+ classifier_dropout = config.classifier_dropout
823
+ elif getattr(config, "hidden_dropout", None) is not None:
824
+ classifier_dropout = config.hidden_dropout
825
+ else:
826
+ classifier_dropout = 0.1
827
+ self.dropout = nn.Dropout(classifier_dropout)
828
+ self.score = nn.Linear(config.hidden_size, config.num_labels)
829
+
830
+ # Initialize weights and apply final processing
831
+ self.post_init()
832
+
833
+ def get_input_embeddings(self):
834
+ return self.model.embed_tokens
835
+
836
+ def set_input_embeddings(self, value):
837
+ self.model.embed_tokens = value
838
+
839
+ @can_return_tuple
840
+ def forward(
841
+ self,
842
+ input_ids: Optional[torch.LongTensor] = None,
843
+ attention_mask: Optional[torch.Tensor] = None,
844
+ position_ids: Optional[torch.LongTensor] = None,
845
+ past_key_values: Optional[Cache] = None,
846
+ inputs_embeds: Optional[torch.FloatTensor] = None,
847
+ labels: Optional[torch.LongTensor] = None,
848
+ use_cache: Optional[bool] = None,
849
+ output_attentions: Optional[bool] = None,
850
+ output_hidden_states: Optional[bool] = None,
851
+ ) -> TokenClassifierOutput:
852
+ r"""
853
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
854
+ Labels for computing the token classification loss. Indices should be in `[0, ...,
855
+ config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If
856
+ `config.num_labels > 1` a classification loss is computed (Cross-Entropy).
857
+ """
858
+
859
+ outputs: BaseModelOutputWithPast = self.model(
860
+ input_ids,
861
+ attention_mask=attention_mask,
862
+ position_ids=position_ids,
863
+ past_key_values=past_key_values,
864
+ inputs_embeds=inputs_embeds,
865
+ use_cache=use_cache,
866
+ output_attentions=output_attentions,
867
+ output_hidden_states=output_hidden_states,
868
+ )
869
+ sequence_output = outputs.last_hidden_state
870
+ sequence_output = self.dropout(sequence_output)
871
+ logits = self.score(sequence_output)
872
+
873
+ loss = None
874
+ if labels is not None:
875
+ loss_fct = nn.CrossEntropyLoss()
876
+ loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
877
+
878
+ return TokenClassifierOutput(
879
+ loss=loss,
880
+ logits=logits,
881
+ hidden_states=outputs.hidden_states,
882
+ attentions=outputs.attentions,
883
+ )
884
+
885
+
886
+ class UnmaskingQwen2Model(Qwen2Model):
887
+ """
888
+ UnmaskingQwen2Model is a modified version of Qwen2Model that removes the causal mask,
889
+ allowing bidirectional attention similar to BERT-like models.
890
+ """
891
+
892
+ def _update_causal_mask(
893
+ self,
894
+ attention_mask: torch.Tensor,
895
+ input_tensor: torch.Tensor,
896
+ cache_position: torch.Tensor,
897
+ past_key_values: Cache,
898
+ output_attentions: bool = False,
899
+ ):
900
+ """
901
+ Override the causal mask creation to create a non-causal (bidirectional) mask.
902
+ This allows each token to attend to all tokens in the sequence.
903
+ """
904
+ # For flash attention, just return None or the padding mask
905
+ if self.config._attn_implementation == "flash_attention_2":
906
+ if attention_mask is not None and 0.0 in attention_mask:
907
+ return attention_mask
908
+ return None
909
+
910
+ # For flex attention, keep the same behavior but without causality
911
+ if self.config._attn_implementation == "flex_attention":
912
+ if isinstance(attention_mask, torch.Tensor):
913
+ # We don't convert to causal mask here
914
+ return attention_mask
915
+ return attention_mask
916
+
917
+ # For other attention implementations, create a non-causal mask
918
+ batch_size = input_tensor.shape[0]
919
+ sequence_length = input_tensor.shape[1]
920
+ dtype = input_tensor.dtype
921
+
922
+ # For SlidingWindowCache or StaticCache
923
+ if isinstance(past_key_values, (SlidingWindowCache, StaticCache)):
924
+ target_length = past_key_values.get_max_cache_shape()
925
+ else:
926
+ # For DynamicCache or no cache
927
+ target_length = (
928
+ attention_mask.shape[-1]
929
+ if isinstance(attention_mask, torch.Tensor)
930
+ else past_key_values.get_seq_length() + sequence_length + 1
931
+ if past_key_values is not None
932
+ else sequence_length
933
+ )
934
+
935
+ # Create a non-causal mask (all zeros, allowing full attention)
936
+ # Instead of using min_dtype to mask out future tokens, we use zeros to allow attention to all positions
937
+ non_causal_mask = torch.zeros(
938
+ (batch_size, 1, sequence_length, target_length),
939
+ dtype=dtype,
940
+ device=input_tensor.device,
941
+ )
942
+
943
+ # If there's a padding attention mask, apply it
944
+ if attention_mask is not None:
945
+ if attention_mask.dim() == 2:
946
+ # Convert 2D attention mask to 4D
947
+ expanded_mask = attention_mask[:, None, None, :].expand(
948
+ batch_size, 1, sequence_length, attention_mask.shape[-1]
949
+ ).to(non_causal_mask.device)
950
+
951
+ # Apply padding mask (0 for tokens to attend to, large negative for padded positions)
952
+ min_dtype = torch.finfo(dtype).min
953
+ padding_mask = expanded_mask == 0
954
+ non_causal_mask = non_causal_mask.masked_fill(padding_mask, min_dtype)
955
+ elif attention_mask.dim() == 4:
956
+ # If already 4D, use as is
957
+ non_causal_mask = attention_mask
958
+
959
+ return non_causal_mask
960
+
961
+
962
+ class UnmaskingQwen2ForTokenClassification(Qwen2PreTrainedModel):
963
+ """
964
+ Qwen2 model with a token classification head on top, but with bidirectional attention.
965
+ This is achieved by using the UnmaskingQwen2Model which removes the causal mask.
966
+ """
967
+
968
+ def __init__(self, config):
969
+ super().__init__(config)
970
+ self.num_labels = config.num_labels
971
+
972
+ # Use the UnmaskingQwen2Model instead of the standard Qwen2Model
973
+ self.model = UnmaskingQwen2Model(config)
974
+
975
+ if getattr(config, "classifier_dropout", None) is not None:
976
+ classifier_dropout = config.classifier_dropout
977
+ elif getattr(config, "hidden_dropout", None) is not None:
978
+ classifier_dropout = config.hidden_dropout
979
+ else:
980
+ classifier_dropout = 0.1
981
+
982
+ self.dropout = nn.Dropout(classifier_dropout)
983
+ self.score = nn.Linear(config.hidden_size, config.num_labels)
984
+
985
+ # Initialize weights and apply final processing
986
+ self.post_init()
987
+
988
+ def get_input_embeddings(self):
989
+ return self.model.embed_tokens
990
+
991
+ def set_input_embeddings(self, value):
992
+ self.model.embed_tokens = value
993
+
994
+ def forward(
995
+ self,
996
+ input_ids: Optional[torch.LongTensor] = None,
997
+ attention_mask: Optional[torch.Tensor] = None,
998
+ position_ids: Optional[torch.LongTensor] = None,
999
+ past_key_values: Optional[Cache] = None,
1000
+ inputs_embeds: Optional[torch.FloatTensor] = None,
1001
+ labels: Optional[torch.LongTensor] = None,
1002
+ use_cache: Optional[bool] = None,
1003
+ output_attentions: Optional[bool] = None,
1004
+ output_hidden_states: Optional[bool] = None,
1005
+ **flash_attn_kwargs: Unpack[FlashAttentionKwargs],
1006
+ ) -> TokenClassifierOutput:
1007
+ """
1008
+ Forward pass for token classification with bidirectional attention.
1009
+
1010
+ Args:
1011
+ input_ids: Input token IDs
1012
+ attention_mask: Attention mask
1013
+ position_ids: Position IDs
1014
+ past_key_values: Past key values for efficient generation
1015
+ inputs_embeds: Pre-computed input embeddings
1016
+ labels: Token classification labels
1017
+ use_cache: Whether to use cache for efficient generation
1018
+ output_attentions: Whether to output attention weights
1019
+ output_hidden_states: Whether to output hidden states
1020
+ flash_attn_kwargs: Additional arguments for flash attention
1021
+
1022
+ Returns:
1023
+ TokenClassifierOutput with loss, logits, and optional hidden states and attentions
1024
+ """
1025
+ outputs: BaseModelOutputWithPast = self.model(
1026
+ input_ids,
1027
+ attention_mask=attention_mask,
1028
+ position_ids=position_ids,
1029
+ past_key_values=past_key_values,
1030
+ inputs_embeds=inputs_embeds,
1031
+ use_cache=use_cache,
1032
+ output_attentions=output_attentions,
1033
+ output_hidden_states=output_hidden_states,
1034
+ **flash_attn_kwargs,
1035
+ )
1036
+
1037
+ sequence_output = outputs.last_hidden_state
1038
+ sequence_output = self.dropout(sequence_output)
1039
+ logits = self.score(sequence_output)
1040
+
1041
+ loss = None
1042
+ if labels is not None:
1043
+ loss = self.loss_function(logits, labels, self.config)
1044
+
1045
+ return TokenClassifierOutput(
1046
+ loss=loss,
1047
+ logits=logits,
1048
+ hidden_states=outputs.hidden_states,
1049
+ attentions=outputs.attentions,
1050
+ )
1051
+
special_tokens_map.json ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "additional_special_tokens": [
3
+ "<|im_start|>",
4
+ "<|im_end|>",
5
+ "<|object_ref_start|>",
6
+ "<|object_ref_end|>",
7
+ "<|box_start|>",
8
+ "<|box_end|>",
9
+ "<|quad_start|>",
10
+ "<|quad_end|>",
11
+ "<|vision_start|>",
12
+ "<|vision_end|>",
13
+ "<|vision_pad|>",
14
+ "<|image_pad|>",
15
+ "<|video_pad|>"
16
+ ],
17
+ "eos_token": {
18
+ "content": "<|im_end|>",
19
+ "lstrip": false,
20
+ "normalized": false,
21
+ "rstrip": false,
22
+ "single_word": false
23
+ },
24
+ "pad_token": {
25
+ "content": "<|endoftext|>",
26
+ "lstrip": false,
27
+ "normalized": false,
28
+ "rstrip": false,
29
+ "single_word": false
30
+ }
31
+ }
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1e72410ddfe59d4ec8aeea923685710c76492112d74f5d127b86e2d08d65a3a4
3
+ size 11422174
tokenizer_config.json ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ },
182
+ "additional_special_tokens": [
183
+ "<|im_start|>",
184
+ "<|im_end|>",
185
+ "<|object_ref_start|>",
186
+ "<|object_ref_end|>",
187
+ "<|box_start|>",
188
+ "<|box_end|>",
189
+ "<|quad_start|>",
190
+ "<|quad_end|>",
191
+ "<|vision_start|>",
192
+ "<|vision_end|>",
193
+ "<|vision_pad|>",
194
+ "<|image_pad|>",
195
+ "<|video_pad|>"
196
+ ],
197
+ "bos_token": null,
198
+ "chat_template": "{%- if tools %}\n {{- '<|im_start|>system\\n' }}\n {%- if messages[0]['role'] == 'system' %}\n {{- messages[0]['content'] }}\n {%- else %}\n {{- 'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.' }}\n {%- endif %}\n {{- \"\\n\\n# Tools\\n\\nYou may call one or more functions to assist with the user query.\\n\\nYou are provided with function signatures within <tools></tools> XML tags:\\n<tools>\" }}\n {%- for tool in tools %}\n {{- \"\\n\" }}\n {{- tool | tojson }}\n {%- endfor %}\n {{- \"\\n</tools>\\n\\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\\n<tool_call>\\n{\\\"name\\\": <function-name>, \\\"arguments\\\": <args-json-object>}\\n</tool_call><|im_end|>\\n\" }}\n{%- else %}\n {%- if messages[0]['role'] == 'system' %}\n {{- '<|im_start|>system\\n' + messages[0]['content'] + '<|im_end|>\\n' }}\n {%- else %}\n {{- '<|im_start|>system\\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\\n' }}\n {%- endif %}\n{%- endif %}\n{%- for message in messages %}\n {%- if (message.role == \"user\") or (message.role == \"system\" and not loop.first) or (message.role == \"assistant\" and not message.tool_calls) %}\n {{- '<|im_start|>' + message.role + '\\n' + message.content + '<|im_end|>' + '\\n' }}\n {%- elif message.role == \"assistant\" %}\n {{- '<|im_start|>' + message.role }}\n {%- if message.content %}\n {{- '\\n' + message.content }}\n {%- endif %}\n {%- for tool_call in message.tool_calls %}\n {%- if tool_call.function is defined %}\n {%- set tool_call = tool_call.function %}\n {%- endif %}\n {{- '\\n<tool_call>\\n{\"name\": \"' }}\n {{- tool_call.name }}\n {{- '\", \"arguments\": ' }}\n {{- tool_call.arguments | tojson }}\n {{- '}\\n</tool_call>' }}\n {%- endfor %}\n {{- '<|im_end|>\\n' }}\n {%- elif message.role == \"tool\" %}\n {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != \"tool\") %}\n {{- '<|im_start|>user' }}\n {%- endif %}\n {{- '\\n<tool_response>\\n' }}\n {{- message.content }}\n {{- '\\n</tool_response>' }}\n {%- if loop.last or (messages[loop.index0 + 1].role != \"tool\") %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n {%- endif %}\n{%- endfor %}\n{%- if add_generation_prompt %}\n {{- '<|im_start|>assistant\\n' }}\n{%- endif %}\n",
199
+ "clean_up_tokenization_spaces": false,
200
+ "eos_token": "<|im_end|>",
201
+ "errors": "replace",
202
+ "extra_special_tokens": {},
203
+ "model_max_length": 131072,
204
+ "pad_token": "<|endoftext|>",
205
+ "split_special_tokens": false,
206
+ "tokenizer_class": "Qwen2Tokenizer",
207
+ "unk_token": null
208
+ }
vocab.json ADDED
The diff for this file is too large to render. See raw diff