jasonyux commited on
Commit
3aa9937
·
verified ·
1 Parent(s): d31df60

Add files using upload-large-folder tool

Browse files
Files changed (50) hide show
  1. .gitattributes +2 -0
  2. README.md +39 -0
  3. chat_template.jinja +18 -0
  4. config.json +66 -0
  5. configuration_deepseek.py +199 -0
  6. debug_template_deep.py +117 -0
  7. generation_config.json +9 -0
  8. inference/configs/config_16B.json +19 -0
  9. inference/configs/config_236B.json +20 -0
  10. inference/configs/config_671B.json +22 -0
  11. inference/convert.py +84 -0
  12. inference/fp8_cast_bf16.py +81 -0
  13. inference/generate.py +137 -0
  14. inference/kernel.py +108 -0
  15. inference/model.py +421 -0
  16. inference/requirements.txt +4 -0
  17. model-00003-of-00074.safetensors +3 -0
  18. model-00005-of-00074.safetensors +3 -0
  19. model-00007-of-00074.safetensors +3 -0
  20. model-00009-of-00074.safetensors +3 -0
  21. model-00010-of-00074.safetensors +3 -0
  22. model-00018-of-00074.safetensors +3 -0
  23. model-00020-of-00074.safetensors +3 -0
  24. model-00021-of-00074.safetensors +3 -0
  25. model-00022-of-00074.safetensors +3 -0
  26. model-00026-of-00074.safetensors +3 -0
  27. model-00027-of-00074.safetensors +3 -0
  28. model-00030-of-00074.safetensors +3 -0
  29. model-00031-of-00074.safetensors +3 -0
  30. model-00032-of-00074.safetensors +3 -0
  31. model-00036-of-00074.safetensors +3 -0
  32. model-00037-of-00074.safetensors +3 -0
  33. model-00041-of-00074.safetensors +3 -0
  34. model-00042-of-00074.safetensors +3 -0
  35. model-00048-of-00074.safetensors +3 -0
  36. model-00050-of-00074.safetensors +3 -0
  37. model-00052-of-00074.safetensors +3 -0
  38. model-00054-of-00074.safetensors +3 -0
  39. model-00055-of-00074.safetensors +3 -0
  40. model-00056-of-00074.safetensors +3 -0
  41. model-00059-of-00074.safetensors +3 -0
  42. model-00061-of-00074.safetensors +3 -0
  43. model-00065-of-00074.safetensors +3 -0
  44. model-00067-of-00074.safetensors +3 -0
  45. modeling_deepseek.py +1848 -0
  46. special_tokens_map.json +23 -0
  47. test.py +159 -0
  48. test_tokenizer_direct.py +75 -0
  49. tokenizer.json +0 -0
  50. tokenizer_config.json +0 -0
