yujiepan commited on
Commit
973b784
·
verified ·
1 Parent(s): 9bda73b

Upload folder using huggingface_hub

Browse files
.meta.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "safetensors": "0.8.0",
3
+ "torch": "2.11.0+cu128",
4
+ "transformers": "5.14.0.dev0",
5
+ "vllm": "0.24.0+cu129"
6
+ }
README.md ADDED
@@ -0,0 +1,441 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: transformers
3
+ base_model:
4
+ - deepseek-ai/DeepSeek-V4-Pro
5
+ ---
6
+
7
+ This tiny model is intended for debugging. It is randomly initialized using the configuration adapted from [deepseek-ai/DeepSeek-V4-Pro](https://huggingface.co/deepseek-ai/DeepSeek-V4-Pro).
8
+
9
+ Note:
10
+ - This model follows the quantization scheme of "FP4 + FP8 Mixed": MoE expert parameters use FP4 precision; most other parameters use FP8.
11
+ - Chat template from [this PR](https://huggingface.co/deepseek-ai/DeepSeek-V4-Pro/discussions/146/files).
12
+
13
+ | File path | Size |
14
+ |------|------|
15
+ | model.safetensors | 144.5MB |
16
+
17
+
18
+ ### Example usage:
19
+
20
+ - vLLM
21
+
22
+ ```bash
23
+ # Not fully tested, please raise an issue if you find any problems.
24
+ model_id=tiny-random/deepseek-v4
25
+ vllm serve $model_id \
26
+ --trust-remote-code \
27
+ --kv-cache-dtype fp8 \
28
+ --block-size 256 \
29
+ --tensor-parallel-size 2 \
30
+ --no-enable-flashinfer-autotune \
31
+ --tokenizer-mode deepseek_v4 \
32
+ --tool-call-parser deepseek_v4 \
33
+ --enable-auto-tool-choice \
34
+ --reasoning-parser deepseek_v4 \
35
+ --speculative-config '{"method":"mtp","num_speculative_tokens":2}'
36
+ ```
37
+
38
+ ### Codes to create this repo:
39
+
40
+ <details><summary>Click to expand</summary>
41
+
42
+ ```python
43
+ import json
44
+ import hashlib
45
+ from pathlib import Path
46
+ from typing import Any, Literal, TypedDict
47
+
48
+ import torch
49
+ from huggingface_hub import file_exists, hf_hub_download
50
+ from safetensors.torch import save_file
51
+ from transformers import AutoTokenizer, GenerationConfig
52
+
53
+ source_model_id = "deepseek-ai/DeepSeek-V4-Pro"
54
+ save_folder = "/tmp/tiny-random/deepseek-v4"
55
+ config = {
56
+ "architectures": [
57
+ "DeepseekV4ForCausalLM"
58
+ ],
59
+ "attention_bias": True,
60
+ "attention_dropout": 0.0,
61
+ "bos_token_id": 0,
62
+ "eos_token_id": 1,
63
+ "expert_dtype": "fp4",
64
+ "hc_eps": 1e-06,
65
+ "hc_mult": 4,
66
+ "hc_sinkhorn_iters": 20,
67
+ "head_dim": 128,
68
+ "hidden_act": "silu",
69
+ "hidden_size": 128,
70
+ "index_head_dim": 128,
71
+ "index_n_heads": 4,
72
+ "index_topk": 1024,
73
+ "initializer_range": 0.02,
74
+ "max_position_embeddings": 1048576,
75
+ "model_type": "deepseek_v4",
76
+ "moe_intermediate_size": 128,
77
+ "n_routed_experts": 256,
78
+ "n_shared_experts": 1,
79
+ "norm_topk_prob": True,
80
+ "num_attention_heads": 4,
81
+ "num_experts_per_tok": 6,
82
+ "num_hidden_layers": 7,
83
+ "num_hash_layers": 3,
84
+ "num_key_value_heads": 1,
85
+ "num_nextn_predict_layers": 1,
86
+ "o_groups": 2,
87
+ "o_lora_rank": 128,
88
+ "q_lora_rank": 128,
89
+ "qk_rope_head_dim": 64,
90
+ "quantization_config": {
91
+ "activation_scheme": "dynamic",
92
+ "fmt": "e4m3",
93
+ "quant_method": "fp8",
94
+ "scale_fmt": "ue8m0",
95
+ "weight_block_size": [
96
+ 128,
97
+ 128
98
+ ]
99
+ },
100
+ "rms_norm_eps": 1e-06,
101
+ "rope_scaling": {
102
+ "beta_fast": 32,
103
+ "beta_slow": 1,
104
+ "factor": 16,
105
+ "original_max_position_embeddings": 65536,
106
+ "type": "yarn"
107
+ },
108
+ "rope_theta": 10000,
109
+ "routed_scaling_factor": 2.5,
110
+ "scoring_func": "sqrtsoftplus",
111
+ "sliding_window": 128,
112
+ "swiglu_limit": 10.0,
113
+ "tie_word_embeddings": False,
114
+ "topk_method": "noaux_tc",
115
+ "torch_dtype": "bfloat16",
116
+ "transformers_version": "4.57.1",
117
+ "use_cache": True,
118
+ "vocab_size": 129280,
119
+ "compress_rope_theta": 160000,
120
+ "compress_ratios": [128, 128, 4, 128, 4, 128, 4, 0]
121
+ }
122
+
123
+ def main():
124
+ torch.manual_seed(42)
125
+ Path(save_folder).mkdir(parents=True, exist_ok=True)
126
+ state_dict = generate(config)
127
+ save_file(state_dict, Path(save_folder) / "model.safetensors")
128
+ with open(Path(save_folder) / "model.safetensors", "rb") as f:
129
+ state_dict = f.read()
130
+ print("Hash: ", hashlib.sha256(state_dict).hexdigest())
131
+
132
+ with open(Path(save_folder) / "config.json", "w", encoding="utf-8") as f:
133
+ json.dump(config, f, indent=2, ensure_ascii=False)
134
+
135
+ tokenizer = AutoTokenizer.from_pretrained(
136
+ source_model_id, trust_remote_code=True,
137
+ )
138
+ if file_exists(filename="chat_template.jinja", repo_id=source_model_id, repo_type='model', revision="refs/pr/146"):
139
+ with open(hf_hub_download(
140
+ source_model_id,
141
+ filename="chat_template.jinja",
142
+ repo_type='model',
143
+ revision="refs/pr/146",
144
+ ), 'r', encoding='utf-8') as f:
145
+ tokenizer.chat_template = f.read()
146
+ tokenizer.save_pretrained(save_folder)
147
+
148
+ generation_config = GenerationConfig.from_pretrained(
149
+ source_model_id, trust_remote_code=True,
150
+ )
151
+ generation_config.save_pretrained(save_folder)
152
+
153
+ BF16 = "torch.bfloat16"
154
+ F32 = "torch.float32"
155
+ FP8 = "torch.float8_e4m3fn"
156
+ SCALE = "torch.float8_e8m0fnu"
157
+ I8 = "torch.int8"
158
+ I64 = "torch.int64"
159
+
160
+ class TensorSpec(TypedDict):
161
+ shape: list[int]
162
+ dtype: str
163
+
164
+ Config = dict[str, Any]
165
+ State = dict[str, TensorSpec]
166
+ TensorDict = dict[str, torch.Tensor]
167
+ WeightKind = Literal["bf16", "fp8", "fp4"]
168
+
169
+ def initialize(state: State, config: Config, init_bound: float) -> TensorDict:
170
+ tensors: TensorDict = {}
171
+ scale_dtype = torch.float8_e8m0fnu
172
+ fp4_boundaries = torch.tensor([0.25, 0.75, 1.25, 1.75, 2.5, 3.5, 5.0])
173
+
174
+ def scale_for(
175
+ amax: torch.Tensor, qmax: float, dtype: torch.dtype
176
+ ) -> torch.Tensor:
177
+ scale = amax.float().clamp_min(torch.finfo(torch.float32).tiny) / qmax
178
+ if dtype == scale_dtype:
179
+ scale = torch.pow(2.0, torch.round(torch.log2(scale)))
180
+ return scale.to(dtype)
181
+
182
+ def fp8_tensor(
183
+ shape: list[int], scale_shape: list[int], dtype: torch.dtype
184
+ ) -> tuple[torch.Tensor, torch.Tensor]:
185
+ block_out, block_in = config["quantization_config"]["weight_block_size"]
186
+ assert shape == [scale_shape[0] * block_out, scale_shape[1] * block_in]
187
+ value = torch.empty(shape, dtype=torch.bfloat16).uniform_(
188
+ -init_bound, init_bound
189
+ )
190
+ blocks = value.view(
191
+ scale_shape[0], block_out, scale_shape[1], block_in
192
+ ).transpose(1, 2)
193
+ scales = scale_for(blocks.abs().amax(dim=(-1, -2)), 448, dtype)
194
+ weight = (
195
+ (blocks.float() / scales.float()[..., None, None])
196
+ .clamp(-448, 448)
197
+ .to(torch.float8_e4m3fn)
198
+ .transpose(1, 2)
199
+ .reshape(shape)
200
+ .contiguous()
201
+ )
202
+ return weight, scales
203
+
204
+ def fp4_tensors(
205
+ count: int,
206
+ shape: list[int],
207
+ scale_shape: list[int],
208
+ dtype: torch.dtype,
209
+ ) -> tuple[torch.Tensor, torch.Tensor]:
210
+ out_dim, packed_in_dim = shape
211
+ block_out, block_in = config["quantization_config"]["weight_block_size"]
212
+ assert out_dim % block_out == 0
213
+ assert packed_in_dim * 2 % block_in == 0
214
+ assert packed_in_dim == scale_shape[1] * 16
215
+ value = torch.empty(
216
+ count, out_dim, packed_in_dim * 2, dtype=torch.bfloat16
217
+ ).uniform_(-init_bound, init_bound)
218
+ blocks = value.view(count, out_dim, scale_shape[1], 32)
219
+ scales = scale_for(blocks.abs().amax(dim=-1), 6, dtype)
220
+ normalized = (blocks.float() / scales.float()[..., None]).clamp(-6, 6)
221
+ code = torch.bucketize(normalized.abs(), fp4_boundaries)
222
+ code += normalized.signbit() * 8
223
+ code = code.view(count, out_dim, packed_in_dim * 2)
224
+ packed = (code[..., ::2] | (code[..., 1::2] << 4)).to(torch.uint8)
225
+ weight = packed.view(torch.int8).contiguous()
226
+ return weight, scales
227
+
228
+ dtype_map: dict[str, torch.dtype] = {
229
+ BF16: torch.bfloat16,
230
+ F32: torch.float32,
231
+ FP8: torch.float8_e4m3fn,
232
+ SCALE: scale_dtype,
233
+ I8: torch.int8,
234
+ I64: torch.int64,
235
+ }
236
+ fp4_groups: dict[
237
+ tuple[tuple[int, ...], tuple[int, ...], torch.dtype], list[str]
238
+ ] = {}
239
+ for name, spec in state.items():
240
+ if spec["dtype"] != I8:
241
+ continue
242
+ scale_spec = state[name.replace(".weight", ".scale")]
243
+ key = (
244
+ tuple(spec["shape"]),
245
+ tuple(scale_spec["shape"]),
246
+ dtype_map[scale_spec["dtype"]],
247
+ )
248
+ fp4_groups.setdefault(key, []).append(name)
249
+
250
+ fp4_cache: dict[str, tuple[torch.Tensor, torch.Tensor]] = {}
251
+ max_batch_elements = 4 * 1024 * 1024
252
+ for (shape_tuple, scale_shape_tuple, dtype), names in fp4_groups.items():
253
+ shape = list(shape_tuple)
254
+ scale_shape = list(scale_shape_tuple)
255
+ logical_elements = shape[0] * shape[1] * 2
256
+ batch_size = max(1, max_batch_elements // logical_elements)
257
+ for start in range(0, len(names), batch_size):
258
+ batch_names = names[start: start + batch_size]
259
+ weights, scales = fp4_tensors(
260
+ len(batch_names), shape, scale_shape, dtype
261
+ )
262
+ for index, name in enumerate(batch_names):
263
+ fp4_cache[name] = (
264
+ weights[index].clone(),
265
+ scales[index].clone(),
266
+ )
267
+
268
+ for name, spec in state.items():
269
+ if name in tensors:
270
+ continue
271
+ shape, dtype = spec["shape"], dtype_map[spec["dtype"]]
272
+ scale_name = name.replace(".weight", ".scale")
273
+ if spec["dtype"] == FP8:
274
+ scale_spec = state[scale_name]
275
+ scale_type = dtype_map[scale_spec["dtype"]]
276
+ tensors[name], tensors[scale_name] = fp8_tensor(
277
+ shape, scale_spec["shape"], scale_type
278
+ )
279
+ elif spec["dtype"] == I8:
280
+ tensors[name], tensors[scale_name] = fp4_cache.pop(name)
281
+ elif spec["dtype"] == I64:
282
+ tensors[name] = torch.randint(
283
+ config["n_routed_experts"], shape, dtype=dtype
284
+ )
285
+ elif not name.endswith(".scale"):
286
+ tensors[name] = torch.empty(shape, dtype=dtype).uniform_(
287
+ -init_bound, init_bound
288
+ )
289
+ print(f"{name}: {shape} {dtype}", flush=True)
290
+ file_size_by_name = {name: tensor.numel() * tensor.element_size() for name, tensor in tensors.items()}
291
+ total_file_size = sum(file_size_by_name.values())
292
+ k = 20
293
+ topk = sorted(file_size_by_name.items(), key=lambda x: x[1], reverse=True)[:k]
294
+ print(f"File size: {total_file_size / 1024 / 1024:.2f} MB")
295
+ print(f"Top {k} largest tensors:")
296
+ for name, size in topk:
297
+ print(f" {name}: {size / 1024 / 1024:.2f} MB")
298
+ return tensors
299
+
300
+ def generate(
301
+ config: Config, init_bound: float = 0.2
302
+ ) -> TensorDict:
303
+ assert init_bound > 0
304
+ state: State = {}
305
+ dim = config["hidden_size"]
306
+ inter = config["moe_intermediate_size"]
307
+ heads = config["num_attention_heads"]
308
+ head_dim = config["head_dim"]
309
+ q_rank = config["q_lora_rank"]
310
+ o_rank = config["o_lora_rank"]
311
+ o_groups = config["o_groups"]
312
+ experts = config["n_routed_experts"]
313
+ vocab = config["vocab_size"]
314
+ hc = config["hc_mult"]
315
+ quant = config["quantization_config"]
316
+ block_out, block_in = quant["weight_block_size"]
317
+ weight_kind: WeightKind = (
318
+ "fp8" if quant["quant_method"] == "fp8" else "bf16"
319
+ )
320
+ scale_dtype = SCALE if quant.get("scale_fmt") == "ue8m0" else F32
321
+
322
+ def add(name: str, shape: list[int], dtype: str) -> None:
323
+ state[name] = {"shape": shape, "dtype": dtype}
324
+
325
+ def linear(
326
+ name: str, out_dim: int, in_dim: int, kind: WeightKind = weight_kind
327
+ ) -> None:
328
+ if kind == "fp4":
329
+ assert out_dim % block_out == 0 and in_dim % block_in == 0, (
330
+ f"{name} shape [{out_dim}, {in_dim}] is not divisible by "
331
+ f"block size [{block_out}, {block_in}]"
332
+ )
333
+ add(f"{name}.weight", [out_dim, in_dim // 2], I8)
334
+ add(f"{name}.scale", [out_dim, in_dim // 32], scale_dtype)
335
+ elif kind == "fp8":
336
+ assert out_dim % block_out == 0 and in_dim % block_in == 0, (
337
+ f"{name} shape [{out_dim}, {in_dim}] is not divisible by "
338
+ f"block size [{block_out}, {block_in}]"
339
+ )
340
+ add(f"{name}.weight", [out_dim, in_dim], FP8)
341
+ add(
342
+ f"{name}.scale",
343
+ [out_dim // block_out, in_dim // block_in],
344
+ scale_dtype,
345
+ )
346
+ else:
347
+ add(f"{name}.weight", [out_dim, in_dim], BF16)
348
+
349
+ def compressor(name: str, ratio: int, size: int) -> None:
350
+ out_dim = size * (2 if ratio == 4 else 1)
351
+ add(f"{name}.ape", [ratio, out_dim], F32)
352
+ add(f"{name}.wkv.weight", [out_dim, dim], BF16)
353
+ add(f"{name}.wgate.weight", [out_dim, dim], BF16)
354
+ add(f"{name}.norm.weight", [size], BF16)
355
+
356
+ def attention(name: str, ratio: int) -> None:
357
+ add(f"{name}.attn_sink", [heads], F32)
358
+ linear(f"{name}.wq_a", q_rank, dim)
359
+ add(f"{name}.q_norm.weight", [q_rank], BF16)
360
+ linear(f"{name}.wq_b", heads * head_dim, q_rank)
361
+ linear(f"{name}.wkv", head_dim, dim)
362
+ add(f"{name}.kv_norm.weight", [head_dim], BF16)
363
+ linear(f"{name}.wo_a", o_groups * o_rank, heads * head_dim // o_groups)
364
+ linear(f"{name}.wo_b", dim, o_groups * o_rank)
365
+
366
+ if ratio:
367
+ compressor(f"{name}.compressor", ratio, head_dim)
368
+ if ratio == 4:
369
+ index_heads = config["index_n_heads"]
370
+ index_dim = config["index_head_dim"]
371
+ linear(f"{name}.indexer.wq_b", index_heads * index_dim, q_rank)
372
+ add(f"{name}.indexer.weights_proj.weight", [index_heads, dim], BF16)
373
+ compressor(f"{name}.indexer.compressor", ratio, index_dim)
374
+
375
+ def expert(name: str, kind: WeightKind) -> None:
376
+ linear(f"{name}.w1", inter, dim, kind)
377
+ linear(f"{name}.w2", dim, inter, kind)
378
+ linear(f"{name}.w3", inter, dim, kind)
379
+
380
+ def moe(name: str, layer_id: int) -> None:
381
+ add(f"{name}.gate.weight", [experts, dim], BF16)
382
+ if layer_id < config["num_hash_layers"]:
383
+ add(
384
+ f"{name}.gate.tid2eid",
385
+ [vocab, config["num_experts_per_tok"]],
386
+ I64,
387
+ )
388
+ else:
389
+ add(f"{name}.gate.bias", [experts], F32)
390
+
391
+ routed_kind = "fp4" if config.get("expert_dtype") == "fp4" else weight_kind
392
+ for expert_id in range(experts):
393
+ expert(f"{name}.experts.{expert_id}", routed_kind)
394
+ expert(f"{name}.shared_experts", weight_kind)
395
+
396
+ def block(name: str, layer_id: int) -> None:
397
+ attention(f"{name}.attn", config["compress_ratios"][layer_id])
398
+ moe(f"{name}.ffn", layer_id)
399
+ add(f"{name}.attn_norm.weight", [dim], BF16)
400
+ add(f"{name}.ffn_norm.weight", [dim], BF16)
401
+ for part in ("attn", "ffn"):
402
+ add(f"{name}.hc_{part}_fn", [(2 + hc) * hc, hc * dim], F32)
403
+ add(f"{name}.hc_{part}_base", [(2 + hc) * hc], F32)
404
+ add(f"{name}.hc_{part}_scale", [3], F32)
405
+
406
+ def hc_head(name: str = "") -> None:
407
+ prefix = f"{name}." if name else ""
408
+ add(f"{prefix}hc_head_fn", [hc, hc * dim], F32)
409
+ add(f"{prefix}hc_head_base", [hc], F32)
410
+ add(f"{prefix}hc_head_scale", [1], F32)
411
+
412
+ add("embed.weight", [vocab, dim], BF16)
413
+ for layer_id in range(config["num_hidden_layers"]):
414
+ block(f"layers.{layer_id}", layer_id)
415
+ add("norm.weight", [dim], BF16)
416
+ add("head.weight", [vocab, dim], BF16)
417
+ hc_head()
418
+
419
+ first_mtp_layer = config["num_hidden_layers"]
420
+ for mtp_id in range(config["num_nextn_predict_layers"]):
421
+ name = f"mtp.{mtp_id}"
422
+ block(name, first_mtp_layer + mtp_id)
423
+ linear(f"{name}.e_proj", dim, dim)
424
+ linear(f"{name}.h_proj", dim, dim)
425
+ for norm in ("enorm", "hnorm", "norm"):
426
+ add(f"{name}.{norm}.weight", [dim], BF16)
427
+ hc_head(name)
428
+
429
+ return initialize(state, config, init_bound)
430
+
431
+ main()
432
+ ```
433
+
434
+ </details>
435
+
436
+ ### Test environment:
437
+
438
+ - safetensors: 0.8.0
439
+ - torch: 2.11.0+cu128
440
+ - transformers: 5.14.0.dev0
441
+ - vllm: 0.24.0+cu129
chat_template.jinja ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- macro render_tools_block(eff_tools) -%}
2
+ {%- set tl_ns = namespace(lines=[]) -%}
3
+ {%- for t in eff_tools -%}
4
+ {%- if t.function is defined -%}
5
+ {%- set tl_ns.lines = tl_ns.lines + [t.function | tojson(ensure_ascii=false)] -%}
6
+ {%- else -%}
7
+ {%- set tl_ns.lines = tl_ns.lines + [t | tojson(ensure_ascii=false)] -%}
8
+ {%- endif -%}
9
+ {%- endfor -%}
10
+ {{- "\n\n## Tools\n\nYou have access to a set of tools to help answer the user's question. You can invoke tools by writing a \"<|DSML|tool_calls>\" block like the following:\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"$TOOL_NAME\">\n<|DSML|parameter name=\"$PARAMETER_NAME\" string=\"true|false\">$PARAMETER_VALUE</|DSML|parameter>\n...\n</|DSML|invoke>\n<|DSML|invoke name=\"$TOOL_NAME2\">\n...\n</|DSML|invoke>\n</|DSML|tool_calls>\n\nString parameters should be specified as is and set `string=\"true\"`. For all other types (numbers, booleans, arrays, objects), pass the value in JSON format and set `string=\"false\"`.\n\nIf thinking_mode is enabled (triggered by <think>), you MUST output your complete reasoning inside <think>...</think> BEFORE any tool calls or final response.\n\nOtherwise, output directly after </think> with tool calls or final response.\n\n### Available Tool Schemas\n\n" -}}
11
+ {{- tl_ns.lines | join("\n") -}}
12
+ {{- "\n\nYou MUST strictly follow the above defined tool name and parameter schemas to invoke tool calls.\n" -}}
13
+ {%- endmacro -%}
14
+
15
+ {%- macro render_response_format(rf) -%}
16
+ {{- "\n\n## Response Format:\n\nYou MUST strictly adhere to the following schema to reply:\n" -}}
17
+ {{- rf | tojson(ensure_ascii=false) -}}
18
+ {%- endmacro -%}
19
+
20
+ {%- if thinking_mode is not defined -%}{%- set thinking_mode = "thinking" -%}{%- endif -%}
21
+ {%- if drop_thinking is not defined -%}{%- set drop_thinking = true -%}{%- endif -%}
22
+ {%- if reasoning_effort is not defined -%}{%- set reasoning_effort = none -%}{%- endif -%}
23
+ {%- if tools is not defined -%}{%- set tools = none -%}{%- endif -%}
24
+ {%- if add_generation_prompt is not defined -%}{%- set add_generation_prompt = false -%}{%- endif -%}
25
+
26
+ {%- set tools_ns = namespace(has_any=false) -%}
27
+ {%- if tools -%}{%- set tools_ns.has_any = true -%}{%- endif -%}
28
+ {%- for m in messages -%}
29
+ {%- if m.tools -%}{%- set tools_ns.has_any = true -%}{%- endif -%}
30
+ {%- endfor -%}
31
+ {%- set effective_drop = drop_thinking and (not tools_ns.has_any) -%}
32
+
33
+ {%- set mns = namespace(list=[]) -%}
34
+ {%- for msg in messages -%}
35
+ {%- if msg.role == "tool" -%}
36
+ {%- set tblock = {"type": "tool_result", "tool_use_id": msg.get("tool_call_id", ""), "content": msg.content} -%}
37
+ {%- if mns.list|length > 0 and mns.list[-1].role == "user" and "content_blocks" in mns.list[-1] -%}
38
+ {%- set last = mns.list[-1] -%}
39
+ {%- set mns.list = mns.list[:-1] + [dict(last, content_blocks=last.content_blocks + [tblock])] -%}
40
+ {%- else -%}
41
+ {%- set mns.list = mns.list + [{"role": "user", "content_blocks": [tblock]}] -%}
42
+ {%- endif -%}
43
+ {%- elif msg.role == "user" -%}
44
+ {%- set text_block = {"type": "text", "text": msg.get("content", "")} -%}
45
+ {%- if mns.list|length > 0 and mns.list[-1].role == "user" and "content_blocks" in mns.list[-1] and mns.list[-1].get("task") is none -%}
46
+ {%- set last = mns.list[-1] -%}
47
+ {%- set mns.list = mns.list[:-1] + [dict(last, content_blocks=last.content_blocks + [text_block])] -%}
48
+ {%- else -%}
49
+ {%- set new_msg = {"role": "user", "content": msg.get("content", ""), "content_blocks": [text_block]} -%}
50
+ {%- if msg.get("task") is not none -%}
51
+ {%- set new_msg = dict(new_msg, task=msg.task) -%}
52
+ {%- endif -%}
53
+ {%- if msg.get("wo_eos") is not none -%}
54
+ {%- set new_msg = dict(new_msg, wo_eos=msg.wo_eos) -%}
55
+ {%- endif -%}
56
+ {%- set mns.list = mns.list + [new_msg] -%}
57
+ {%- endif -%}
58
+ {%- else -%}
59
+ {%- set mns.list = mns.list + [msg] -%}
60
+ {%- endif -%}
61
+ {%- endfor -%}
62
+
63
+ {%- if tools -%}
64
+ {%- set anchor_ns = namespace(found=false) -%}
65
+ {%- for m in mns.list -%}
66
+ {%- if m.role == "system" or m.role == "developer" -%}{%- set anchor_ns.found = true -%}{%- endif -%}
67
+ {%- endfor -%}
68
+ {%- if not anchor_ns.found -%}
69
+ {%- set mns.list = [{"role": "system", "content": ""}] + mns.list -%}
70
+ {%- endif -%}
71
+ {%- endif -%}
72
+
73
+ {%- set lu = namespace(idx=-1) -%}
74
+ {%- for m in mns.list -%}
75
+ {%- if m.role == "user" or m.role == "developer" -%}
76
+ {%- set lu.idx = loop.index0 -%}
77
+ {%- endif -%}
78
+ {%- endfor -%}
79
+
80
+ {%- set fns = namespace(list=[], lu_idx=-1) -%}
81
+ {%- if thinking_mode == "thinking" and effective_drop -%}
82
+ {%- for m in mns.list -%}
83
+ {%- if not (m.role == "developer" and loop.index0 < lu.idx) -%}
84
+ {%- if loop.index0 == lu.idx -%}{%- set fns.lu_idx = fns.list|length -%}{%- endif -%}
85
+ {%- set fns.list = fns.list + [m] -%}
86
+ {%- endif -%}
87
+ {%- endfor -%}
88
+ {%- else -%}
89
+ {%- set fns.list = mns.list -%}
90
+ {%- set fns.lu_idx = lu.idx -%}
91
+ {%- endif -%}
92
+
93
+ {%- set att = namespace(idx=-1, sys=-1) -%}
94
+ {%- if tools -%}
95
+ {%- for m in fns.list -%}
96
+ {%- if m.role == "developer" and att.idx == -1 -%}{%- set att.idx = loop.index0 -%}{%- endif -%}
97
+ {%- if m.role == "system" and att.sys == -1 -%}{%- set att.sys = loop.index0 -%}{%- endif -%}
98
+ {%- endfor -%}
99
+ {%- if att.idx == -1 -%}{%- set att.idx = att.sys -%}{%- endif -%}
100
+ {%- endif -%}
101
+
102
+ {{- "<|begin▁of▁sentence|>" -}}
103
+
104
+ {%- if thinking_mode == "thinking" and reasoning_effort == "max" -%}
105
+ {{- "Reasoning Effort: Absolute maximum with no shortcuts permitted.\nYou MUST be very thorough in your thinking and comprehensively decompose the problem to resolve the root cause, rigorously stress-testing your logic against all potential paths, edge cases, and adversarial scenarios.\nExplicitly write out your entire deliberation process, documenting every intermediate step, considered alternative, and rejected hypothesis to ensure absolutely no assumption is left unchecked.\n\n" -}}
106
+ {%- endif -%}
107
+
108
+ {%- for msg in fns.list -%}
109
+ {%- set idx = loop.index0 -%}
110
+ {%- set is_last = (idx == fns.list|length - 1) -%}
111
+ {%- set next_role = (fns.list[idx + 1].role) if (not is_last) else none -%}
112
+ {%- set prev_has_task = (idx > 0) and (fns.list[idx - 1].get("task") is not none) -%}
113
+
114
+ {%- set eff_tools = none -%}
115
+ {%- if msg.tools -%}{%- set eff_tools = msg.tools -%}
116
+ {%- elif idx == att.idx -%}{%- set eff_tools = tools -%}{%- endif -%}
117
+
118
+ {%- if msg.role == "system" or msg.role == "developer" -%}
119
+ {%- if msg.role == "developer" -%}{{- "<|User|>" -}}{%- endif -%}
120
+ {{- (msg.get("content", "") or "") -}}
121
+ {%- if eff_tools -%}{{- render_tools_block(eff_tools) -}}{%- endif -%}
122
+ {%- if msg.response_format is defined and msg.response_format -%}{{- render_response_format(msg.response_format) -}}{%- endif -%}
123
+
124
+ {%- elif msg.role == "user" -%}
125
+ {{- "<|User|>" -}}
126
+ {%- set parts_ns = namespace(parts=[]) -%}
127
+ {%- for b in msg.content_blocks -%}
128
+ {%- if b.type == "text" -%}
129
+ {%- set parts_ns.parts = parts_ns.parts + [b.get("text", "")] -%}
130
+ {%- elif b.type == "tool_result" -%}
131
+ {%- set tc_content = b.get("content", "") -%}
132
+ {%- if tc_content is iterable and tc_content is not string and tc_content is not mapping -%}
133
+ {%- set txt_ns = namespace(texts=[]) -%}
134
+ {%- for sub in tc_content -%}
135
+ {%- if sub.type == "text" -%}
136
+ {%- set txt_ns.texts = txt_ns.texts + [sub.get("text", "")] -%}
137
+ {%- else -%}
138
+ {%- set txt_ns.texts = txt_ns.texts + ["[Unsupported " ~ sub.type ~ "]"] -%}
139
+ {%- endif -%}
140
+ {%- endfor -%}
141
+ {%- set tc_content = txt_ns.texts | join("\n\n") -%}
142
+ {%- endif -%}
143
+ {%- set parts_ns.parts = parts_ns.parts + ["<tool_result>" ~ tc_content ~ "</tool_result>"] -%}
144
+ {%- else -%}
145
+ {%- set parts_ns.parts = parts_ns.parts + ["[Unsupported " ~ b.type ~ "]"] -%}
146
+ {%- endif -%}
147
+ {%- endfor -%}
148
+ {{- parts_ns.parts | join("\n\n") -}}
149
+
150
+ {%- elif msg.role == "latest_reminder" -%}
151
+ {{- "<|latest_reminder|>" -}}{{- msg.content -}}
152
+
153
+ {%- elif msg.role == "assistant" -%}
154
+ {%- set rc = msg.get("reasoning_content", "") or "" -%}
155
+ {%- if (thinking_mode == "thinking") and (not prev_has_task) and ((not effective_drop) or idx > fns.lu_idx) -%}
156
+ {{- rc -}}{{- "</think>" -}}
157
+ {%- endif -%}
158
+ {{- msg.get("content", "") or "" -}}
159
+ {%- if msg.tool_calls -%}
160
+ {{- "\n\n<|DSML|tool_calls>\n" -}}
161
+ {%- set tc_ns = namespace(lines=[]) -%}
162
+ {%- for tc in msg.tool_calls -%}
163
+ {%- if tc.function is defined -%}
164
+ {%- set tc_name = tc.function.name -%}{%- set tc_args = tc.function.arguments -%}
165
+ {%- else -%}
166
+ {%- set tc_name = tc.name -%}{%- set tc_args = tc.arguments -%}
167
+ {%- endif -%}
168
+ {%- set p_ns = namespace(lines=[]) -%}
169
+ {%- if tc_args is mapping -%}
170
+ {%- for key, value in tc_args.items() -%}
171
+ {%- if value is string -%}
172
+ {%- set p_ns.lines = p_ns.lines + ['<|DSML|parameter name="' ~ key ~ '" string="true">' ~ value ~ '</|DSML|parameter>'] -%}
173
+ {%- else -%}
174
+ {%- set p_ns.lines = p_ns.lines + ['<|DSML|parameter name="' ~ key ~ '" string="false">' ~ (value | tojson(ensure_ascii=false)) ~ '</|DSML|parameter>'] -%}
175
+ {%- endif -%}
176
+ {%- endfor -%}
177
+ {%- else -%}
178
+ {%- set p_ns.lines = p_ns.lines + ['<|DSML|parameter name="arguments" string="true">' ~ (tc_args | string) ~ '</|DSML|parameter>'] -%}
179
+ {%- endif -%}
180
+ {%- set tc_ns.lines = tc_ns.lines + ['<|DSML|invoke name="' ~ tc_name ~ '">\n' ~ (p_ns.lines | join("\n")) ~ '\n</|DSML|invoke>'] -%}
181
+ {%- endfor -%}
182
+ {{- tc_ns.lines | join("\n") -}}{{- "\n</|DSML|tool_calls>" -}}
183
+ {%- endif -%}
184
+ {%- if not msg.get("wo_eos") -%}{{- "<|end▁of▁sentence|>" -}}{%- endif -%}
185
+
186
+ {%- else -%}
187
+ {{- raise_exception("Unknown role: " ~ msg.role) -}}
188
+ {%- endif -%}
189
+
190
+ {%- set need_transition = is_last or (next_role == "assistant") or (next_role == "latest_reminder") -%}
191
+ {%- set this_task = msg.get("task", none) -%}
192
+
193
+ {%- if need_transition and this_task is not none -%}
194
+ {%- set task_tokens = {"action": "<|action|>", "query": "<|query|>", "authority": "<|authority|>", "domain": "<|domain|>", "title": "<|title|>", "read_url": "<|read_url|>"} -%}
195
+ {%- if this_task not in task_tokens -%}{{- raise_exception("Invalid task: " ~ this_task) -}}{%- endif -%}
196
+ {%- if this_task == "action" -%}
197
+ {{- "<|Assistant|>" -}}{{- "<think>" if thinking_mode == "thinking" else "</think>" -}}
198
+ {%- endif -%}
199
+ {{- task_tokens[this_task] -}}
200
+ {%- elif need_transition and (msg.role == "user" or msg.role == "developer") and not (is_last and not add_generation_prompt) -%}
201
+ {{- "<|Assistant|>" -}}
202
+ {%- if thinking_mode == "thinking" -%}
203
+ {{- "<think>" if (not effective_drop) or idx >= fns.lu_idx else "</think>" -}}
204
+ {%- else -%}
205
+ {{- "</think>" -}}
206
+ {%- endif -%}
207
+ {%- endif -%}
208
+ {%- endfor -%}
config.json ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "DeepseekV4ForCausalLM"
4
+ ],
5
+ "attention_bias": true,
6
+ "attention_dropout": 0.0,
7
+ "bos_token_id": 0,
8
+ "eos_token_id": 1,
9
+ "expert_dtype": "fp4",
10
+ "hc_eps": 1e-06,
11
+ "hc_mult": 4,
12
+ "hc_sinkhorn_iters": 20,
13
+ "head_dim": 128,
14
+ "hidden_act": "silu",
15
+ "hidden_size": 128,
16
+ "index_head_dim": 128,
17
+ "index_n_heads": 4,
18
+ "index_topk": 1024,
19
+ "initializer_range": 0.02,
20
+ "max_position_embeddings": 1048576,
21
+ "model_type": "deepseek_v4",
22
+ "moe_intermediate_size": 128,
23
+ "n_routed_experts": 256,
24
+ "n_shared_experts": 1,
25
+ "norm_topk_prob": true,
26
+ "num_attention_heads": 4,
27
+ "num_experts_per_tok": 6,
28
+ "num_hidden_layers": 7,
29
+ "num_hash_layers": 3,
30
+ "num_key_value_heads": 1,
31
+ "num_nextn_predict_layers": 1,
32
+ "o_groups": 2,
33
+ "o_lora_rank": 128,
34
+ "q_lora_rank": 128,
35
+ "qk_rope_head_dim": 64,
36
+ "quantization_config": {
37
+ "activation_scheme": "dynamic",
38
+ "fmt": "e4m3",
39
+ "quant_method": "fp8",
40
+ "scale_fmt": "ue8m0",
41
+ "weight_block_size": [
42
+ 128,
43
+ 128
44
+ ]
45
+ },
46
+ "rms_norm_eps": 1e-06,
47
+ "rope_scaling": {
48
+ "beta_fast": 32,
49
+ "beta_slow": 1,
50
+ "factor": 16,
51
+ "original_max_position_embeddings": 65536,
52
+ "type": "yarn"
53
+ },
54
+ "rope_theta": 10000,
55
+ "routed_scaling_factor": 2.5,
56
+ "scoring_func": "sqrtsoftplus",
57
+ "sliding_window": 128,
58
+ "swiglu_limit": 10.0,
59
+ "tie_word_embeddings": false,
60
+ "topk_method": "noaux_tc",
61
+ "torch_dtype": "bfloat16",
62
+ "transformers_version": "4.57.1",
63
+ "use_cache": true,
64
+ "vocab_size": 129280,
65
+ "compress_rope_theta": 160000,
66
+ "compress_ratios": [
67
+ 128,
68
+ 128,
69
+ 4,
70
+ 128,
71
+ 4,
72
+ 128,
73
+ 4,
74
+ 0
75
+ ]
76
+ }
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": 1.0,
7
+ "top_p": 1.0,
8
+ "transformers_version": "5.14.0.dev0"
9
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6bb51a655eeb37fce67ffa08ce55536613c967db1fb591a57d79630280ac7e00
3
+ size 144491198
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "bos_token": "<|begin▁of▁sentence|>",
4
+ "clean_up_tokenization_spaces": false,
5
+ "eos_token": "<|end▁of▁sentence|>",
6
+ "is_local": false,
7
+ "legacy": true,
8
+ "local_files_only": false,
9
+ "model_max_length": 1048576,
10
+ "pad_token": "<|end▁of▁sentence|>",
11
+ "sp_model_kwargs": {},
12
+ "tokenizer_class": "TokenizersBackend",
13
+ "unk_token": null
14
+ }