.gitattributes CHANGED
@@ -33,3 +33,5 @@ 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
+ figures/benchmark.png filter=lfs diff=lfs merge=lfs -text
37
+ model.safetensors.index.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ language:
4
+ - en
5
+ - zh
6
+ base_model:
7
+ - deepseek-ai/DeepSeek-R1-0528
8
+ pipeline_tag: text-generation
9
+ library_name: transformers
10
+ ---
11
+ # DeepSeek-R1-0528-AWQ
12
+ AWQ of DeepSeek R1 0528.
13
+
14
+ Quantized by [Eric Hartford](https://huggingface.co/ehartford) and [v2ray](https://huggingface.co/v2ray).
15
+
16
+ Compute for this quant was generously sponsored by [Hot Aisle](https://hotaisle.xyz/). Thank you for supporting the community!
17
+
18
+ This quant modified some of the model code to fix an overflow issue when using float16.
19
+
20
+ To serve using vLLM with 8x 80GB GPUs, use the following command:
21
+ ```sh
22
+ VLLM_USE_V1=0 VLLM_WORKER_MULTIPROC_METHOD=spawn VLLM_MARLIN_USE_ATOMIC_ADD=1 python -m vllm.entrypoints.openai.api_server --host 0.0.0.0 --port 12345 --max-model-len 65536 --max-seq-len-to-capture 65536 --enable-chunked-prefill --enable-prefix-caching --trust-remote-code --tensor-parallel-size 8 --gpu-memory-utilization 0.95 --served-model-name deepseek-chat --model cognitivecomputations/DeepSeek-V3-0324-AWQ
23
+ ```
24
+ You can download the wheel I built for PyTorch 2.6, Python 3.12 by clicking [here](https://huggingface.co/x2ray/wheels/resolve/main/vllm-0.8.3.dev250%2Bg10afedcfd.cu128-cp312-cp312-linux_x86_64.whl), the benchmark below was done with this wheel, it contains [2 PR merges](https://github.com/vllm-project/vllm/issues?q=is%3Apr+is%3Aopen+author%3Ajinzhen-lin) and an unoptimized FlashMLA (still faster than Triton) for A100 which boosted performance a lot. The vLLM repo which contained A100 FlashMLA can be found at [LagPixelLOL/vllm@sm80_flashmla](https://github.com/LagPixelLOL/vllm/tree/sm80_flashmla), which is a fork of [vllm-project/vllm](https://github.com/vllm-project/vllm). The A100 FlashMLA it used is based on [LagPixelLOL/FlashMLA@vllm](https://github.com/LagPixelLOL/FlashMLA/tree/vllm), which is a fork of [pzhao-eng/FlashMLA](https://github.com/pzhao-eng/FlashMLA).
25
+
26
+ ## TPS Per Request
27
+ | GPU \ Batch Input Output | B: 1 I: 2 O: 2K | B: 32 I: 4K O: 256 | B: 1 I: 63K O: 2K | Prefill |
28
+ |:-:|:-:|:-:|:-:|:-:|
29
+ | **8x H100/H200** | 61.5 | 30.1 | 54.3 | 4732.2 |
30
+ | **4x H200** | 58.4 | 19.8 | 53.7 | 2653.1 |
31
+ | **8x A100 80GB** | 46.8 | 12.8 | 30.4 | 2442.4 |
32
+ | **8x L40S** | 46.3 | OOM | OOM | 688.5 |
33
+
34
+ Note:
35
+ - The A100 config uses an unoptimized FlashMLA implementation, which is only superior than Triton during high context inference, it would be faster if it's optimized.
36
+ - The L40S config doesn't support FlashMLA, thus the Triton implementation is used, this makes it extremely slow with high context. But the L40S doesn't have much VRAM, so it can't really have that much context anyway, and it also doesn't have the fast GPU to GPU interconnection bandwidth, making it even slower. It is not recommended to serve with this config, as you must limit the context to <= 4096, `--gpu-memory-utilization` to 0.98, and `--max-num-seqs` to 4.
37
+ - All types of GPU used during benchmark are SXM form factor except L40S.
38
+ - Inference speed will be better than FP8 at low batch size but worse than FP8 at high batch size, this is the nature of low bit quantization.
39
+ - vLLM supports MLA for AWQ now, you can run this model with full context length on just 8x 80GB GPUs.
chat_template.jinja ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% set ns = namespace(is_first=false, is_tool=false, is_output_first=true, system_prompt='', is_first_sp=true, is_last_user=false) %}{%- for message in messages %}{%- if message['role'] == 'system' %}{%- if ns.is_first_sp %}{% set ns.system_prompt = ns.system_prompt + message['content'] %}{% set ns.is_first_sp = false %}{%- else %}{% set ns.system_prompt = ns.system_prompt + '
2
+
3
+ ' + message['content'] %}{%- endif %}{%- endif %}{%- endfor %}{{ bos_token }}{{ ns.system_prompt }}{%- for message in messages %}{% set content = message['content'] %}{%- if message['role'] == 'user' %}{%- set ns.is_tool = false -%}{%- set ns.is_first = false -%}{%- set ns.is_last_user = true -%}{{'<|User|>' + content + '<|Assistant|>'}}{%- endif %}{%- if message['role'] == 'assistant' %}{% if '</think>' in content %}{% set content = content.split('</think>')[-1] %}{% endif %}{% endif %}{%- if message['role'] == 'assistant' and message['tool_calls'] is defined and message['tool_calls'] is not none %}{%- set ns.is_last_user = false -%}{%- if ns.is_tool %}{{'<|tool▁outputs▁end|>'}}{%- endif %}{%- set ns.is_first = false %}{%- set ns.is_tool = false -%}{%- set ns.is_output_first = true %}{%- for tool in message['tool_calls'] %}{%- if not ns.is_first %}{%- if content is none %}{{'<|tool▁calls▁begin|><|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '
4
+ ' + '```json' + '
5
+ ' + tool['function']['arguments'] + '
6
+ ' + '```' + '<|tool▁call▁end|>'}}{%- else %}{{content + '<|tool▁calls▁begin|><|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '
7
+ ' + '```json' + '
8
+ ' + tool['function']['arguments'] + '
9
+ ' + '```' + '<|tool▁call▁end|>'}}{%- endif %}{%- set ns.is_first = true -%}{%- else %}{{'
10
+ ' + '<|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '
11
+ ' + '```json' + '
12
+ ' + tool['function']['arguments'] + '
13
+ ' + '```' + '<|tool▁call▁end|>'}}{%- endif %}{%- endfor %}{{'<|tool▁calls▁end|><|end▁of▁sentence|>'}}{%- endif %}{%- if message['role'] == 'assistant' and (message['tool_calls'] is not defined or message['tool_calls'] is none)%}{%- set ns.is_last_user = false -%}{%- if ns.is_tool %}{{'<|tool▁outputs▁end|>' + content + '<|end▁of▁sentence|>'}}{%- set ns.is_tool = false -%}{%- else %}{{content + '<|end▁of▁sentence|>'}}{%- endif %}{%- endif %}{%- if message['role'] == 'tool' %}{%- set ns.is_last_user = false -%}{%- set ns.is_tool = true -%}{%- if ns.is_output_first %}{{'<|tool▁outputs▁begin|><|tool▁output▁begin|>' + content + '<|tool▁output▁end|>'}}{%- set ns.is_output_first = false %}{%- else %}{{'
14
+ <|tool▁output▁begin|>' + content + '<|tool▁output▁end|>'}}{%- endif %}{%- endif %}{%- endfor -%}{% if ns.is_tool %}{{'<|tool▁outputs▁end|>'}}{% endif %}{% if add_generation_prompt and ns.is_last_user and not ns.is_tool %}{{'<|Assistant|>'}}{% if enable_thinking is defined and enable_thinking is false %}{{'<think>
15
+
16
+ </think>
17
+
18
+ '}}{% endif %}{% endif %}
config.json ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "DeepseekV3ForCausalLM"
4
+ ],
5
+ "attention_bias": false,
6
+ "attention_dropout": 0.0,
7
+ "auto_map": {
8
+ "AutoConfig": "configuration_deepseek.DeepseekV3Config",
9
+ "AutoModel": "modeling_deepseek.DeepseekV3Model",
10
+ "AutoModelForCausalLM": "modeling_deepseek.DeepseekV3ForCausalLM"
11
+ },
12
+ "bos_token_id": 0,
13
+ "eos_token_id": 1,
14
+ "ep_size": 1,
15
+ "first_k_dense_replace": 3,
16
+ "hidden_act": "silu",
17
+ "hidden_size": 7168,
18
+ "initializer_range": 0.02,
19
+ "intermediate_size": 18432,
20
+ "kv_lora_rank": 512,
21
+ "max_position_embeddings": 163840,
22
+ "model_type": "deepseek_v3",
23
+ "moe_intermediate_size": 2048,
24
+ "moe_layer_freq": 1,
25
+ "n_group": 8,
26
+ "n_routed_experts": 256,
27
+ "n_shared_experts": 1,
28
+ "norm_topk_prob": true,
29
+ "num_attention_heads": 128,
30
+ "num_experts_per_tok": 8,
31
+ "num_hidden_layers": 61,
32
+ "num_key_value_heads": 128,
33
+ "num_nextn_predict_layers": 1,
34
+ "q_lora_rank": 1536,
35
+ "qk_nope_head_dim": 128,
36
+ "qk_rope_head_dim": 64,
37
+ "quantization_config": {
38
+ "bits": 4,
39
+ "group_size": 64,
40
+ "modules_to_not_convert": null,
41
+ "quant_method": "awq",
42
+ "version": "gemm",
43
+ "zero_point": true
44
+ },
45
+ "rms_norm_eps": 1e-06,
46
+ "rope_scaling": {
47
+ "beta_fast": 32,
48
+ "beta_slow": 1,
49
+ "factor": 40,
50
+ "mscale": 1.0,
51
+ "mscale_all_dim": 1.0,
52
+ "original_max_position_embeddings": 4096,
53
+ "type": "yarn"
54
+ },
55
+ "rope_theta": 10000,
56
+ "routed_scaling_factor": 2.5,
57
+ "scoring_func": "sigmoid",
58
+ "tie_word_embeddings": false,
59
+ "topk_group": 4,
60
+ "topk_method": "noaux_tc",
61
+ "torch_dtype": "bfloat16",
62
+ "transformers_version": "4.52.4",
63
+ "use_cache": false,
64
+ "v_head_dim": 128,
65
+ "vocab_size": 129280
66
+ }
configuration_deepseek.py ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers.configuration_utils import PretrainedConfig
2
+ from transformers.utils import logging
3
+
4
+ logger = logging.get_logger(__name__)
5
+
6
+ DEEPSEEK_PRETRAINED_CONFIG_ARCHIVE_MAP = {}
7
+ class DeepseekV3Config(PretrainedConfig):
8
+ r"""
9
+ This is the configuration class to store the configuration of a [`DeepseekV3Model`]. It is used to instantiate an DeepSeek
10
+ model according to the specified arguments, defining the model architecture. Instantiating a configuration with the
11
+ defaults will yield a similar configuration to that of the DeepSeek-V3.
12
+
13
+ Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
14
+ documentation from [`PretrainedConfig`] for more information.
15
+
16
+
17
+ Args:
18
+ vocab_size (`int`, *optional*, defaults to 129280):
19
+ Vocabulary size of the Deep model. Defines the number of different tokens that can be represented by the
20
+ `inputs_ids` passed when calling [`DeepseekV3Model`]
21
+ hidden_size (`int`, *optional*, defaults to 4096):
22
+ Dimension of the hidden representations.
23
+ intermediate_size (`int`, *optional*, defaults to 11008):
24
+ Dimension of the MLP representations.
25
+ moe_intermediate_size (`int`, *optional*, defaults to 1407):
26
+ Dimension of the MoE representations.
27
+ num_hidden_layers (`int`, *optional*, defaults to 32):
28
+ Number of hidden layers in the Transformer decoder.
29
+ num_nextn_predict_layers (`int`, *optional*, defaults to 1):
30
+ Number of nextn predict layers in the DeepSeekV3 Model.
31
+ num_attention_heads (`int`, *optional*, defaults to 32):
32
+ Number of attention heads for each attention layer in the Transformer decoder.
33
+ n_shared_experts (`int`, *optional*, defaults to None):
34
+ Number of shared experts, None means dense model.
35
+ n_routed_experts (`int`, *optional*, defaults to None):
36
+ Number of routed experts, None means dense model.
37
+ routed_scaling_factor (`float`, *optional*, defaults to 1.0):
38
+ Scaling factor or routed experts.
39
+ topk_method (`str`, *optional*, defaults to `gready`):
40
+ Topk method used in routed gate.
41
+ n_group (`int`, *optional*, defaults to None):
42
+ Number of groups for routed experts.
43
+ topk_group (`int`, *optional*, defaults to None):
44
+ Number of selected groups for each token(for each token, ensuring the selected experts is only within `topk_group` groups).
45
+ num_experts_per_tok (`int`, *optional*, defaults to None):
46
+ Number of selected experts, None means dense model.
47
+ moe_layer_freq (`int`, *optional*, defaults to 1):
48
+ The frequency of the MoE layer: one expert layer for every `moe_layer_freq - 1` dense layers.
49
+ first_k_dense_replace (`int`, *optional*, defaults to 0):
50
+ Number of dense layers in shallow layers(embed->dense->dense->...->dense->moe->moe...->lm_head).
51
+ \--k dense layers--/
52
+ norm_topk_prob (`bool`, *optional*, defaults to False):
53
+ Whether to normalize the weights of the routed experts.
54
+ scoring_func (`str`, *optional*, defaults to 'softmax'):
55
+ Method of computing expert weights.
56
+ aux_loss_alpha (`float`, *optional*, defaults to 0.001):
57
+ Auxiliary loss weight coefficient.
58
+ seq_aux = (`bool`, *optional*, defaults to True):
59
+ Whether to compute the auxiliary loss for each individual sample.
60
+ num_key_value_heads (`int`, *optional*):
61
+ This is the number of key_value heads that should be used to implement Grouped Query Attention. If
62
+ `num_key_value_heads=num_attention_heads`, the model will use Multi Head Attention (MHA), if
63
+ `num_key_value_heads=1 the model will use Multi Query Attention (MQA) otherwise GQA is used. When
64
+ converting a multi-head checkpoint to a GQA checkpoint, each group key and value head should be constructed
65
+ by meanpooling all the original heads within that group. For more details checkout [this
66
+ paper](https://arxiv.org/pdf/2305.13245.pdf). If it is not specified, will default to
67
+ `num_attention_heads`.
68
+ hidden_act (`str` or `function`, *optional*, defaults to `"silu"`):
69
+ The non-linear activation function (function or string) in the decoder.
70
+ max_position_embeddings (`int`, *optional*, defaults to 2048):
71
+ The maximum sequence length that this model might ever be used with.
72
+ initializer_range (`float`, *optional*, defaults to 0.02):
73
+ The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
74
+ rms_norm_eps (`float`, *optional*, defaults to 1e-06):
75
+ The epsilon used by the rms normalization layers.
76
+ use_cache (`bool`, *optional*, defaults to `True`):
77
+ Whether or not the model should return the last key/values attentions (not used by all models). Only
78
+ relevant if `config.is_decoder=True`.
79
+ pad_token_id (`int`, *optional*):
80
+ Padding token id.
81
+ bos_token_id (`int`, *optional*, defaults to 1):
82
+ Beginning of stream token id.
83
+ eos_token_id (`int`, *optional*, defaults to 2):
84
+ End of stream token id.
85
+ tie_word_embeddings (`bool`, *optional*, defaults to `False`):
86
+ Whether to tie weight embeddings
87
+ rope_theta (`float`, *optional*, defaults to 10000.0):
88
+ The base period of the RoPE embeddings.
89
+ rope_scaling (`Dict`, *optional*):
90
+ Dictionary containing the scaling configuration for the RoPE embeddings. Currently supports two scaling
91
+ strategies: linear and dynamic. Their scaling factor must be a float greater than 1. The expected format is
92
+ `{"type": strategy name, "factor": scaling factor}`. When using this flag, don't update
93
+ `max_position_embeddings` to the expected new maximum.
94
+ attention_bias (`bool`, defaults to `False`, *optional*, defaults to `False`):
95
+ Whether to use a bias in the query, key, value and output projection layers during self-attention.
96
+ attention_dropout (`float`, *optional*, defaults to 0.0):
97
+ The dropout ratio for the attention probabilities.
98
+
99
+ ```python
100
+ >>> from transformers import DeepseekV3Model, DeepseekV3Config
101
+
102
+ >>> # Initializing a Deepseek-V3 style configuration
103
+ >>> configuration = DeepseekV3Config()
104
+
105
+ >>> # Accessing the model configuration
106
+ >>> configuration = model.config
107
+ ```"""
108
+
109
+ model_type = "deepseek_v3"
110
+ keys_to_ignore_at_inference = ["past_key_values"]
111
+
112
+ def __init__(
113
+ self,
114
+ vocab_size=129280,
115
+ hidden_size=7168,
116
+ intermediate_size=18432,
117
+ moe_intermediate_size = 2048,
118
+ num_hidden_layers=61,
119
+ num_nextn_predict_layers=1,
120
+ num_attention_heads=128,
121
+ num_key_value_heads=128,
122
+ n_shared_experts = 1,
123
+ n_routed_experts = 256,
124
+ ep_size = 1,
125
+ routed_scaling_factor = 2.5,
126
+ kv_lora_rank = 512,
127
+ q_lora_rank = 1536,
128
+ qk_rope_head_dim = 64,
129
+ v_head_dim = 128,
130
+ qk_nope_head_dim = 128,
131
+ topk_method = 'noaux_tc',
132
+ n_group = 8,
133
+ topk_group = 4,
134
+ num_experts_per_tok = 8,
135
+ moe_layer_freq = 1,
136
+ first_k_dense_replace = 3,
137
+ norm_topk_prob = True,
138
+ scoring_func = 'sigmoid',
139
+ hidden_act="silu",
140
+ max_position_embeddings=4096,
141
+ initializer_range=0.02,
142
+ rms_norm_eps=1e-6,
143
+ use_cache=True,
144
+ pad_token_id=None,
145
+ bos_token_id=0,
146
+ eos_token_id=1,
147
+ tie_word_embeddings=False,
148
+ rope_theta=10000.0,
149
+ rope_scaling=None,
150
+ attention_bias=False,
151
+ attention_dropout=0.0,
152
+ **kwargs,
153
+ ):
154
+ self.vocab_size = vocab_size
155
+ self.max_position_embeddings = max_position_embeddings
156
+ self.hidden_size = hidden_size
157
+ self.intermediate_size = intermediate_size
158
+ self.moe_intermediate_size = moe_intermediate_size
159
+ self.num_hidden_layers = num_hidden_layers
160
+ self.num_nextn_predict_layers = num_nextn_predict_layers
161
+ self.num_attention_heads = num_attention_heads
162
+ self.n_shared_experts = n_shared_experts
163
+ self.n_routed_experts = n_routed_experts
164
+ self.ep_size = ep_size
165
+ self.routed_scaling_factor = routed_scaling_factor
166
+ self.kv_lora_rank = kv_lora_rank
167
+ self.q_lora_rank = q_lora_rank
168
+ self.qk_rope_head_dim = qk_rope_head_dim
169
+ self.v_head_dim = v_head_dim
170
+ self.qk_nope_head_dim = qk_nope_head_dim
171
+ self.topk_method = topk_method
172
+ self.n_group = n_group
173
+ self.topk_group = topk_group
174
+ self.num_experts_per_tok = num_experts_per_tok
175
+ self.moe_layer_freq = moe_layer_freq
176
+ self.first_k_dense_replace = first_k_dense_replace
177
+ self.norm_topk_prob = norm_topk_prob
178
+ self.scoring_func = scoring_func
179
+ # for backward compatibility
180
+ if num_key_value_heads is None:
181
+ num_key_value_heads = num_attention_heads
182
+
183
+ self.num_key_value_heads = num_key_value_heads
184
+ self.hidden_act = hidden_act
185
+ self.initializer_range = initializer_range
186
+ self.rms_norm_eps = rms_norm_eps
187
+ self.use_cache = use_cache
188
+ self.rope_theta = rope_theta
189
+ self.rope_scaling = rope_scaling
190
+ self.attention_bias = attention_bias
191
+ self.attention_dropout = attention_dropout
192
+
193
+ super().__init__(
194
+ pad_token_id=pad_token_id,
195
+ bos_token_id=bos_token_id,
196
+ eos_token_id=eos_token_id,
197
+ tie_word_embeddings=tie_word_embeddings,
198
+ **kwargs,
199
+ )
debug_template_deep.py ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Deep debugging of the chat template issue.
4
+ """
5
+
6
+ import transformers
7
+ from transformers import AutoTokenizer
8
+ import jinja2
9
+ import json
10
+
11
+ MODEL_PATH = "/home/hotaisle/workspace/models/DeepSeek-R1-0528"
12
+
13
+ print(f"Transformers version: {transformers.__version__}")
14
+ print("-" * 60)
15
+
16
+ # Load tokenizer
17
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
18
+
19
+ # Test 1: Check if the tokenizer supports custom kwargs
20
+ print("\nTest 1: Checking tokenizer's apply_chat_template signature")
21
+ import inspect
22
+ sig = inspect.signature(tokenizer.apply_chat_template)
23
+ print(f"Parameters: {list(sig.parameters.keys())}")
24
+
25
+ # Test 2: Try to apply template manually with Jinja2
26
+ print("\n\nTest 2: Manual Jinja2 template application")
27
+ try:
28
+ from jinja2 import Environment, BaseLoader
29
+
30
+ # Create Jinja2 environment
31
+ env = Environment(loader=BaseLoader())
32
+ template_str = tokenizer.chat_template
33
+ template = env.from_string(template_str)
34
+
35
+ # Prepare variables
36
+ messages = [{"role": "user", "content": "What is 2+2?"}]
37
+
38
+ # Test with enable_thinking=False
39
+ output = template.render(
40
+ messages=messages,
41
+ bos_token=tokenizer.bos_token,
42
+ eos_token=tokenizer.eos_token,
43
+ add_generation_prompt=True,
44
+ enable_thinking=False # This is what we're testing
45
+ )
46
+
47
+ print(f"Manual render with enable_thinking=False:")
48
+ print(f"Output ends with: {repr(output[-130:])}")
49
+ print(f"Contains empty think block: {'<think>\\n\\n</think>\\n\\n' in output}")
50
+
51
+ except Exception as e:
52
+ print(f"Error in manual rendering: {e}")
53
+
54
+ # Test 3: Check the exact template condition
55
+ print("\n\nTest 3: Analyzing template condition")
56
+ template_str = tokenizer.chat_template
57
+ enable_thinking_idx = template_str.find("enable_thinking")
58
+ if enable_thinking_idx != -1:
59
+ # Extract the condition
60
+ start = template_str.rfind("{%", 0, enable_thinking_idx)
61
+ end = template_str.find("%}", enable_thinking_idx) + 2
62
+ condition = template_str[start:end]
63
+ print(f"Found condition: {condition}")
64
+
65
+ # Check for potential issues
66
+ if "is false" in condition:
67
+ print("✓ Uses 'is false' (correct for Jinja2)")
68
+ elif "== false" in condition:
69
+ print("⚠ Uses '== false' (might need 'is false')")
70
+ elif "== False" in condition:
71
+ print("⚠ Uses '== False' (Python style, might need 'is false')")
72
+
73
+ # Test 4: Try different ways to pass the parameter
74
+ print("\n\nTest 4: Testing different parameter passing methods")
75
+
76
+ # Method 1: Direct kwargs (what we've been trying)
77
+ try:
78
+ result1 = tokenizer.apply_chat_template(
79
+ messages,
80
+ tokenize=False,
81
+ add_generation_prompt=True,
82
+ enable_thinking=False
83
+ )
84
+ print("Method 1 (kwargs): Works")
85
+ except Exception as e:
86
+ print(f"Method 1 (kwargs): Error - {e}")
87
+
88
+ # Method 2: Through a dict
89
+ try:
90
+ result2 = tokenizer.apply_chat_template(
91
+ messages,
92
+ tokenize=False,
93
+ add_generation_prompt=True,
94
+ **{"enable_thinking": False}
95
+ )
96
+ print("Method 2 (dict unpacking): Works")
97
+ except Exception as e:
98
+ print(f"Method 2 (dict unpacking): Error - {e}")
99
+
100
+ # Test 5: Check if newer transformers supports it
101
+ print("\n\nTest 5: Checking transformers version compatibility")
102
+ print(f"Current version: {transformers.__version__}")
103
+ print("Note: Custom chat template parameters require transformers >= 4.34.0")
104
+
105
+ # Parse version
106
+ version_parts = transformers.__version__.split('.')
107
+ major = int(version_parts[0])
108
+ minor = int(version_parts[1].split('.')[0] if '.' in version_parts[1] else version_parts[1])
109
+ if major > 4 or (major == 4 and minor >= 34):
110
+ print("✓ Version should support custom parameters")
111
+ else:
112
+ print("✗ Version too old for custom parameters!")
113
+
114
+ # Test 6: Alternative - modify the template to always inject empty think
115
+ print("\n\nTest 6: Testing a simpler template modification")
116
+ print("If all else fails, you could modify the template to always inject empty think")
117
+ print("when a specific string is in the user message, like 'NOTHINK'")
generation_config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "bos_token_id": 0,
4
+ "do_sample": true,
5
+ "eos_token_id": 1,
6
+ "temperature": 0.6,
7
+ "top_p": 0.95,
8
+ "transformers_version": "4.52.4"
9
+ }
inference/configs/config_16B.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "vocab_size": 102400,
3
+ "dim": 2048,
4
+ "inter_dim": 10944,
5
+ "moe_inter_dim": 1408,
6
+ "n_layers": 27,
7
+ "n_dense_layers": 1,
8
+ "n_heads": 16,
9
+ "n_routed_experts": 64,
10
+ "n_shared_experts": 2,
11
+ "n_activated_experts": 6,
12
+ "route_scale": 1.0,
13
+ "q_lora_rank": 0,
14
+ "kv_lora_rank": 512,
15
+ "qk_nope_head_dim": 128,
16
+ "qk_rope_head_dim": 64,
17
+ "v_head_dim": 128,
18
+ "mscale": 0.707
19
+ }
inference/configs/config_236B.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "vocab_size": 102400,
3
+ "dim": 5120,
4
+ "inter_dim": 12288,
5
+ "moe_inter_dim": 1536,
6
+ "n_layers": 60,
7
+ "n_dense_layers": 1,
8
+ "n_heads": 128,
9
+ "n_routed_experts": 160,
10
+ "n_shared_experts": 2,
11
+ "n_activated_experts": 6,
12
+ "n_expert_groups": 8,
13
+ "n_limited_groups": 3,
14
+ "route_scale": 16.0,
15
+ "q_lora_rank": 1536,
16
+ "kv_lora_rank": 512,
17
+ "qk_nope_head_dim": 128,
18
+ "qk_rope_head_dim": 64,
19
+ "v_head_dim": 128
20
+ }
inference/configs/config_671B.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "vocab_size": 129280,
3
+ "dim": 7168,
4
+ "inter_dim": 18432,
5
+ "moe_inter_dim": 2048,
6
+ "n_layers": 61,
7
+ "n_dense_layers": 3,
8
+ "n_heads": 128,
9
+ "n_routed_experts": 256,
10
+ "n_shared_experts": 1,
11
+ "n_activated_experts": 8,
12
+ "n_expert_groups": 8,
13
+ "n_limited_groups": 4,
14
+ "route_scale": 2.5,
15
+ "score_func": "sigmoid",
16
+ "q_lora_rank": 1536,
17
+ "kv_lora_rank": 512,
18
+ "qk_nope_head_dim": 128,
19
+ "qk_rope_head_dim": 64,
20
+ "v_head_dim": 128,
21
+ "dtype": "fp8"
22
+ }
inference/convert.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import shutil
3
+ from argparse import ArgumentParser
4
+ from glob import glob
5
+ from tqdm import tqdm, trange
6
+
7
+ import torch
8
+ from safetensors.torch import safe_open, save_file
9
+
10
+
11
+ mapping = {
12
+ "embed_tokens": ("embed", 0),
13
+ "input_layernorm": ("attn_norm", None),
14
+ "post_attention_layernorm": ("ffn_norm", None),
15
+ "q_proj": ("wq", 0),
16
+ "q_a_proj": ("wq_a", None),
17
+ "q_a_layernorm": ("q_norm", None),
18
+ "q_b_proj": ("wq_b", 0),
19
+ "kv_a_proj_with_mqa": ("wkv_a", None),
20
+ "kv_a_layernorm": ("kv_norm", None),
21
+ "kv_b_proj": ("wkv_b", 0),
22
+ "o_proj": ("wo", 1),
23
+ "gate": ("gate", None),
24
+ "gate_proj": ("w1", 0),
25
+ "down_proj": ("w2", 1),
26
+ "up_proj": ("w3", 0),
27
+ "norm": ("norm", None),
28
+ "lm_head": ("head", 0),
29
+ "scale": ("scale", None),
30
+ }
31
+
32
+
33
+ def main(hf_ckpt_path, save_path, n_experts, mp):
34
+ torch.set_num_threads(8)
35
+ n_local_experts = n_experts // mp
36
+ state_dicts = [{} for _ in range(mp)]
37
+
38
+ for file_path in tqdm(glob(os.path.join(hf_ckpt_path, "*.safetensors"))):
39
+ with safe_open(file_path, framework="pt", device="cpu") as f:
40
+ for name in f.keys():
41
+ if "model.layers.61" in name:
42
+ continue
43
+ param: torch.Tensor = f.get_tensor(name)
44
+ if name.startswith("model."):
45
+ name = name[len("model."):]
46
+ name = name.replace("self_attn", "attn")
47
+ name = name.replace("mlp", "ffn")
48
+ name = name.replace("weight_scale_inv", "scale")
49
+ name = name.replace("e_score_correction_bias", "bias")
50
+ key = name.split(".")[-2]
51
+ assert key in mapping
52
+ new_key, dim = mapping[key]
53
+ name = name.replace(key, new_key)
54
+ for i in range(mp):
55
+ new_param = param
56
+ if "experts" in name and "shared_experts" not in name:
57
+ idx = int(name.split(".")[-3])
58
+ if idx < i * n_local_experts or idx >= (i + 1) * n_local_experts:
59
+ continue
60
+ elif dim is not None:
61
+ assert param.size(dim) % mp == 0
62
+ shard_size = param.size(dim) // mp
63
+ new_param = param.narrow(dim, i * shard_size, shard_size).contiguous()
64
+ state_dicts[i][name] = new_param
65
+
66
+ os.makedirs(save_path, exist_ok=True)
67
+
68
+ for i in trange(mp):
69
+ save_file(state_dicts[i], os.path.join(save_path, f"model{i}-mp{mp}.safetensors"))
70
+
71
+ for file_path in glob(os.path.join(hf_ckpt_path, "*token*")):
72
+ new_file_path = os.path.join(save_path, os.path.basename(file_path))
73
+ shutil.copyfile(file_path, new_file_path)
74
+
75
+
76
+ if __name__ == "__main__":
77
+ parser = ArgumentParser()
78
+ parser.add_argument("--hf-ckpt-path", type=str, required=True)
79
+ parser.add_argument("--save-path", type=str, required=True)
80
+ parser.add_argument("--n-experts", type=int, required=True)
81
+ parser.add_argument("--model-parallel", type=int, default=1)
82
+ args = parser.parse_args()
83
+ assert args.n_experts % args.model_parallel == 0
84
+ main(args.hf_ckpt_path, args.save_path, args.n_experts, args.model_parallel)
inference/fp8_cast_bf16.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ from argparse import ArgumentParser
4
+ from glob import glob
5
+ from tqdm import tqdm
6
+
7
+ import torch
8
+ from safetensors.torch import load_file, save_file
9
+
10
+ from kernel import weight_dequant
11
+
12
+ def main(fp8_path, bf16_path):
13
+ torch.set_default_dtype(torch.bfloat16)
14
+ os.makedirs(bf16_path, exist_ok=True)
15
+ model_index_file = os.path.join(fp8_path, "model.safetensors.index.json")
16
+ with open(model_index_file, "r") as f:
17
+ model_index = json.load(f)
18
+ weight_map = model_index["weight_map"]
19
+
20
+ # Cache for loaded safetensor files
21
+ loaded_files = {}
22
+ fp8_weight_names = []
23
+
24
+ # Helper function to get tensor from the correct file
25
+ def get_tensor(tensor_name):
26
+ file_name = weight_map[tensor_name]
27
+ if file_name not in loaded_files:
28
+ file_path = os.path.join(fp8_path, file_name)
29
+ loaded_files[file_name] = load_file(file_path, device="cuda")
30
+ return loaded_files[file_name][tensor_name]
31
+
32
+ safetensor_files = list(glob(os.path.join(fp8_path, "*.safetensors")))
33
+ safetensor_files.sort()
34
+ for safetensor_file in tqdm(safetensor_files):
35
+ file_name = os.path.basename(safetensor_file)
36
+ current_state_dict = load_file(safetensor_file, device="cuda")
37
+ loaded_files[file_name] = current_state_dict
38
+
39
+ new_state_dict = {}
40
+ for weight_name, weight in current_state_dict.items():
41
+ if weight_name.endswith("_scale_inv"):
42
+ continue
43
+ elif weight.element_size() == 1: # FP8 weight
44
+ scale_inv_name = f"{weight_name}_scale_inv"
45
+ try:
46
+ # Get scale_inv from the correct file
47
+ scale_inv = get_tensor(scale_inv_name)
48
+ fp8_weight_names.append(weight_name)
49
+ new_state_dict[weight_name] = weight_dequant(weight, scale_inv)
50
+ except KeyError:
51
+ print(f"Warning: Missing scale_inv tensor for {weight_name}, skipping conversion")
52
+ new_state_dict[weight_name] = weight
53
+ else:
54
+ new_state_dict[weight_name] = weight
55
+
56
+ new_safetensor_file = os.path.join(bf16_path, file_name)
57
+ save_file(new_state_dict, new_safetensor_file)
58
+
59
+ # Memory management: keep only the 2 most recently used files
60
+ if len(loaded_files) > 2:
61
+ oldest_file = next(iter(loaded_files))
62
+ del loaded_files[oldest_file]
63
+ torch.cuda.empty_cache()
64
+
65
+ # Update model index
66
+ new_model_index_file = os.path.join(bf16_path, "model.safetensors.index.json")
67
+ for weight_name in fp8_weight_names:
68
+ scale_inv_name = f"{weight_name}_scale_inv"
69
+ if scale_inv_name in weight_map:
70
+ weight_map.pop(scale_inv_name)
71
+ with open(new_model_index_file, "w") as f:
72
+ json.dump({"metadata": {}, "weight_map": weight_map}, f, indent=2)
73
+
74
+
75
+ if __name__ == "__main__":
76
+ parser = ArgumentParser()
77
+ parser.add_argument("--input-fp8-hf-path", type=str, required=True)
78
+ parser.add_argument("--output-bf16-hf-path", type=str, required=True)
79
+ args = parser.parse_args()
80
+ main(args.input_fp8_hf_path, args.output_bf16_hf_path)
81
+
inference/generate.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ from argparse import ArgumentParser
4
+ from typing import List
5
+
6
+ import torch
7
+ import torch.distributed as dist
8
+ from transformers import AutoTokenizer
9
+ from safetensors.torch import load_model
10
+
11
+ from model import Transformer, ModelArgs
12
+
13
+
14
+ def sample(logits, temperature: float = 1.0):
15
+ logits = logits / max(temperature, 1e-5)
16
+ probs = torch.softmax(logits, dim=-1)
17
+ return probs.div_(torch.empty_like(probs).exponential_(1)).argmax(dim=-1)
18
+
19
+
20
+ @torch.inference_mode()
21
+ def generate(
22
+ model: Transformer,
23
+ prompt_tokens: List[List[int]],
24
+ max_new_tokens: int,
25
+ eos_id: int,
26
+ temperature: float = 1.0
27
+ ) -> List[List[int]]:
28
+ prompt_lens = [len(t) for t in prompt_tokens]
29
+ assert max(prompt_lens) <= model.max_seq_len
30
+ total_len = min(model.max_seq_len, max_new_tokens + max(prompt_lens))
31
+ tokens = torch.full((len(prompt_tokens), total_len), -1, dtype=torch.long, device="cuda")
32
+ for i, t in enumerate(prompt_tokens):
33
+ tokens[i, :len(t)] = torch.tensor(t, dtype=torch.long, device="cuda")
34
+ prev_pos = 0
35
+ finished = torch.tensor([False] * len(prompt_tokens), device="cuda")
36
+ prompt_mask = tokens != -1
37
+ for cur_pos in range(min(prompt_lens), total_len):
38
+ logits = model.forward(tokens[:, prev_pos:cur_pos], prev_pos)
39
+ if temperature > 0:
40
+ next_token = sample(logits, temperature)
41
+ else:
42
+ next_token = logits.argmax(dim=-1)
43
+ next_token = torch.where(prompt_mask[:, cur_pos], tokens[:, cur_pos], next_token)
44
+ tokens[:, cur_pos] = next_token
45
+ finished |= torch.logical_and(~prompt_mask[:, cur_pos], next_token == eos_id)
46
+ prev_pos = cur_pos
47
+ if finished.all():
48
+ break
49
+ completion_tokens = []
50
+ for i, toks in enumerate(tokens.tolist()):
51
+ toks = toks[prompt_lens[i]:prompt_lens[i]+max_new_tokens]
52
+ if eos_id in toks:
53
+ toks = toks[:toks.index(eos_id)]
54
+ completion_tokens.append(toks)
55
+ return completion_tokens
56
+
57
+
58
+ def main(
59
+ ckpt_path: str,
60
+ config: str,
61
+ input_file: str = "",
62
+ interactive: bool = True,
63
+ max_new_tokens: int = 100,
64
+ temperature: float = 1.0,
65
+ ) -> None:
66
+ world_size = int(os.getenv("WORLD_SIZE", "1"))
67
+ rank = int(os.getenv("RANK", "0"))
68
+ local_rank = int(os.getenv("LOCAL_RANK", "0"))
69
+ if world_size > 1:
70
+ dist.init_process_group("nccl")
71
+ global print
72
+ if rank != 0:
73
+ print = lambda *_, **__: None
74
+ torch.cuda.set_device(local_rank)
75
+ torch.set_default_dtype(torch.bfloat16)
76
+ torch.set_num_threads(8)
77
+ torch.manual_seed(965)
78
+ with open(config) as f:
79
+ args = ModelArgs(**json.load(f))
80
+ print(args)
81
+ with torch.device("cuda"):
82
+ model = Transformer(args)
83
+ tokenizer = AutoTokenizer.from_pretrained(ckpt_path)
84
+ tokenizer.decode(generate(model, [tokenizer.encode("DeepSeek")], 2, -1, 1.)[0])
85
+ load_model(model, os.path.join(ckpt_path, f"model{rank}-mp{world_size}.safetensors"))
86
+
87
+ if interactive:
88
+ messages = []
89
+ while True:
90
+ if world_size == 1:
91
+ prompt = input(">>> ")
92
+ elif rank == 0:
93
+ prompt = input(">>> ")
94
+ objects = [prompt]
95
+ dist.broadcast_object_list(objects, 0)
96
+ else:
97
+ objects = [None]
98
+ dist.broadcast_object_list(objects, 0)
99
+ prompt = objects[0]
100
+ if prompt == "/exit":
101
+ break
102
+ elif prompt == "/clear":
103
+ messages.clear()
104
+ continue
105
+ messages.append({"role": "user", "content": prompt})
106
+ prompt_tokens = tokenizer.apply_chat_template(messages, add_generation_prompt=True)
107
+ completion_tokens = generate(model, [prompt_tokens], max_new_tokens, tokenizer.eos_token_id, temperature)
108
+ completion = tokenizer.decode(completion_tokens[0], skip_special_tokens=True)
109
+ print(completion)
110
+ messages.append({"role": "assistant", "content": completion})
111
+ else:
112
+ with open(input_file) as f:
113
+ prompts = [line.strip() for line in f.readlines()]
114
+ assert len(prompts) <= args.max_batch_size
115
+ prompt_tokens = [tokenizer.apply_chat_template([{"role": "user", "content": prompt}], add_generation_prompt=True) for prompt in prompts]
116
+ completion_tokens = generate(model, prompt_tokens, max_new_tokens, tokenizer.eos_token_id, temperature)
117
+ completions = tokenizer.batch_decode(completion_tokens, skip_special_tokens=True)
118
+ for prompt, completion in zip(prompts, completions):
119
+ print("Prompt:", prompt)
120
+ print("Completion:", completion)
121
+ print()
122
+
123
+ if world_size > 1:
124
+ dist.destroy_process_group()
125
+
126
+
127
+ if __name__ == "__main__":
128
+ parser = ArgumentParser()
129
+ parser.add_argument("--ckpt-path", type=str, required=True)
130
+ parser.add_argument("--config", type=str, required=True)
131
+ parser.add_argument("--input-file", type=str, default="")
132
+ parser.add_argument("--interactive", action="store_true")
133
+ parser.add_argument("--max-new-tokens", type=int, default=200)
134
+ parser.add_argument("--temperature", type=float, default=0.2)
135
+ args = parser.parse_args()
136
+ assert args.input_file or args.interactive
137
+ main(args.ckpt_path, args.config, args.input_file, args.interactive, args.max_new_tokens, args.temperature)
inference/kernel.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Tuple
2
+
3
+ import torch
4
+ import triton
5
+ import triton.language as tl
6
+ from triton import Config
7
+
8
+
9
+ @triton.jit
10
+ def act_quant_kernel(x_ptr, y_ptr, s_ptr, BLOCK_SIZE: tl.constexpr):
11
+ pid = tl.program_id(axis=0)
12
+ offs = pid * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
13
+ x = tl.load(x_ptr + offs).to(tl.float32)
14
+ s = tl.max(tl.abs(x)) / 448.
15
+ y = x / s
16
+ y = y.to(y_ptr.dtype.element_ty)
17
+ tl.store(y_ptr + offs, y)
18
+ tl.store(s_ptr + pid, s)
19
+
20
+
21
+ def act_quant(x: torch.Tensor, block_size: int = 128) -> Tuple[torch.Tensor, torch.Tensor]:
22
+ assert x.is_contiguous()
23
+ assert x.size(-1) % block_size == 0
24
+ y = torch.empty_like(x, dtype=torch.float8_e4m3fn)
25
+ s = x.new_empty(*x.size()[:-1], x.size(-1) // block_size, dtype=torch.float32)
26
+ grid = lambda meta: (triton.cdiv(x.numel(), meta['BLOCK_SIZE']), )
27
+ act_quant_kernel[grid](x, y, s, BLOCK_SIZE=block_size)
28
+ return y, s
29
+
30
+
31
+ @triton.jit
32
+ def weight_dequant_kernel(x_ptr, s_ptr, y_ptr, M, N, BLOCK_SIZE: tl.constexpr):
33
+ pid_m = tl.program_id(axis=0)
34
+ pid_n = tl.program_id(axis=1)
35
+ n = tl.cdiv(N, BLOCK_SIZE)
36
+ offs_m = pid_m * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
37
+ offs_n = pid_n * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
38
+ offs = offs_m[:, None] * N + offs_n[None, :]
39
+ mask = (offs_m[:, None] < M) & (offs_n[None, :] < N)
40
+ x = tl.load(x_ptr + offs, mask=mask).to(tl.float32)
41
+ s = tl.load(s_ptr + pid_m * n + pid_n)
42
+ y = x * s
43
+ tl.store(y_ptr + offs, y, mask=mask)
44
+
45
+
46
+ def weight_dequant(x: torch.Tensor, s: torch.Tensor, block_size: int = 128) -> torch.Tensor:
47
+ assert x.is_contiguous() and s.is_contiguous()
48
+ assert x.dim() == 2 and s.dim() == 2
49
+ M, N = x.size()
50
+ y = torch.empty_like(x, dtype=torch.get_default_dtype())
51
+ grid = lambda meta: (triton.cdiv(M, meta['BLOCK_SIZE']), triton.cdiv(N, meta['BLOCK_SIZE']))
52
+ weight_dequant_kernel[grid](x, s, y, M, N, BLOCK_SIZE=block_size)
53
+ return y
54
+
55
+
56
+ fp8_gemm_configs = [
57
+ Config({'BLOCK_SIZE_M': block_m, 'BLOCK_SIZE_N': block_n, 'BLOCK_SIZE_K': 128}, num_stages=num_stages, num_warps=8)
58
+ for block_m in [16, 32, 64] for block_n in [32, 64, 128] for num_stages in [3, 4, 5, 6]
59
+ ]
60
+
61
+ @triton.autotune(configs=fp8_gemm_configs, key=['N', 'K'])
62
+ @triton.jit
63
+ def fp8_gemm_kernel(a_ptr, b_ptr, c_ptr,
64
+ a_s_ptr, b_s_ptr,
65
+ M, N: tl.constexpr, K: tl.constexpr,
66
+ BLOCK_SIZE_M: tl.constexpr,
67
+ BLOCK_SIZE_N: tl.constexpr,
68
+ BLOCK_SIZE_K: tl.constexpr):
69
+ pid_m = tl.program_id(axis=0)
70
+ pid_n = tl.program_id(axis=1)
71
+ k = tl.cdiv(K, BLOCK_SIZE_K)
72
+ offs_m = (pid_m * BLOCK_SIZE_M + tl.arange(0, BLOCK_SIZE_M)) % M
73
+ offs_n = (pid_n * BLOCK_SIZE_N + tl.arange(0, BLOCK_SIZE_N)) % N
74
+ offs_k = tl.arange(0, BLOCK_SIZE_K)
75
+ a_ptrs = a_ptr + offs_m[:, None] * K + offs_k[None, :]
76
+ b_ptrs = b_ptr + offs_n[None, :] * K + offs_k[:, None]
77
+ a_s_ptrs = a_s_ptr + offs_m * k
78
+ b_s_ptrs = b_s_ptr + (offs_n // BLOCK_SIZE_K) * k
79
+
80
+ accumulator = tl.zeros((BLOCK_SIZE_M, BLOCK_SIZE_N), dtype=tl.float32)
81
+ for i in range(k):
82
+ a = tl.load(a_ptrs, mask=offs_k[None, :] < K - i * BLOCK_SIZE_K, other=0.0)
83
+ b = tl.load(b_ptrs, mask=offs_k[:, None] < K - i * BLOCK_SIZE_K, other=0.0)
84
+ a_s = tl.load(a_s_ptrs)
85
+ b_s = tl.load(b_s_ptrs)
86
+ accumulator += tl.dot(a, b) * a_s[:, None] * b_s[None, :]
87
+ a_ptrs += BLOCK_SIZE_K
88
+ b_ptrs += BLOCK_SIZE_K
89
+ a_s_ptrs += 1
90
+ b_s_ptrs += 1
91
+ c = accumulator.to(c_ptr.dtype.element_ty)
92
+ offs_m = pid_m * BLOCK_SIZE_M + tl.arange(0, BLOCK_SIZE_M)
93
+ offs_n = pid_n * BLOCK_SIZE_N + tl.arange(0, BLOCK_SIZE_N)
94
+ c_ptrs = c_ptr + offs_m[:, None] * N + offs_n[None, :]
95
+ mask = (offs_m[:, None] < M) & (offs_n[None, :] < N)
96
+ tl.store(c_ptrs, c, mask=mask)
97
+
98
+
99
+ def fp8_gemm(a: torch.Tensor, a_s: torch.Tensor, b: torch.Tensor, b_s: torch.Tensor):
100
+ assert a.is_contiguous() and b.is_contiguous()
101
+ assert a_s.is_contiguous() and b_s.is_contiguous()
102
+ K = a.size(-1)
103
+ M = a.numel() // K
104
+ N = b.size(0)
105
+ c = a.new_empty(*a.size()[:-1], N, dtype=torch.get_default_dtype())
106
+ grid = lambda META: (triton.cdiv(M, META['BLOCK_SIZE_M']), triton.cdiv(N, META['BLOCK_SIZE_N']))
107
+ fp8_gemm_kernel[grid](a, b, c, a_s, b_s, M, N, K)
108
+ return c
inference/model.py ADDED
@@ -0,0 +1,421 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ from dataclasses import dataclass
3
+ from typing import Tuple, Optional, Literal
4
+
5
+ import torch
6
+ from torch import nn
7
+ import torch.nn.functional as F
8
+ import torch.distributed as dist
9
+
10
+ from kernel import act_quant, weight_dequant, fp8_gemm
11
+
12
+
13
+ world_size = 1
14
+ rank = 0
15
+ block_size = 128
16
+ gemm_impl: Literal["bf16", "fp8"] = "bf16"
17
+ attn_impl: Literal["naive", "absorb"] = "absorb"
18
+
19
+ @dataclass
20
+ class ModelArgs:
21
+ max_batch_size: int = 8
22
+ max_seq_len: int = 4096 * 4
23
+ dtype: Literal["bf16", "fp8"] = "bf16"
24
+ vocab_size: int = 102400
25
+ dim: int = 2048
26
+ inter_dim: int = 10944
27
+ moe_inter_dim: int = 1408
28
+ n_layers: int = 27
29
+ n_dense_layers: int = 1
30
+ n_heads: int = 16
31
+ # moe
32
+ n_routed_experts: int = 64
33
+ n_shared_experts: int = 2
34
+ n_activated_experts: int = 6
35
+ n_expert_groups: int = 1
36
+ n_limited_groups: int = 1
37
+ score_func: Literal["softmax", "sigmoid"] = "softmax"
38
+ route_scale: float = 1.
39
+ # mla
40
+ q_lora_rank: int = 0
41
+ kv_lora_rank: int = 512
42
+ qk_nope_head_dim: int = 128
43
+ qk_rope_head_dim: int = 64
44
+ v_head_dim: int = 128
45
+ # yarn
46
+ original_seq_len: int = 4096
47
+ rope_theta: float = 10000.0
48
+ rope_factor: float = 40
49
+ beta_fast: int = 32
50
+ beta_slow: int = 1
51
+ mscale: float = 1.
52
+
53
+
54
+ class ParallelEmbedding(nn.Module):
55
+ def __init__(self, vocab_size: int, dim: int):
56
+ super().__init__()
57
+ self.vocab_size = vocab_size
58
+ self.dim = dim
59
+ assert vocab_size % world_size == 0
60
+ self.part_vocab_size = (vocab_size // world_size)
61
+ self.vocab_start_idx = rank * self.part_vocab_size
62
+ self.vocab_end_idx = self.vocab_start_idx + self.part_vocab_size
63
+ self.weight = nn.Parameter(torch.empty(self.part_vocab_size, self.dim))
64
+
65
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
66
+ if world_size > 1:
67
+ mask = (x < self.vocab_start_idx) | (x >= self.vocab_end_idx)
68
+ x = x - self.vocab_start_idx
69
+ x[mask] = 0
70
+ y = F.embedding(x, self.weight)
71
+ if world_size > 1:
72
+ y[mask] = 0
73
+ dist.all_reduce(y)
74
+ return y
75
+
76
+
77
+ def linear(x: torch.Tensor, weight: torch.Tensor, bias: Optional[torch.Tensor] = None) -> torch.Tensor:
78
+ if weight.element_size() > 1:
79
+ return F.linear(x, weight, bias)
80
+ elif gemm_impl == "bf16":
81
+ weight = weight_dequant(weight, weight.scale)
82
+ return F.linear(x, weight, bias)
83
+ else:
84
+ x, scale = act_quant(x, block_size)
85
+ y = fp8_gemm(x, scale, weight, weight.scale)
86
+ if bias is not None:
87
+ y += bias
88
+ return y
89
+
90
+
91
+ class Linear(nn.Module):
92
+ dtype = torch.bfloat16
93
+
94
+ def __init__(self, in_features: int, out_features: int, bias: bool = False, dtype = None):
95
+ super().__init__()
96
+ self.in_features = in_features
97
+ self.out_features = out_features
98
+ self.weight = nn.Parameter(torch.empty(out_features, in_features, dtype=dtype or Linear.dtype))
99
+ if self.weight.element_size() == 1:
100
+ scale_out_features = (out_features + block_size - 1) // block_size
101
+ scale_in_features = (in_features + block_size - 1) // block_size
102
+ self.weight.scale = self.scale = nn.Parameter(torch.empty(scale_out_features, scale_in_features, dtype=torch.float32))
103
+ else:
104
+ self.register_parameter("scale", None)
105
+ if bias:
106
+ self.bias = nn.Parameter(torch.empty(self.part_out_features))
107
+ else:
108
+ self.register_parameter("bias", None)
109
+
110
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
111
+ return linear(x, self.weight, self.bias)
112
+
113
+
114
+ class ColumnParallelLinear(Linear):
115
+ def __init__(self, in_features: int, out_features: int, bias: bool = False, dtype = None):
116
+ assert out_features % world_size == 0
117
+ self.part_out_features = out_features // world_size
118
+ super().__init__(in_features, self.part_out_features, bias, dtype)
119
+
120
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
121
+ y = linear(x, self.weight, self.bias)
122
+ return y
123
+
124
+
125
+ class RowParallelLinear(Linear):
126
+ def __init__(self, in_features: int, out_features: int, bias: bool = False, dtype = None):
127
+ assert in_features % world_size == 0
128
+ self.part_in_features = in_features // world_size
129
+ super().__init__(self.part_in_features, out_features, bias, dtype)
130
+
131
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
132
+ y = linear(x, self.weight)
133
+ if world_size > 1:
134
+ dist.all_reduce(y)
135
+ if self.bias is not None:
136
+ y += self.bias
137
+ return y
138
+
139
+
140
+ class RMSNorm(nn.Module):
141
+ def __init__(self, dim: int, eps: float = 1e-6):
142
+ super().__init__()
143
+ self.eps = eps
144
+ self.weight = nn.Parameter(torch.ones(dim))
145
+
146
+ def forward(self, x: torch.Tensor):
147
+ x = x.float()
148
+ y = x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
149
+ return y.type_as(self.weight) * self.weight
150
+
151
+
152
+ def precompute_freqs_cis(args: ModelArgs) -> torch.Tensor:
153
+ dim = args.qk_rope_head_dim
154
+ seqlen = args.max_seq_len
155
+ beta_fast = args.beta_fast
156
+ beta_slow = args.beta_slow
157
+ base = args.rope_theta
158
+ factor = args.rope_factor
159
+
160
+ def find_correction_dim(num_rotations, dim, base, max_seq_len):
161
+ return dim * math.log(max_seq_len / (num_rotations * 2 * math.pi)) / (2 * math.log(base))
162
+
163
+ def find_correction_range(low_rot, high_rot, dim, base, max_seq_len):
164
+ low = math.floor(find_correction_dim(low_rot, dim, base, max_seq_len))
165
+ high = math.ceil(find_correction_dim(high_rot, dim, base, max_seq_len))
166
+ return max(low, 0), min(high, dim-1)
167
+
168
+ def linear_ramp_factor(min, max, dim):
169
+ if min == max:
170
+ max += 0.001
171
+ linear_func = (torch.arange(dim, dtype=torch.float32) - min) / (max - min)
172
+ ramp_func = torch.clamp(linear_func, 0, 1)
173
+ return ramp_func
174
+
175
+ freqs = 1.0 / (base ** (torch.arange(0, dim, 2, dtype=torch.float32) / dim))
176
+ if seqlen > args.original_seq_len:
177
+ low, high = find_correction_range(beta_fast, beta_slow, dim, base, args.original_seq_len)
178
+ smooth = 1 - linear_ramp_factor(low, high, dim // 2)
179
+ freqs = freqs / factor * (1 - smooth) + freqs * smooth
180
+
181
+ t = torch.arange(seqlen)
182
+ freqs = torch.outer(t, freqs)
183
+ freqs_cis = torch.polar(torch.ones_like(freqs), freqs)
184
+ return freqs_cis
185
+
186
+
187
+ def apply_rotary_emb(x: torch.Tensor, freqs_cis: torch.Tensor) -> torch.Tensor:
188
+ dtype = x.dtype
189
+ x = torch.view_as_complex(x.float().view(*x.shape[:-1], -1, 2))
190
+ freqs_cis = freqs_cis.view(1, x.size(1), 1, x.size(-1))
191
+ y = torch.view_as_real(x * freqs_cis).flatten(3)
192
+ return y.to(dtype)
193
+
194
+
195
+ class MLA(nn.Module):
196
+ def __init__(self, args: ModelArgs):
197
+ super().__init__()
198
+ self.dim = args.dim
199
+ self.n_heads = args.n_heads
200
+ self.n_local_heads = args.n_heads // world_size
201
+ self.q_lora_rank = args.q_lora_rank
202
+ self.kv_lora_rank = args.kv_lora_rank
203
+ self.qk_nope_head_dim = args.qk_nope_head_dim
204
+ self.qk_rope_head_dim = args.qk_rope_head_dim
205
+ self.qk_head_dim = args.qk_nope_head_dim + args.qk_rope_head_dim
206
+ self.v_head_dim = args.v_head_dim
207
+
208
+ if self.q_lora_rank == 0:
209
+ self.wq = ColumnParallelLinear(self.dim, self.n_heads * self.qk_head_dim)
210
+ else:
211
+ self.wq_a = Linear(self.dim, self.q_lora_rank)
212
+ self.q_norm = RMSNorm(self.q_lora_rank)
213
+ self.wq_b = ColumnParallelLinear(self.q_lora_rank, self.n_heads * self.qk_head_dim)
214
+ self.wkv_a = Linear(self.dim, self.kv_lora_rank + self.qk_rope_head_dim)
215
+ self.kv_norm = RMSNorm(self.kv_lora_rank)
216
+ self.wkv_b = ColumnParallelLinear(self.kv_lora_rank, self.n_heads * (self.qk_nope_head_dim + self.v_head_dim))
217
+ self.wo = RowParallelLinear(self.n_heads * self.v_head_dim, self.dim)
218
+ self.softmax_scale = self.qk_head_dim ** -0.5
219
+ if args.max_seq_len > args.original_seq_len:
220
+ mscale = 0.1 * args.mscale * math.log(args.rope_factor) + 1.0
221
+ self.softmax_scale = self.softmax_scale * mscale * mscale
222
+
223
+ if attn_impl == "naive":
224
+ self.register_buffer("k_cache", torch.zeros(args.max_batch_size, args.max_seq_len, self.n_local_heads, self.qk_head_dim), persistent=False)
225
+ self.register_buffer("v_cache", torch.zeros(args.max_batch_size, args.max_seq_len, self.n_local_heads, self.v_head_dim), persistent=False)
226
+ else:
227
+ self.register_buffer("kv_cache", torch.zeros(args.max_batch_size, args.max_seq_len, self.kv_lora_rank), persistent=False)
228
+ self.register_buffer("pe_cache", torch.zeros(args.max_batch_size, args.max_seq_len, self.qk_rope_head_dim), persistent=False)
229
+
230
+ def forward(self, x: torch.Tensor, start_pos: int, freqs_cis: torch.Tensor, mask: Optional[torch.Tensor]):
231
+ bsz, seqlen, _ = x.size()
232
+ end_pos = start_pos + seqlen
233
+ if self.q_lora_rank == 0:
234
+ q = self.wq(x)
235
+ else:
236
+ q = self.wq_b(self.q_norm(self.wq_a(x)))
237
+ q = q.view(bsz, seqlen, self.n_local_heads, self.qk_head_dim)
238
+ q_nope, q_pe = torch.split(q, [self.qk_nope_head_dim, self.qk_rope_head_dim], dim=-1)
239
+ q_pe = apply_rotary_emb(q_pe, freqs_cis)
240
+ kv = self.wkv_a(x)
241
+ kv, k_pe = torch.split(kv, [self.kv_lora_rank, self.qk_rope_head_dim], dim=-1)
242
+ k_pe = apply_rotary_emb(k_pe.unsqueeze(2), freqs_cis)
243
+ if attn_impl == "naive":
244
+ q = torch.cat([q_nope, q_pe], dim=-1)
245
+ kv = self.wkv_b(self.kv_norm(kv))
246
+ kv = kv.view(bsz, seqlen, self.n_local_heads, self.qk_nope_head_dim + self.v_head_dim)
247
+ k_nope, v = torch.split(kv, [self.qk_nope_head_dim, self.v_head_dim], dim=-1)
248
+ k = torch.cat([k_nope, k_pe.expand(-1, -1, self.n_local_heads, -1)], dim=-1)
249
+ self.k_cache[:bsz, start_pos:end_pos] = k
250
+ self.v_cache[:bsz, start_pos:end_pos] = v
251
+ scores = torch.einsum("bshd,bthd->bsht", q, self.k_cache[:bsz, :end_pos]) * self.softmax_scale
252
+ else:
253
+ wkv_b = self.wkv_b.weight if self.wkv_b.scale is None else weight_dequant(self.wkv_b.weight, self.wkv_b.scale, block_size)
254
+ wkv_b = wkv_b.view(self.n_local_heads, -1, self.kv_lora_rank)
255
+ q_nope = torch.einsum("bshd,hdc->bshc", q_nope, wkv_b[:, :self.qk_nope_head_dim])
256
+ self.kv_cache[:bsz, start_pos:end_pos] = self.kv_norm(kv)
257
+ self.pe_cache[:bsz, start_pos:end_pos] = k_pe.squeeze(2)
258
+ scores = (torch.einsum("bshc,btc->bsht", q_nope, self.kv_cache[:bsz, :end_pos]) +
259
+ torch.einsum("bshr,btr->bsht", q_pe, self.pe_cache[:bsz, :end_pos])) * self.softmax_scale
260
+ if mask is not None:
261
+ scores += mask.unsqueeze(1)
262
+ scores = scores.softmax(dim=-1, dtype=torch.float32).type_as(x)
263
+ if attn_impl == "naive":
264
+ x = torch.einsum("bsht,bthd->bshd", scores, self.v_cache[:bsz, :end_pos])
265
+ else:
266
+ x = torch.einsum("bsht,btc->bshc", scores, self.kv_cache[:bsz, :end_pos])
267
+ x = torch.einsum("bshc,hdc->bshd", x, wkv_b[:, -self.v_head_dim:])
268
+ x = self.wo(x.flatten(2))
269
+ return x
270
+
271
+
272
+ class MLP(nn.Module):
273
+ def __init__(self, dim: int, inter_dim: int):
274
+ super().__init__()
275
+ self.w1 = ColumnParallelLinear(dim, inter_dim)
276
+ self.w2 = RowParallelLinear(inter_dim, dim)
277
+ self.w3 = ColumnParallelLinear(dim, inter_dim)
278
+
279
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
280
+ return self.w2(F.silu(self.w1(x)) * self.w3(x))
281
+
282
+
283
+ class Gate(nn.Module):
284
+ def __init__(self, args: ModelArgs):
285
+ super().__init__()
286
+ self.dim = args.dim
287
+ self.topk = args.n_activated_experts
288
+ self.n_groups = args.n_expert_groups
289
+ self.topk_groups = args.n_limited_groups
290
+ self.score_func = args.score_func
291
+ self.route_scale = args.route_scale
292
+ self.weight = nn.Parameter(torch.empty(args.n_routed_experts, args.dim))
293
+ self.bias = nn.Parameter(torch.empty(args.n_routed_experts)) if self.dim == 7168 else None
294
+
295
+ def forward(self, x: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
296
+ scores = linear(x, self.weight)
297
+ if self.score_func == "softmax":
298
+ scores = scores.softmax(dim=-1, dtype=torch.float32)
299
+ else:
300
+ scores = scores.sigmoid()
301
+ original_scores = scores
302
+ if self.bias is not None:
303
+ scores = scores + self.bias
304
+ if self.n_groups > 1:
305
+ scores = scores.view(x.size(0), self.n_groups, -1)
306
+ if self.bias is None:
307
+ group_scores = scores.amax(dim=-1)
308
+ else:
309
+ group_scores = scores.topk(2, dim=-1)[0].sum(dim=-1)
310
+ indices = group_scores.topk(self.topk_groups, dim=-1)[1]
311
+ mask = torch.zeros_like(scores[..., 0]).scatter_(1, indices, True)
312
+ scores = (scores * mask.unsqueeze(-1)).flatten(1)
313
+ indices = torch.topk(scores, self.topk, dim=-1)[1]
314
+ weights = original_scores.gather(1, indices)
315
+ if self.score_func == "sigmoid":
316
+ weights /= weights.sum(dim=-1, keepdim=True)
317
+ weights *= self.route_scale
318
+ return weights.type_as(x), indices
319
+
320
+
321
+ class Expert(nn.Module):
322
+ def __init__(self, dim: int, inter_dim: int):
323
+ super().__init__()
324
+ self.w1 = Linear(dim, inter_dim)
325
+ self.w2 = Linear(inter_dim, dim)
326
+ self.w3 = Linear(dim, inter_dim)
327
+
328
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
329
+ return self.w2(F.silu(self.w1(x)) * self.w3(x))
330
+
331
+
332
+ class MoE(nn.Module):
333
+ def __init__(self, args: ModelArgs):
334
+ super().__init__()
335
+ self.dim = args.dim
336
+ assert args.n_routed_experts % world_size == 0
337
+ self.n_routed_experts = args.n_routed_experts
338
+ self.n_local_experts = args.n_routed_experts // world_size
339
+ self.n_activated_experts = args.n_activated_experts
340
+ self.experts_start_idx = rank * self.n_local_experts
341
+ self.experts_end_idx = self.experts_start_idx + self.n_local_experts
342
+ self.gate = Gate(args)
343
+ self.experts = nn.ModuleList([Expert(args.dim, args.moe_inter_dim) if self.experts_start_idx <= i < self.experts_end_idx else None
344
+ for i in range(self.n_routed_experts)])
345
+ self.shared_experts = MLP(args.dim, args.n_shared_experts * args.moe_inter_dim)
346
+
347
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
348
+ shape = x.size()
349
+ x = x.view(-1, self.dim)
350
+ weights, indices = self.gate(x)
351
+ y = torch.zeros_like(x)
352
+ counts = torch.bincount(indices.flatten(), minlength=self.n_routed_experts).tolist()
353
+ for i in range(self.experts_start_idx, self.experts_end_idx):
354
+ if counts[i] == 0:
355
+ continue
356
+ expert = self.experts[i]
357
+ idx, top = torch.where(indices == i)
358
+ y[idx] += expert(x[idx]) * weights[idx, top, None]
359
+ z = self.shared_experts(x)
360
+ if world_size > 1:
361
+ dist.all_reduce(y)
362
+ return (y + z).view(shape)
363
+
364
+
365
+ class Block(nn.Module):
366
+ def __init__(self, layer_id: int, args: ModelArgs):
367
+ super().__init__()
368
+ self.attn = MLA(args)
369
+ self.ffn = MLP(args.dim, args.inter_dim) if layer_id < args.n_dense_layers else MoE(args)
370
+ self.attn_norm = RMSNorm(args.dim)
371
+ self.ffn_norm = RMSNorm(args.dim)
372
+
373
+ def forward(self, x: torch.Tensor, start_pos: int, freqs_cis: torch.Tensor, mask: Optional[torch.Tensor]) -> torch.Tensor:
374
+ x = x + self.attn(self.attn_norm(x), start_pos, freqs_cis, mask)
375
+ x = x + self.ffn(self.ffn_norm(x))
376
+ return x
377
+
378
+
379
+ class Transformer(nn.Module):
380
+ def __init__(self, args: ModelArgs):
381
+ global world_size, rank
382
+ world_size = dist.get_world_size() if dist.is_initialized() else 1
383
+ rank = dist.get_rank() if dist.is_initialized() else 0
384
+ Linear.dtype = torch.float8_e4m3fn if args.dtype == "fp8" else torch.bfloat16
385
+ super().__init__()
386
+ self.max_seq_len = args.max_seq_len
387
+ self.embed = ParallelEmbedding(args.vocab_size, args.dim)
388
+ self.layers = torch.nn.ModuleList()
389
+ for layer_id in range(args.n_layers):
390
+ self.layers.append(Block(layer_id, args))
391
+ self.norm = RMSNorm(args.dim)
392
+ self.head = ColumnParallelLinear(args.dim, args.vocab_size, dtype=torch.get_default_dtype())
393
+ self.register_buffer("freqs_cis", precompute_freqs_cis(args), persistent=False)
394
+
395
+ @torch.inference_mode()
396
+ def forward(self, tokens: torch.Tensor, start_pos: int = 0):
397
+ seqlen = tokens.size(1)
398
+ h = self.embed(tokens)
399
+ freqs_cis = self.freqs_cis[start_pos:start_pos+seqlen]
400
+ mask = None
401
+ if seqlen > 1:
402
+ mask = torch.full((seqlen, seqlen), float("-inf"), device=tokens.device).triu_(1)
403
+ for layer in self.layers:
404
+ h = layer(h, start_pos, freqs_cis, mask)
405
+ h = self.norm(h)[:, -1]
406
+ logits = self.head(h)
407
+ if world_size > 1:
408
+ all_logits = [torch.empty_like(logits) for _ in range(world_size)]
409
+ dist.all_gather(all_logits, logits)
410
+ logits = torch.cat(all_logits, dim=-1)
411
+ return logits
412
+
413
+
414
+ if __name__ == "__main__":
415
+ torch.set_default_dtype(torch.bfloat16)
416
+ torch.set_default_device("cuda")
417
+ torch.manual_seed(0)
418
+ args = ModelArgs()
419
+ x = torch.randint(0, args.vocab_size, (2, 128))
420
+ model = Transformer(args)
421
+ print(model(x).size())
inference/requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ torch==2.4.1
2
+ triton==3.0.0
3
+ transformers==4.46.3
4
+ safetensors==0.4.5
model-00003-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:58158ac20ee9d172ea608661455522abff0e15b77e1741b9a3cf47824ee6edfd
3
+ size 4993632760
model-00005-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a5ea93773ad17d5cea5efddba311450dcde3d049c4ca4d28302c83ed06b8ac90
3
+ size 4995319632
model-00007-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:85e160a67721ac51747444798be5795d5d85acc4fa966f59a58d32c8ab3baab9
3
+ size 4995320096
model-00009-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4247281ba28718bc82a32205a66bd04a7faa286e13eb28f3eddf49a6e38f9174
3
+ size 4995319632
model-00010-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8ed77e5f02f04e320795f90c4e0c841f3a8165e24dfe426b4bf011fd2ea25a43
3
+ size 4995321024
model-00018-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5ffd8145469784585d8a298c0e211daa564a425e00efd4aff7bf61d4ed290291
3
+ size 4995322024
model-00020-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:008cbe0670877e7c97ae081af91f8d45ef21f13c3cc980021a3386cf97d5dbff
3
+ size 4995321512
model-00021-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f9833870bfe2dc2b8dd362715e2dd508f3fa5faca1c346e82cd3ddff39c061ba
3
+ size 4995321512
model-00022-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:577d12c56677faceeb62d7362e302dfd861a8832fd71eaa9487d3ce1563cf669
3
+ size 4995321864
model-00026-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0e9983e679a580841bec617af7a3c43308a41b0b50beb78bfc0e11c7c66bc2f0
3
+ size 4995321512
model-00027-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:105db9e79a4ae5601abb2dc6567ae7b04d7973445ba7c63413437d7348021691
3
+ size 4995321808
model-00030-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:35414c6a26c8f542a3d4bfb2fd52ac4b5c3f41a69f42e98ad68669303ef1fae7
3
+ size 4995321512
model-00031-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:884d8ae5e9a8c5a446eb729f158d263080ce415fe18567b6071773b93e237824
3
+ size 4995321512
model-00032-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1d3cc78283bb31e77b3535ed9c29986230d950ac15550355177ab96e1fb0a2a1
3
+ size 4995321744
model-00036-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b6893e00cba2e6b4cd86875583e155b02a26808de8433e28c69743d3c4c51ea8
3
+ size 4995321512
model-00037-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:838b1ac2fe02d92d60258c3a4950d0734aac2cf21a411b6e261b1e4573249eba
3
+ size 4995321688
model-00041-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2196f35b3f9a5fc3db18430e98aa44a8a58ccce2542f39e18bc215f3d35eb29c
3
+ size 4995321512
model-00042-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:306de3f5592f4bfb30ac8af9f53cbacd7f92449229310ca400201f50f9ad67ce
3
+ size 4995321632
model-00048-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a1e532f3a6fc90f973bbdfdb085c3bcfecc94a57ce3aee6b57617dc61bc982ed
3
+ size 4995321968
model-00050-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fa39f11aa61d5436269c01e0991d0c31047be9bb98a79c83dbb309db4030dff0
3
+ size 4995321512
model-00052-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:61fe56c8eaea75db188ef13fd002a2fa49248efc42e3de1f68f5a040a73167de
3
+ size 4995321520
model-00054-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5a9c8670fc890342029c2975cc0ad2c30b6fa31407dea90d74a3c41524cd45d6
3
+ size 4994194184
model-00055-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1b5e327baca2f10368902d4dc8bea8bf77c352a83eb29410ca24cfe8ef747082
3
+ size 4994762080
model-00056-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f624628bccf83df5def1fc39e369f6d1dad4c900e0abf91173f9d14bf7c6dbf8
3
+ size 4995321512
model-00059-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:27569edd5a46f3b37dee1ae9617f1e28ad3349773c05d0aa9cccd3c366387c36
3
+ size 4995322032
model-00061-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:142ce32dd6d8521b8e95b8b8302696bc93e6069fa084c25f0fc0b09728e8e8a4
3
+ size 4995321512
model-00065-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:06183158d386c8e4a7c14db04a62c5389971d9d77a61b4c6de16b5bcf808bd57
3
+ size 4993634400
model-00067-of-00074.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d35db7a92e4ee1ec217b27489459b378d90b800fa2e170ad78840b78a81da9f8
3
+ size 4995321512
modeling_deepseek.py ADDED
@@ -0,0 +1,1848 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2023 DeepSeek-AI and The HuggingFace Inc. team. All rights reserved.
3
+ #
4
+ # This code is based on EleutherAI's GPT-NeoX library and the GPT-NeoX
5
+ # and OPT implementations in this library. It has been modified from its
6
+ # original forms to accommodate minor architectural differences compared
7
+ # to GPT-NeoX and OPT used by the Meta AI team that trained the model.
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+ """ PyTorch DeepSeek model."""
21
+ import math
22
+ import warnings
23
+ from typing import List, Optional, Tuple, Union
24
+
25
+ import torch
26
+ import torch.nn.functional as F
27
+ import torch.utils.checkpoint
28
+ from torch import nn
29
+ from torch.nn import BCEWithLogitsLoss, CrossEntropyLoss, MSELoss
30
+
31
+ from transformers.activations import ACT2FN
32
+ from transformers.cache_utils import Cache, DynamicCache
33
+ from transformers.modeling_attn_mask_utils import (
34
+ AttentionMaskConverter,
35
+ _prepare_4d_attention_mask,
36
+ _prepare_4d_causal_attention_mask,
37
+ )
38
+ from transformers.modeling_outputs import (
39
+ BaseModelOutputWithPast,
40
+ CausalLMOutputWithPast,
41
+ SequenceClassifierOutputWithPast,
42
+ )
43
+ from transformers.modeling_utils import PreTrainedModel
44
+ from transformers.pytorch_utils import (
45
+ ALL_LAYERNORM_LAYERS,
46
+ is_torch_greater_or_equal_than_1_13,
47
+ )
48
+ from transformers.utils import (
49
+ add_start_docstrings,
50
+ add_start_docstrings_to_model_forward,
51
+ is_flash_attn_2_available,
52
+ is_flash_attn_greater_or_equal_2_10,
53
+ logging,
54
+ replace_return_docstrings,
55
+ )
56
+ from transformers.utils.import_utils import is_torch_fx_available
57
+ from .configuration_deepseek import DeepseekV3Config
58
+ import torch.distributed as dist
59
+ import numpy as np
60
+
61
+ if is_flash_attn_2_available():
62
+ from flash_attn import flash_attn_func, flash_attn_varlen_func
63
+ from flash_attn.bert_padding import index_first_axis, pad_input, unpad_input # noqa
64
+
65
+
66
+ # This makes `_prepare_4d_causal_attention_mask` a leaf function in the FX graph.
67
+ # It means that the function will not be traced through and simply appear as a node in the graph.
68
+ if is_torch_fx_available():
69
+ if not is_torch_greater_or_equal_than_1_13:
70
+ import torch.fx
71
+
72
+ _prepare_4d_causal_attention_mask = torch.fx.wrap(_prepare_4d_causal_attention_mask)
73
+
74
+
75
+ logger = logging.get_logger(__name__)
76
+
77
+ _CONFIG_FOR_DOC = "DeepseekV3Config"
78
+
79
+
80
+ def _get_unpad_data(attention_mask):
81
+ seqlens_in_batch = attention_mask.sum(dim=-1, dtype=torch.int32)
82
+ indices = torch.nonzero(attention_mask.flatten(), as_tuple=False).flatten()
83
+ max_seqlen_in_batch = seqlens_in_batch.max().item()
84
+ cu_seqlens = F.pad(
85
+ torch.cumsum(seqlens_in_batch, dim=0, dtype=torch.torch.int32), (1, 0)
86
+ )
87
+ return (
88
+ indices,
89
+ cu_seqlens,
90
+ max_seqlen_in_batch,
91
+ )
92
+
93
+
94
+ class DeepseekV3RMSNorm(nn.Module):
95
+ def __init__(self, hidden_size, eps=1e-6):
96
+ """
97
+ DeepseekV3RMSNorm is equivalent to T5LayerNorm
98
+ """
99
+ super().__init__()
100
+ self.weight = nn.Parameter(torch.ones(hidden_size))
101
+ self.variance_epsilon = eps
102
+
103
+ def forward(self, hidden_states):
104
+ input_dtype = hidden_states.dtype
105
+ hidden_states = hidden_states.to(torch.float32)
106
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
107
+ hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
108
+ return self.weight * hidden_states.to(input_dtype)
109
+
110
+
111
+ ALL_LAYERNORM_LAYERS.append(DeepseekV3RMSNorm)
112
+
113
+
114
+ class DeepseekV3RotaryEmbedding(nn.Module):
115
+ def __init__(self, dim, max_position_embeddings=2048, base=10000, device=None):
116
+ super().__init__()
117
+
118
+ self.dim = dim
119
+ self.max_position_embeddings = max_position_embeddings
120
+ self.base = base
121
+ inv_freq = 1.0 / (
122
+ self.base ** (torch.arange(0, self.dim, 2).float().to(device) / self.dim)
123
+ )
124
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
125
+
126
+ # Build here to make `torch.jit.trace` work.
127
+ self._set_cos_sin_cache(
128
+ seq_len=max_position_embeddings,
129
+ device=self.inv_freq.device,
130
+ dtype=torch.get_default_dtype(),
131
+ )
132
+ self.max_seq_len_cached = None
133
+
134
+ def _set_cos_sin_cache(self, seq_len, device, dtype):
135
+ self.max_seq_len_cached = seq_len
136
+ t = torch.arange(
137
+ self.max_seq_len_cached, device=device, dtype=self.inv_freq.dtype
138
+ )
139
+
140
+ freqs = torch.outer(t, self.inv_freq.to(t.device))
141
+ # Different from paper, but it uses a different permutation in order to obtain the same calculation
142
+ emb = torch.cat((freqs, freqs), dim=-1)
143
+ self.register_buffer("cos_cached", emb.cos().to(dtype), persistent=False)
144
+ self.register_buffer("sin_cached", emb.sin().to(dtype), persistent=False)
145
+
146
+ def forward(self, x, seq_len=None):
147
+ # x: [bs, num_attention_heads, seq_len, head_size]
148
+ if self.max_seq_len_cached is None or seq_len > self.max_seq_len_cached:
149
+ self._set_cos_sin_cache(seq_len=seq_len, device=x.device, dtype=x.dtype)
150
+
151
+ return (
152
+ self.cos_cached[:seq_len].to(dtype=x.dtype),
153
+ self.sin_cached[:seq_len].to(dtype=x.dtype),
154
+ )
155
+
156
+
157
+ # Copied from transformers.models.llama.modeling_llama.LlamaLinearScalingRotaryEmbedding with Llama->DeepseekV3
158
+ class DeepseekV3LinearScalingRotaryEmbedding(DeepseekV3RotaryEmbedding):
159
+ """DeepseekV3RotaryEmbedding extended with linear scaling. Credits to the Reddit user /u/kaiokendev"""
160
+
161
+ def __init__(
162
+ self,
163
+ dim,
164
+ max_position_embeddings=2048,
165
+ base=10000,
166
+ device=None,
167
+ scaling_factor=1.0,
168
+ ):
169
+ self.scaling_factor = scaling_factor
170
+ super().__init__(dim, max_position_embeddings, base, device)
171
+
172
+ def _set_cos_sin_cache(self, seq_len, device, dtype):
173
+ self.max_seq_len_cached = seq_len
174
+ t = torch.arange(
175
+ self.max_seq_len_cached, device=device, dtype=self.inv_freq.dtype
176
+ )
177
+ t = t / self.scaling_factor
178
+
179
+ freqs = torch.outer(t, self.inv_freq)
180
+ # Different from paper, but it uses a different permutation in order to obtain the same calculation
181
+ emb = torch.cat((freqs, freqs), dim=-1)
182
+ self.register_buffer("cos_cached", emb.cos().to(dtype), persistent=False)
183
+ self.register_buffer("sin_cached", emb.sin().to(dtype), persistent=False)
184
+
185
+
186
+ # Copied from transformers.models.llama.modeling_llama.LlamaDynamicNTKScalingRotaryEmbedding with Llama->DeepseekV3
187
+ class DeepseekV3DynamicNTKScalingRotaryEmbedding(DeepseekV3RotaryEmbedding):
188
+ """DeepseekV3RotaryEmbedding extended with Dynamic NTK scaling. Credits to the Reddit users /u/bloc97 and /u/emozilla"""
189
+
190
+ def __init__(
191
+ self,
192
+ dim,
193
+ max_position_embeddings=2048,
194
+ base=10000,
195
+ device=None,
196
+ scaling_factor=1.0,
197
+ ):
198
+ self.scaling_factor = scaling_factor
199
+ super().__init__(dim, max_position_embeddings, base, device)
200
+
201
+ def _set_cos_sin_cache(self, seq_len, device, dtype):
202
+ self.max_seq_len_cached = seq_len
203
+
204
+ if seq_len > self.max_position_embeddings:
205
+ base = self.base * (
206
+ (self.scaling_factor * seq_len / self.max_position_embeddings)
207
+ - (self.scaling_factor - 1)
208
+ ) ** (self.dim / (self.dim - 2))
209
+ inv_freq = 1.0 / (
210
+ base ** (torch.arange(0, self.dim, 2).float().to(device) / self.dim)
211
+ )
212
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
213
+
214
+ t = torch.arange(
215
+ self.max_seq_len_cached, device=device, dtype=self.inv_freq.dtype
216
+ )
217
+
218
+ freqs = torch.outer(t, self.inv_freq)
219
+ # Different from paper, but it uses a different permutation in order to obtain the same calculation
220
+ emb = torch.cat((freqs, freqs), dim=-1)
221
+ self.register_buffer("cos_cached", emb.cos().to(dtype), persistent=False)
222
+ self.register_buffer("sin_cached", emb.sin().to(dtype), persistent=False)
223
+
224
+
225
+ # Inverse dim formula to find dim based on number of rotations
226
+ def yarn_find_correction_dim(
227
+ num_rotations, dim, base=10000, max_position_embeddings=2048
228
+ ):
229
+ return (dim * math.log(max_position_embeddings / (num_rotations * 2 * math.pi))) / (
230
+ 2 * math.log(base)
231
+ )
232
+
233
+
234
+ # Find dim range bounds based on rotations
235
+ def yarn_find_correction_range(
236
+ low_rot, high_rot, dim, base=10000, max_position_embeddings=2048
237
+ ):
238
+ low = math.floor(
239
+ yarn_find_correction_dim(low_rot, dim, base, max_position_embeddings)
240
+ )
241
+ high = math.ceil(
242
+ yarn_find_correction_dim(high_rot, dim, base, max_position_embeddings)
243
+ )
244
+ return max(low, 0), min(high, dim - 1) # Clamp values just in case
245
+
246
+
247
+ def yarn_get_mscale(scale=1, mscale=1):
248
+ if scale <= 1:
249
+ return 1.0
250
+ return 0.1 * mscale * math.log(scale) + 1.0
251
+
252
+
253
+ def yarn_linear_ramp_mask(min, max, dim):
254
+ if min == max:
255
+ max += 0.001 # Prevent singularity
256
+
257
+ linear_func = (torch.arange(dim, dtype=torch.float32) - min) / (max - min)
258
+ ramp_func = torch.clamp(linear_func, 0, 1)
259
+ return ramp_func
260
+
261
+
262
+ class DeepseekV3YarnRotaryEmbedding(DeepseekV3RotaryEmbedding):
263
+
264
+ def __init__(
265
+ self,
266
+ dim,
267
+ max_position_embeddings=2048,
268
+ base=10000,
269
+ device=None,
270
+ scaling_factor=1.0,
271
+ original_max_position_embeddings=4096,
272
+ beta_fast=32,
273
+ beta_slow=1,
274
+ mscale=1,
275
+ mscale_all_dim=0,
276
+ ):
277
+ self.scaling_factor = scaling_factor
278
+ self.original_max_position_embeddings = original_max_position_embeddings
279
+ self.beta_fast = beta_fast
280
+ self.beta_slow = beta_slow
281
+ self.mscale = mscale
282
+ self.mscale_all_dim = mscale_all_dim
283
+ super().__init__(dim, max_position_embeddings, base, device)
284
+
285
+ def _set_cos_sin_cache(self, seq_len, device, dtype):
286
+ self.max_seq_len_cached = seq_len
287
+ dim = self.dim
288
+
289
+ freq_extra = 1.0 / (
290
+ self.base
291
+ ** (torch.arange(0, dim, 2, dtype=torch.float32, device=device) / dim)
292
+ )
293
+ freq_inter = 1.0 / (
294
+ self.scaling_factor
295
+ * self.base
296
+ ** (torch.arange(0, dim, 2, dtype=torch.float32, device=device) / dim)
297
+ )
298
+
299
+ low, high = yarn_find_correction_range(
300
+ self.beta_fast,
301
+ self.beta_slow,
302
+ dim,
303
+ self.base,
304
+ self.original_max_position_embeddings,
305
+ )
306
+ inv_freq_mask = 1.0 - yarn_linear_ramp_mask(low, high, dim // 2).to(
307
+ device=device, dtype=torch.float32
308
+ )
309
+ inv_freq = freq_inter * (1 - inv_freq_mask) + freq_extra * inv_freq_mask
310
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
311
+
312
+ t = torch.arange(seq_len, device=device, dtype=torch.float32)
313
+
314
+ freqs = torch.outer(t, inv_freq)
315
+
316
+ _mscale = float(
317
+ yarn_get_mscale(self.scaling_factor, self.mscale)
318
+ / yarn_get_mscale(self.scaling_factor, self.mscale_all_dim)
319
+ )
320
+
321
+ emb = torch.cat((freqs, freqs), dim=-1)
322
+ self.register_buffer(
323
+ "cos_cached", (emb.cos() * _mscale).to(dtype), persistent=False
324
+ )
325
+ self.register_buffer(
326
+ "sin_cached", (emb.sin() * _mscale).to(dtype), persistent=False
327
+ )
328
+
329
+
330
+ # Copied from transformers.models.llama.modeling_llama.rotate_half
331
+ def rotate_half(x):
332
+ """Rotates half the hidden dims of the input."""
333
+ x1 = x[..., : x.shape[-1] // 2]
334
+ x2 = x[..., x.shape[-1] // 2 :]
335
+ return torch.cat((-x2, x1), dim=-1)
336
+
337
+
338
+ # Copied from transformers.models.llama.modeling_llama.apply_rotary_pos_emb
339
+ def apply_rotary_pos_emb(q, k, cos, sin, position_ids, unsqueeze_dim=1):
340
+ """Applies Rotary Position Embedding to the query and key tensors.
341
+
342
+ Args:
343
+ q (`torch.Tensor`): The query tensor.
344
+ k (`torch.Tensor`): The key tensor.
345
+ cos (`torch.Tensor`): The cosine part of the rotary embedding.
346
+ sin (`torch.Tensor`): The sine part of the rotary embedding.
347
+ position_ids (`torch.Tensor`):
348
+ The position indices of the tokens corresponding to the query and key tensors. For example, this can be
349
+ used to pass offsetted position ids when working with a KV-cache.
350
+ unsqueeze_dim (`int`, *optional*, defaults to 1):
351
+ The 'unsqueeze_dim' argument specifies the dimension along which to unsqueeze cos[position_ids] and
352
+ sin[position_ids] so that they can be properly broadcasted to the dimensions of q and k. For example, note
353
+ that cos[position_ids] and sin[position_ids] have the shape [batch_size, seq_len, head_dim]. Then, if q and
354
+ k have the shape [batch_size, heads, seq_len, head_dim], then setting unsqueeze_dim=1 makes
355
+ cos[position_ids] and sin[position_ids] broadcastable to the shapes of q and k. Similarly, if q and k have
356
+ the shape [batch_size, seq_len, heads, head_dim], then set unsqueeze_dim=2.
357
+ Returns:
358
+ `tuple(torch.Tensor)` comprising of the query and key tensors rotated using the Rotary Position Embedding.
359
+ """
360
+ cos = cos[position_ids].unsqueeze(unsqueeze_dim)
361
+ sin = sin[position_ids].unsqueeze(unsqueeze_dim)
362
+
363
+ b, h, s, d = q.shape
364
+ q = q.view(b, h, s, d // 2, 2).transpose(4, 3).reshape(b, h, s, d)
365
+
366
+ b, h, s, d = k.shape
367
+ k = k.view(b, h, s, d // 2, 2).transpose(4, 3).reshape(b, h, s, d)
368
+
369
+ q_embed = (q * cos) + (rotate_half(q) * sin)
370
+ k_embed = (k * cos) + (rotate_half(k) * sin)
371
+ return q_embed, k_embed
372
+
373
+
374
+ class DeepseekV3MLP(nn.Module):
375
+ def __init__(self, config, hidden_size=None, intermediate_size=None):
376
+ super().__init__()
377
+ self.config = config
378
+ self.hidden_size = config.hidden_size if hidden_size is None else hidden_size
379
+ self.intermediate_size = (
380
+ config.intermediate_size if intermediate_size is None else intermediate_size
381
+ )
382
+
383
+ self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
384
+ self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
385
+ self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
386
+ self.act_fn = ACT2FN[config.hidden_act]
387
+
388
+ def forward(self, x):
389
+ down_proj = self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
390
+ return down_proj
391
+
392
+
393
+ class MoEGate(nn.Module):
394
+ def __init__(self, config):
395
+ super().__init__()
396
+ self.config = config
397
+ self.top_k = config.num_experts_per_tok
398
+ self.n_routed_experts = config.n_routed_experts
399
+ self.routed_scaling_factor = config.routed_scaling_factor
400
+ self.scoring_func = config.scoring_func
401
+ self.topk_method = config.topk_method
402
+ self.n_group = config.n_group
403
+ self.topk_group = config.topk_group
404
+
405
+ # topk selection algorithm
406
+ self.norm_topk_prob = config.norm_topk_prob
407
+ self.gating_dim = config.hidden_size
408
+ self.weight = nn.Parameter(
409
+ torch.empty((self.n_routed_experts, self.gating_dim))
410
+ )
411
+ if self.topk_method == "noaux_tc":
412
+ self.e_score_correction_bias = nn.Parameter(
413
+ torch.empty((self.n_routed_experts))
414
+ )
415
+ self.reset_parameters()
416
+
417
+ def reset_parameters(self) -> None:
418
+ import torch.nn.init as init
419
+
420
+ init.kaiming_uniform_(self.weight, a=math.sqrt(5))
421
+
422
+ def forward(self, hidden_states):
423
+ bsz, seq_len, h = hidden_states.shape
424
+ ### compute gating score
425
+ hidden_states = hidden_states.view(-1, h)
426
+ logits = F.linear(
427
+ hidden_states.type(torch.float32), self.weight.type(torch.float32), None
428
+ )
429
+ if self.scoring_func == "sigmoid":
430
+ scores = logits.sigmoid()
431
+ else:
432
+ raise NotImplementedError(
433
+ f"insupportable scoring function for MoE gating: {self.scoring_func}"
434
+ )
435
+
436
+ ### select top-k experts
437
+ if self.topk_method == "noaux_tc":
438
+ assert not self.training
439
+ scores_for_choice = scores.view(bsz * seq_len, -1) + self.e_score_correction_bias.unsqueeze(0)
440
+ group_scores = (
441
+ scores_for_choice.view(bsz * seq_len, self.n_group, -1).topk(2, dim=-1)[0].sum(dim = -1)
442
+ ) # [n, n_group]
443
+ group_idx = torch.topk(
444
+ group_scores, k=self.topk_group, dim=-1, sorted=False
445
+ )[
446
+ 1
447
+ ] # [n, top_k_group]
448
+ group_mask = torch.zeros_like(group_scores) # [n, n_group]
449
+ group_mask.scatter_(1, group_idx, 1) # [n, n_group]
450
+ score_mask = (
451
+ group_mask.unsqueeze(-1)
452
+ .expand(
453
+ bsz * seq_len, self.n_group, self.n_routed_experts // self.n_group
454
+ )
455
+ .reshape(bsz * seq_len, -1)
456
+ ) # [n, e]
457
+ tmp_scores = scores_for_choice.masked_fill(~score_mask.bool(), float("-inf")) # [n, e]
458
+ _, topk_idx = torch.topk(
459
+ tmp_scores, k=self.top_k, dim=-1, sorted=False
460
+ )
461
+ topk_weight = scores.gather(1, topk_idx)
462
+ else:
463
+ raise NotImplementedError(
464
+ f"insupportable TopK function for MoE gating: {self.topk_method}"
465
+ )
466
+
467
+ ### norm gate to sum 1
468
+ if self.top_k > 1 and self.norm_topk_prob:
469
+ denominator = topk_weight.sum(dim=-1, keepdim=True) + 1e-20
470
+ topk_weight = topk_weight / denominator
471
+ topk_weight = topk_weight * self.routed_scaling_factor # must multiply the scaling factor
472
+
473
+ return topk_idx, topk_weight
474
+
475
+ class DeepseekV3MoE(nn.Module):
476
+ """
477
+ A mixed expert module containing shared experts.
478
+ """
479
+
480
+ def __init__(self, config):
481
+ super().__init__()
482
+ self.config = config
483
+ self.num_experts_per_tok = config.num_experts_per_tok
484
+
485
+ if hasattr(config, "ep_size") and config.ep_size > 1:
486
+ assert config.ep_size == dist.get_world_size()
487
+ self.ep_size = config.ep_size
488
+ self.experts_per_rank = config.n_routed_experts // config.ep_size
489
+ self.ep_rank = dist.get_rank()
490
+ self.experts = nn.ModuleList(
491
+ [
492
+ (
493
+ DeepseekV3MLP(
494
+ config, intermediate_size=config.moe_intermediate_size
495
+ )
496
+ if i >= self.ep_rank * self.experts_per_rank
497
+ and i < (self.ep_rank + 1) * self.experts_per_rank
498
+ else None
499
+ )
500
+ for i in range(config.n_routed_experts)
501
+ ]
502
+ )
503
+ else:
504
+ self.ep_size = 1
505
+ self.experts_per_rank = config.n_routed_experts
506
+ self.ep_rank = 0
507
+ self.experts = nn.ModuleList(
508
+ [
509
+ DeepseekV3MLP(
510
+ config, intermediate_size=config.moe_intermediate_size
511
+ )
512
+ for i in range(config.n_routed_experts)
513
+ ]
514
+ )
515
+ self.gate = MoEGate(config)
516
+ if config.n_shared_experts is not None:
517
+ intermediate_size = config.moe_intermediate_size * config.n_shared_experts
518
+ self.shared_experts = DeepseekV3MLP(
519
+ config=config, intermediate_size=intermediate_size
520
+ )
521
+
522
+ def forward(self, hidden_states):
523
+ identity = hidden_states
524
+ orig_shape = hidden_states.shape
525
+ topk_idx, topk_weight = self.gate(hidden_states)
526
+ hidden_states = hidden_states.view(-1, hidden_states.shape[-1])
527
+ flat_topk_idx = topk_idx.view(-1)
528
+ if not self.training:
529
+ y = self.moe_infer(hidden_states, topk_idx, topk_weight).view(*orig_shape)
530
+ if self.config.n_shared_experts is not None:
531
+ y = y + self.shared_experts(identity)
532
+ return y
533
+
534
+ @torch.no_grad()
535
+ def moe_infer(self, x, topk_ids, topk_weight):
536
+ cnts = topk_ids.new_zeros((topk_ids.shape[0], len(self.experts)))
537
+ cnts.scatter_(1, topk_ids, 1)
538
+ tokens_per_expert = cnts.sum(dim=0)
539
+ idxs = topk_ids.view(-1).argsort()
540
+ sorted_tokens = x[idxs // topk_ids.shape[1]]
541
+ sorted_tokens_shape = sorted_tokens.shape
542
+ if self.ep_size > 1:
543
+ tokens_per_ep_rank = tokens_per_expert.view(self.ep_size, -1).sum(dim=1)
544
+ tokens_per_expert_group = tokens_per_expert.new_empty(
545
+ tokens_per_expert.shape[0]
546
+ )
547
+ dist.all_to_all_single(tokens_per_expert_group, tokens_per_expert)
548
+ output_splits = (
549
+ tokens_per_expert_group.view(self.ep_size, -1)
550
+ .sum(1)
551
+ .cpu()
552
+ .numpy()
553
+ .tolist()
554
+ )
555
+ gathered_tokens = sorted_tokens.new_empty(
556
+ tokens_per_expert_group.sum(dim=0).cpu().item(), sorted_tokens.shape[1]
557
+ )
558
+ input_split_sizes = tokens_per_ep_rank.cpu().numpy().tolist()
559
+ dist.all_to_all(
560
+ list(gathered_tokens.split(output_splits)),
561
+ list(sorted_tokens.split(input_split_sizes)),
562
+ )
563
+ tokens_per_expert_post_gather = tokens_per_expert_group.view(
564
+ self.ep_size, self.experts_per_rank
565
+ ).sum(dim=0)
566
+ gatherd_idxs = np.zeros(shape=(gathered_tokens.shape[0],), dtype=np.int32)
567
+ s = 0
568
+ for i, k in enumerate(tokens_per_expert_group.cpu().numpy()):
569
+ gatherd_idxs[s : s + k] = i % self.experts_per_rank
570
+ s += k
571
+ gatherd_idxs = gatherd_idxs.argsort()
572
+ sorted_tokens = gathered_tokens[gatherd_idxs]
573
+ tokens_per_expert = tokens_per_expert_post_gather
574
+ tokens_per_expert = tokens_per_expert.cpu().numpy()
575
+
576
+ outputs = []
577
+ start_idx = 0
578
+ for i, num_tokens in enumerate(tokens_per_expert):
579
+ end_idx = start_idx + num_tokens
580
+ if num_tokens == 0:
581
+ continue
582
+ expert = self.experts[i + self.ep_rank * self.experts_per_rank]
583
+ tokens_for_this_expert = sorted_tokens[start_idx:end_idx]
584
+ expert_out = expert(tokens_for_this_expert)
585
+ outputs.append(expert_out)
586
+ start_idx = end_idx
587
+
588
+ outs = torch.cat(outputs, dim=0) if len(outputs) else sorted_tokens.new_empty(0)
589
+ if self.ep_size > 1:
590
+ new_x = torch.empty_like(outs)
591
+ new_x[gatherd_idxs] = outs
592
+ gathered_tokens = new_x.new_empty(*sorted_tokens_shape)
593
+ dist.all_to_all(
594
+ list(gathered_tokens.split(input_split_sizes)),
595
+ list(new_x.split(output_splits)),
596
+ )
597
+ outs = gathered_tokens
598
+
599
+ new_x = torch.empty_like(outs)
600
+ new_x[idxs] = outs
601
+ final_out = (
602
+ new_x.view(*topk_ids.shape, -1)
603
+ .type(topk_weight.dtype)
604
+ .mul_(topk_weight.unsqueeze(dim=-1))
605
+ .sum(dim=1)
606
+ .type(new_x.dtype)
607
+ )
608
+ return final_out
609
+
610
+
611
+ # Copied from transformers.models.llama.modeling_llama.repeat_kv
612
+ def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
613
+ """
614
+ This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
615
+ num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
616
+ """
617
+ batch, num_key_value_heads, slen, head_dim = hidden_states.shape
618
+ if n_rep == 1:
619
+ return hidden_states
620
+ hidden_states = hidden_states[:, :, None, :, :].expand(
621
+ batch, num_key_value_heads, n_rep, slen, head_dim
622
+ )
623
+ return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
624
+
625
+
626
+ # Copied from transformers.models.llama.modeling_llama.LlamaAttention with Llama->DeepseekV3
627
+ class DeepseekV3Attention(nn.Module):
628
+ """Multi-headed attention from 'Attention Is All You Need' paper"""
629
+
630
+ def __init__(self, config: DeepseekV3Config, layer_idx: Optional[int] = None):
631
+ super().__init__()
632
+ self.config = config
633
+ self.layer_idx = layer_idx
634
+ if layer_idx is None:
635
+ logger.warning_once(
636
+ f"Instantiating {self.__class__.__name__} without passing `layer_idx` is not recommended and will "
637
+ "to errors during the forward call, if caching is used. Please make sure to provide a `layer_idx` "
638
+ "when creating this class."
639
+ )
640
+
641
+ self.attention_dropout = config.attention_dropout
642
+ self.hidden_size = config.hidden_size
643
+ self.num_heads = config.num_attention_heads
644
+
645
+ self.max_position_embeddings = config.max_position_embeddings
646
+ self.rope_theta = config.rope_theta
647
+ self.q_lora_rank = config.q_lora_rank
648
+ self.qk_rope_head_dim = config.qk_rope_head_dim
649
+ self.kv_lora_rank = config.kv_lora_rank
650
+ self.v_head_dim = config.v_head_dim
651
+ self.qk_nope_head_dim = config.qk_nope_head_dim
652
+ self.q_head_dim = config.qk_nope_head_dim + config.qk_rope_head_dim
653
+
654
+ self.is_causal = True
655
+
656
+ if self.q_lora_rank is None:
657
+ self.q_proj = nn.Linear(
658
+ self.hidden_size, self.num_heads * self.q_head_dim, bias=False
659
+ )
660
+ else:
661
+ self.q_a_proj = nn.Linear(
662
+ self.hidden_size, config.q_lora_rank, bias=config.attention_bias
663
+ )
664
+ self.q_a_layernorm = DeepseekV3RMSNorm(config.q_lora_rank)
665
+ self.q_b_proj = nn.Linear(
666
+ config.q_lora_rank, self.num_heads * self.q_head_dim, bias=False
667
+ )
668
+
669
+ self.kv_a_proj_with_mqa = nn.Linear(
670
+ self.hidden_size,
671
+ config.kv_lora_rank + config.qk_rope_head_dim,
672
+ bias=config.attention_bias,
673
+ )
674
+ self.kv_a_layernorm = DeepseekV3RMSNorm(config.kv_lora_rank)
675
+ self.kv_b_proj = nn.Linear(
676
+ config.kv_lora_rank,
677
+ self.num_heads
678
+ * (self.q_head_dim - self.qk_rope_head_dim + self.v_head_dim),
679
+ bias=False,
680
+ )
681
+
682
+ self.o_proj = nn.Linear(
683
+ self.num_heads * self.v_head_dim,
684
+ self.hidden_size,
685
+ bias=config.attention_bias,
686
+ )
687
+ self._init_rope()
688
+
689
+ self.softmax_scale = self.q_head_dim ** (-0.5)
690
+ if self.config.rope_scaling is not None:
691
+ mscale_all_dim = self.config.rope_scaling.get("mscale_all_dim", 0)
692
+ scaling_factor = self.config.rope_scaling["factor"]
693
+ if mscale_all_dim:
694
+ mscale = yarn_get_mscale(scaling_factor, mscale_all_dim)
695
+ self.softmax_scale = self.softmax_scale * mscale * mscale
696
+
697
+ def _init_rope(self):
698
+ if self.config.rope_scaling is None:
699
+ self.rotary_emb = DeepseekV3RotaryEmbedding(
700
+ self.qk_rope_head_dim,
701
+ max_position_embeddings=self.max_position_embeddings,
702
+ base=self.rope_theta,
703
+ )
704
+ else:
705
+ scaling_type = self.config.rope_scaling["type"]
706
+ scaling_factor = self.config.rope_scaling["factor"]
707
+ if scaling_type == "linear":
708
+ self.rotary_emb = DeepseekV3LinearScalingRotaryEmbedding(
709
+ self.qk_rope_head_dim,
710
+ max_position_embeddings=self.max_position_embeddings,
711
+ scaling_factor=scaling_factor,
712
+ base=self.rope_theta,
713
+ )
714
+ elif scaling_type == "dynamic":
715
+ self.rotary_emb = DeepseekV3DynamicNTKScalingRotaryEmbedding(
716
+ self.qk_rope_head_dim,
717
+ max_position_embeddings=self.max_position_embeddings,
718
+ scaling_factor=scaling_factor,
719
+ base=self.rope_theta,
720
+ )
721
+ elif scaling_type == "yarn":
722
+ kwargs = {
723
+ key: self.config.rope_scaling[key]
724
+ for key in [
725
+ "original_max_position_embeddings",
726
+ "beta_fast",
727
+ "beta_slow",
728
+ "mscale",
729
+ "mscale_all_dim",
730
+ ]
731
+ if key in self.config.rope_scaling
732
+ }
733
+ self.rotary_emb = DeepseekV3YarnRotaryEmbedding(
734
+ self.qk_rope_head_dim,
735
+ max_position_embeddings=self.max_position_embeddings,
736
+ scaling_factor=scaling_factor,
737
+ base=self.rope_theta,
738
+ **kwargs,
739
+ )
740
+ else:
741
+ raise ValueError(f"Unknown RoPE scaling type {scaling_type}")
742
+
743
+ def _shape(self, tensor: torch.Tensor, seq_len: int, bsz: int):
744
+ return (
745
+ tensor.view(bsz, seq_len, self.num_heads, self.v_head_dim)
746
+ .transpose(1, 2)
747
+ .contiguous()
748
+ )
749
+
750
+ def forward(
751
+ self,
752
+ hidden_states: torch.Tensor,
753
+ attention_mask: Optional[torch.Tensor] = None,
754
+ position_ids: Optional[torch.LongTensor] = None,
755
+ past_key_value: Optional[Cache] = None,
756
+ output_attentions: bool = False,
757
+ use_cache: bool = False,
758
+ **kwargs,
759
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
760
+ if "padding_mask" in kwargs:
761
+ warnings.warn(
762
+ "Passing `padding_mask` is deprecated and will be removed in v4.37. Please make sure use `attention_mask` instead.`"
763
+ )
764
+ bsz, q_len, _ = hidden_states.size()
765
+
766
+ if self.q_lora_rank is None:
767
+ q = self.q_proj(hidden_states)
768
+ else:
769
+ q = self.q_b_proj(self.q_a_layernorm(self.q_a_proj(hidden_states)))
770
+ q = q.view(bsz, q_len, self.num_heads, self.q_head_dim).transpose(1, 2)
771
+ q_nope, q_pe = torch.split(
772
+ q, [self.qk_nope_head_dim, self.qk_rope_head_dim], dim=-1
773
+ )
774
+
775
+ compressed_kv = self.kv_a_proj_with_mqa(hidden_states)
776
+ compressed_kv, k_pe = torch.split(
777
+ compressed_kv, [self.kv_lora_rank, self.qk_rope_head_dim], dim=-1
778
+ )
779
+ k_pe = k_pe.view(bsz, q_len, 1, self.qk_rope_head_dim).transpose(1, 2)
780
+ kv = (
781
+ self.kv_b_proj(self.kv_a_layernorm(compressed_kv))
782
+ .view(bsz, q_len, self.num_heads, self.qk_nope_head_dim + self.v_head_dim)
783
+ .transpose(1, 2)
784
+ )
785
+
786
+ k_nope, value_states = torch.split(
787
+ kv, [self.qk_nope_head_dim, self.v_head_dim], dim=-1
788
+ )
789
+ kv_seq_len = value_states.shape[-2]
790
+ if past_key_value is not None:
791
+ if self.layer_idx is None:
792
+ raise ValueError(
793
+ f"The cache structure has changed since version v4.36. If you are using {self.__class__.__name__} "
794
+ "for auto-regressive decoding with k/v caching, please make sure to initialize the attention class "
795
+ "with a layer index."
796
+ )
797
+ kv_seq_len += past_key_value.get_usable_length(kv_seq_len, self.layer_idx)
798
+ cos, sin = self.rotary_emb(value_states, seq_len=kv_seq_len)
799
+
800
+ q_pe, k_pe = apply_rotary_pos_emb(q_pe, k_pe, cos, sin, position_ids)
801
+
802
+ query_states = k_pe.new_empty(bsz, self.num_heads, q_len, self.q_head_dim)
803
+ query_states[:, :, :, : self.qk_nope_head_dim] = q_nope
804
+ query_states[:, :, :, self.qk_nope_head_dim :] = q_pe
805
+
806
+ key_states = k_pe.new_empty(bsz, self.num_heads, q_len, self.q_head_dim)
807
+ key_states[:, :, :, : self.qk_nope_head_dim] = k_nope
808
+ key_states[:, :, :, self.qk_nope_head_dim :] = k_pe
809
+ if past_key_value is not None:
810
+ cache_kwargs = {"sin": sin, "cos": cos} # Specific to RoPE models
811
+ key_states, value_states = past_key_value.update(
812
+ key_states, value_states, self.layer_idx, cache_kwargs
813
+ )
814
+
815
+ attn_weights = (
816
+ torch.matmul(query_states, key_states.transpose(2, 3)) * self.softmax_scale
817
+ )
818
+
819
+ if attn_weights.size() != (bsz, self.num_heads, q_len, kv_seq_len):
820
+ raise ValueError(
821
+ f"Attention weights should be of size {(bsz, self.num_heads, q_len, kv_seq_len)}, but is"
822
+ f" {attn_weights.size()}"
823
+ )
824
+ assert attention_mask is not None
825
+ if attention_mask is not None:
826
+ if attention_mask.size() != (bsz, 1, q_len, kv_seq_len):
827
+ raise ValueError(
828
+ f"Attention mask should be of size {(bsz, 1, q_len, kv_seq_len)}, but is {attention_mask.size()}"
829
+ )
830
+ attn_weights = attn_weights + attention_mask
831
+
832
+ # upcast attention to fp32
833
+ attn_weights = nn.functional.softmax(
834
+ attn_weights, dim=-1, dtype=torch.float32
835
+ ).to(query_states.dtype)
836
+ attn_weights = nn.functional.dropout(
837
+ attn_weights, p=self.attention_dropout, training=self.training
838
+ )
839
+ attn_output = torch.matmul(attn_weights, value_states)
840
+
841
+ if attn_output.size() != (bsz, self.num_heads, q_len, self.v_head_dim):
842
+ raise ValueError(
843
+ f"`attn_output` should be of size {(bsz, self.num_heads, q_len, self.v_head_dim)}, but is"
844
+ f" {attn_output.size()}"
845
+ )
846
+
847
+ attn_output = attn_output.transpose(1, 2).contiguous()
848
+
849
+ attn_output = attn_output.reshape(bsz, q_len, self.num_heads * self.v_head_dim)
850
+
851
+ attn_output = self.o_proj(attn_output)
852
+
853
+ if not output_attentions:
854
+ attn_weights = None
855
+
856
+ return attn_output, attn_weights, past_key_value
857
+
858
+
859
+ # Copied from transformers.models.llama.modeling_llama.LlamaFlashAttention2 with Llama->DeepseekV3
860
+ class DeepseekV3FlashAttention2(DeepseekV3Attention):
861
+ """
862
+ DeepseekV3 flash attention module. This module inherits from `DeepseekV3Attention` as the weights of the module stays
863
+ untouched. The only required change would be on the forward pass where it needs to correctly call the public API of
864
+ flash attention and deal with padding tokens in case the input contains any of them.
865
+ """
866
+
867
+ def __init__(self, *args, **kwargs):
868
+ super().__init__(*args, **kwargs)
869
+
870
+ # TODO: Should be removed once Flash Attention for RoCm is bumped to 2.1.
871
+ # flash_attn<2.1 generates top-left aligned causal mask, while what is needed here is bottom-right alignement, that was made default for flash_attn>=2.1. This attribute is used to handle this difference. Reference: https://github.com/Dao-AILab/flash-attention/releases/tag/v2.1.0.
872
+ # Beware that with flash_attn<2.1, using q_seqlen != k_seqlen (except for the case q_seqlen == 1) produces a wrong mask (top-left).
873
+ self._flash_attn_uses_top_left_mask = not is_flash_attn_greater_or_equal_2_10()
874
+
875
+ def forward(
876
+ self,
877
+ hidden_states: torch.Tensor,
878
+ attention_mask: Optional[torch.LongTensor] = None,
879
+ position_ids: Optional[torch.LongTensor] = None,
880
+ past_key_value: Optional[Cache] = None,
881
+ output_attentions: bool = False,
882
+ use_cache: bool = False,
883
+ **kwargs,
884
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
885
+ # DeepseekV3FlashAttention2 attention does not support output_attentions
886
+ if "padding_mask" in kwargs:
887
+ warnings.warn(
888
+ "Passing `padding_mask` is deprecated and will be removed in v4.37. Please make sure use `attention_mask` instead.`"
889
+ )
890
+
891
+ # overwrite attention_mask with padding_mask
892
+ attention_mask = kwargs.pop("padding_mask")
893
+
894
+ output_attentions = False
895
+
896
+ bsz, q_len, _ = hidden_states.size()
897
+
898
+ if self.q_lora_rank is None:
899
+ q = self.q_proj(hidden_states)
900
+ else:
901
+ q = self.q_b_proj(self.q_a_layernorm(self.q_a_proj(hidden_states)))
902
+ q = q.view(bsz, q_len, self.num_heads, self.q_head_dim).transpose(1, 2)
903
+ q_nope, q_pe = torch.split(
904
+ q, [self.qk_nope_head_dim, self.qk_rope_head_dim], dim=-1
905
+ )
906
+
907
+ # Flash attention requires the input to have the shape
908
+ # batch_size x seq_length x head_dim x hidden_dim
909
+ # therefore we just need to keep the original shape
910
+ compressed_kv = self.kv_a_proj_with_mqa(hidden_states)
911
+ compressed_kv, k_pe = torch.split(
912
+ compressed_kv, [self.kv_lora_rank, self.qk_rope_head_dim], dim=-1
913
+ )
914
+ k_pe = k_pe.view(bsz, q_len, 1, self.qk_rope_head_dim).transpose(1, 2)
915
+ kv = (
916
+ self.kv_b_proj(self.kv_a_layernorm(compressed_kv))
917
+ .view(bsz, q_len, self.num_heads, self.qk_nope_head_dim + self.v_head_dim)
918
+ .transpose(1, 2)
919
+ )
920
+
921
+ k_nope, value_states = torch.split(
922
+ kv, [self.qk_nope_head_dim, self.v_head_dim], dim=-1
923
+ )
924
+ kv_seq_len = value_states.shape[-2]
925
+
926
+ kv_seq_len = value_states.shape[-2]
927
+ if past_key_value is not None:
928
+ kv_seq_len += past_key_value.get_usable_length(kv_seq_len, self.layer_idx)
929
+
930
+ cos, sin = self.rotary_emb(value_states, seq_len=kv_seq_len)
931
+ q_pe, k_pe = apply_rotary_pos_emb(q_pe, k_pe, cos, sin, position_ids)
932
+
933
+ query_states = k_pe.new_empty(bsz, self.num_heads, q_len, self.q_head_dim)
934
+ query_states[:, :, :, : self.qk_nope_head_dim] = q_nope
935
+ query_states[:, :, :, self.qk_nope_head_dim :] = q_pe
936
+
937
+ key_states = k_pe.new_empty(bsz, self.num_heads, q_len, self.q_head_dim)
938
+ key_states[:, :, :, : self.qk_nope_head_dim] = k_nope
939
+ key_states[:, :, :, self.qk_nope_head_dim :] = k_pe
940
+
941
+ if self.q_head_dim != self.v_head_dim:
942
+ value_states = F.pad(value_states, [0, self.q_head_dim - self.v_head_dim])
943
+
944
+ if past_key_value is not None:
945
+ cache_kwargs = {"sin": sin, "cos": cos} # Specific to RoPE models
946
+ key_states, value_states = past_key_value.update(
947
+ key_states, value_states, self.layer_idx, cache_kwargs
948
+ )
949
+
950
+ # TODO: These transpose are quite inefficient but Flash Attention requires the layout [batch_size, sequence_length, num_heads, head_dim]. We would need to refactor the KV cache
951
+ # to be able to avoid many of these transpose/reshape/view.
952
+ query_states = query_states.transpose(1, 2)
953
+ key_states = key_states.transpose(1, 2)
954
+ value_states = value_states.transpose(1, 2)
955
+
956
+ dropout_rate = self.attention_dropout if self.training else 0.0
957
+
958
+ # In PEFT, usually we cast the layer norms in float32 for training stability reasons
959
+ # therefore the input hidden states gets silently casted in float32. Hence, we need
960
+ # cast them back in the correct dtype just to be sure everything works as expected.
961
+ # This might slowdown training & inference so it is recommended to not cast the LayerNorms
962
+ # in fp32. (DeepseekV3RMSNorm handles it correctly)
963
+
964
+ input_dtype = query_states.dtype
965
+ if input_dtype == torch.float32:
966
+ # Handle the case where the model is quantized
967
+ if hasattr(self.config, "_pre_quantization_dtype"):
968
+ target_dtype = self.config._pre_quantization_dtype
969
+ elif torch.is_autocast_enabled():
970
+ target_dtype = torch.get_autocast_gpu_dtype()
971
+ else:
972
+ target_dtype = (
973
+ self.q_proj.weight.dtype
974
+ if self.q_lora_rank is None
975
+ else self.q_a_proj.weight.dtype
976
+ )
977
+
978
+ logger.warning_once(
979
+ f"The input hidden states seems to be silently casted in float32, this might be related to"
980
+ f" the fact you have upcasted embedding or layer norm layers in float32. We will cast back the input in"
981
+ f" {target_dtype}."
982
+ )
983
+
984
+ query_states = query_states.to(target_dtype)
985
+ key_states = key_states.to(target_dtype)
986
+ value_states = value_states.to(target_dtype)
987
+
988
+ attn_output = self._flash_attention_forward(
989
+ query_states,
990
+ key_states,
991
+ value_states,
992
+ attention_mask,
993
+ q_len,
994
+ dropout=dropout_rate,
995
+ softmax_scale=self.softmax_scale,
996
+ )
997
+ if self.q_head_dim != self.v_head_dim:
998
+ attn_output = attn_output[:, :, :, : self.v_head_dim]
999
+
1000
+ attn_output = attn_output.reshape(
1001
+ bsz, q_len, self.num_heads * self.v_head_dim
1002
+ ).contiguous()
1003
+ attn_output = self.o_proj(attn_output)
1004
+
1005
+ if not output_attentions:
1006
+ attn_weights = None
1007
+
1008
+ return attn_output, attn_weights, past_key_value
1009
+
1010
+ def _flash_attention_forward(
1011
+ self,
1012
+ query_states,
1013
+ key_states,
1014
+ value_states,
1015
+ attention_mask,
1016
+ query_length,
1017
+ dropout=0.0,
1018
+ softmax_scale=None,
1019
+ ):
1020
+ """
1021
+ Calls the forward method of Flash Attention - if the input hidden states contain at least one padding token
1022
+ first unpad the input, then computes the attention scores and pad the final attention scores.
1023
+
1024
+ Args:
1025
+ query_states (`torch.Tensor`):
1026
+ Input query states to be passed to Flash Attention API
1027
+ key_states (`torch.Tensor`):
1028
+ Input key states to be passed to Flash Attention API
1029
+ value_states (`torch.Tensor`):
1030
+ Input value states to be passed to Flash Attention API
1031
+ attention_mask (`torch.Tensor`):
1032
+ The padding mask - corresponds to a tensor of size `(batch_size, seq_len)` where 0 stands for the
1033
+ position of padding tokens and 1 for the position of non-padding tokens.
1034
+ dropout (`int`, *optional*):
1035
+ Attention dropout
1036
+ softmax_scale (`float`, *optional*):
1037
+ The scaling of QK^T before applying softmax. Default to 1 / sqrt(head_dim)
1038
+ """
1039
+ if not self._flash_attn_uses_top_left_mask:
1040
+ causal = self.is_causal
1041
+ else:
1042
+ # TODO: Remove the `query_length != 1` check once Flash Attention for RoCm is bumped to 2.1. For details, please see the comment in DeepseekV3FlashAttention2 __init__.
1043
+ causal = self.is_causal and query_length != 1
1044
+
1045
+ # Contains at least one padding token in the sequence
1046
+ if attention_mask is not None:
1047
+ batch_size = query_states.shape[0]
1048
+ (
1049
+ query_states,
1050
+ key_states,
1051
+ value_states,
1052
+ indices_q,
1053
+ cu_seq_lens,
1054
+ max_seq_lens,
1055
+ ) = self._upad_input(
1056
+ query_states, key_states, value_states, attention_mask, query_length
1057
+ )
1058
+
1059
+ cu_seqlens_q, cu_seqlens_k = cu_seq_lens
1060
+ max_seqlen_in_batch_q, max_seqlen_in_batch_k = max_seq_lens
1061
+
1062
+ attn_output_unpad = flash_attn_varlen_func(
1063
+ query_states,
1064
+ key_states,
1065
+ value_states,
1066
+ cu_seqlens_q=cu_seqlens_q,
1067
+ cu_seqlens_k=cu_seqlens_k,
1068
+ max_seqlen_q=max_seqlen_in_batch_q,
1069
+ max_seqlen_k=max_seqlen_in_batch_k,
1070
+ dropout_p=dropout,
1071
+ softmax_scale=softmax_scale,
1072
+ causal=causal,
1073
+ )
1074
+
1075
+ attn_output = pad_input(
1076
+ attn_output_unpad, indices_q, batch_size, query_length
1077
+ )
1078
+ else:
1079
+ attn_output = flash_attn_func(
1080
+ query_states,
1081
+ key_states,
1082
+ value_states,
1083
+ dropout,
1084
+ softmax_scale=softmax_scale,
1085
+ causal=causal,
1086
+ )
1087
+
1088
+ return attn_output
1089
+
1090
+ def _upad_input(
1091
+ self, query_layer, key_layer, value_layer, attention_mask, query_length
1092
+ ):
1093
+ indices_k, cu_seqlens_k, max_seqlen_in_batch_k = _get_unpad_data(attention_mask)
1094
+ batch_size, kv_seq_len, num_key_value_heads, head_dim = key_layer.shape
1095
+
1096
+ key_layer = index_first_axis(
1097
+ key_layer.reshape(batch_size * kv_seq_len, num_key_value_heads, head_dim),
1098
+ indices_k,
1099
+ )
1100
+ value_layer = index_first_axis(
1101
+ value_layer.reshape(batch_size * kv_seq_len, num_key_value_heads, head_dim),
1102
+ indices_k,
1103
+ )
1104
+ if query_length == kv_seq_len:
1105
+ query_layer = index_first_axis(
1106
+ query_layer.reshape(batch_size * kv_seq_len, self.num_heads, head_dim),
1107
+ indices_k,
1108
+ )
1109
+ cu_seqlens_q = cu_seqlens_k
1110
+ max_seqlen_in_batch_q = max_seqlen_in_batch_k
1111
+ indices_q = indices_k
1112
+ elif query_length == 1:
1113
+ max_seqlen_in_batch_q = 1
1114
+ cu_seqlens_q = torch.arange(
1115
+ batch_size + 1, dtype=torch.int32, device=query_layer.device
1116
+ ) # There is a memcpy here, that is very bad.
1117
+ indices_q = cu_seqlens_q[:-1]
1118
+ query_layer = query_layer.squeeze(1)
1119
+ else:
1120
+ # The -q_len: slice assumes left padding.
1121
+ attention_mask = attention_mask[:, -query_length:]
1122
+ query_layer, indices_q, cu_seqlens_q, max_seqlen_in_batch_q = unpad_input(
1123
+ query_layer, attention_mask
1124
+ )
1125
+
1126
+ return (
1127
+ query_layer,
1128
+ key_layer,
1129
+ value_layer,
1130
+ indices_q,
1131
+ (cu_seqlens_q, cu_seqlens_k),
1132
+ (max_seqlen_in_batch_q, max_seqlen_in_batch_k),
1133
+ )
1134
+
1135
+
1136
+ ATTENTION_CLASSES = {
1137
+ "eager": DeepseekV3Attention,
1138
+ "flash_attention_2": DeepseekV3FlashAttention2,
1139
+ }
1140
+
1141
+
1142
+ class DeepseekV3DecoderLayer(nn.Module):
1143
+ def __init__(self, config: DeepseekV3Config, layer_idx: int):
1144
+ super().__init__()
1145
+ self.hidden_size = config.hidden_size
1146
+
1147
+ self.self_attn = ATTENTION_CLASSES[config._attn_implementation](
1148
+ config=config, layer_idx=layer_idx
1149
+ )
1150
+
1151
+ self.mlp = (
1152
+ DeepseekV3MoE(config)
1153
+ if (
1154
+ config.n_routed_experts is not None
1155
+ and layer_idx >= config.first_k_dense_replace
1156
+ and layer_idx % config.moe_layer_freq == 0
1157
+ )
1158
+ else DeepseekV3MLP(config)
1159
+ )
1160
+ self.input_layernorm = DeepseekV3RMSNorm(
1161
+ config.hidden_size, eps=config.rms_norm_eps
1162
+ )
1163
+ self.post_attention_layernorm = DeepseekV3RMSNorm(
1164
+ config.hidden_size, eps=config.rms_norm_eps
1165
+ )
1166
+
1167
+ def forward(
1168
+ self,
1169
+ hidden_states: torch.Tensor,
1170
+ attention_mask: Optional[torch.Tensor] = None,
1171
+ position_ids: Optional[torch.LongTensor] = None,
1172
+ past_key_value: Optional[Tuple[torch.Tensor]] = None,
1173
+ output_attentions: Optional[bool] = False,
1174
+ use_cache: Optional[bool] = False,
1175
+ **kwargs,
1176
+ ) -> Tuple[
1177
+ torch.FloatTensor, Optional[Tuple[torch.FloatTensor, torch.FloatTensor]]
1178
+ ]:
1179
+ """
1180
+ Args:
1181
+ hidden_states (`torch.FloatTensor`): input to the layer of shape `(batch, seq_len, embed_dim)`
1182
+ attention_mask (`torch.FloatTensor`, *optional*):
1183
+ attention mask of size `(batch_size, sequence_length)` if flash attention is used or `(batch_size, 1,
1184
+ query_sequence_length, key_sequence_length)` if default attention is used.
1185
+ output_attentions (`bool`, *optional*):
1186
+ Whether or not to return the attentions tensors of all attention layers. See `attentions` under
1187
+ returned tensors for more detail.
1188
+ use_cache (`bool`, *optional*):
1189
+ If set to `True`, `past_key_values` key value states are returned and can be used to speed up decoding
1190
+ (see `past_key_values`).
1191
+ past_key_value (`Tuple(torch.FloatTensor)`, *optional*): cached past key and value projection states
1192
+ """
1193
+ if "padding_mask" in kwargs:
1194
+ warnings.warn(
1195
+ "Passing `padding_mask` is deprecated and will be removed in v4.37. Please make sure use `attention_mask` instead.`"
1196
+ )
1197
+ residual = hidden_states
1198
+
1199
+ hidden_states = self.input_layernorm(hidden_states)
1200
+
1201
+ # Self Attention
1202
+ hidden_states, self_attn_weights, present_key_value = self.self_attn(
1203
+ hidden_states=hidden_states,
1204
+ attention_mask=attention_mask,
1205
+ position_ids=position_ids,
1206
+ past_key_value=past_key_value,
1207
+ output_attentions=output_attentions,
1208
+ use_cache=use_cache,
1209
+ **kwargs,
1210
+ )
1211
+ hidden_states = residual + hidden_states
1212
+
1213
+ # Fully Connected
1214
+ residual = hidden_states
1215
+ hidden_states = self.post_attention_layernorm(hidden_states)
1216
+ hidden_states = self.mlp(hidden_states)
1217
+ hidden_states = residual + hidden_states
1218
+
1219
+ outputs = (hidden_states,)
1220
+
1221
+ if output_attentions:
1222
+ outputs += (self_attn_weights,)
1223
+
1224
+ if use_cache:
1225
+ outputs += (present_key_value,)
1226
+
1227
+ return outputs
1228
+
1229
+
1230
+ DeepseekV3_START_DOCSTRING = r"""
1231
+ This model inherits from [`PreTrainedModel`]. Check the superclass documentation for the generic methods the
1232
+ library implements for all its model (such as downloading or saving, resizing the input embeddings, pruning heads
1233
+ etc.)
1234
+
1235
+ This model is also a PyTorch [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) subclass.
1236
+ Use it as a regular PyTorch Module and refer to the PyTorch documentation for all matter related to general usage
1237
+ and behavior.
1238
+
1239
+ Parameters:
1240
+ config ([`DeepseekV3Config`]):
1241
+ Model configuration class with all the parameters of the model. Initializing with a config file does not
1242
+ load the weights associated with the model, only the configuration. Check out the
1243
+ [`~PreTrainedModel.from_pretrained`] method to load the model weights.
1244
+ """
1245
+
1246
+
1247
+ @add_start_docstrings(
1248
+ "The bare DeepseekV3 Model outputting raw hidden-states without any specific head on top.",
1249
+ DeepseekV3_START_DOCSTRING,
1250
+ )
1251
+ class DeepseekV3PreTrainedModel(PreTrainedModel):
1252
+ config_class = DeepseekV3Config
1253
+ base_model_prefix = "model"
1254
+ supports_gradient_checkpointing = True
1255
+ _no_split_modules = ["DeepseekV3DecoderLayer"]
1256
+ _skip_keys_device_placement = "past_key_values"
1257
+ _supports_flash_attn_2 = True
1258
+ _supports_cache_class = True
1259
+
1260
+ def _init_weights(self, module):
1261
+ std = self.config.initializer_range
1262
+ if isinstance(module, nn.Linear):
1263
+ module.weight.data.normal_(mean=0.0, std=std)
1264
+ if module.bias is not None:
1265
+ module.bias.data.zero_()
1266
+ elif isinstance(module, nn.Embedding):
1267
+ module.weight.data.normal_(mean=0.0, std=std)
1268
+ if module.padding_idx is not None:
1269
+ module.weight.data[module.padding_idx].zero_()
1270
+
1271
+
1272
+ DeepseekV3_INPUTS_DOCSTRING = r"""
1273
+ Args:
1274
+ input_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`):
1275
+ Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you provide
1276
+ it.
1277
+
1278
+ Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
1279
+ [`PreTrainedTokenizer.__call__`] for details.
1280
+
1281
+ [What are input IDs?](../glossary#input-ids)
1282
+ attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
1283
+ Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
1284
+
1285
+ - 1 for tokens that are **not masked**,
1286
+ - 0 for tokens that are **masked**.
1287
+
1288
+ [What are attention masks?](../glossary#attention-mask)
1289
+
1290
+ Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
1291
+ [`PreTrainedTokenizer.__call__`] for details.
1292
+
1293
+ If `past_key_values` is used, optionally only the last `input_ids` have to be input (see
1294
+ `past_key_values`).
1295
+
1296
+ If you want to change padding behavior, you should read [`modeling_opt._prepare_decoder_attention_mask`]
1297
+ and modify to your needs. See diagram 1 in [the paper](https://arxiv.org/abs/1910.13461) for more
1298
+ information on the default strategy.
1299
+
1300
+ - 1 indicates the head is **not masked**,
1301
+ - 0 indicates the head is **masked**.
1302
+ position_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
1303
+ Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0,
1304
+ config.n_positions - 1]`.
1305
+
1306
+ [What are position IDs?](../glossary#position-ids)
1307
+ past_key_values (`Cache` or `tuple(tuple(torch.FloatTensor))`, *optional*):
1308
+ Pre-computed hidden-states (key and values in the self-attention blocks and in the cross-attention
1309
+ blocks) that can be used to speed up sequential decoding. This typically consists in the `past_key_values`
1310
+ returned by the model at a previous stage of decoding, when `use_cache=True` or `config.use_cache=True`.
1311
+
1312
+ Two formats are allowed:
1313
+ - a [`~cache_utils.Cache`] instance;
1314
+ - Tuple of `tuple(torch.FloatTensor)` of length `config.n_layers`, with each tuple having 2 tensors of
1315
+ shape `(batch_size, num_heads, sequence_length, embed_size_per_head)`). This is also known as the legacy
1316
+ cache format.
1317
+
1318
+ The model will output the same cache format that is fed as input. If no `past_key_values` are passed, the
1319
+ legacy cache format will be returned.
1320
+
1321
+ If `past_key_values` are used, the user can optionally input only the last `input_ids` (those that don't
1322
+ have their past key value states given to this model) of shape `(batch_size, 1)` instead of all `input_ids`
1323
+ of shape `(batch_size, sequence_length)`.
1324
+ inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):
1325
+ Optionally, instead of passing `input_ids` you can choose to directly pass an embedded representation. This
1326
+ is useful if you want more control over how to convert `input_ids` indices into associated vectors than the
1327
+ model's internal embedding lookup matrix.
1328
+ use_cache (`bool`, *optional*):
1329
+ If set to `True`, `past_key_values` key value states are returned and can be used to speed up decoding (see
1330
+ `past_key_values`).
1331
+ output_attentions (`bool`, *optional*):
1332
+ Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
1333
+ tensors for more detail.
1334
+ output_hidden_states (`bool`, *optional*):
1335
+ Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
1336
+ more detail.
1337
+ return_dict (`bool`, *optional*):
1338
+ Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
1339
+ """
1340
+
1341
+
1342
+ @add_start_docstrings(
1343
+ "The bare DeepseekV3 Model outputting raw hidden-states without any specific head on top.",
1344
+ DeepseekV3_START_DOCSTRING,
1345
+ )
1346
+ class DeepseekV3Model(DeepseekV3PreTrainedModel):
1347
+ """
1348
+ Transformer decoder consisting of *config.num_hidden_layers* layers. Each layer is a [`DeepseekV3DecoderLayer`]
1349
+
1350
+ Args:
1351
+ config: DeepseekV3Config
1352
+ """
1353
+
1354
+ def __init__(self, config: DeepseekV3Config):
1355
+ super().__init__(config)
1356
+ self.padding_idx = config.pad_token_id
1357
+ self.vocab_size = config.vocab_size
1358
+
1359
+ self.embed_tokens = nn.Embedding(
1360
+ config.vocab_size, config.hidden_size, self.padding_idx
1361
+ )
1362
+ self.layers = nn.ModuleList(
1363
+ [
1364
+ DeepseekV3DecoderLayer(config, layer_idx)
1365
+ for layer_idx in range(config.num_hidden_layers)
1366
+ ]
1367
+ )
1368
+ self._use_flash_attention_2 = config._attn_implementation == "flash_attention_2"
1369
+ self.norm = DeepseekV3RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
1370
+
1371
+ self.gradient_checkpointing = False
1372
+ # Initialize weights and apply final processing
1373
+ self.post_init()
1374
+
1375
+ def get_input_embeddings(self):
1376
+ return self.embed_tokens
1377
+
1378
+ def set_input_embeddings(self, value):
1379
+ self.embed_tokens = value
1380
+
1381
+ @add_start_docstrings_to_model_forward(DeepseekV3_INPUTS_DOCSTRING)
1382
+ def forward(
1383
+ self,
1384
+ input_ids: torch.LongTensor = None,
1385
+ attention_mask: Optional[torch.Tensor] = None,
1386
+ position_ids: Optional[torch.LongTensor] = None,
1387
+ past_key_values: Optional[List[torch.FloatTensor]] = None,
1388
+ inputs_embeds: Optional[torch.FloatTensor] = None,
1389
+ use_cache: Optional[bool] = None,
1390
+ output_attentions: Optional[bool] = None,
1391
+ output_hidden_states: Optional[bool] = None,
1392
+ return_dict: Optional[bool] = None,
1393
+ ) -> Union[Tuple, BaseModelOutputWithPast]:
1394
+ output_attentions = (
1395
+ output_attentions
1396
+ if output_attentions is not None
1397
+ else self.config.output_attentions
1398
+ )
1399
+ output_hidden_states = (
1400
+ output_hidden_states
1401
+ if output_hidden_states is not None
1402
+ else self.config.output_hidden_states
1403
+ )
1404
+ use_cache = use_cache if use_cache is not None else self.config.use_cache
1405
+
1406
+ return_dict = (
1407
+ return_dict if return_dict is not None else self.config.use_return_dict
1408
+ )
1409
+
1410
+ # retrieve input_ids and inputs_embeds
1411
+ if input_ids is not None and inputs_embeds is not None:
1412
+ raise ValueError(
1413
+ "You cannot specify both input_ids and inputs_embeds at the same time"
1414
+ )
1415
+ elif input_ids is not None:
1416
+ batch_size, seq_length = input_ids.shape[:2]
1417
+ elif inputs_embeds is not None:
1418
+ batch_size, seq_length = inputs_embeds.shape[:2]
1419
+ else:
1420
+ raise ValueError("You have to specify either input_ids or inputs_embeds")
1421
+
1422
+ past_key_values_length = 0
1423
+ if use_cache:
1424
+ use_legacy_cache = not isinstance(past_key_values, Cache)
1425
+ if use_legacy_cache:
1426
+ past_key_values = DynamicCache.from_legacy_cache(past_key_values)
1427
+ past_key_values_length = past_key_values.get_usable_length(seq_length)
1428
+
1429
+ if position_ids is None:
1430
+ device = input_ids.device if input_ids is not None else inputs_embeds.device
1431
+ position_ids = torch.arange(
1432
+ past_key_values_length,
1433
+ seq_length + past_key_values_length,
1434
+ dtype=torch.long,
1435
+ device=device,
1436
+ )
1437
+ position_ids = position_ids.unsqueeze(0)
1438
+
1439
+ if inputs_embeds is None:
1440
+ inputs_embeds = self.embed_tokens(input_ids)
1441
+
1442
+ if self._use_flash_attention_2:
1443
+ # 2d mask is passed through the layers
1444
+ attention_mask = (
1445
+ attention_mask
1446
+ if (attention_mask is not None and 0 in attention_mask)
1447
+ else None
1448
+ )
1449
+ else:
1450
+ # 4d mask is passed through the layers
1451
+ attention_mask = _prepare_4d_causal_attention_mask(
1452
+ attention_mask,
1453
+ (batch_size, seq_length),
1454
+ inputs_embeds,
1455
+ past_key_values_length,
1456
+ )
1457
+
1458
+ # embed positions
1459
+ hidden_states = inputs_embeds
1460
+
1461
+ # decoder layers
1462
+ all_hidden_states = () if output_hidden_states else None
1463
+ all_self_attns = () if output_attentions else None
1464
+ next_decoder_cache = None
1465
+
1466
+ for decoder_layer in self.layers:
1467
+ if output_hidden_states:
1468
+ all_hidden_states += (hidden_states,)
1469
+
1470
+ layer_outputs = decoder_layer(
1471
+ hidden_states,
1472
+ attention_mask=attention_mask,
1473
+ position_ids=position_ids,
1474
+ past_key_value=past_key_values,
1475
+ output_attentions=output_attentions,
1476
+ use_cache=use_cache,
1477
+ )
1478
+
1479
+ hidden_states = layer_outputs[0]
1480
+
1481
+ if use_cache:
1482
+ next_decoder_cache = layer_outputs[2 if output_attentions else 1]
1483
+
1484
+ if output_attentions:
1485
+ all_self_attns += (layer_outputs[1],)
1486
+
1487
+ hidden_states = self.norm(hidden_states)
1488
+
1489
+ # add hidden states from the last decoder layer
1490
+ if output_hidden_states:
1491
+ all_hidden_states += (hidden_states,)
1492
+
1493
+ next_cache = None
1494
+ if use_cache:
1495
+ next_cache = (
1496
+ next_decoder_cache.to_legacy_cache()
1497
+ if use_legacy_cache
1498
+ else next_decoder_cache
1499
+ )
1500
+ if not return_dict:
1501
+ return tuple(
1502
+ v
1503
+ for v in [hidden_states, next_cache, all_hidden_states, all_self_attns]
1504
+ if v is not None
1505
+ )
1506
+ return BaseModelOutputWithPast(
1507
+ last_hidden_state=hidden_states,
1508
+ past_key_values=next_cache,
1509
+ hidden_states=all_hidden_states,
1510
+ attentions=all_self_attns,
1511
+ )
1512
+
1513
+
1514
+ class DeepseekV3ForCausalLM(DeepseekV3PreTrainedModel):
1515
+ _tied_weights_keys = ["lm_head.weight"]
1516
+
1517
+ def __init__(self, config):
1518
+ super().__init__(config)
1519
+ self.model = DeepseekV3Model(config)
1520
+ self.vocab_size = config.vocab_size
1521
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
1522
+
1523
+ # Initialize weights and apply final processing
1524
+ self.post_init()
1525
+
1526
+ def get_input_embeddings(self):
1527
+ return self.model.embed_tokens
1528
+
1529
+ def set_input_embeddings(self, value):
1530
+ self.model.embed_tokens = value
1531
+
1532
+ def get_output_embeddings(self):
1533
+ return self.lm_head
1534
+
1535
+ def set_output_embeddings(self, new_embeddings):
1536
+ self.lm_head = new_embeddings
1537
+
1538
+ def set_decoder(self, decoder):
1539
+ self.model = decoder
1540
+
1541
+ def get_decoder(self):
1542
+ return self.model
1543
+
1544
+ @add_start_docstrings_to_model_forward(DeepseekV3_INPUTS_DOCSTRING)
1545
+ @replace_return_docstrings(
1546
+ output_type=CausalLMOutputWithPast, config_class=_CONFIG_FOR_DOC
1547
+ )
1548
+ def forward(
1549
+ self,
1550
+ input_ids: torch.LongTensor = None,
1551
+ attention_mask: Optional[torch.Tensor] = None,
1552
+ position_ids: Optional[torch.LongTensor] = None,
1553
+ past_key_values: Optional[List[torch.FloatTensor]] = None,
1554
+ inputs_embeds: Optional[torch.FloatTensor] = None,
1555
+ labels: Optional[torch.LongTensor] = None,
1556
+ use_cache: Optional[bool] = None,
1557
+ output_attentions: Optional[bool] = None,
1558
+ output_hidden_states: Optional[bool] = None,
1559
+ return_dict: Optional[bool] = None,
1560
+ ) -> Union[Tuple, CausalLMOutputWithPast]:
1561
+ r"""
1562
+ Args:
1563
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
1564
+ Labels for computing the masked language modeling loss. Indices should either be in `[0, transformers.,
1565
+ config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
1566
+ (masked), the loss is only computed for the tokens with labels in `[0, transformers., config.vocab_size]`.
1567
+
1568
+ Returns:
1569
+
1570
+ Example:
1571
+
1572
+ ```python
1573
+ >>> from transformers import AutoTokenizer, DeepseekV3ForCausalLM
1574
+
1575
+ >>> model = DeepseekV3ForCausalLM.from_pretrained(PATH_TO_CONVERTED_WEIGHTS)
1576
+ >>> tokenizer = AutoTokenizer.from_pretrained(PATH_TO_CONVERTED_TOKENIZER)
1577
+
1578
+ >>> prompt = "Hey, are you conscious? Can you talk to me?"
1579
+ >>> inputs = tokenizer(prompt, return_tensors="pt")
1580
+
1581
+ >>> # Generate
1582
+ >>> generate_ids = model.generate(inputs.input_ids, max_length=30)
1583
+ >>> tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
1584
+ "Hey, are you conscious? Can you talk to me?\nI'm not conscious, but I can talk to you."
1585
+ ```"""
1586
+ output_attentions = (
1587
+ output_attentions
1588
+ if output_attentions is not None
1589
+ else self.config.output_attentions
1590
+ )
1591
+ output_hidden_states = (
1592
+ output_hidden_states
1593
+ if output_hidden_states is not None
1594
+ else self.config.output_hidden_states
1595
+ )
1596
+ return_dict = (
1597
+ return_dict if return_dict is not None else self.config.use_return_dict
1598
+ )
1599
+
1600
+ # decoder outputs consists of (dec_features, layer_state, dec_hidden, dec_attn)
1601
+ outputs = self.model(
1602
+ input_ids=input_ids,
1603
+ attention_mask=attention_mask,
1604
+ position_ids=position_ids,
1605
+ past_key_values=past_key_values,
1606
+ inputs_embeds=inputs_embeds,
1607
+ use_cache=use_cache,
1608
+ output_attentions=output_attentions,
1609
+ output_hidden_states=output_hidden_states,
1610
+ return_dict=return_dict,
1611
+ )
1612
+
1613
+ hidden_states = outputs[0]
1614
+ logits = self.lm_head(hidden_states)
1615
+ logits = logits.float()
1616
+
1617
+ loss = None
1618
+ if labels is not None:
1619
+ # Shift so that tokens < n predict n
1620
+ shift_logits = logits[..., :-1, :].contiguous()
1621
+ shift_labels = labels[..., 1:].contiguous()
1622
+ # Flatten the tokens
1623
+ loss_fct = CrossEntropyLoss()
1624
+ shift_logits = shift_logits.view(-1, self.config.vocab_size)
1625
+ shift_labels = shift_labels.view(-1)
1626
+ # Enable model parallelism
1627
+ shift_labels = shift_labels.to(shift_logits.device)
1628
+ loss = loss_fct(shift_logits, shift_labels)
1629
+
1630
+ if not return_dict:
1631
+ output = (logits,) + outputs[1:]
1632
+ return (loss,) + output if loss is not None else output
1633
+
1634
+ return CausalLMOutputWithPast(
1635
+ loss=loss,
1636
+ logits=logits,
1637
+ past_key_values=outputs.past_key_values,
1638
+ hidden_states=outputs.hidden_states,
1639
+ attentions=outputs.attentions,
1640
+ )
1641
+
1642
+ def prepare_inputs_for_generation(
1643
+ self,
1644
+ input_ids,
1645
+ past_key_values=None,
1646
+ attention_mask=None,
1647
+ inputs_embeds=None,
1648
+ **kwargs,
1649
+ ):
1650
+ if past_key_values is not None:
1651
+ if isinstance(past_key_values, Cache):
1652
+ cache_length = past_key_values.get_seq_length()
1653
+ past_length = past_key_values.seen_tokens
1654
+ max_cache_length = past_key_values.get_max_length()
1655
+ else:
1656
+ cache_length = past_length = past_key_values[0][0].shape[2]
1657
+ max_cache_length = None
1658
+
1659
+ # Keep only the unprocessed tokens:
1660
+ # 1 - If the length of the attention_mask exceeds the length of input_ids, then we are in a setting where
1661
+ # some of the inputs are exclusivelly passed as part of the cache (e.g. when passing input_embeds as
1662
+ # input)
1663
+ if (
1664
+ attention_mask is not None
1665
+ and attention_mask.shape[1] > input_ids.shape[1]
1666
+ ):
1667
+ input_ids = input_ids[:, -(attention_mask.shape[1] - past_length) :]
1668
+ # 2 - If the past_length is smaller than input_ids', then input_ids holds all input tokens. We can discard
1669
+ # input_ids based on the past_length.
1670
+ elif past_length < input_ids.shape[1]:
1671
+ input_ids = input_ids[:, past_length:]
1672
+ # 3 - Otherwise (past_length >= input_ids.shape[1]), let's assume input_ids only has unprocessed tokens.
1673
+
1674
+ # If we are about to go beyond the maximum cache length, we need to crop the input attention mask.
1675
+ if (
1676
+ max_cache_length is not None
1677
+ and attention_mask is not None
1678
+ and cache_length + input_ids.shape[1] > max_cache_length
1679
+ ):
1680
+ attention_mask = attention_mask[:, -max_cache_length:]
1681
+
1682
+ position_ids = kwargs.get("position_ids", None)
1683
+ if attention_mask is not None and position_ids is None:
1684
+ # create position_ids on the fly for batch generation
1685
+ position_ids = attention_mask.long().cumsum(-1) - 1
1686
+ position_ids.masked_fill_(attention_mask == 0, 1)
1687
+ if past_key_values:
1688
+ position_ids = position_ids[:, -input_ids.shape[1] :]
1689
+
1690
+ # if `inputs_embeds` are passed, we only want to use them in the 1st generation step
1691
+ if inputs_embeds is not None and past_key_values is None:
1692
+ model_inputs = {"inputs_embeds": inputs_embeds}
1693
+ else:
1694
+ model_inputs = {"input_ids": input_ids}
1695
+
1696
+ model_inputs.update(
1697
+ {
1698
+ "position_ids": position_ids,
1699
+ "past_key_values": past_key_values,
1700
+ "use_cache": kwargs.get("use_cache"),
1701
+ "attention_mask": attention_mask,
1702
+ }
1703
+ )
1704
+ return model_inputs
1705
+
1706
+ @staticmethod
1707
+ def _reorder_cache(past_key_values, beam_idx):
1708
+ reordered_past = ()
1709
+ for layer_past in past_key_values:
1710
+ reordered_past += (
1711
+ tuple(
1712
+ past_state.index_select(0, beam_idx.to(past_state.device))
1713
+ for past_state in layer_past
1714
+ ),
1715
+ )
1716
+ return reordered_past
1717
+
1718
+
1719
+ @add_start_docstrings(
1720
+ """
1721
+ The DeepseekV3 Model transformer with a sequence classification head on top (linear layer).
1722
+
1723
+ [`DeepseekV3ForSequenceClassification`] uses the last token in order to do the classification, as other causal models
1724
+ (e.g. GPT-2) do.
1725
+
1726
+ Since it does classification on the last token, it requires to know the position of the last token. If a
1727
+ `pad_token_id` is defined in the configuration, it finds the last token that is not a padding token in each row. If
1728
+ no `pad_token_id` is defined, it simply takes the last value in each row of the batch. Since it cannot guess the
1729
+ padding tokens when `inputs_embeds` are passed instead of `input_ids`, it does the same (take the last value in
1730
+ each row of the batch).
1731
+ """,
1732
+ DeepseekV3_START_DOCSTRING,
1733
+ )
1734
+ class DeepseekV3ForSequenceClassification(DeepseekV3PreTrainedModel):
1735
+ def __init__(self, config):
1736
+ super().__init__(config)
1737
+ self.num_labels = config.num_labels
1738
+ self.model = DeepseekV3Model(config)
1739
+ self.score = nn.Linear(config.hidden_size, self.num_labels, bias=False)
1740
+
1741
+ # Initialize weights and apply final processing
1742
+ self.post_init()
1743
+
1744
+ def get_input_embeddings(self):
1745
+ return self.model.embed_tokens
1746
+
1747
+ def set_input_embeddings(self, value):
1748
+ self.model.embed_tokens = value
1749
+
1750
+ @add_start_docstrings_to_model_forward(DeepseekV3_INPUTS_DOCSTRING)
1751
+ def forward(
1752
+ self,
1753
+ input_ids: torch.LongTensor = None,
1754
+ attention_mask: Optional[torch.Tensor] = None,
1755
+ position_ids: Optional[torch.LongTensor] = None,
1756
+ past_key_values: Optional[List[torch.FloatTensor]] = None,
1757
+ inputs_embeds: Optional[torch.FloatTensor] = None,
1758
+ labels: Optional[torch.LongTensor] = None,
1759
+ use_cache: Optional[bool] = None,
1760
+ output_attentions: Optional[bool] = None,
1761
+ output_hidden_states: Optional[bool] = None,
1762
+ return_dict: Optional[bool] = None,
1763
+ ) -> Union[Tuple, SequenceClassifierOutputWithPast]:
1764
+ r"""
1765
+ labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
1766
+ Labels for computing the sequence classification/regression loss. Indices should be in `[0, transformers.,
1767
+ config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If
1768
+ `config.num_labels > 1` a classification loss is computed (Cross-Entropy).
1769
+ """
1770
+ return_dict = (
1771
+ return_dict if return_dict is not None else self.config.use_return_dict
1772
+ )
1773
+
1774
+ transformer_outputs = self.model(
1775
+ input_ids,
1776
+ attention_mask=attention_mask,
1777
+ position_ids=position_ids,
1778
+ past_key_values=past_key_values,
1779
+ inputs_embeds=inputs_embeds,
1780
+ use_cache=use_cache,
1781
+ output_attentions=output_attentions,
1782
+ output_hidden_states=output_hidden_states,
1783
+ return_dict=return_dict,
1784
+ )
1785
+ hidden_states = transformer_outputs[0]
1786
+ logits = self.score(hidden_states)
1787
+
1788
+ if input_ids is not None:
1789
+ batch_size = input_ids.shape[0]
1790
+ else:
1791
+ batch_size = inputs_embeds.shape[0]
1792
+
1793
+ if self.config.pad_token_id is None and batch_size != 1:
1794
+ raise ValueError(
1795
+ "Cannot handle batch sizes > 1 if no padding token is defined."
1796
+ )
1797
+ if self.config.pad_token_id is None:
1798
+ sequence_lengths = -1
1799
+ else:
1800
+ if input_ids is not None:
1801
+ sequence_lengths = (
1802
+ torch.eq(input_ids, self.config.pad_token_id).int().argmax(-1) - 1
1803
+ ).to(logits.device)
1804
+ else:
1805
+ sequence_lengths = -1
1806
+
1807
+ pooled_logits = logits[
1808
+ torch.arange(batch_size, device=logits.device), sequence_lengths
1809
+ ]
1810
+
1811
+ loss = None
1812
+ if labels is not None:
1813
+ labels = labels.to(logits.device)
1814
+ if self.config.problem_type is None:
1815
+ if self.num_labels == 1:
1816
+ self.config.problem_type = "regression"
1817
+ elif self.num_labels > 1 and (
1818
+ labels.dtype == torch.long or labels.dtype == torch.int
1819
+ ):
1820
+ self.config.problem_type = "single_label_classification"
1821
+ else:
1822
+ self.config.problem_type = "multi_label_classification"
1823
+
1824
+ if self.config.problem_type == "regression":
1825
+ loss_fct = MSELoss()
1826
+ if self.num_labels == 1:
1827
+ loss = loss_fct(pooled_logits.squeeze(), labels.squeeze())
1828
+ else:
1829
+ loss = loss_fct(pooled_logits, labels)
1830
+ elif self.config.problem_type == "single_label_classification":
1831
+ loss_fct = CrossEntropyLoss()
1832
+ loss = loss_fct(
1833
+ pooled_logits.view(-1, self.num_labels), labels.view(-1)
1834
+ )
1835
+ elif self.config.problem_type == "multi_label_classification":
1836
+ loss_fct = BCEWithLogitsLoss()
1837
+ loss = loss_fct(pooled_logits, labels)
1838
+ if not return_dict:
1839
+ output = (pooled_logits,) + transformer_outputs[1:]
1840
+ return ((loss,) + output) if loss is not None else output
1841
+
1842
+ return SequenceClassifierOutputWithPast(
1843
+ loss=loss,
1844
+ logits=pooled_logits,
1845
+ past_key_values=transformer_outputs.past_key_values,
1846
+ hidden_states=transformer_outputs.hidden_states,
1847
+ attentions=transformer_outputs.attentions,
1848
+ )
special_tokens_map.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": {
3
+ "content": "<|begin▁of▁sentence|>",
4
+ "lstrip": false,
5
+ "normalized": false,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "eos_token": {
10
+ "content": "<|end▁of▁sentence|>",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "pad_token": {
17
+ "content": "<|end▁of▁sentence|>",
18
+ "lstrip": false,
19
+ "normalized": false,
20
+ "rstrip": false,
21
+ "single_word": false
22
+ }
23
+ }
test.py ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Debug script to check if vLLM is using the modified chat template.
4
+ """
5
+
6
+ import requests
7
+ import json
8
+ from transformers import AutoTokenizer
9
+
10
+ API_URL = "http://localhost:8000/v1"
11
+ MODEL_ID = "/models/DeepSeek-R1-0528"
12
+ MODEL_PATH = "/home/hotaisle/workspace/models/DeepSeek-R1-0528"
13
+
14
+ def check_local_template():
15
+ """Check what the local tokenizer produces."""
16
+ print("=" * 80)
17
+ print("LOCAL TOKENIZER TEST")
18
+ print("=" * 80)
19
+
20
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
21
+ messages = [{"role": "user", "content": "What is 2+2?"}]
22
+
23
+ # Test with enable_thinking=False
24
+ prompt_with_false = tokenizer.apply_chat_template(
25
+ messages,
26
+ tokenize=False,
27
+ add_generation_prompt=True,
28
+ enable_thinking=False
29
+ )
30
+
31
+ # Test without enable_thinking (default)
32
+ prompt_default = tokenizer.apply_chat_template(
33
+ messages,
34
+ tokenize=False,
35
+ add_generation_prompt=True
36
+ )
37
+
38
+ print("\nWith enable_thinking=False:")
39
+ print(f"Prompt ends with: {repr(prompt_with_false[-80:])}")
40
+ print(f"Contains empty think block: {'<think>\\n\\n</think>\\n\\n' in prompt_with_false}")
41
+
42
+ print("\nDefault (no enable_thinking):")
43
+ print(f"Prompt ends with: {repr(prompt_default[-50:])}")
44
+
45
+ return prompt_with_false, prompt_default
46
+
47
+ def test_completions_api():
48
+ """Test using completions API with manual prompts."""
49
+ print("\n\n" + "=" * 80)
50
+ print("COMPLETIONS API TEST")
51
+ print("=" * 80)
52
+
53
+ # Get the prompts from local tokenizer
54
+ prompt_with_empty_think, prompt_default = check_local_template()
55
+
56
+ # Test 1: With manually injected empty think block
57
+ print("\n[Test 1] Completions API with empty think block")
58
+ response = requests.post(
59
+ f"{API_URL}/completions",
60
+ json={
61
+ "model": MODEL_ID,
62
+ "prompt": prompt_with_empty_think,
63
+ "max_tokens": 100,
64
+ "temperature": 0,
65
+ "stop": ["<|end▁of▁sentence|>"]
66
+ }
67
+ )
68
+
69
+ if response.status_code == 200:
70
+ result = response.json()
71
+ text = result["choices"][0]["text"]
72
+ print(f"Response: {repr(text[:100])}")
73
+ print(f"Model generated <think>: {'<think>' in text}")
74
+ else:
75
+ print(f"Error: {response.status_code}")
76
+
77
+ # Test 2: Normal prompt
78
+ print("\n[Test 2] Completions API with normal prompt")
79
+ response = requests.post(
80
+ f"{API_URL}/completions",
81
+ json={
82
+ "model": MODEL_ID,
83
+ "prompt": prompt_default,
84
+ "max_tokens": 100,
85
+ "temperature": 0,
86
+ "stop": ["<|end▁of▁sentence|>"]
87
+ }
88
+ )
89
+
90
+ if response.status_code == 200:
91
+ result = response.json()
92
+ text = result["choices"][0]["text"]
93
+ print(f"Response: {repr(text[:100])}")
94
+ print(f"Model generated <think>: {'<think>' in text}")
95
+
96
+ def test_chat_raw_request():
97
+ """Test chat API with raw request to see what vLLM sends."""
98
+ print("\n\n" + "=" * 80)
99
+ print("CHAT API RAW REQUEST TEST")
100
+ print("=" * 80)
101
+
102
+ # Try different parameter variations
103
+ test_params = [
104
+ {"chat_template_kwargs": {"enable_thinking": False}},
105
+ {"extra_kwargs": {"enable_thinking": False}},
106
+ {"template_kwargs": {"enable_thinking": False}},
107
+ ]
108
+
109
+ for i, params in enumerate(test_params):
110
+ print(f"\n[Attempt {i+1}] Using {list(params.keys())[0]}")
111
+
112
+ data = {
113
+ "model": MODEL_ID,
114
+ "messages": [{"role": "user", "content": "What is 2+2?"}],
115
+ "max_tokens": 50,
116
+ "temperature": 0,
117
+ **params
118
+ }
119
+
120
+ response = requests.post(f"{API_URL}/chat/completions", json=data)
121
+ print(f"Status: {response.status_code}")
122
+
123
+ if response.status_code == 200:
124
+ result = response.json()
125
+ content = result["choices"][0]["message"]["content"]
126
+ print(f"Response starts with: {repr(content[:50])}")
127
+
128
+ def check_vllm_info():
129
+ """Try to get vLLM version info."""
130
+ print("\n\n" + "=" * 80)
131
+ print("vLLM SERVER INFO")
132
+ print("=" * 80)
133
+
134
+ # Check if there's a version endpoint
135
+ endpoints = ["/version", "/info", "/health"]
136
+ for endpoint in endpoints:
137
+ try:
138
+ response = requests.get(f"{API_URL}{endpoint}")
139
+ if response.status_code == 200:
140
+ print(f"{endpoint}: {response.text}")
141
+ except:
142
+ pass
143
+
144
+ if __name__ == "__main__":
145
+ print("Debugging vLLM chat template handling\n")
146
+
147
+ # Run all tests
148
+ check_local_template()
149
+ test_completions_api()
150
+ test_chat_raw_request()
151
+ check_vllm_info()
152
+
153
+ print("\n\nCONCLUSIONS:")
154
+ print("-" * 60)
155
+ print("1. If the local tokenizer test shows the empty think block but")
156
+ print(" the completions API test doesn't prevent thinking, then the")
157
+ print(" model itself might need fine-tuning to respect empty blocks.")
158
+ print("2. If none of the chat API parameter variations work, vLLM")
159
+ print(" likely doesn't support passing kwargs to the chat template.")
test_tokenizer_direct.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Direct test of the tokenizer to verify enable_thinking parameter works.
4
+ """
5
+
6
+ from transformers import AutoTokenizer
7
+
8
+ MODEL_PATH = "/home/hotaisle/workspace/models/DeepSeek-R1-0528"
9
+
10
+ print("Testing tokenizer directly with enable_thinking parameter\n")
11
+
12
+ # Load tokenizer
13
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
14
+ messages = [{"role": "user", "content": "What is 2+2?"}]
15
+
16
+ # Test 1: Default (no enable_thinking)
17
+ print("Test 1: Default (no enable_thinking parameter)")
18
+ prompt1 = tokenizer.apply_chat_template(
19
+ messages,
20
+ tokenize=False,
21
+ add_generation_prompt=True
22
+ )
23
+ print(f"Prompt ends with: {repr(prompt1[-100:])}")
24
+ print(f"Contains <think>: {'<think>' in prompt1}")
25
+
26
+ # Test 2: enable_thinking=True
27
+ print("\n\nTest 2: enable_thinking=True")
28
+ prompt2 = tokenizer.apply_chat_template(
29
+ messages,
30
+ tokenize=False,
31
+ add_generation_prompt=True,
32
+ enable_thinking=True
33
+ )
34
+ print(f"Prompt ends with: {repr(prompt2[-100:])}")
35
+ print(f"Contains <think>: {'<think>' in prompt2}")
36
+
37
+ # Test 3: enable_thinking=False
38
+ print("\n\nTest 3: enable_thinking=False")
39
+ prompt3 = tokenizer.apply_chat_template(
40
+ messages,
41
+ tokenize=False,
42
+ add_generation_prompt=True,
43
+ enable_thinking=False
44
+ )
45
+ print(f"Prompt ends with: {repr(prompt3[-130:])}")
46
+ print(f"Contains empty think block: {'<think>\\n\\n</think>\\n\\n' in prompt3}")
47
+
48
+ # Show the difference
49
+ print("\n\nDifference between prompts:")
50
+ print("-" * 60)
51
+ if prompt1 == prompt2:
52
+ print("Default and enable_thinking=True are identical ✓")
53
+ if prompt1 != prompt3:
54
+ print("enable_thinking=False is different ✓")
55
+ # Find where they differ
56
+ for i, (c1, c3) in enumerate(zip(prompt1, prompt3)):
57
+ if c1 != c3:
58
+ print(f"First difference at position {i}:")
59
+ print(f" Default: ...{repr(prompt1[i-20:i+50])}")
60
+ print(f" False: ...{repr(prompt3[i-20:i+50])}")
61
+ break
62
+ else:
63
+ print("ERROR: enable_thinking=False produces same output as default!")
64
+
65
+ # Test the actual template string
66
+ print("\n\nChecking template directly:")
67
+ template = tokenizer.chat_template
68
+ if "enable_thinking" in template:
69
+ print("✓ Template contains 'enable_thinking' logic")
70
+ # Find the exact part
71
+ idx = template.find("enable_thinking")
72
+ print(f"Found at position {idx}")
73
+ print(f"Context: ...{template[idx-50:idx+100]}...")
74
+ else:
75
+ print("✗ Template does NOT contain 'enable_thinking' logic!")
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
The diff for this file is too large to render. See raw diff