tiny226 commited on
Commit
fc1e7cb
·
verified ·
1 Parent(s): 626efb4

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +9 -0
  2. README.md +58 -0
  3. qwen3-1.7b-teutonic-2e5/README.md +58 -0
  4. qwen3-1.7b-teutonic-2e5/chat_template.jinja +89 -0
  5. qwen3-1.7b-teutonic-2e5/checkpoint-1000/chat_template.jinja +89 -0
  6. qwen3-1.7b-teutonic-2e5/checkpoint-1000/config.json +63 -0
  7. qwen3-1.7b-teutonic-2e5/checkpoint-1000/generation_config.json +12 -0
  8. qwen3-1.7b-teutonic-2e5/checkpoint-1000/global_step1000/bf16_zero_pp_rank_0_mp_rank_00_optim_states.pt +3 -0
  9. qwen3-1.7b-teutonic-2e5/checkpoint-1000/global_step1000/bf16_zero_pp_rank_1_mp_rank_00_optim_states.pt +3 -0
  10. qwen3-1.7b-teutonic-2e5/checkpoint-1000/global_step1000/mp_rank_00_model_states.pt +3 -0
  11. qwen3-1.7b-teutonic-2e5/checkpoint-1000/latest +1 -0
  12. qwen3-1.7b-teutonic-2e5/checkpoint-1000/model.safetensors +3 -0
  13. qwen3-1.7b-teutonic-2e5/checkpoint-1000/rng_state_0.pth +3 -0
  14. qwen3-1.7b-teutonic-2e5/checkpoint-1000/rng_state_1.pth +3 -0
  15. qwen3-1.7b-teutonic-2e5/checkpoint-1000/scheduler.pt +3 -0
  16. qwen3-1.7b-teutonic-2e5/checkpoint-1000/tokenizer.json +3 -0
  17. qwen3-1.7b-teutonic-2e5/checkpoint-1000/tokenizer_config.json +30 -0
  18. qwen3-1.7b-teutonic-2e5/checkpoint-1000/trainer_state.json +0 -0
  19. qwen3-1.7b-teutonic-2e5/checkpoint-1000/training_args.bin +3 -0
  20. qwen3-1.7b-teutonic-2e5/checkpoint-1000/zero_to_fp32.py +854 -0
  21. qwen3-1.7b-teutonic-2e5/checkpoint-1000/zero_to_torch.py +54 -0
  22. qwen3-1.7b-teutonic-2e5/checkpoint-1485/chat_template.jinja +89 -0
  23. qwen3-1.7b-teutonic-2e5/checkpoint-1485/config.json +63 -0
  24. qwen3-1.7b-teutonic-2e5/checkpoint-1485/generation_config.json +12 -0
  25. qwen3-1.7b-teutonic-2e5/checkpoint-1485/global_step1485/bf16_zero_pp_rank_0_mp_rank_00_optim_states.pt +3 -0
  26. qwen3-1.7b-teutonic-2e5/checkpoint-1485/global_step1485/bf16_zero_pp_rank_1_mp_rank_00_optim_states.pt +3 -0
  27. qwen3-1.7b-teutonic-2e5/checkpoint-1485/global_step1485/mp_rank_00_model_states.pt +3 -0
  28. qwen3-1.7b-teutonic-2e5/checkpoint-1485/latest +1 -0
  29. qwen3-1.7b-teutonic-2e5/checkpoint-1485/model.safetensors +3 -0
  30. qwen3-1.7b-teutonic-2e5/checkpoint-1485/rng_state_0.pth +3 -0
  31. qwen3-1.7b-teutonic-2e5/checkpoint-1485/rng_state_1.pth +3 -0
  32. qwen3-1.7b-teutonic-2e5/checkpoint-1485/scheduler.pt +3 -0
  33. qwen3-1.7b-teutonic-2e5/checkpoint-1485/tokenizer.json +3 -0
  34. qwen3-1.7b-teutonic-2e5/checkpoint-1485/tokenizer_config.json +30 -0
  35. qwen3-1.7b-teutonic-2e5/checkpoint-1485/trainer_state.json +0 -0
  36. qwen3-1.7b-teutonic-2e5/checkpoint-1485/training_args.bin +3 -0
  37. qwen3-1.7b-teutonic-2e5/checkpoint-1485/zero_to_fp32.py +854 -0
  38. qwen3-1.7b-teutonic-2e5/checkpoint-1485/zero_to_torch.py +54 -0
  39. qwen3-1.7b-teutonic-2e5/checkpoint-500/chat_template.jinja +89 -0
  40. qwen3-1.7b-teutonic-2e5/checkpoint-500/config.json +63 -0
  41. qwen3-1.7b-teutonic-2e5/checkpoint-500/generation_config.json +12 -0
  42. qwen3-1.7b-teutonic-2e5/checkpoint-500/global_step500/bf16_zero_pp_rank_0_mp_rank_00_optim_states.pt +3 -0
  43. qwen3-1.7b-teutonic-2e5/checkpoint-500/global_step500/bf16_zero_pp_rank_1_mp_rank_00_optim_states.pt +3 -0
  44. qwen3-1.7b-teutonic-2e5/checkpoint-500/global_step500/mp_rank_00_model_states.pt +3 -0
  45. qwen3-1.7b-teutonic-2e5/checkpoint-500/latest +1 -0
  46. qwen3-1.7b-teutonic-2e5/checkpoint-500/model.safetensors +3 -0
  47. qwen3-1.7b-teutonic-2e5/checkpoint-500/rng_state_0.pth +3 -0
  48. qwen3-1.7b-teutonic-2e5/checkpoint-500/rng_state_1.pth +3 -0
  49. qwen3-1.7b-teutonic-2e5/checkpoint-500/scheduler.pt +3 -0
  50. qwen3-1.7b-teutonic-2e5/checkpoint-500/tokenizer.json +3 -0
.gitattributes CHANGED
@@ -33,3 +33,12 @@ 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
+ qwen3-1.7b-teutonic-2e5/checkpoint-1000/tokenizer.json filter=lfs diff=lfs merge=lfs -text
37
+ qwen3-1.7b-teutonic-2e5/checkpoint-1485/tokenizer.json filter=lfs diff=lfs merge=lfs -text
38
+ qwen3-1.7b-teutonic-2e5/checkpoint-500/tokenizer.json filter=lfs diff=lfs merge=lfs -text
39
+ qwen3-1.7b-teutonic-2e5/tokenizer.json filter=lfs diff=lfs merge=lfs -text
40
+ qwen3-1.7b-teutonic-5e6/checkpoint-1000/tokenizer.json filter=lfs diff=lfs merge=lfs -text
41
+ qwen3-1.7b-teutonic-5e6/checkpoint-1500/tokenizer.json filter=lfs diff=lfs merge=lfs -text
42
+ qwen3-1.7b-teutonic-5e6/checkpoint-2000/tokenizer.json filter=lfs diff=lfs merge=lfs -text
43
+ qwen3-1.7b-teutonic-5e6/checkpoint-2475/tokenizer.json filter=lfs diff=lfs merge=lfs -text
44
+ qwen3-1.7b-teutonic-5e6/checkpoint-500/tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ base_model: Qwen/Qwen3-1.7B
3
+ library_name: transformers
4
+ model_name: checkpoints
5
+ tags:
6
+ - generated_from_trainer
7
+ - trl
8
+ - sft
9
+ licence: license
10
+ ---
11
+
12
+ # Model Card for checkpoints
13
+
14
+ This model is a fine-tuned version of [Qwen/Qwen3-1.7B](https://huggingface.co/Qwen/Qwen3-1.7B).
15
+ It has been trained using [TRL](https://github.com/huggingface/trl).
16
+
17
+ ## Quick start
18
+
19
+ ```python
20
+ from transformers import pipeline
21
+
22
+ question = "If you had a time machine, but could only go to the past or the future once and never return, which would you choose and why?"
23
+ generator = pipeline("text-generation", model="None", device_map="auto")
24
+ output = generator([{"role": "user", "content": question}], max_new_tokens=128, return_full_text=False)[0]
25
+ print(output["generated_text"])
26
+ ```
27
+
28
+ ## Training procedure
29
+
30
+
31
+
32
+
33
+
34
+ This model was trained with SFT.
35
+
36
+ ### Framework versions
37
+
38
+ - TRL: 1.14.0
39
+ - Transformers: 5.17.0
40
+ - Pytorch: 2.14.0
41
+ - Datasets: 5.0.1
42
+ - Tokenizers: 0.23.2
43
+
44
+ ## Citations
45
+
46
+
47
+
48
+ Cite TRL as:
49
+
50
+ ```bibtex
51
+ @software{vonwerra2020trl,
52
+ title = {{TRL: Transformers Reinforcement Learning}},
53
+ author = {von Werra, Leandro and Belkada, Younes and Tunstall, Lewis and Beeching, Edward and Thrush, Tristan and Lambert, Nathan and Huang, Shengyi and Rasul, Kashif and Gallouédec, Quentin},
54
+ license = {Apache-2.0},
55
+ url = {https://github.com/huggingface/trl},
56
+ year = {2020}
57
+ }
58
+ ```
qwen3-1.7b-teutonic-2e5/README.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ base_model: Qwen/Qwen3-1.7B
3
+ library_name: transformers
4
+ model_name: qwen3-1.7b-teutonic
5
+ tags:
6
+ - generated_from_trainer
7
+ - sft
8
+ - trl
9
+ licence: license
10
+ ---
11
+
12
+ # Model Card for qwen3-1.7b-teutonic
13
+
14
+ This model is a fine-tuned version of [Qwen/Qwen3-1.7B](https://huggingface.co/Qwen/Qwen3-1.7B).
15
+ It has been trained using [TRL](https://github.com/huggingface/trl).
16
+
17
+ ## Quick start
18
+
19
+ ```python
20
+ from transformers import pipeline
21
+
22
+ question = "If you had a time machine, but could only go to the past or the future once and never return, which would you choose and why?"
23
+ generator = pipeline("text-generation", model="None", device_map="auto")
24
+ output = generator([{"role": "user", "content": question}], max_new_tokens=128, return_full_text=False)[0]
25
+ print(output["generated_text"])
26
+ ```
27
+
28
+ ## Training procedure
29
+
30
+ [<img src="https://raw.githubusercontent.com/wandb/assets/main/wandb-github-badge-28.svg" alt="Visualize in Weights & Biases" width="150" height="24"/>](https://wandb.ai/digitallibrary849-adobe/tiny-teutonic-sn3/runs/p68ygpe9)
31
+
32
+
33
+
34
+ This model was trained with SFT.
35
+
36
+ ### Framework versions
37
+
38
+ - TRL: 1.14.0
39
+ - Transformers: 5.17.0
40
+ - Pytorch: 2.14.0
41
+ - Datasets: 5.0.1
42
+ - Tokenizers: 0.23.2
43
+
44
+ ## Citations
45
+
46
+
47
+
48
+ Cite TRL as:
49
+
50
+ ```bibtex
51
+ @software{vonwerra2020trl,
52
+ title = {{TRL: Transformers Reinforcement Learning}},
53
+ author = {von Werra, Leandro and Belkada, Younes and Tunstall, Lewis and Beeching, Edward and Thrush, Tristan and Lambert, Nathan and Huang, Shengyi and Rasul, Kashif and Gallouédec, Quentin},
54
+ license = {Apache-2.0},
55
+ url = {https://github.com/huggingface/trl},
56
+ year = {2020}
57
+ }
58
+ ```
qwen3-1.7b-teutonic-2e5/chat_template.jinja ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0].role == 'system' %}
4
+ {{- messages[0].content + '\n\n' }}
5
+ {%- endif %}
6
+ {{- "# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
7
+ {%- for tool in tools %}
8
+ {{- "\n" }}
9
+ {{- tool | tojson }}
10
+ {%- endfor %}
11
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
12
+ {%- else %}
13
+ {%- if messages[0].role == 'system' %}
14
+ {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
15
+ {%- endif %}
16
+ {%- endif %}
17
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
18
+ {%- for message in messages[::-1] %}
19
+ {%- set index = (messages|length - 1) - loop.index0 %}
20
+ {%- if ns.multi_step_tool and message.role == "user" and message.content is string and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}
21
+ {%- set ns.multi_step_tool = false %}
22
+ {%- set ns.last_query_index = index %}
23
+ {%- endif %}
24
+ {%- endfor %}
25
+ {%- for message in messages %}
26
+ {%- if message.content is string %}
27
+ {%- set content = message.content %}
28
+ {%- else %}
29
+ {%- set content = '' %}
30
+ {%- endif %}
31
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
32
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
33
+ {%- elif message.role == "assistant" %}
34
+ {%- set reasoning_content = '' %}
35
+ {%- if message.reasoning_content is string %}
36
+ {%- set reasoning_content = message.reasoning_content %}
37
+ {%- else %}
38
+ {%- if '</think>' in content %}
39
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
40
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
41
+ {%- endif %}
42
+ {%- endif %}
43
+ {%- if loop.index0 > ns.last_query_index %}
44
+ {%- if loop.last or (not loop.last and reasoning_content) %}
45
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
46
+ {%- else %}
47
+ {{- '<|im_start|>' + message.role + '\n' + content }}
48
+ {%- endif %}
49
+ {%- else %}
50
+ {{- '<|im_start|>' + message.role + '\n' + content }}
51
+ {%- endif %}
52
+ {%- if message.tool_calls %}
53
+ {%- for tool_call in message.tool_calls %}
54
+ {%- if (loop.first and content) or (not loop.first) %}
55
+ {{- '\n' }}
56
+ {%- endif %}
57
+ {%- if tool_call.function %}
58
+ {%- set tool_call = tool_call.function %}
59
+ {%- endif %}
60
+ {{- '<tool_call>\n{"name": "' }}
61
+ {{- tool_call.name }}
62
+ {{- '", "arguments": ' }}
63
+ {%- if tool_call.arguments is string %}
64
+ {{- tool_call.arguments }}
65
+ {%- else %}
66
+ {{- tool_call.arguments | tojson }}
67
+ {%- endif %}
68
+ {{- '}\n</tool_call>' }}
69
+ {%- endfor %}
70
+ {%- endif %}
71
+ {{- '<|im_end|>\n' }}
72
+ {%- elif message.role == "tool" %}
73
+ {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
74
+ {{- '<|im_start|>user' }}
75
+ {%- endif %}
76
+ {{- '\n<tool_response>\n' }}
77
+ {{- content }}
78
+ {{- '\n</tool_response>' }}
79
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
80
+ {{- '<|im_end|>\n' }}
81
+ {%- endif %}
82
+ {%- endif %}
83
+ {%- endfor %}
84
+ {%- if add_generation_prompt %}
85
+ {{- '<|im_start|>assistant\n' }}
86
+ {%- if enable_thinking is defined and enable_thinking is false %}
87
+ {{- '<think>\n\n</think>\n\n' }}
88
+ {%- endif %}
89
+ {%- endif %}
qwen3-1.7b-teutonic-2e5/checkpoint-1000/chat_template.jinja ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0].role == 'system' %}
4
+ {{- messages[0].content + '\n\n' }}
5
+ {%- endif %}
6
+ {{- "# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
7
+ {%- for tool in tools %}
8
+ {{- "\n" }}
9
+ {{- tool | tojson }}
10
+ {%- endfor %}
11
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
12
+ {%- else %}
13
+ {%- if messages[0].role == 'system' %}
14
+ {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
15
+ {%- endif %}
16
+ {%- endif %}
17
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
18
+ {%- for message in messages[::-1] %}
19
+ {%- set index = (messages|length - 1) - loop.index0 %}
20
+ {%- if ns.multi_step_tool and message.role == "user" and message.content is string and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}
21
+ {%- set ns.multi_step_tool = false %}
22
+ {%- set ns.last_query_index = index %}
23
+ {%- endif %}
24
+ {%- endfor %}
25
+ {%- for message in messages %}
26
+ {%- if message.content is string %}
27
+ {%- set content = message.content %}
28
+ {%- else %}
29
+ {%- set content = '' %}
30
+ {%- endif %}
31
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
32
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
33
+ {%- elif message.role == "assistant" %}
34
+ {%- set reasoning_content = '' %}
35
+ {%- if message.reasoning_content is string %}
36
+ {%- set reasoning_content = message.reasoning_content %}
37
+ {%- else %}
38
+ {%- if '</think>' in content %}
39
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
40
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
41
+ {%- endif %}
42
+ {%- endif %}
43
+ {%- if loop.index0 > ns.last_query_index %}
44
+ {%- if loop.last or (not loop.last and reasoning_content) %}
45
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
46
+ {%- else %}
47
+ {{- '<|im_start|>' + message.role + '\n' + content }}
48
+ {%- endif %}
49
+ {%- else %}
50
+ {{- '<|im_start|>' + message.role + '\n' + content }}
51
+ {%- endif %}
52
+ {%- if message.tool_calls %}
53
+ {%- for tool_call in message.tool_calls %}
54
+ {%- if (loop.first and content) or (not loop.first) %}
55
+ {{- '\n' }}
56
+ {%- endif %}
57
+ {%- if tool_call.function %}
58
+ {%- set tool_call = tool_call.function %}
59
+ {%- endif %}
60
+ {{- '<tool_call>\n{"name": "' }}
61
+ {{- tool_call.name }}
62
+ {{- '", "arguments": ' }}
63
+ {%- if tool_call.arguments is string %}
64
+ {{- tool_call.arguments }}
65
+ {%- else %}
66
+ {{- tool_call.arguments | tojson }}
67
+ {%- endif %}
68
+ {{- '}\n</tool_call>' }}
69
+ {%- endfor %}
70
+ {%- endif %}
71
+ {{- '<|im_end|>\n' }}
72
+ {%- elif message.role == "tool" %}
73
+ {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
74
+ {{- '<|im_start|>user' }}
75
+ {%- endif %}
76
+ {{- '\n<tool_response>\n' }}
77
+ {{- content }}
78
+ {{- '\n</tool_response>' }}
79
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
80
+ {{- '<|im_end|>\n' }}
81
+ {%- endif %}
82
+ {%- endif %}
83
+ {%- endfor %}
84
+ {%- if add_generation_prompt %}
85
+ {{- '<|im_start|>assistant\n' }}
86
+ {%- if enable_thinking is defined and enable_thinking is false %}
87
+ {{- '<think>\n\n</think>\n\n' }}
88
+ {%- endif %}
89
+ {%- endif %}
qwen3-1.7b-teutonic-2e5/checkpoint-1000/config.json ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Qwen3ForCausalLM"
4
+ ],
5
+ "attention_bias": false,
6
+ "attention_dropout": 0.0,
7
+ "bos_token_id": null,
8
+ "dtype": "bfloat16",
9
+ "eos_token_id": 151645,
10
+ "head_dim": 128,
11
+ "hidden_act": "silu",
12
+ "hidden_size": 2048,
13
+ "initializer_range": 0.02,
14
+ "intermediate_size": 6144,
15
+ "layer_types": [
16
+ "full_attention",
17
+ "full_attention",
18
+ "full_attention",
19
+ "full_attention",
20
+ "full_attention",
21
+ "full_attention",
22
+ "full_attention",
23
+ "full_attention",
24
+ "full_attention",
25
+ "full_attention",
26
+ "full_attention",
27
+ "full_attention",
28
+ "full_attention",
29
+ "full_attention",
30
+ "full_attention",
31
+ "full_attention",
32
+ "full_attention",
33
+ "full_attention",
34
+ "full_attention",
35
+ "full_attention",
36
+ "full_attention",
37
+ "full_attention",
38
+ "full_attention",
39
+ "full_attention",
40
+ "full_attention",
41
+ "full_attention",
42
+ "full_attention",
43
+ "full_attention"
44
+ ],
45
+ "max_position_embeddings": 40960,
46
+ "max_window_layers": 28,
47
+ "model_type": "qwen3",
48
+ "num_attention_heads": 16,
49
+ "num_hidden_layers": 28,
50
+ "num_key_value_heads": 8,
51
+ "pad_token_id": 151643,
52
+ "rms_norm_eps": 1e-06,
53
+ "rope_parameters": {
54
+ "rope_theta": 1000000,
55
+ "rope_type": "default"
56
+ },
57
+ "sliding_window": null,
58
+ "tie_word_embeddings": true,
59
+ "transformers_version": "5.17.0",
60
+ "use_cache": false,
61
+ "use_sliding_window": false,
62
+ "vocab_size": 151936
63
+ }
qwen3-1.7b-teutonic-2e5/checkpoint-1000/generation_config.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "do_sample": true,
3
+ "eos_token_id": [
4
+ 151645,
5
+ 151643
6
+ ],
7
+ "pad_token_id": 151643,
8
+ "temperature": 0.6,
9
+ "top_k": 20,
10
+ "top_p": 0.95,
11
+ "transformers_version": "5.17.0"
12
+ }
qwen3-1.7b-teutonic-2e5/checkpoint-1000/global_step1000/bf16_zero_pp_rank_0_mp_rank_00_optim_states.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:96cfd9e21801ef6218fbab21a5c0f8a89417a68b23f7f172cc103b7b9096465c
3
+ size 10323466465
qwen3-1.7b-teutonic-2e5/checkpoint-1000/global_step1000/bf16_zero_pp_rank_1_mp_rank_00_optim_states.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8631f97305801b329e34c86ed9f95e0df053ebc887476664878777bae4a6655d
3
+ size 10323469601
qwen3-1.7b-teutonic-2e5/checkpoint-1000/global_step1000/mp_rank_00_model_states.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6fdea8231d72131f1af5a5eeb83f486070f5229920fd247e7c86efb5e7c2da49
3
+ size 3441239653
qwen3-1.7b-teutonic-2e5/checkpoint-1000/latest ADDED
@@ -0,0 +1 @@
 
 
1
+ global_step1000
qwen3-1.7b-teutonic-2e5/checkpoint-1000/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7a4034a382d3c7ce1b02a0e0d59a33235e272d8268672220ec4e5778d9d82f57
3
+ size 4063515640
qwen3-1.7b-teutonic-2e5/checkpoint-1000/rng_state_0.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e1557eea53882574b3f18c13a4ba48b553f2cf8514c888f71896ffe922a42d70
3
+ size 14917
qwen3-1.7b-teutonic-2e5/checkpoint-1000/rng_state_1.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ed239779e6c9f5466cc9b1bc2adf2c4f487688a6bf675c36513a13bc18b548da
3
+ size 14917
qwen3-1.7b-teutonic-2e5/checkpoint-1000/scheduler.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:08d162c3c2b666c2182c3e6d9eac8ea5b3fa1bb5f4607fd0a76b169eb562c178
3
+ size 1465
qwen3-1.7b-teutonic-2e5/checkpoint-1000/tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:be75606093db2094d7cd20f3c2f385c212750648bd6ea4fb2bf507a6a4c55506
3
+ size 11422650
qwen3-1.7b-teutonic-2e5/checkpoint-1000/tokenizer_config.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "backend": "tokenizers",
4
+ "bos_token": null,
5
+ "clean_up_tokenization_spaces": false,
6
+ "eos_token": "<|im_end|>",
7
+ "errors": "replace",
8
+ "extra_special_tokens": [
9
+ "<|im_start|>",
10
+ "<|im_end|>",
11
+ "<|object_ref_start|>",
12
+ "<|object_ref_end|>",
13
+ "<|box_start|>",
14
+ "<|box_end|>",
15
+ "<|quad_start|>",
16
+ "<|quad_end|>",
17
+ "<|vision_start|>",
18
+ "<|vision_end|>",
19
+ "<|vision_pad|>",
20
+ "<|image_pad|>",
21
+ "<|video_pad|>"
22
+ ],
23
+ "is_local": false,
24
+ "local_files_only": false,
25
+ "model_max_length": 131072,
26
+ "pad_token": "<|endoftext|>",
27
+ "split_special_tokens": false,
28
+ "tokenizer_class": "Qwen2Tokenizer",
29
+ "unk_token": null
30
+ }
qwen3-1.7b-teutonic-2e5/checkpoint-1000/trainer_state.json ADDED
The diff for this file is too large to render. See raw diff
 
qwen3-1.7b-teutonic-2e5/checkpoint-1000/training_args.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2c573bdac95c796f8f7368ab9af6d35c5687f53373737ea965b8102d518df7cb
3
+ size 7121
qwen3-1.7b-teutonic-2e5/checkpoint-1000/zero_to_fp32.py ADDED
@@ -0,0 +1,854 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ # Copyright (c) Microsoft Corporation.
4
+ # SPDX-License-Identifier: Apache-2.0
5
+
6
+ # DeepSpeed Team
7
+
8
+ # This script extracts fp32 consolidated weights from a zero 1, 2 and 3 DeepSpeed checkpoints. It gets
9
+ # copied into the top level checkpoint dir, so the user can easily do the conversion at any point in
10
+ # the future. Once extracted, the weights don't require DeepSpeed and can be used in any
11
+ # application.
12
+ #
13
+ # example:
14
+ # python zero_to_fp32.py . output_dir/
15
+ # or
16
+ # python zero_to_fp32.py . output_dir/ --safe_serialization
17
+
18
+ import argparse
19
+ import torch
20
+ import glob
21
+ import math
22
+ import os
23
+ import re
24
+ import gc
25
+ import json
26
+ import numpy as np
27
+ from tqdm import tqdm
28
+ from collections import OrderedDict
29
+ from dataclasses import dataclass
30
+
31
+ # while this script doesn't use deepspeed to recover data, since the checkpoints are pickled with
32
+ # DeepSpeed data structures it has to be available in the current python environment.
33
+ from deepspeed.utils import logger
34
+ from deepspeed.checkpoint.constants import (DS_VERSION, OPTIMIZER_STATE_DICT, SINGLE_PARTITION_OF_FP32_GROUPS,
35
+ FP32_FLAT_GROUPS, ZERO_STAGE, PARTITION_COUNT, PARAM_SHAPES, BUFFER_NAMES,
36
+ FROZEN_PARAM_SHAPES, FROZEN_PARAM_FRAGMENTS, AUTOEP_LAYERS_KEY,
37
+ AUTOEP_LAYERS_KEY_LEGACY, AUTOEP_ZERO3_EXPERT_STATE_FORMAT_KEY,
38
+ AUTOEP_ZERO3_PARTITIONED_EXPERT_STATE_FORMAT, PARAM_ALIGNMENT_PADDINGS)
39
+
40
+
41
+ @dataclass
42
+ class zero_model_state:
43
+ buffers: dict()
44
+ param_shapes: dict()
45
+ shared_params: list
46
+ ds_version: int
47
+ frozen_param_shapes: dict()
48
+ frozen_param_fragments: dict()
49
+
50
+
51
+ debug = 0
52
+
53
+ # load to cpu
54
+ device = torch.device('cpu')
55
+
56
+ OUTPUT_DTYPE_NAMES = {
57
+ 'float32': torch.float32,
58
+ 'fp32': torch.float32,
59
+ 'float16': torch.float16,
60
+ 'fp16': torch.float16,
61
+ 'bfloat16': torch.bfloat16,
62
+ 'bf16': torch.bfloat16,
63
+ }
64
+
65
+
66
+ def _resolve_output_dtype(dtype):
67
+ requested_dtype = dtype
68
+ if isinstance(dtype, str):
69
+ dtype_name = dtype[6:] if dtype.startswith('torch.') else dtype
70
+ dtype = OUTPUT_DTYPE_NAMES.get(dtype_name.lower())
71
+ if dtype not in set(OUTPUT_DTYPE_NAMES.values()):
72
+ supported = ', '.join(sorted(OUTPUT_DTYPE_NAMES))
73
+ raise ValueError(f"Unsupported output dtype {requested_dtype!r}. Choose one of: {supported}")
74
+ return dtype
75
+
76
+
77
+ def atoi(text):
78
+ return int(text) if text.isdigit() else text
79
+
80
+
81
+ def natural_keys(text):
82
+ '''
83
+ alist.sort(key=natural_keys) sorts in human order
84
+ http://nedbatchelder.com/blog/200712/human_sorting.html
85
+ (See Toothy's implementation in the comments)
86
+ '''
87
+ return [atoi(c) for c in re.split(r'(\d+)', text)]
88
+
89
+
90
+ def get_model_state_file(checkpoint_dir, zero_stage):
91
+ if not os.path.isdir(checkpoint_dir):
92
+ raise FileNotFoundError(f"Directory '{checkpoint_dir}' doesn't exist")
93
+
94
+ # there should be only one file
95
+ if zero_stage <= 2:
96
+ file = os.path.join(checkpoint_dir, "mp_rank_00_model_states.pt")
97
+ elif zero_stage == 3:
98
+ file = os.path.join(checkpoint_dir, "zero_pp_rank_0_mp_rank_00_model_states.pt")
99
+
100
+ if not os.path.exists(file):
101
+ raise FileNotFoundError(f"can't find model states file at '{file}'")
102
+
103
+ return file
104
+
105
+
106
+ def get_checkpoint_files(checkpoint_dir, glob_pattern):
107
+ # XXX: need to test that this simple glob rule works for multi-node setup too
108
+ ckpt_files = sorted(glob.glob(os.path.join(checkpoint_dir, glob_pattern)), key=natural_keys)
109
+
110
+ if len(ckpt_files) == 0:
111
+ raise FileNotFoundError(f"can't find {glob_pattern} files in directory '{checkpoint_dir}'")
112
+
113
+ return ckpt_files
114
+
115
+
116
+ def get_optim_files(checkpoint_dir):
117
+ return get_checkpoint_files(checkpoint_dir, "*_optim_states.pt")
118
+
119
+
120
+ def get_model_state_files(checkpoint_dir):
121
+ return get_checkpoint_files(checkpoint_dir, "*_model_states.pt")
122
+
123
+
124
+ def _has_autoep_zero3_partitioned_metadata(state_dict):
125
+ autoep_layers = state_dict.get(AUTOEP_LAYERS_KEY)
126
+ if autoep_layers is None:
127
+ autoep_layers = state_dict.get(AUTOEP_LAYERS_KEY_LEGACY)
128
+ if not isinstance(autoep_layers, list):
129
+ return False
130
+ return any(
131
+ isinstance(entry, dict)
132
+ and entry.get(AUTOEP_ZERO3_EXPERT_STATE_FORMAT_KEY) == AUTOEP_ZERO3_PARTITIONED_EXPERT_STATE_FORMAT
133
+ for entry in autoep_layers)
134
+
135
+
136
+ def _raise_if_autoep_zero3_partitioned_state(state_dict):
137
+ if _has_autoep_zero3_partitioned_metadata(state_dict):
138
+ raise NotImplementedError("zero_to_fp32 does not support AutoEP ZeRO-3 partition-native checkpoints. "
139
+ "AutoEP expert parameters are partitioned over expert replica groups, so "
140
+ "global data-parallel consolidation would produce incomplete expert tensors. "
141
+ "Use ds_to_universal.py for expert-aware conversion.")
142
+
143
+
144
+ def _raise_if_autoep_zero3_partitioned_checkpoint(model_files):
145
+ for file in model_files:
146
+ state_dict = torch.load(file, map_location=device, weights_only=False)
147
+ _raise_if_autoep_zero3_partitioned_state(state_dict)
148
+
149
+
150
+ def parse_model_states(files):
151
+ zero_model_states = []
152
+ for file in files:
153
+ state_dict = torch.load(file, map_location=device, weights_only=False)
154
+ _raise_if_autoep_zero3_partitioned_state(state_dict)
155
+
156
+ if BUFFER_NAMES not in state_dict:
157
+ raise ValueError(f"{file} is not a model state checkpoint")
158
+ buffer_names = state_dict[BUFFER_NAMES]
159
+ if debug:
160
+ print("Found buffers:", buffer_names)
161
+
162
+ # recover just the buffers while restoring them to fp32 if they were saved in fp16
163
+ buffers = {k: v.float() for k, v in state_dict["module"].items() if k in buffer_names}
164
+ param_shapes = state_dict[PARAM_SHAPES]
165
+
166
+ # collect parameters that are included in param_shapes
167
+ param_names = []
168
+ for s in param_shapes:
169
+ for name in s.keys():
170
+ param_names.append(name)
171
+
172
+ # update with frozen parameters
173
+ frozen_param_shapes = state_dict.get(FROZEN_PARAM_SHAPES, None)
174
+ if frozen_param_shapes is not None:
175
+ if debug:
176
+ print(f"Found frozen_param_shapes: {frozen_param_shapes}")
177
+ param_names += list(frozen_param_shapes.keys())
178
+
179
+ # handle shared params
180
+ shared_params = [[k, v] for k, v in state_dict["shared_params"].items()]
181
+
182
+ ds_version = state_dict.get(DS_VERSION, None)
183
+
184
+ frozen_param_fragments = state_dict.get(FROZEN_PARAM_FRAGMENTS, None)
185
+
186
+ z_model_state = zero_model_state(buffers=buffers,
187
+ param_shapes=param_shapes,
188
+ shared_params=shared_params,
189
+ ds_version=ds_version,
190
+ frozen_param_shapes=frozen_param_shapes,
191
+ frozen_param_fragments=frozen_param_fragments)
192
+ zero_model_states.append(z_model_state)
193
+
194
+ return zero_model_states
195
+
196
+
197
+ def parse_optim_states(files, ds_checkpoint_dir):
198
+ total_files = len(files)
199
+ state_dicts = []
200
+ for f in tqdm(files, desc='Loading checkpoint shards'):
201
+ state_dict = torch.load(f, map_location=device, mmap=True, weights_only=False)
202
+ # immediately discard the potentially huge 2 optimizer states as we only care for fp32 master weights
203
+ # and also handle the case where it was already removed by another helper script
204
+ state_dict["optimizer_state_dict"].pop("optimizer_state_dict", None)
205
+ state_dicts.append(state_dict)
206
+
207
+ if ZERO_STAGE not in state_dicts[0][OPTIMIZER_STATE_DICT]:
208
+ raise ValueError(f"{files[0]} is not a zero checkpoint")
209
+ zero_stage = state_dicts[0][OPTIMIZER_STATE_DICT][ZERO_STAGE]
210
+ world_size = state_dicts[0][OPTIMIZER_STATE_DICT][PARTITION_COUNT]
211
+
212
+ # For ZeRO-2 each param group can have different partition_count as data parallelism for expert
213
+ # parameters can be different from data parallelism for non-expert parameters. So we can just
214
+ # use the max of the partition_count to get the dp world_size.
215
+
216
+ if type(world_size) is list:
217
+ world_size = max(world_size)
218
+
219
+ if world_size != total_files:
220
+ raise ValueError(
221
+ f"Expected {world_size} of '*_optim_states.pt' under '{ds_checkpoint_dir}' but found {total_files} files. "
222
+ "Possibly due to an overwrite of an old checkpoint, or a checkpoint didn't get saved by one or more processes."
223
+ )
224
+
225
+ # the groups are named differently in each stage
226
+ if zero_stage <= 2:
227
+ fp32_groups_key = SINGLE_PARTITION_OF_FP32_GROUPS
228
+ elif zero_stage == 3:
229
+ fp32_groups_key = FP32_FLAT_GROUPS
230
+ else:
231
+ raise ValueError(f"unknown zero stage {zero_stage}")
232
+
233
+ fp32_flat_groups = [state_dicts[i][OPTIMIZER_STATE_DICT][fp32_groups_key] for i in range(len(state_dicts))]
234
+ param_alignment_paddings = state_dicts[0][OPTIMIZER_STATE_DICT].get(PARAM_ALIGNMENT_PADDINGS)
235
+ return zero_stage, world_size, fp32_flat_groups, param_alignment_paddings
236
+
237
+
238
+ def _get_fp32_state_dict_from_zero_checkpoint(ds_checkpoint_dir, exclude_frozen_parameters):
239
+ """
240
+ Returns fp32 state_dict reconstructed from ds checkpoint
241
+
242
+ Args:
243
+ - ``ds_checkpoint_dir``: path to the deepspeed checkpoint folder (where the optimizer files are)
244
+
245
+ """
246
+ print(f"Processing zero checkpoint '{ds_checkpoint_dir}'")
247
+
248
+ # parse_model_states rejects AutoEP ZeRO-3 partition-native checkpoints
249
+ # before the expensive optimizer-shard load below.
250
+ model_files = get_model_state_files(ds_checkpoint_dir)
251
+ zero_model_states = parse_model_states(model_files)
252
+ print(f'Parsing checkpoint created by deepspeed=={zero_model_states[0].ds_version}')
253
+
254
+ optim_files = get_optim_files(ds_checkpoint_dir)
255
+ zero_stage, world_size, fp32_flat_groups, param_alignment_paddings = parse_optim_states(
256
+ optim_files, ds_checkpoint_dir)
257
+ print(f"Detected checkpoint of type zero stage {zero_stage}, world_size: {world_size}")
258
+
259
+ if zero_stage <= 2:
260
+ return _get_fp32_state_dict_from_zero2_checkpoint(world_size, fp32_flat_groups, zero_model_states,
261
+ exclude_frozen_parameters, param_alignment_paddings)
262
+ elif zero_stage == 3:
263
+ return _get_fp32_state_dict_from_zero3_checkpoint(world_size, fp32_flat_groups, zero_model_states,
264
+ exclude_frozen_parameters)
265
+
266
+
267
+ def _zero2_merge_frozen_params(state_dict, zero_model_states):
268
+ if zero_model_states[0].frozen_param_shapes is None or len(zero_model_states[0].frozen_param_shapes) == 0:
269
+ return
270
+
271
+ frozen_param_shapes = zero_model_states[0].frozen_param_shapes
272
+ frozen_param_fragments = zero_model_states[0].frozen_param_fragments
273
+
274
+ if debug:
275
+ num_elem = sum(s.numel() for s in frozen_param_shapes.values())
276
+ print(f'rank 0: {FROZEN_PARAM_SHAPES}.numel = {num_elem}')
277
+
278
+ wanted_params = len(frozen_param_shapes)
279
+ wanted_numel = sum(s.numel() for s in frozen_param_shapes.values())
280
+ avail_numel = sum([p.numel() for p in frozen_param_fragments.values()])
281
+ print(f'Frozen params: Have {avail_numel} numels to process.')
282
+ print(f'Frozen params: Need {wanted_numel} numels in {wanted_params} params')
283
+
284
+ total_params = 0
285
+ total_numel = 0
286
+ for name, shape in frozen_param_shapes.items():
287
+ total_params += 1
288
+ unpartitioned_numel = shape.numel()
289
+ total_numel += unpartitioned_numel
290
+
291
+ state_dict[name] = frozen_param_fragments[name]
292
+
293
+ if debug:
294
+ print(f"{name} full shape: {shape} unpartitioned numel {unpartitioned_numel} ")
295
+
296
+ print(f"Reconstructed Frozen fp32 state dict with {total_params} params {total_numel} elements")
297
+
298
+
299
+ def _has_callable(obj, fn):
300
+ attr = getattr(obj, fn, None)
301
+ return callable(attr)
302
+
303
+
304
+ def _zero2_merge_trainable_params(state_dict,
305
+ world_size,
306
+ fp32_flat_groups,
307
+ zero_model_states,
308
+ param_alignment_paddings=None):
309
+ param_shapes = zero_model_states[0].param_shapes
310
+
311
+ # Reconstruction protocol:
312
+ #
313
+ # XXX: document this
314
+
315
+ if debug:
316
+ for i in range(world_size):
317
+ for j in range(len(fp32_flat_groups[0])):
318
+ print(f"{FP32_FLAT_GROUPS}[{i}][{j}].shape={fp32_flat_groups[i][j].shape}")
319
+
320
+ # XXX: memory usage doubles here (zero2)
321
+ num_param_groups = len(fp32_flat_groups[0])
322
+ merged_single_partition_of_fp32_groups = []
323
+ for i in range(num_param_groups):
324
+ merged_partitions = [sd[i] for sd in fp32_flat_groups]
325
+ full_single_fp32_vector = torch.cat(merged_partitions, 0)
326
+ merged_single_partition_of_fp32_groups.append(full_single_fp32_vector)
327
+ avail_numel = sum(
328
+ [full_single_fp32_vector.numel() for full_single_fp32_vector in merged_single_partition_of_fp32_groups])
329
+
330
+ if debug:
331
+ wanted_params = sum([len(shapes) for shapes in param_shapes])
332
+ wanted_numel = sum([sum(shape.numel() for shape in shapes.values()) for shapes in param_shapes])
333
+ # not asserting if there is a mismatch due to possible padding
334
+ print(f"Have {avail_numel} numels to process.")
335
+ print(f"Need {wanted_numel} numels in {wanted_params} params.")
336
+
337
+ # params
338
+ # XXX: for huge models that can't fit into the host's RAM we will have to recode this to support
339
+ # out-of-core computing solution
340
+ total_numel = 0
341
+ total_params = 0
342
+ for group_idx, (shapes,
343
+ full_single_fp32_vector) in enumerate(zip(param_shapes, merged_single_partition_of_fp32_groups)):
344
+ offset = 0
345
+ avail_numel = full_single_fp32_vector.numel()
346
+ group_alignment_paddings = None
347
+ if param_alignment_paddings is not None:
348
+ group_alignment_paddings = param_alignment_paddings[group_idx]
349
+ if len(group_alignment_paddings) != len(shapes):
350
+ raise ValueError(f"Expected {len(shapes)} parameter alignment paddings for group {group_idx}, "
351
+ f"but found {len(group_alignment_paddings)}")
352
+
353
+ for param_idx, (name, shape) in enumerate(shapes.items()):
354
+
355
+ unpartitioned_numel = shape.numel() if _has_callable(shape, 'numel') else math.prod(shape)
356
+ total_numel += unpartitioned_numel
357
+ total_params += 1
358
+
359
+ if debug:
360
+ print(f"{name} full shape: {shape} unpartitioned numel {unpartitioned_numel} ")
361
+ state_dict[name] = full_single_fp32_vector.narrow(0, offset, unpartitioned_numel).view(shape)
362
+ offset += unpartitioned_numel
363
+ if group_alignment_paddings is not None:
364
+ offset += group_alignment_paddings[param_idx]
365
+
366
+ # Z2 started to align to 2*world_size to improve nccl performance. Therefore both offset and
367
+ # avail_numel can differ by anywhere between 0..2*world_size. Due to two unrelated complex
368
+ # paddings performed in the code it's almost impossible to predict the exact numbers w/o the
369
+ # live optimizer object, so we are checking that the numbers are within the right range
370
+ align_to = 2 * world_size
371
+
372
+ def zero2_align(x):
373
+ return align_to * math.ceil(x / align_to)
374
+
375
+ if debug:
376
+ print(f"original offset={offset}, avail_numel={avail_numel}")
377
+
378
+ offset = zero2_align(offset)
379
+ avail_numel = zero2_align(avail_numel)
380
+
381
+ if debug:
382
+ print(f"aligned offset={offset}, avail_numel={avail_numel}")
383
+
384
+ # Sanity check
385
+ if offset != avail_numel:
386
+ raise ValueError(f"consumed {offset} numels out of {avail_numel} - something is wrong")
387
+
388
+ print(f"Reconstructed fp32 state dict with {total_params} params {total_numel} elements")
389
+
390
+
391
+ def _get_fp32_state_dict_from_zero2_checkpoint(world_size,
392
+ fp32_flat_groups,
393
+ zero_model_states,
394
+ exclude_frozen_parameters,
395
+ param_alignment_paddings=None):
396
+ state_dict = OrderedDict()
397
+
398
+ # buffers
399
+ buffers = zero_model_states[0].buffers
400
+ state_dict.update(buffers)
401
+ if debug:
402
+ print(f"added {len(buffers)} buffers")
403
+
404
+ if not exclude_frozen_parameters:
405
+ _zero2_merge_frozen_params(state_dict, zero_model_states)
406
+
407
+ _zero2_merge_trainable_params(state_dict, world_size, fp32_flat_groups, zero_model_states,
408
+ param_alignment_paddings)
409
+
410
+ # recover shared parameters
411
+ for pair in zero_model_states[0].shared_params:
412
+ if pair[1] in state_dict:
413
+ state_dict[pair[0]] = state_dict[pair[1]]
414
+
415
+ return state_dict
416
+
417
+
418
+ def zero3_partitioned_param_info(unpartitioned_numel, world_size):
419
+ remainder = unpartitioned_numel % world_size
420
+ padding_numel = (world_size - remainder) if remainder else 0
421
+ partitioned_numel = math.ceil(unpartitioned_numel / world_size)
422
+ return partitioned_numel, padding_numel
423
+
424
+
425
+ def _zero3_merge_frozen_params(state_dict, world_size, zero_model_states):
426
+ if zero_model_states[0].frozen_param_shapes is None or len(zero_model_states[0].frozen_param_shapes) == 0:
427
+ return
428
+
429
+ if debug:
430
+ for i in range(world_size):
431
+ num_elem = sum(s.numel() for s in zero_model_states[i].frozen_param_fragments.values())
432
+ print(f'rank {i}: {FROZEN_PARAM_SHAPES}.numel = {num_elem}')
433
+
434
+ frozen_param_shapes = zero_model_states[0].frozen_param_shapes
435
+ wanted_params = len(frozen_param_shapes)
436
+ wanted_numel = sum(s.numel() for s in frozen_param_shapes.values())
437
+ avail_numel = sum([p.numel() for p in zero_model_states[0].frozen_param_fragments.values()]) * world_size
438
+ print(f'Frozen params: Have {avail_numel} numels to process.')
439
+ print(f'Frozen params: Need {wanted_numel} numels in {wanted_params} params')
440
+
441
+ total_params = 0
442
+ total_numel = 0
443
+ for name, shape in zero_model_states[0].frozen_param_shapes.items():
444
+ total_params += 1
445
+ unpartitioned_numel = shape.numel()
446
+ total_numel += unpartitioned_numel
447
+
448
+ param_frags = tuple(model_state.frozen_param_fragments[name] for model_state in zero_model_states)
449
+ state_dict[name] = torch.cat(param_frags, 0).narrow(0, 0, unpartitioned_numel).view(shape)
450
+
451
+ partitioned_numel, partitioned_padding_numel = zero3_partitioned_param_info(unpartitioned_numel, world_size)
452
+
453
+ if debug:
454
+ print(
455
+ f"Frozen params: {total_params} {name} full shape: {shape} partition0 numel={partitioned_numel} partitioned_padding_numel={partitioned_padding_numel}"
456
+ )
457
+
458
+ print(f"Reconstructed Frozen fp32 state dict with {total_params} params {total_numel} elements")
459
+
460
+
461
+ class GatheredTensor:
462
+ """
463
+ A pseudo tensor that collects partitioned weights.
464
+ It is more memory efficient when there are multiple groups.
465
+ """
466
+
467
+ def __init__(self, flat_groups, flat_groups_offset, offset, partitioned_numel, shape):
468
+ self.flat_groups = flat_groups
469
+ self.flat_groups_offset = flat_groups_offset
470
+ self.offset = offset
471
+ self.partitioned_numel = partitioned_numel
472
+ self.shape = shape
473
+ self.dtype = self.flat_groups[0][0].dtype
474
+
475
+ def contiguous(self):
476
+ """
477
+ Merge partitioned weights from flat_groups into a single tensor.
478
+ """
479
+ end_idx = self.offset + self.partitioned_numel
480
+ world_size = len(self.flat_groups)
481
+ pad_flat_param_chunks = []
482
+
483
+ for rank_i in range(world_size):
484
+ # for each rank, we need to collect weights from related group/groups
485
+ flat_groups_at_rank_i = self.flat_groups[rank_i]
486
+ start_group_id = None
487
+ end_group_id = None
488
+ for group_id in range(len(self.flat_groups_offset)):
489
+ if self.flat_groups_offset[group_id] <= self.offset < self.flat_groups_offset[group_id + 1]:
490
+ start_group_id = group_id
491
+ if self.flat_groups_offset[group_id] < end_idx <= self.flat_groups_offset[group_id + 1]:
492
+ end_group_id = group_id
493
+ break
494
+ # collect weights from related group/groups
495
+ for group_id in range(start_group_id, end_group_id + 1):
496
+ flat_tensor = flat_groups_at_rank_i[group_id]
497
+ start_offset = self.offset - self.flat_groups_offset[group_id]
498
+ end_offset = min(end_idx, self.flat_groups_offset[group_id + 1]) - self.flat_groups_offset[group_id]
499
+ pad_flat_param_chunks.append(flat_tensor[start_offset:end_offset])
500
+
501
+ # collect weights from all ranks
502
+ pad_flat_param = torch.cat(pad_flat_param_chunks, dim=0)
503
+ param = pad_flat_param[:self.shape.numel()].view(self.shape).contiguous()
504
+ return param
505
+
506
+
507
+ def _zero3_merge_trainable_params(state_dict, world_size, fp32_flat_groups, zero_model_states):
508
+ param_shapes = zero_model_states[0].param_shapes
509
+ avail_numel = sum([flat_group.numel() for flat_group in fp32_flat_groups[0]]) * world_size
510
+
511
+ # Reconstruction protocol: For zero3 we need to zip the partitions together at boundary of each
512
+ # param, re-consolidating each param, while dealing with padding if any
513
+
514
+ # merge list of dicts, preserving order
515
+ param_shapes = {k: v for d in param_shapes for k, v in d.items()}
516
+
517
+ if debug:
518
+ for i in range(world_size):
519
+ print(f"{FP32_FLAT_GROUPS}[{i}].shape={fp32_flat_groups[i].shape}")
520
+
521
+ wanted_params = len(param_shapes)
522
+ wanted_numel = sum(shape.numel() for shape in param_shapes.values())
523
+ # not asserting if there is a mismatch due to possible padding
524
+ avail_numel = fp32_flat_groups[0].numel() * world_size
525
+ print(f"Trainable params: Have {avail_numel} numels to process.")
526
+ print(f"Trainable params: Need {wanted_numel} numels in {wanted_params} params.")
527
+
528
+ # params
529
+ # XXX: for huge models that can't fit into the host's RAM we will have to recode this to support
530
+ # out-of-core computing solution
531
+ offset = 0
532
+ total_numel = 0
533
+ total_params = 0
534
+ flat_groups_offset = [0] + list(np.cumsum([flat_tensor.numel() for flat_tensor in fp32_flat_groups[0]]))
535
+ for name, shape in tqdm(param_shapes.items(), desc='Gathering sharded weights'):
536
+ unpartitioned_numel = shape.numel()
537
+ total_numel += unpartitioned_numel
538
+ total_params += 1
539
+ partitioned_numel, partitioned_padding_numel = zero3_partitioned_param_info(unpartitioned_numel, world_size)
540
+
541
+ if debug:
542
+ print(
543
+ f"Trainable params: {total_params} {name} full shape: {shape} partition0 numel={partitioned_numel} partitioned_padding_numel={partitioned_padding_numel}"
544
+ )
545
+
546
+ # memory efficient tensor
547
+ tensor = GatheredTensor(fp32_flat_groups, flat_groups_offset, offset, partitioned_numel, shape)
548
+ state_dict[name] = tensor
549
+ offset += partitioned_numel
550
+
551
+ offset *= world_size
552
+
553
+ # Sanity check
554
+ if offset != avail_numel:
555
+ raise ValueError(f"consumed {offset} numels out of {avail_numel} - something is wrong")
556
+
557
+ print(f"Reconstructed Trainable fp32 state dict with {total_params} params {total_numel} elements")
558
+
559
+
560
+ def _get_fp32_state_dict_from_zero3_checkpoint(world_size, fp32_flat_groups, zero_model_states,
561
+ exclude_frozen_parameters):
562
+ state_dict = OrderedDict()
563
+
564
+ # buffers
565
+ buffers = zero_model_states[0].buffers
566
+ state_dict.update(buffers)
567
+ if debug:
568
+ print(f"added {len(buffers)} buffers")
569
+
570
+ if not exclude_frozen_parameters:
571
+ _zero3_merge_frozen_params(state_dict, world_size, zero_model_states)
572
+
573
+ _zero3_merge_trainable_params(state_dict, world_size, fp32_flat_groups, zero_model_states)
574
+
575
+ # recover shared parameters
576
+ for pair in zero_model_states[0].shared_params:
577
+ if pair[1] in state_dict:
578
+ state_dict[pair[0]] = state_dict[pair[1]]
579
+
580
+ return state_dict
581
+
582
+
583
+ def to_torch_tensor(state_dict, return_empty_tensor=False, dtype=None):
584
+ """
585
+ Convert state_dict of GatheredTensor to torch tensor
586
+ """
587
+ if dtype is not None:
588
+ dtype = _resolve_output_dtype(dtype)
589
+
590
+ torch_state_dict = {}
591
+ converted_tensors = {}
592
+ for name, tensor in state_dict.items():
593
+ tensor_id = id(tensor)
594
+ if tensor_id in converted_tensors: # shared tensors
595
+ shared_tensor = torch_state_dict[converted_tensors[tensor_id]]
596
+ torch_state_dict[name] = shared_tensor
597
+ else:
598
+ converted_tensors[tensor_id] = name
599
+ if return_empty_tensor:
600
+ torch_state_dict[name] = torch.empty(tensor.shape, dtype=dtype or tensor.dtype)
601
+ else:
602
+ contiguous_tensor = tensor.contiguous()
603
+ torch_state_dict[name] = contiguous_tensor.to(dtype=dtype) if dtype else contiguous_tensor
604
+ return torch_state_dict
605
+
606
+
607
+ def get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir,
608
+ tag=None,
609
+ exclude_frozen_parameters=False,
610
+ lazy_mode=False):
611
+ """
612
+ Convert ZeRO 2 or 3 checkpoint into a single fp32 consolidated state_dict that can be loaded with
613
+ ``load_state_dict()`` and used for training without DeepSpeed or shared with others, for example
614
+ via a model hub.
615
+
616
+ Args:
617
+ - ``checkpoint_dir``: path to the desired checkpoint folder
618
+ - ``tag``: checkpoint tag used as a unique identifier for checkpoint. If not provided will attempt to load tag in 'latest' file. e.g., ``global_step14``
619
+ - ``exclude_frozen_parameters``: exclude frozen parameters
620
+ - ``lazy_mode``: get state_dict in lazy mode. It returns a dict of pesduo tensor instead of torch tensor, which is more memory efficient.
621
+ Convert the pesduo tensor to torch tensor by ``.contiguous()``
622
+
623
+ Returns:
624
+ - pytorch ``state_dict``
625
+
626
+ A typical usage might be ::
627
+
628
+ from deepspeed.utils.zero_to_fp32 import get_fp32_state_dict_from_zero_checkpoint
629
+ # do the training and checkpoint saving
630
+ state_dict = get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir) # already on cpu
631
+ model = model.cpu() # move to cpu
632
+ model.load_state_dict(state_dict)
633
+ # submit to model hub or save the model to share with others
634
+
635
+ In this example the ``model`` will no longer be usable in the deepspeed context of the same
636
+ application. i.e. you will need to re-initialize the deepspeed engine, since
637
+ ``model.load_state_dict(state_dict)`` will remove all the deepspeed magic from it.
638
+
639
+ If you want it all done for you, use ``load_state_dict_from_zero_checkpoint`` instead.
640
+
641
+ Note: the above usage may not work if your application doesn't have sufficient free CPU memory.
642
+ You may need to use the offline approach using the ``zero_to_fp32.py`` script that is saved with
643
+ the checkpoint. Or you can load state_dict in lazy mode ::
644
+
645
+ from deepspeed.utils.zero_to_fp32 import get_fp32_state_dict_from_zero_checkpoint
646
+ state_dict = get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir, lazy_mode=True) # not on cpu
647
+ for name, lazy_tensor in state_dict.item():
648
+ tensor = lazy_tensor.contiguous() # to cpu
649
+ print(name, tensor)
650
+ # del tensor to release memory if it no longer in use
651
+ """
652
+ if tag is None:
653
+ latest_path = os.path.join(checkpoint_dir, 'latest')
654
+ if os.path.isfile(latest_path):
655
+ with open(latest_path, 'r') as fd:
656
+ tag = fd.read().strip()
657
+ else:
658
+ raise ValueError(f"Unable to find 'latest' file at {latest_path}")
659
+
660
+ ds_checkpoint_dir = os.path.join(checkpoint_dir, tag)
661
+
662
+ if not os.path.isdir(ds_checkpoint_dir):
663
+ raise FileNotFoundError(f"Directory '{ds_checkpoint_dir}' doesn't exist")
664
+
665
+ state_dict = _get_fp32_state_dict_from_zero_checkpoint(ds_checkpoint_dir, exclude_frozen_parameters)
666
+ if lazy_mode:
667
+ return state_dict
668
+ else:
669
+ return to_torch_tensor(state_dict)
670
+
671
+
672
+ def convert_zero_checkpoint_to_state_dict(checkpoint_dir,
673
+ output_dir,
674
+ dtype=torch.float32,
675
+ max_shard_size="5GB",
676
+ safe_serialization=False,
677
+ tag=None,
678
+ exclude_frozen_parameters=False):
679
+ """
680
+ Convert ZeRO 2 or 3 checkpoint into a consolidated ``state_dict`` file that can be
681
+ loaded with ``torch.load(file)`` + ``load_state_dict()`` and used for training without DeepSpeed.
682
+
683
+ Args:
684
+ - ``checkpoint_dir``: path to the desired checkpoint folder. (one that contains the tag-folder, like ``global_step14``)
685
+ - ``output_dir``: directory for the PyTorch state_dict output files
686
+ - ``dtype``: output tensor dtype. Supports float32, float16, and bfloat16 as strings or torch dtypes.
687
+ - ``max_shard_size``: the maximum size for a checkpoint before being sharded, default value is 5GB
688
+ - ``safe_serialization``: whether to save the model using `safetensors` or the traditional PyTorch way (that uses `pickle`).
689
+ - ``tag``: checkpoint tag used as a unique identifier for checkpoint. If not provided will attempt to load tag in the file named ``latest`` in the checkpoint folder, e.g., ``global_step14``
690
+ - ``exclude_frozen_parameters``: exclude frozen parameters
691
+ """
692
+
693
+ dtype = _resolve_output_dtype(dtype)
694
+
695
+ # Dependency pre-check
696
+ if safe_serialization:
697
+ try:
698
+ from safetensors.torch import save_file
699
+ except ImportError:
700
+ print('If you want to use `safe_serialization`, please `pip install safetensors`')
701
+ raise
702
+ if max_shard_size is not None:
703
+ try:
704
+ from huggingface_hub import split_torch_state_dict_into_shards
705
+ except ImportError:
706
+ print('If you want to use `max_shard_size`, please `pip install huggingface_hub`')
707
+ raise
708
+
709
+ # Convert zero checkpoint to state_dict
710
+ state_dict = get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir,
711
+ tag,
712
+ exclude_frozen_parameters,
713
+ lazy_mode=True)
714
+
715
+ # Shard the model if it is too big.
716
+ weights_name = "model.safetensors" if safe_serialization else "pytorch_model.bin"
717
+ if max_shard_size is not None:
718
+ filename_pattern = weights_name.replace(".bin", "{suffix}.bin").replace(".safetensors", "{suffix}.safetensors")
719
+ # an memory-efficient approach for sharding
720
+ empty_state_dict = to_torch_tensor(state_dict, return_empty_tensor=True, dtype=dtype)
721
+ state_dict_split = split_torch_state_dict_into_shards(empty_state_dict,
722
+ filename_pattern=filename_pattern,
723
+ max_shard_size=max_shard_size)
724
+ else:
725
+ from collections import namedtuple
726
+ StateDictSplit = namedtuple("StateDictSplit", ["is_sharded", "filename_to_tensors"])
727
+ state_dict_split = StateDictSplit(is_sharded=False,
728
+ filename_to_tensors={weights_name: list(state_dict.keys())})
729
+
730
+ # Save the model by shard
731
+ os.makedirs(output_dir, exist_ok=True)
732
+ filename_to_tensors = state_dict_split.filename_to_tensors.items()
733
+ for shard_file, tensors in tqdm(filename_to_tensors, desc="Saving checkpoint shards"):
734
+ shard_state_dict = {tensor_name: state_dict[tensor_name] for tensor_name in tensors}
735
+ shard_state_dict = to_torch_tensor(shard_state_dict, dtype=dtype)
736
+ output_path = os.path.join(output_dir, shard_file)
737
+ if safe_serialization:
738
+ save_file(shard_state_dict, output_path, metadata={"format": "pt"})
739
+ else:
740
+ torch.save(shard_state_dict, output_path)
741
+ # release the memory of current shard
742
+ for tensor_name in list(shard_state_dict.keys()):
743
+ del state_dict[tensor_name]
744
+ del shard_state_dict[tensor_name]
745
+ del shard_state_dict
746
+ gc.collect()
747
+
748
+ # Save index if sharded
749
+ if state_dict_split.is_sharded:
750
+ index = {
751
+ "metadata": state_dict_split.metadata,
752
+ "weight_map": state_dict_split.tensor_to_filename,
753
+ }
754
+ save_index_file = "model.safetensors.index.json" if safe_serialization else "pytorch_model.bin.index.json"
755
+ save_index_file = os.path.join(output_dir, save_index_file)
756
+ with open(save_index_file, "w", encoding="utf-8") as f:
757
+ content = json.dumps(index, indent=2, sort_keys=True) + "\n"
758
+ f.write(content)
759
+
760
+
761
+ def convert_zero_checkpoint_to_fp32_state_dict(checkpoint_dir,
762
+ output_dir,
763
+ max_shard_size="5GB",
764
+ safe_serialization=False,
765
+ tag=None,
766
+ exclude_frozen_parameters=False):
767
+ """Backward-compatible fp32 checkpoint conversion."""
768
+ return convert_zero_checkpoint_to_state_dict(checkpoint_dir,
769
+ output_dir,
770
+ dtype=torch.float32,
771
+ max_shard_size=max_shard_size,
772
+ safe_serialization=safe_serialization,
773
+ tag=tag,
774
+ exclude_frozen_parameters=exclude_frozen_parameters)
775
+
776
+
777
+ def load_state_dict_from_zero_checkpoint(model, checkpoint_dir, tag=None):
778
+ """
779
+ 1. Put the provided model to cpu
780
+ 2. Convert ZeRO 2 or 3 checkpoint into a single fp32 consolidated ``state_dict``
781
+ 3. Load it into the provided model
782
+
783
+ Args:
784
+ - ``model``: the model object to update
785
+ - ``checkpoint_dir``: path to the desired checkpoint folder. (one that contains the tag-folder, like ``global_step14``)
786
+ - ``tag``: checkpoint tag used as a unique identifier for checkpoint. If not provided will attempt to load tag in the file named ``latest`` in the checkpoint folder, e.g., ``global_step14``
787
+
788
+ Returns:
789
+ - ``model`: modified model
790
+
791
+ Make sure you have plenty of CPU memory available before you call this function. If you don't
792
+ have enough use the ``zero_to_fp32.py`` utility to do the conversion. You will find it
793
+ conveniently placed for you in the checkpoint folder.
794
+
795
+ A typical usage might be ::
796
+
797
+ from deepspeed.utils.zero_to_fp32 import load_state_dict_from_zero_checkpoint
798
+ model = load_state_dict_from_zero_checkpoint(trainer.model, checkpoint_dir)
799
+ # submit to model hub or save the model to share with others
800
+
801
+ Note, that once this was run, the ``model`` will no longer be usable in the deepspeed context
802
+ of the same application. i.e. you will need to re-initialize the deepspeed engine, since
803
+ ``model.load_state_dict(state_dict)`` will remove all the deepspeed magic from it.
804
+
805
+ """
806
+ logger.info("Extracting fp32 weights")
807
+ state_dict = get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir, tag)
808
+
809
+ logger.info("Overwriting model with fp32 weights")
810
+ model = model.cpu()
811
+ model.load_state_dict(state_dict, strict=False)
812
+
813
+ return model
814
+
815
+
816
+ if __name__ == "__main__":
817
+ parser = argparse.ArgumentParser()
818
+ parser.add_argument("checkpoint_dir",
819
+ type=str,
820
+ help="path to the desired checkpoint folder, e.g., path/checkpoint-12")
821
+ parser.add_argument("output_dir",
822
+ type=str,
823
+ help="directory to the pytorch fp32 state_dict output files"
824
+ "(e.g. path/checkpoint-12-output/)")
825
+ parser.add_argument(
826
+ "--max_shard_size",
827
+ type=str,
828
+ default="5GB",
829
+ help="The maximum size for a checkpoint before being sharded. Checkpoints shard will then be each of size"
830
+ "lower than this size. If expressed as a string, needs to be digits followed by a unit (like `5MB`"
831
+ "We default it to 5GB in order for models to be able to run easily on free-tier google colab instances"
832
+ "without CPU OOM issues.")
833
+ parser.add_argument(
834
+ "--safe_serialization",
835
+ default=False,
836
+ action='store_true',
837
+ help="Whether to save the model using `safetensors` or the traditional PyTorch way (that uses `pickle`).")
838
+ parser.add_argument("-t",
839
+ "--tag",
840
+ type=str,
841
+ default=None,
842
+ help="checkpoint tag used as a unique identifier for checkpoint. e.g., global_step1")
843
+ parser.add_argument("--exclude_frozen_parameters", action='store_true', help="exclude frozen parameters")
844
+ parser.add_argument("-d", "--debug", action='store_true', help="enable debug")
845
+ args = parser.parse_args()
846
+
847
+ debug = args.debug
848
+
849
+ convert_zero_checkpoint_to_fp32_state_dict(args.checkpoint_dir,
850
+ args.output_dir,
851
+ max_shard_size=args.max_shard_size,
852
+ safe_serialization=args.safe_serialization,
853
+ tag=args.tag,
854
+ exclude_frozen_parameters=args.exclude_frozen_parameters)
qwen3-1.7b-teutonic-2e5/checkpoint-1000/zero_to_torch.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ # DeepSpeed Team
5
+
6
+ import argparse
7
+
8
+ if __package__:
9
+ from . import zero_to_fp32
10
+ else:
11
+ import zero_to_fp32
12
+
13
+
14
+ def main(args=None):
15
+ parser = argparse.ArgumentParser(
16
+ description="Convert a DeepSpeed ZeRO checkpoint to float32, float16, or bfloat16 PyTorch weights.")
17
+ parser.add_argument("checkpoint_dir",
18
+ type=str,
19
+ help="path to the desired checkpoint folder, e.g., path/checkpoint-12")
20
+ parser.add_argument("output_dir", type=str, help="directory for the converted PyTorch state_dict files")
21
+ parser.add_argument("--dtype",
22
+ type=str,
23
+ choices=sorted(zero_to_fp32.OUTPUT_DTYPE_NAMES),
24
+ required=True,
25
+ help="output tensor dtype")
26
+ parser.add_argument("--max_shard_size",
27
+ type=str,
28
+ default="5GB",
29
+ help="maximum size of each checkpoint shard, such as 5GB or 500MB")
30
+ parser.add_argument("--safe_serialization",
31
+ default=False,
32
+ action='store_true',
33
+ help="save with safetensors instead of PyTorch pickle serialization")
34
+ parser.add_argument("-t",
35
+ "--tag",
36
+ type=str,
37
+ default=None,
38
+ help="checkpoint tag used as a unique identifier, e.g., global_step1")
39
+ parser.add_argument("--exclude_frozen_parameters", action='store_true', help="exclude frozen parameters")
40
+ parser.add_argument("-d", "--debug", action='store_true', help="enable debug output")
41
+ parsed_args = parser.parse_args(args)
42
+
43
+ zero_to_fp32.debug = parsed_args.debug
44
+ zero_to_fp32.convert_zero_checkpoint_to_state_dict(parsed_args.checkpoint_dir,
45
+ parsed_args.output_dir,
46
+ dtype=parsed_args.dtype,
47
+ max_shard_size=parsed_args.max_shard_size,
48
+ safe_serialization=parsed_args.safe_serialization,
49
+ tag=parsed_args.tag,
50
+ exclude_frozen_parameters=parsed_args.exclude_frozen_parameters)
51
+
52
+
53
+ if __name__ == "__main__":
54
+ main()
qwen3-1.7b-teutonic-2e5/checkpoint-1485/chat_template.jinja ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0].role == 'system' %}
4
+ {{- messages[0].content + '\n\n' }}
5
+ {%- endif %}
6
+ {{- "# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
7
+ {%- for tool in tools %}
8
+ {{- "\n" }}
9
+ {{- tool | tojson }}
10
+ {%- endfor %}
11
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
12
+ {%- else %}
13
+ {%- if messages[0].role == 'system' %}
14
+ {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
15
+ {%- endif %}
16
+ {%- endif %}
17
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
18
+ {%- for message in messages[::-1] %}
19
+ {%- set index = (messages|length - 1) - loop.index0 %}
20
+ {%- if ns.multi_step_tool and message.role == "user" and message.content is string and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}
21
+ {%- set ns.multi_step_tool = false %}
22
+ {%- set ns.last_query_index = index %}
23
+ {%- endif %}
24
+ {%- endfor %}
25
+ {%- for message in messages %}
26
+ {%- if message.content is string %}
27
+ {%- set content = message.content %}
28
+ {%- else %}
29
+ {%- set content = '' %}
30
+ {%- endif %}
31
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
32
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
33
+ {%- elif message.role == "assistant" %}
34
+ {%- set reasoning_content = '' %}
35
+ {%- if message.reasoning_content is string %}
36
+ {%- set reasoning_content = message.reasoning_content %}
37
+ {%- else %}
38
+ {%- if '</think>' in content %}
39
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
40
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
41
+ {%- endif %}
42
+ {%- endif %}
43
+ {%- if loop.index0 > ns.last_query_index %}
44
+ {%- if loop.last or (not loop.last and reasoning_content) %}
45
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
46
+ {%- else %}
47
+ {{- '<|im_start|>' + message.role + '\n' + content }}
48
+ {%- endif %}
49
+ {%- else %}
50
+ {{- '<|im_start|>' + message.role + '\n' + content }}
51
+ {%- endif %}
52
+ {%- if message.tool_calls %}
53
+ {%- for tool_call in message.tool_calls %}
54
+ {%- if (loop.first and content) or (not loop.first) %}
55
+ {{- '\n' }}
56
+ {%- endif %}
57
+ {%- if tool_call.function %}
58
+ {%- set tool_call = tool_call.function %}
59
+ {%- endif %}
60
+ {{- '<tool_call>\n{"name": "' }}
61
+ {{- tool_call.name }}
62
+ {{- '", "arguments": ' }}
63
+ {%- if tool_call.arguments is string %}
64
+ {{- tool_call.arguments }}
65
+ {%- else %}
66
+ {{- tool_call.arguments | tojson }}
67
+ {%- endif %}
68
+ {{- '}\n</tool_call>' }}
69
+ {%- endfor %}
70
+ {%- endif %}
71
+ {{- '<|im_end|>\n' }}
72
+ {%- elif message.role == "tool" %}
73
+ {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
74
+ {{- '<|im_start|>user' }}
75
+ {%- endif %}
76
+ {{- '\n<tool_response>\n' }}
77
+ {{- content }}
78
+ {{- '\n</tool_response>' }}
79
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
80
+ {{- '<|im_end|>\n' }}
81
+ {%- endif %}
82
+ {%- endif %}
83
+ {%- endfor %}
84
+ {%- if add_generation_prompt %}
85
+ {{- '<|im_start|>assistant\n' }}
86
+ {%- if enable_thinking is defined and enable_thinking is false %}
87
+ {{- '<think>\n\n</think>\n\n' }}
88
+ {%- endif %}
89
+ {%- endif %}
qwen3-1.7b-teutonic-2e5/checkpoint-1485/config.json ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Qwen3ForCausalLM"
4
+ ],
5
+ "attention_bias": false,
6
+ "attention_dropout": 0.0,
7
+ "bos_token_id": null,
8
+ "dtype": "bfloat16",
9
+ "eos_token_id": 151645,
10
+ "head_dim": 128,
11
+ "hidden_act": "silu",
12
+ "hidden_size": 2048,
13
+ "initializer_range": 0.02,
14
+ "intermediate_size": 6144,
15
+ "layer_types": [
16
+ "full_attention",
17
+ "full_attention",
18
+ "full_attention",
19
+ "full_attention",
20
+ "full_attention",
21
+ "full_attention",
22
+ "full_attention",
23
+ "full_attention",
24
+ "full_attention",
25
+ "full_attention",
26
+ "full_attention",
27
+ "full_attention",
28
+ "full_attention",
29
+ "full_attention",
30
+ "full_attention",
31
+ "full_attention",
32
+ "full_attention",
33
+ "full_attention",
34
+ "full_attention",
35
+ "full_attention",
36
+ "full_attention",
37
+ "full_attention",
38
+ "full_attention",
39
+ "full_attention",
40
+ "full_attention",
41
+ "full_attention",
42
+ "full_attention",
43
+ "full_attention"
44
+ ],
45
+ "max_position_embeddings": 40960,
46
+ "max_window_layers": 28,
47
+ "model_type": "qwen3",
48
+ "num_attention_heads": 16,
49
+ "num_hidden_layers": 28,
50
+ "num_key_value_heads": 8,
51
+ "pad_token_id": 151643,
52
+ "rms_norm_eps": 1e-06,
53
+ "rope_parameters": {
54
+ "rope_theta": 1000000,
55
+ "rope_type": "default"
56
+ },
57
+ "sliding_window": null,
58
+ "tie_word_embeddings": true,
59
+ "transformers_version": "5.17.0",
60
+ "use_cache": false,
61
+ "use_sliding_window": false,
62
+ "vocab_size": 151936
63
+ }
qwen3-1.7b-teutonic-2e5/checkpoint-1485/generation_config.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "do_sample": true,
3
+ "eos_token_id": [
4
+ 151645,
5
+ 151643
6
+ ],
7
+ "pad_token_id": 151643,
8
+ "temperature": 0.6,
9
+ "top_k": 20,
10
+ "top_p": 0.95,
11
+ "transformers_version": "5.17.0"
12
+ }
qwen3-1.7b-teutonic-2e5/checkpoint-1485/global_step1485/bf16_zero_pp_rank_0_mp_rank_00_optim_states.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8d310f5466bf901784c39740d2ba6dcabb6904e9280df6b5865f7360cc07f04e
3
+ size 10323466465
qwen3-1.7b-teutonic-2e5/checkpoint-1485/global_step1485/bf16_zero_pp_rank_1_mp_rank_00_optim_states.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:eda7d5c3c134c7f2ad759957a202b8b021838ec2f20d5185dc1a52989a7d6ccd
3
+ size 10323469601
qwen3-1.7b-teutonic-2e5/checkpoint-1485/global_step1485/mp_rank_00_model_states.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a8fc309912ee1059d08a4b85263fc00dc1c46571b061b11e2eb9439979613e40
3
+ size 3441239653
qwen3-1.7b-teutonic-2e5/checkpoint-1485/latest ADDED
@@ -0,0 +1 @@
 
 
1
+ global_step1485
qwen3-1.7b-teutonic-2e5/checkpoint-1485/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5cdc018ad7b517ba5e4c7c4f00035390b4e85dec1fc68e477966614a72cda70c
3
+ size 4063515640
qwen3-1.7b-teutonic-2e5/checkpoint-1485/rng_state_0.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b6d0c8203f86526d5059f583df0d5b1c246458bd95b5ae63a840d384d95e1811
3
+ size 14917
qwen3-1.7b-teutonic-2e5/checkpoint-1485/rng_state_1.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f13fc77f33fd9dd376569b0baf2c19ef17d863b26d8028118541e9f7a36ca898
3
+ size 14917
qwen3-1.7b-teutonic-2e5/checkpoint-1485/scheduler.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d0945608dfeb2871410bf8eb511453bb37137eb1373134300fb59491a6a0b399
3
+ size 1465
qwen3-1.7b-teutonic-2e5/checkpoint-1485/tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:be75606093db2094d7cd20f3c2f385c212750648bd6ea4fb2bf507a6a4c55506
3
+ size 11422650
qwen3-1.7b-teutonic-2e5/checkpoint-1485/tokenizer_config.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "backend": "tokenizers",
4
+ "bos_token": null,
5
+ "clean_up_tokenization_spaces": false,
6
+ "eos_token": "<|im_end|>",
7
+ "errors": "replace",
8
+ "extra_special_tokens": [
9
+ "<|im_start|>",
10
+ "<|im_end|>",
11
+ "<|object_ref_start|>",
12
+ "<|object_ref_end|>",
13
+ "<|box_start|>",
14
+ "<|box_end|>",
15
+ "<|quad_start|>",
16
+ "<|quad_end|>",
17
+ "<|vision_start|>",
18
+ "<|vision_end|>",
19
+ "<|vision_pad|>",
20
+ "<|image_pad|>",
21
+ "<|video_pad|>"
22
+ ],
23
+ "is_local": false,
24
+ "local_files_only": false,
25
+ "model_max_length": 131072,
26
+ "pad_token": "<|endoftext|>",
27
+ "split_special_tokens": false,
28
+ "tokenizer_class": "Qwen2Tokenizer",
29
+ "unk_token": null
30
+ }
qwen3-1.7b-teutonic-2e5/checkpoint-1485/trainer_state.json ADDED
The diff for this file is too large to render. See raw diff
 
qwen3-1.7b-teutonic-2e5/checkpoint-1485/training_args.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2c573bdac95c796f8f7368ab9af6d35c5687f53373737ea965b8102d518df7cb
3
+ size 7121
qwen3-1.7b-teutonic-2e5/checkpoint-1485/zero_to_fp32.py ADDED
@@ -0,0 +1,854 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ # Copyright (c) Microsoft Corporation.
4
+ # SPDX-License-Identifier: Apache-2.0
5
+
6
+ # DeepSpeed Team
7
+
8
+ # This script extracts fp32 consolidated weights from a zero 1, 2 and 3 DeepSpeed checkpoints. It gets
9
+ # copied into the top level checkpoint dir, so the user can easily do the conversion at any point in
10
+ # the future. Once extracted, the weights don't require DeepSpeed and can be used in any
11
+ # application.
12
+ #
13
+ # example:
14
+ # python zero_to_fp32.py . output_dir/
15
+ # or
16
+ # python zero_to_fp32.py . output_dir/ --safe_serialization
17
+
18
+ import argparse
19
+ import torch
20
+ import glob
21
+ import math
22
+ import os
23
+ import re
24
+ import gc
25
+ import json
26
+ import numpy as np
27
+ from tqdm import tqdm
28
+ from collections import OrderedDict
29
+ from dataclasses import dataclass
30
+
31
+ # while this script doesn't use deepspeed to recover data, since the checkpoints are pickled with
32
+ # DeepSpeed data structures it has to be available in the current python environment.
33
+ from deepspeed.utils import logger
34
+ from deepspeed.checkpoint.constants import (DS_VERSION, OPTIMIZER_STATE_DICT, SINGLE_PARTITION_OF_FP32_GROUPS,
35
+ FP32_FLAT_GROUPS, ZERO_STAGE, PARTITION_COUNT, PARAM_SHAPES, BUFFER_NAMES,
36
+ FROZEN_PARAM_SHAPES, FROZEN_PARAM_FRAGMENTS, AUTOEP_LAYERS_KEY,
37
+ AUTOEP_LAYERS_KEY_LEGACY, AUTOEP_ZERO3_EXPERT_STATE_FORMAT_KEY,
38
+ AUTOEP_ZERO3_PARTITIONED_EXPERT_STATE_FORMAT, PARAM_ALIGNMENT_PADDINGS)
39
+
40
+
41
+ @dataclass
42
+ class zero_model_state:
43
+ buffers: dict()
44
+ param_shapes: dict()
45
+ shared_params: list
46
+ ds_version: int
47
+ frozen_param_shapes: dict()
48
+ frozen_param_fragments: dict()
49
+
50
+
51
+ debug = 0
52
+
53
+ # load to cpu
54
+ device = torch.device('cpu')
55
+
56
+ OUTPUT_DTYPE_NAMES = {
57
+ 'float32': torch.float32,
58
+ 'fp32': torch.float32,
59
+ 'float16': torch.float16,
60
+ 'fp16': torch.float16,
61
+ 'bfloat16': torch.bfloat16,
62
+ 'bf16': torch.bfloat16,
63
+ }
64
+
65
+
66
+ def _resolve_output_dtype(dtype):
67
+ requested_dtype = dtype
68
+ if isinstance(dtype, str):
69
+ dtype_name = dtype[6:] if dtype.startswith('torch.') else dtype
70
+ dtype = OUTPUT_DTYPE_NAMES.get(dtype_name.lower())
71
+ if dtype not in set(OUTPUT_DTYPE_NAMES.values()):
72
+ supported = ', '.join(sorted(OUTPUT_DTYPE_NAMES))
73
+ raise ValueError(f"Unsupported output dtype {requested_dtype!r}. Choose one of: {supported}")
74
+ return dtype
75
+
76
+
77
+ def atoi(text):
78
+ return int(text) if text.isdigit() else text
79
+
80
+
81
+ def natural_keys(text):
82
+ '''
83
+ alist.sort(key=natural_keys) sorts in human order
84
+ http://nedbatchelder.com/blog/200712/human_sorting.html
85
+ (See Toothy's implementation in the comments)
86
+ '''
87
+ return [atoi(c) for c in re.split(r'(\d+)', text)]
88
+
89
+
90
+ def get_model_state_file(checkpoint_dir, zero_stage):
91
+ if not os.path.isdir(checkpoint_dir):
92
+ raise FileNotFoundError(f"Directory '{checkpoint_dir}' doesn't exist")
93
+
94
+ # there should be only one file
95
+ if zero_stage <= 2:
96
+ file = os.path.join(checkpoint_dir, "mp_rank_00_model_states.pt")
97
+ elif zero_stage == 3:
98
+ file = os.path.join(checkpoint_dir, "zero_pp_rank_0_mp_rank_00_model_states.pt")
99
+
100
+ if not os.path.exists(file):
101
+ raise FileNotFoundError(f"can't find model states file at '{file}'")
102
+
103
+ return file
104
+
105
+
106
+ def get_checkpoint_files(checkpoint_dir, glob_pattern):
107
+ # XXX: need to test that this simple glob rule works for multi-node setup too
108
+ ckpt_files = sorted(glob.glob(os.path.join(checkpoint_dir, glob_pattern)), key=natural_keys)
109
+
110
+ if len(ckpt_files) == 0:
111
+ raise FileNotFoundError(f"can't find {glob_pattern} files in directory '{checkpoint_dir}'")
112
+
113
+ return ckpt_files
114
+
115
+
116
+ def get_optim_files(checkpoint_dir):
117
+ return get_checkpoint_files(checkpoint_dir, "*_optim_states.pt")
118
+
119
+
120
+ def get_model_state_files(checkpoint_dir):
121
+ return get_checkpoint_files(checkpoint_dir, "*_model_states.pt")
122
+
123
+
124
+ def _has_autoep_zero3_partitioned_metadata(state_dict):
125
+ autoep_layers = state_dict.get(AUTOEP_LAYERS_KEY)
126
+ if autoep_layers is None:
127
+ autoep_layers = state_dict.get(AUTOEP_LAYERS_KEY_LEGACY)
128
+ if not isinstance(autoep_layers, list):
129
+ return False
130
+ return any(
131
+ isinstance(entry, dict)
132
+ and entry.get(AUTOEP_ZERO3_EXPERT_STATE_FORMAT_KEY) == AUTOEP_ZERO3_PARTITIONED_EXPERT_STATE_FORMAT
133
+ for entry in autoep_layers)
134
+
135
+
136
+ def _raise_if_autoep_zero3_partitioned_state(state_dict):
137
+ if _has_autoep_zero3_partitioned_metadata(state_dict):
138
+ raise NotImplementedError("zero_to_fp32 does not support AutoEP ZeRO-3 partition-native checkpoints. "
139
+ "AutoEP expert parameters are partitioned over expert replica groups, so "
140
+ "global data-parallel consolidation would produce incomplete expert tensors. "
141
+ "Use ds_to_universal.py for expert-aware conversion.")
142
+
143
+
144
+ def _raise_if_autoep_zero3_partitioned_checkpoint(model_files):
145
+ for file in model_files:
146
+ state_dict = torch.load(file, map_location=device, weights_only=False)
147
+ _raise_if_autoep_zero3_partitioned_state(state_dict)
148
+
149
+
150
+ def parse_model_states(files):
151
+ zero_model_states = []
152
+ for file in files:
153
+ state_dict = torch.load(file, map_location=device, weights_only=False)
154
+ _raise_if_autoep_zero3_partitioned_state(state_dict)
155
+
156
+ if BUFFER_NAMES not in state_dict:
157
+ raise ValueError(f"{file} is not a model state checkpoint")
158
+ buffer_names = state_dict[BUFFER_NAMES]
159
+ if debug:
160
+ print("Found buffers:", buffer_names)
161
+
162
+ # recover just the buffers while restoring them to fp32 if they were saved in fp16
163
+ buffers = {k: v.float() for k, v in state_dict["module"].items() if k in buffer_names}
164
+ param_shapes = state_dict[PARAM_SHAPES]
165
+
166
+ # collect parameters that are included in param_shapes
167
+ param_names = []
168
+ for s in param_shapes:
169
+ for name in s.keys():
170
+ param_names.append(name)
171
+
172
+ # update with frozen parameters
173
+ frozen_param_shapes = state_dict.get(FROZEN_PARAM_SHAPES, None)
174
+ if frozen_param_shapes is not None:
175
+ if debug:
176
+ print(f"Found frozen_param_shapes: {frozen_param_shapes}")
177
+ param_names += list(frozen_param_shapes.keys())
178
+
179
+ # handle shared params
180
+ shared_params = [[k, v] for k, v in state_dict["shared_params"].items()]
181
+
182
+ ds_version = state_dict.get(DS_VERSION, None)
183
+
184
+ frozen_param_fragments = state_dict.get(FROZEN_PARAM_FRAGMENTS, None)
185
+
186
+ z_model_state = zero_model_state(buffers=buffers,
187
+ param_shapes=param_shapes,
188
+ shared_params=shared_params,
189
+ ds_version=ds_version,
190
+ frozen_param_shapes=frozen_param_shapes,
191
+ frozen_param_fragments=frozen_param_fragments)
192
+ zero_model_states.append(z_model_state)
193
+
194
+ return zero_model_states
195
+
196
+
197
+ def parse_optim_states(files, ds_checkpoint_dir):
198
+ total_files = len(files)
199
+ state_dicts = []
200
+ for f in tqdm(files, desc='Loading checkpoint shards'):
201
+ state_dict = torch.load(f, map_location=device, mmap=True, weights_only=False)
202
+ # immediately discard the potentially huge 2 optimizer states as we only care for fp32 master weights
203
+ # and also handle the case where it was already removed by another helper script
204
+ state_dict["optimizer_state_dict"].pop("optimizer_state_dict", None)
205
+ state_dicts.append(state_dict)
206
+
207
+ if ZERO_STAGE not in state_dicts[0][OPTIMIZER_STATE_DICT]:
208
+ raise ValueError(f"{files[0]} is not a zero checkpoint")
209
+ zero_stage = state_dicts[0][OPTIMIZER_STATE_DICT][ZERO_STAGE]
210
+ world_size = state_dicts[0][OPTIMIZER_STATE_DICT][PARTITION_COUNT]
211
+
212
+ # For ZeRO-2 each param group can have different partition_count as data parallelism for expert
213
+ # parameters can be different from data parallelism for non-expert parameters. So we can just
214
+ # use the max of the partition_count to get the dp world_size.
215
+
216
+ if type(world_size) is list:
217
+ world_size = max(world_size)
218
+
219
+ if world_size != total_files:
220
+ raise ValueError(
221
+ f"Expected {world_size} of '*_optim_states.pt' under '{ds_checkpoint_dir}' but found {total_files} files. "
222
+ "Possibly due to an overwrite of an old checkpoint, or a checkpoint didn't get saved by one or more processes."
223
+ )
224
+
225
+ # the groups are named differently in each stage
226
+ if zero_stage <= 2:
227
+ fp32_groups_key = SINGLE_PARTITION_OF_FP32_GROUPS
228
+ elif zero_stage == 3:
229
+ fp32_groups_key = FP32_FLAT_GROUPS
230
+ else:
231
+ raise ValueError(f"unknown zero stage {zero_stage}")
232
+
233
+ fp32_flat_groups = [state_dicts[i][OPTIMIZER_STATE_DICT][fp32_groups_key] for i in range(len(state_dicts))]
234
+ param_alignment_paddings = state_dicts[0][OPTIMIZER_STATE_DICT].get(PARAM_ALIGNMENT_PADDINGS)
235
+ return zero_stage, world_size, fp32_flat_groups, param_alignment_paddings
236
+
237
+
238
+ def _get_fp32_state_dict_from_zero_checkpoint(ds_checkpoint_dir, exclude_frozen_parameters):
239
+ """
240
+ Returns fp32 state_dict reconstructed from ds checkpoint
241
+
242
+ Args:
243
+ - ``ds_checkpoint_dir``: path to the deepspeed checkpoint folder (where the optimizer files are)
244
+
245
+ """
246
+ print(f"Processing zero checkpoint '{ds_checkpoint_dir}'")
247
+
248
+ # parse_model_states rejects AutoEP ZeRO-3 partition-native checkpoints
249
+ # before the expensive optimizer-shard load below.
250
+ model_files = get_model_state_files(ds_checkpoint_dir)
251
+ zero_model_states = parse_model_states(model_files)
252
+ print(f'Parsing checkpoint created by deepspeed=={zero_model_states[0].ds_version}')
253
+
254
+ optim_files = get_optim_files(ds_checkpoint_dir)
255
+ zero_stage, world_size, fp32_flat_groups, param_alignment_paddings = parse_optim_states(
256
+ optim_files, ds_checkpoint_dir)
257
+ print(f"Detected checkpoint of type zero stage {zero_stage}, world_size: {world_size}")
258
+
259
+ if zero_stage <= 2:
260
+ return _get_fp32_state_dict_from_zero2_checkpoint(world_size, fp32_flat_groups, zero_model_states,
261
+ exclude_frozen_parameters, param_alignment_paddings)
262
+ elif zero_stage == 3:
263
+ return _get_fp32_state_dict_from_zero3_checkpoint(world_size, fp32_flat_groups, zero_model_states,
264
+ exclude_frozen_parameters)
265
+
266
+
267
+ def _zero2_merge_frozen_params(state_dict, zero_model_states):
268
+ if zero_model_states[0].frozen_param_shapes is None or len(zero_model_states[0].frozen_param_shapes) == 0:
269
+ return
270
+
271
+ frozen_param_shapes = zero_model_states[0].frozen_param_shapes
272
+ frozen_param_fragments = zero_model_states[0].frozen_param_fragments
273
+
274
+ if debug:
275
+ num_elem = sum(s.numel() for s in frozen_param_shapes.values())
276
+ print(f'rank 0: {FROZEN_PARAM_SHAPES}.numel = {num_elem}')
277
+
278
+ wanted_params = len(frozen_param_shapes)
279
+ wanted_numel = sum(s.numel() for s in frozen_param_shapes.values())
280
+ avail_numel = sum([p.numel() for p in frozen_param_fragments.values()])
281
+ print(f'Frozen params: Have {avail_numel} numels to process.')
282
+ print(f'Frozen params: Need {wanted_numel} numels in {wanted_params} params')
283
+
284
+ total_params = 0
285
+ total_numel = 0
286
+ for name, shape in frozen_param_shapes.items():
287
+ total_params += 1
288
+ unpartitioned_numel = shape.numel()
289
+ total_numel += unpartitioned_numel
290
+
291
+ state_dict[name] = frozen_param_fragments[name]
292
+
293
+ if debug:
294
+ print(f"{name} full shape: {shape} unpartitioned numel {unpartitioned_numel} ")
295
+
296
+ print(f"Reconstructed Frozen fp32 state dict with {total_params} params {total_numel} elements")
297
+
298
+
299
+ def _has_callable(obj, fn):
300
+ attr = getattr(obj, fn, None)
301
+ return callable(attr)
302
+
303
+
304
+ def _zero2_merge_trainable_params(state_dict,
305
+ world_size,
306
+ fp32_flat_groups,
307
+ zero_model_states,
308
+ param_alignment_paddings=None):
309
+ param_shapes = zero_model_states[0].param_shapes
310
+
311
+ # Reconstruction protocol:
312
+ #
313
+ # XXX: document this
314
+
315
+ if debug:
316
+ for i in range(world_size):
317
+ for j in range(len(fp32_flat_groups[0])):
318
+ print(f"{FP32_FLAT_GROUPS}[{i}][{j}].shape={fp32_flat_groups[i][j].shape}")
319
+
320
+ # XXX: memory usage doubles here (zero2)
321
+ num_param_groups = len(fp32_flat_groups[0])
322
+ merged_single_partition_of_fp32_groups = []
323
+ for i in range(num_param_groups):
324
+ merged_partitions = [sd[i] for sd in fp32_flat_groups]
325
+ full_single_fp32_vector = torch.cat(merged_partitions, 0)
326
+ merged_single_partition_of_fp32_groups.append(full_single_fp32_vector)
327
+ avail_numel = sum(
328
+ [full_single_fp32_vector.numel() for full_single_fp32_vector in merged_single_partition_of_fp32_groups])
329
+
330
+ if debug:
331
+ wanted_params = sum([len(shapes) for shapes in param_shapes])
332
+ wanted_numel = sum([sum(shape.numel() for shape in shapes.values()) for shapes in param_shapes])
333
+ # not asserting if there is a mismatch due to possible padding
334
+ print(f"Have {avail_numel} numels to process.")
335
+ print(f"Need {wanted_numel} numels in {wanted_params} params.")
336
+
337
+ # params
338
+ # XXX: for huge models that can't fit into the host's RAM we will have to recode this to support
339
+ # out-of-core computing solution
340
+ total_numel = 0
341
+ total_params = 0
342
+ for group_idx, (shapes,
343
+ full_single_fp32_vector) in enumerate(zip(param_shapes, merged_single_partition_of_fp32_groups)):
344
+ offset = 0
345
+ avail_numel = full_single_fp32_vector.numel()
346
+ group_alignment_paddings = None
347
+ if param_alignment_paddings is not None:
348
+ group_alignment_paddings = param_alignment_paddings[group_idx]
349
+ if len(group_alignment_paddings) != len(shapes):
350
+ raise ValueError(f"Expected {len(shapes)} parameter alignment paddings for group {group_idx}, "
351
+ f"but found {len(group_alignment_paddings)}")
352
+
353
+ for param_idx, (name, shape) in enumerate(shapes.items()):
354
+
355
+ unpartitioned_numel = shape.numel() if _has_callable(shape, 'numel') else math.prod(shape)
356
+ total_numel += unpartitioned_numel
357
+ total_params += 1
358
+
359
+ if debug:
360
+ print(f"{name} full shape: {shape} unpartitioned numel {unpartitioned_numel} ")
361
+ state_dict[name] = full_single_fp32_vector.narrow(0, offset, unpartitioned_numel).view(shape)
362
+ offset += unpartitioned_numel
363
+ if group_alignment_paddings is not None:
364
+ offset += group_alignment_paddings[param_idx]
365
+
366
+ # Z2 started to align to 2*world_size to improve nccl performance. Therefore both offset and
367
+ # avail_numel can differ by anywhere between 0..2*world_size. Due to two unrelated complex
368
+ # paddings performed in the code it's almost impossible to predict the exact numbers w/o the
369
+ # live optimizer object, so we are checking that the numbers are within the right range
370
+ align_to = 2 * world_size
371
+
372
+ def zero2_align(x):
373
+ return align_to * math.ceil(x / align_to)
374
+
375
+ if debug:
376
+ print(f"original offset={offset}, avail_numel={avail_numel}")
377
+
378
+ offset = zero2_align(offset)
379
+ avail_numel = zero2_align(avail_numel)
380
+
381
+ if debug:
382
+ print(f"aligned offset={offset}, avail_numel={avail_numel}")
383
+
384
+ # Sanity check
385
+ if offset != avail_numel:
386
+ raise ValueError(f"consumed {offset} numels out of {avail_numel} - something is wrong")
387
+
388
+ print(f"Reconstructed fp32 state dict with {total_params} params {total_numel} elements")
389
+
390
+
391
+ def _get_fp32_state_dict_from_zero2_checkpoint(world_size,
392
+ fp32_flat_groups,
393
+ zero_model_states,
394
+ exclude_frozen_parameters,
395
+ param_alignment_paddings=None):
396
+ state_dict = OrderedDict()
397
+
398
+ # buffers
399
+ buffers = zero_model_states[0].buffers
400
+ state_dict.update(buffers)
401
+ if debug:
402
+ print(f"added {len(buffers)} buffers")
403
+
404
+ if not exclude_frozen_parameters:
405
+ _zero2_merge_frozen_params(state_dict, zero_model_states)
406
+
407
+ _zero2_merge_trainable_params(state_dict, world_size, fp32_flat_groups, zero_model_states,
408
+ param_alignment_paddings)
409
+
410
+ # recover shared parameters
411
+ for pair in zero_model_states[0].shared_params:
412
+ if pair[1] in state_dict:
413
+ state_dict[pair[0]] = state_dict[pair[1]]
414
+
415
+ return state_dict
416
+
417
+
418
+ def zero3_partitioned_param_info(unpartitioned_numel, world_size):
419
+ remainder = unpartitioned_numel % world_size
420
+ padding_numel = (world_size - remainder) if remainder else 0
421
+ partitioned_numel = math.ceil(unpartitioned_numel / world_size)
422
+ return partitioned_numel, padding_numel
423
+
424
+
425
+ def _zero3_merge_frozen_params(state_dict, world_size, zero_model_states):
426
+ if zero_model_states[0].frozen_param_shapes is None or len(zero_model_states[0].frozen_param_shapes) == 0:
427
+ return
428
+
429
+ if debug:
430
+ for i in range(world_size):
431
+ num_elem = sum(s.numel() for s in zero_model_states[i].frozen_param_fragments.values())
432
+ print(f'rank {i}: {FROZEN_PARAM_SHAPES}.numel = {num_elem}')
433
+
434
+ frozen_param_shapes = zero_model_states[0].frozen_param_shapes
435
+ wanted_params = len(frozen_param_shapes)
436
+ wanted_numel = sum(s.numel() for s in frozen_param_shapes.values())
437
+ avail_numel = sum([p.numel() for p in zero_model_states[0].frozen_param_fragments.values()]) * world_size
438
+ print(f'Frozen params: Have {avail_numel} numels to process.')
439
+ print(f'Frozen params: Need {wanted_numel} numels in {wanted_params} params')
440
+
441
+ total_params = 0
442
+ total_numel = 0
443
+ for name, shape in zero_model_states[0].frozen_param_shapes.items():
444
+ total_params += 1
445
+ unpartitioned_numel = shape.numel()
446
+ total_numel += unpartitioned_numel
447
+
448
+ param_frags = tuple(model_state.frozen_param_fragments[name] for model_state in zero_model_states)
449
+ state_dict[name] = torch.cat(param_frags, 0).narrow(0, 0, unpartitioned_numel).view(shape)
450
+
451
+ partitioned_numel, partitioned_padding_numel = zero3_partitioned_param_info(unpartitioned_numel, world_size)
452
+
453
+ if debug:
454
+ print(
455
+ f"Frozen params: {total_params} {name} full shape: {shape} partition0 numel={partitioned_numel} partitioned_padding_numel={partitioned_padding_numel}"
456
+ )
457
+
458
+ print(f"Reconstructed Frozen fp32 state dict with {total_params} params {total_numel} elements")
459
+
460
+
461
+ class GatheredTensor:
462
+ """
463
+ A pseudo tensor that collects partitioned weights.
464
+ It is more memory efficient when there are multiple groups.
465
+ """
466
+
467
+ def __init__(self, flat_groups, flat_groups_offset, offset, partitioned_numel, shape):
468
+ self.flat_groups = flat_groups
469
+ self.flat_groups_offset = flat_groups_offset
470
+ self.offset = offset
471
+ self.partitioned_numel = partitioned_numel
472
+ self.shape = shape
473
+ self.dtype = self.flat_groups[0][0].dtype
474
+
475
+ def contiguous(self):
476
+ """
477
+ Merge partitioned weights from flat_groups into a single tensor.
478
+ """
479
+ end_idx = self.offset + self.partitioned_numel
480
+ world_size = len(self.flat_groups)
481
+ pad_flat_param_chunks = []
482
+
483
+ for rank_i in range(world_size):
484
+ # for each rank, we need to collect weights from related group/groups
485
+ flat_groups_at_rank_i = self.flat_groups[rank_i]
486
+ start_group_id = None
487
+ end_group_id = None
488
+ for group_id in range(len(self.flat_groups_offset)):
489
+ if self.flat_groups_offset[group_id] <= self.offset < self.flat_groups_offset[group_id + 1]:
490
+ start_group_id = group_id
491
+ if self.flat_groups_offset[group_id] < end_idx <= self.flat_groups_offset[group_id + 1]:
492
+ end_group_id = group_id
493
+ break
494
+ # collect weights from related group/groups
495
+ for group_id in range(start_group_id, end_group_id + 1):
496
+ flat_tensor = flat_groups_at_rank_i[group_id]
497
+ start_offset = self.offset - self.flat_groups_offset[group_id]
498
+ end_offset = min(end_idx, self.flat_groups_offset[group_id + 1]) - self.flat_groups_offset[group_id]
499
+ pad_flat_param_chunks.append(flat_tensor[start_offset:end_offset])
500
+
501
+ # collect weights from all ranks
502
+ pad_flat_param = torch.cat(pad_flat_param_chunks, dim=0)
503
+ param = pad_flat_param[:self.shape.numel()].view(self.shape).contiguous()
504
+ return param
505
+
506
+
507
+ def _zero3_merge_trainable_params(state_dict, world_size, fp32_flat_groups, zero_model_states):
508
+ param_shapes = zero_model_states[0].param_shapes
509
+ avail_numel = sum([flat_group.numel() for flat_group in fp32_flat_groups[0]]) * world_size
510
+
511
+ # Reconstruction protocol: For zero3 we need to zip the partitions together at boundary of each
512
+ # param, re-consolidating each param, while dealing with padding if any
513
+
514
+ # merge list of dicts, preserving order
515
+ param_shapes = {k: v for d in param_shapes for k, v in d.items()}
516
+
517
+ if debug:
518
+ for i in range(world_size):
519
+ print(f"{FP32_FLAT_GROUPS}[{i}].shape={fp32_flat_groups[i].shape}")
520
+
521
+ wanted_params = len(param_shapes)
522
+ wanted_numel = sum(shape.numel() for shape in param_shapes.values())
523
+ # not asserting if there is a mismatch due to possible padding
524
+ avail_numel = fp32_flat_groups[0].numel() * world_size
525
+ print(f"Trainable params: Have {avail_numel} numels to process.")
526
+ print(f"Trainable params: Need {wanted_numel} numels in {wanted_params} params.")
527
+
528
+ # params
529
+ # XXX: for huge models that can't fit into the host's RAM we will have to recode this to support
530
+ # out-of-core computing solution
531
+ offset = 0
532
+ total_numel = 0
533
+ total_params = 0
534
+ flat_groups_offset = [0] + list(np.cumsum([flat_tensor.numel() for flat_tensor in fp32_flat_groups[0]]))
535
+ for name, shape in tqdm(param_shapes.items(), desc='Gathering sharded weights'):
536
+ unpartitioned_numel = shape.numel()
537
+ total_numel += unpartitioned_numel
538
+ total_params += 1
539
+ partitioned_numel, partitioned_padding_numel = zero3_partitioned_param_info(unpartitioned_numel, world_size)
540
+
541
+ if debug:
542
+ print(
543
+ f"Trainable params: {total_params} {name} full shape: {shape} partition0 numel={partitioned_numel} partitioned_padding_numel={partitioned_padding_numel}"
544
+ )
545
+
546
+ # memory efficient tensor
547
+ tensor = GatheredTensor(fp32_flat_groups, flat_groups_offset, offset, partitioned_numel, shape)
548
+ state_dict[name] = tensor
549
+ offset += partitioned_numel
550
+
551
+ offset *= world_size
552
+
553
+ # Sanity check
554
+ if offset != avail_numel:
555
+ raise ValueError(f"consumed {offset} numels out of {avail_numel} - something is wrong")
556
+
557
+ print(f"Reconstructed Trainable fp32 state dict with {total_params} params {total_numel} elements")
558
+
559
+
560
+ def _get_fp32_state_dict_from_zero3_checkpoint(world_size, fp32_flat_groups, zero_model_states,
561
+ exclude_frozen_parameters):
562
+ state_dict = OrderedDict()
563
+
564
+ # buffers
565
+ buffers = zero_model_states[0].buffers
566
+ state_dict.update(buffers)
567
+ if debug:
568
+ print(f"added {len(buffers)} buffers")
569
+
570
+ if not exclude_frozen_parameters:
571
+ _zero3_merge_frozen_params(state_dict, world_size, zero_model_states)
572
+
573
+ _zero3_merge_trainable_params(state_dict, world_size, fp32_flat_groups, zero_model_states)
574
+
575
+ # recover shared parameters
576
+ for pair in zero_model_states[0].shared_params:
577
+ if pair[1] in state_dict:
578
+ state_dict[pair[0]] = state_dict[pair[1]]
579
+
580
+ return state_dict
581
+
582
+
583
+ def to_torch_tensor(state_dict, return_empty_tensor=False, dtype=None):
584
+ """
585
+ Convert state_dict of GatheredTensor to torch tensor
586
+ """
587
+ if dtype is not None:
588
+ dtype = _resolve_output_dtype(dtype)
589
+
590
+ torch_state_dict = {}
591
+ converted_tensors = {}
592
+ for name, tensor in state_dict.items():
593
+ tensor_id = id(tensor)
594
+ if tensor_id in converted_tensors: # shared tensors
595
+ shared_tensor = torch_state_dict[converted_tensors[tensor_id]]
596
+ torch_state_dict[name] = shared_tensor
597
+ else:
598
+ converted_tensors[tensor_id] = name
599
+ if return_empty_tensor:
600
+ torch_state_dict[name] = torch.empty(tensor.shape, dtype=dtype or tensor.dtype)
601
+ else:
602
+ contiguous_tensor = tensor.contiguous()
603
+ torch_state_dict[name] = contiguous_tensor.to(dtype=dtype) if dtype else contiguous_tensor
604
+ return torch_state_dict
605
+
606
+
607
+ def get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir,
608
+ tag=None,
609
+ exclude_frozen_parameters=False,
610
+ lazy_mode=False):
611
+ """
612
+ Convert ZeRO 2 or 3 checkpoint into a single fp32 consolidated state_dict that can be loaded with
613
+ ``load_state_dict()`` and used for training without DeepSpeed or shared with others, for example
614
+ via a model hub.
615
+
616
+ Args:
617
+ - ``checkpoint_dir``: path to the desired checkpoint folder
618
+ - ``tag``: checkpoint tag used as a unique identifier for checkpoint. If not provided will attempt to load tag in 'latest' file. e.g., ``global_step14``
619
+ - ``exclude_frozen_parameters``: exclude frozen parameters
620
+ - ``lazy_mode``: get state_dict in lazy mode. It returns a dict of pesduo tensor instead of torch tensor, which is more memory efficient.
621
+ Convert the pesduo tensor to torch tensor by ``.contiguous()``
622
+
623
+ Returns:
624
+ - pytorch ``state_dict``
625
+
626
+ A typical usage might be ::
627
+
628
+ from deepspeed.utils.zero_to_fp32 import get_fp32_state_dict_from_zero_checkpoint
629
+ # do the training and checkpoint saving
630
+ state_dict = get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir) # already on cpu
631
+ model = model.cpu() # move to cpu
632
+ model.load_state_dict(state_dict)
633
+ # submit to model hub or save the model to share with others
634
+
635
+ In this example the ``model`` will no longer be usable in the deepspeed context of the same
636
+ application. i.e. you will need to re-initialize the deepspeed engine, since
637
+ ``model.load_state_dict(state_dict)`` will remove all the deepspeed magic from it.
638
+
639
+ If you want it all done for you, use ``load_state_dict_from_zero_checkpoint`` instead.
640
+
641
+ Note: the above usage may not work if your application doesn't have sufficient free CPU memory.
642
+ You may need to use the offline approach using the ``zero_to_fp32.py`` script that is saved with
643
+ the checkpoint. Or you can load state_dict in lazy mode ::
644
+
645
+ from deepspeed.utils.zero_to_fp32 import get_fp32_state_dict_from_zero_checkpoint
646
+ state_dict = get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir, lazy_mode=True) # not on cpu
647
+ for name, lazy_tensor in state_dict.item():
648
+ tensor = lazy_tensor.contiguous() # to cpu
649
+ print(name, tensor)
650
+ # del tensor to release memory if it no longer in use
651
+ """
652
+ if tag is None:
653
+ latest_path = os.path.join(checkpoint_dir, 'latest')
654
+ if os.path.isfile(latest_path):
655
+ with open(latest_path, 'r') as fd:
656
+ tag = fd.read().strip()
657
+ else:
658
+ raise ValueError(f"Unable to find 'latest' file at {latest_path}")
659
+
660
+ ds_checkpoint_dir = os.path.join(checkpoint_dir, tag)
661
+
662
+ if not os.path.isdir(ds_checkpoint_dir):
663
+ raise FileNotFoundError(f"Directory '{ds_checkpoint_dir}' doesn't exist")
664
+
665
+ state_dict = _get_fp32_state_dict_from_zero_checkpoint(ds_checkpoint_dir, exclude_frozen_parameters)
666
+ if lazy_mode:
667
+ return state_dict
668
+ else:
669
+ return to_torch_tensor(state_dict)
670
+
671
+
672
+ def convert_zero_checkpoint_to_state_dict(checkpoint_dir,
673
+ output_dir,
674
+ dtype=torch.float32,
675
+ max_shard_size="5GB",
676
+ safe_serialization=False,
677
+ tag=None,
678
+ exclude_frozen_parameters=False):
679
+ """
680
+ Convert ZeRO 2 or 3 checkpoint into a consolidated ``state_dict`` file that can be
681
+ loaded with ``torch.load(file)`` + ``load_state_dict()`` and used for training without DeepSpeed.
682
+
683
+ Args:
684
+ - ``checkpoint_dir``: path to the desired checkpoint folder. (one that contains the tag-folder, like ``global_step14``)
685
+ - ``output_dir``: directory for the PyTorch state_dict output files
686
+ - ``dtype``: output tensor dtype. Supports float32, float16, and bfloat16 as strings or torch dtypes.
687
+ - ``max_shard_size``: the maximum size for a checkpoint before being sharded, default value is 5GB
688
+ - ``safe_serialization``: whether to save the model using `safetensors` or the traditional PyTorch way (that uses `pickle`).
689
+ - ``tag``: checkpoint tag used as a unique identifier for checkpoint. If not provided will attempt to load tag in the file named ``latest`` in the checkpoint folder, e.g., ``global_step14``
690
+ - ``exclude_frozen_parameters``: exclude frozen parameters
691
+ """
692
+
693
+ dtype = _resolve_output_dtype(dtype)
694
+
695
+ # Dependency pre-check
696
+ if safe_serialization:
697
+ try:
698
+ from safetensors.torch import save_file
699
+ except ImportError:
700
+ print('If you want to use `safe_serialization`, please `pip install safetensors`')
701
+ raise
702
+ if max_shard_size is not None:
703
+ try:
704
+ from huggingface_hub import split_torch_state_dict_into_shards
705
+ except ImportError:
706
+ print('If you want to use `max_shard_size`, please `pip install huggingface_hub`')
707
+ raise
708
+
709
+ # Convert zero checkpoint to state_dict
710
+ state_dict = get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir,
711
+ tag,
712
+ exclude_frozen_parameters,
713
+ lazy_mode=True)
714
+
715
+ # Shard the model if it is too big.
716
+ weights_name = "model.safetensors" if safe_serialization else "pytorch_model.bin"
717
+ if max_shard_size is not None:
718
+ filename_pattern = weights_name.replace(".bin", "{suffix}.bin").replace(".safetensors", "{suffix}.safetensors")
719
+ # an memory-efficient approach for sharding
720
+ empty_state_dict = to_torch_tensor(state_dict, return_empty_tensor=True, dtype=dtype)
721
+ state_dict_split = split_torch_state_dict_into_shards(empty_state_dict,
722
+ filename_pattern=filename_pattern,
723
+ max_shard_size=max_shard_size)
724
+ else:
725
+ from collections import namedtuple
726
+ StateDictSplit = namedtuple("StateDictSplit", ["is_sharded", "filename_to_tensors"])
727
+ state_dict_split = StateDictSplit(is_sharded=False,
728
+ filename_to_tensors={weights_name: list(state_dict.keys())})
729
+
730
+ # Save the model by shard
731
+ os.makedirs(output_dir, exist_ok=True)
732
+ filename_to_tensors = state_dict_split.filename_to_tensors.items()
733
+ for shard_file, tensors in tqdm(filename_to_tensors, desc="Saving checkpoint shards"):
734
+ shard_state_dict = {tensor_name: state_dict[tensor_name] for tensor_name in tensors}
735
+ shard_state_dict = to_torch_tensor(shard_state_dict, dtype=dtype)
736
+ output_path = os.path.join(output_dir, shard_file)
737
+ if safe_serialization:
738
+ save_file(shard_state_dict, output_path, metadata={"format": "pt"})
739
+ else:
740
+ torch.save(shard_state_dict, output_path)
741
+ # release the memory of current shard
742
+ for tensor_name in list(shard_state_dict.keys()):
743
+ del state_dict[tensor_name]
744
+ del shard_state_dict[tensor_name]
745
+ del shard_state_dict
746
+ gc.collect()
747
+
748
+ # Save index if sharded
749
+ if state_dict_split.is_sharded:
750
+ index = {
751
+ "metadata": state_dict_split.metadata,
752
+ "weight_map": state_dict_split.tensor_to_filename,
753
+ }
754
+ save_index_file = "model.safetensors.index.json" if safe_serialization else "pytorch_model.bin.index.json"
755
+ save_index_file = os.path.join(output_dir, save_index_file)
756
+ with open(save_index_file, "w", encoding="utf-8") as f:
757
+ content = json.dumps(index, indent=2, sort_keys=True) + "\n"
758
+ f.write(content)
759
+
760
+
761
+ def convert_zero_checkpoint_to_fp32_state_dict(checkpoint_dir,
762
+ output_dir,
763
+ max_shard_size="5GB",
764
+ safe_serialization=False,
765
+ tag=None,
766
+ exclude_frozen_parameters=False):
767
+ """Backward-compatible fp32 checkpoint conversion."""
768
+ return convert_zero_checkpoint_to_state_dict(checkpoint_dir,
769
+ output_dir,
770
+ dtype=torch.float32,
771
+ max_shard_size=max_shard_size,
772
+ safe_serialization=safe_serialization,
773
+ tag=tag,
774
+ exclude_frozen_parameters=exclude_frozen_parameters)
775
+
776
+
777
+ def load_state_dict_from_zero_checkpoint(model, checkpoint_dir, tag=None):
778
+ """
779
+ 1. Put the provided model to cpu
780
+ 2. Convert ZeRO 2 or 3 checkpoint into a single fp32 consolidated ``state_dict``
781
+ 3. Load it into the provided model
782
+
783
+ Args:
784
+ - ``model``: the model object to update
785
+ - ``checkpoint_dir``: path to the desired checkpoint folder. (one that contains the tag-folder, like ``global_step14``)
786
+ - ``tag``: checkpoint tag used as a unique identifier for checkpoint. If not provided will attempt to load tag in the file named ``latest`` in the checkpoint folder, e.g., ``global_step14``
787
+
788
+ Returns:
789
+ - ``model`: modified model
790
+
791
+ Make sure you have plenty of CPU memory available before you call this function. If you don't
792
+ have enough use the ``zero_to_fp32.py`` utility to do the conversion. You will find it
793
+ conveniently placed for you in the checkpoint folder.
794
+
795
+ A typical usage might be ::
796
+
797
+ from deepspeed.utils.zero_to_fp32 import load_state_dict_from_zero_checkpoint
798
+ model = load_state_dict_from_zero_checkpoint(trainer.model, checkpoint_dir)
799
+ # submit to model hub or save the model to share with others
800
+
801
+ Note, that once this was run, the ``model`` will no longer be usable in the deepspeed context
802
+ of the same application. i.e. you will need to re-initialize the deepspeed engine, since
803
+ ``model.load_state_dict(state_dict)`` will remove all the deepspeed magic from it.
804
+
805
+ """
806
+ logger.info("Extracting fp32 weights")
807
+ state_dict = get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir, tag)
808
+
809
+ logger.info("Overwriting model with fp32 weights")
810
+ model = model.cpu()
811
+ model.load_state_dict(state_dict, strict=False)
812
+
813
+ return model
814
+
815
+
816
+ if __name__ == "__main__":
817
+ parser = argparse.ArgumentParser()
818
+ parser.add_argument("checkpoint_dir",
819
+ type=str,
820
+ help="path to the desired checkpoint folder, e.g., path/checkpoint-12")
821
+ parser.add_argument("output_dir",
822
+ type=str,
823
+ help="directory to the pytorch fp32 state_dict output files"
824
+ "(e.g. path/checkpoint-12-output/)")
825
+ parser.add_argument(
826
+ "--max_shard_size",
827
+ type=str,
828
+ default="5GB",
829
+ help="The maximum size for a checkpoint before being sharded. Checkpoints shard will then be each of size"
830
+ "lower than this size. If expressed as a string, needs to be digits followed by a unit (like `5MB`"
831
+ "We default it to 5GB in order for models to be able to run easily on free-tier google colab instances"
832
+ "without CPU OOM issues.")
833
+ parser.add_argument(
834
+ "--safe_serialization",
835
+ default=False,
836
+ action='store_true',
837
+ help="Whether to save the model using `safetensors` or the traditional PyTorch way (that uses `pickle`).")
838
+ parser.add_argument("-t",
839
+ "--tag",
840
+ type=str,
841
+ default=None,
842
+ help="checkpoint tag used as a unique identifier for checkpoint. e.g., global_step1")
843
+ parser.add_argument("--exclude_frozen_parameters", action='store_true', help="exclude frozen parameters")
844
+ parser.add_argument("-d", "--debug", action='store_true', help="enable debug")
845
+ args = parser.parse_args()
846
+
847
+ debug = args.debug
848
+
849
+ convert_zero_checkpoint_to_fp32_state_dict(args.checkpoint_dir,
850
+ args.output_dir,
851
+ max_shard_size=args.max_shard_size,
852
+ safe_serialization=args.safe_serialization,
853
+ tag=args.tag,
854
+ exclude_frozen_parameters=args.exclude_frozen_parameters)
qwen3-1.7b-teutonic-2e5/checkpoint-1485/zero_to_torch.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ # DeepSpeed Team
5
+
6
+ import argparse
7
+
8
+ if __package__:
9
+ from . import zero_to_fp32
10
+ else:
11
+ import zero_to_fp32
12
+
13
+
14
+ def main(args=None):
15
+ parser = argparse.ArgumentParser(
16
+ description="Convert a DeepSpeed ZeRO checkpoint to float32, float16, or bfloat16 PyTorch weights.")
17
+ parser.add_argument("checkpoint_dir",
18
+ type=str,
19
+ help="path to the desired checkpoint folder, e.g., path/checkpoint-12")
20
+ parser.add_argument("output_dir", type=str, help="directory for the converted PyTorch state_dict files")
21
+ parser.add_argument("--dtype",
22
+ type=str,
23
+ choices=sorted(zero_to_fp32.OUTPUT_DTYPE_NAMES),
24
+ required=True,
25
+ help="output tensor dtype")
26
+ parser.add_argument("--max_shard_size",
27
+ type=str,
28
+ default="5GB",
29
+ help="maximum size of each checkpoint shard, such as 5GB or 500MB")
30
+ parser.add_argument("--safe_serialization",
31
+ default=False,
32
+ action='store_true',
33
+ help="save with safetensors instead of PyTorch pickle serialization")
34
+ parser.add_argument("-t",
35
+ "--tag",
36
+ type=str,
37
+ default=None,
38
+ help="checkpoint tag used as a unique identifier, e.g., global_step1")
39
+ parser.add_argument("--exclude_frozen_parameters", action='store_true', help="exclude frozen parameters")
40
+ parser.add_argument("-d", "--debug", action='store_true', help="enable debug output")
41
+ parsed_args = parser.parse_args(args)
42
+
43
+ zero_to_fp32.debug = parsed_args.debug
44
+ zero_to_fp32.convert_zero_checkpoint_to_state_dict(parsed_args.checkpoint_dir,
45
+ parsed_args.output_dir,
46
+ dtype=parsed_args.dtype,
47
+ max_shard_size=parsed_args.max_shard_size,
48
+ safe_serialization=parsed_args.safe_serialization,
49
+ tag=parsed_args.tag,
50
+ exclude_frozen_parameters=parsed_args.exclude_frozen_parameters)
51
+
52
+
53
+ if __name__ == "__main__":
54
+ main()
qwen3-1.7b-teutonic-2e5/checkpoint-500/chat_template.jinja ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0].role == 'system' %}
4
+ {{- messages[0].content + '\n\n' }}
5
+ {%- endif %}
6
+ {{- "# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
7
+ {%- for tool in tools %}
8
+ {{- "\n" }}
9
+ {{- tool | tojson }}
10
+ {%- endfor %}
11
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
12
+ {%- else %}
13
+ {%- if messages[0].role == 'system' %}
14
+ {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
15
+ {%- endif %}
16
+ {%- endif %}
17
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
18
+ {%- for message in messages[::-1] %}
19
+ {%- set index = (messages|length - 1) - loop.index0 %}
20
+ {%- if ns.multi_step_tool and message.role == "user" and message.content is string and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}
21
+ {%- set ns.multi_step_tool = false %}
22
+ {%- set ns.last_query_index = index %}
23
+ {%- endif %}
24
+ {%- endfor %}
25
+ {%- for message in messages %}
26
+ {%- if message.content is string %}
27
+ {%- set content = message.content %}
28
+ {%- else %}
29
+ {%- set content = '' %}
30
+ {%- endif %}
31
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
32
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
33
+ {%- elif message.role == "assistant" %}
34
+ {%- set reasoning_content = '' %}
35
+ {%- if message.reasoning_content is string %}
36
+ {%- set reasoning_content = message.reasoning_content %}
37
+ {%- else %}
38
+ {%- if '</think>' in content %}
39
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
40
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
41
+ {%- endif %}
42
+ {%- endif %}
43
+ {%- if loop.index0 > ns.last_query_index %}
44
+ {%- if loop.last or (not loop.last and reasoning_content) %}
45
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
46
+ {%- else %}
47
+ {{- '<|im_start|>' + message.role + '\n' + content }}
48
+ {%- endif %}
49
+ {%- else %}
50
+ {{- '<|im_start|>' + message.role + '\n' + content }}
51
+ {%- endif %}
52
+ {%- if message.tool_calls %}
53
+ {%- for tool_call in message.tool_calls %}
54
+ {%- if (loop.first and content) or (not loop.first) %}
55
+ {{- '\n' }}
56
+ {%- endif %}
57
+ {%- if tool_call.function %}
58
+ {%- set tool_call = tool_call.function %}
59
+ {%- endif %}
60
+ {{- '<tool_call>\n{"name": "' }}
61
+ {{- tool_call.name }}
62
+ {{- '", "arguments": ' }}
63
+ {%- if tool_call.arguments is string %}
64
+ {{- tool_call.arguments }}
65
+ {%- else %}
66
+ {{- tool_call.arguments | tojson }}
67
+ {%- endif %}
68
+ {{- '}\n</tool_call>' }}
69
+ {%- endfor %}
70
+ {%- endif %}
71
+ {{- '<|im_end|>\n' }}
72
+ {%- elif message.role == "tool" %}
73
+ {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
74
+ {{- '<|im_start|>user' }}
75
+ {%- endif %}
76
+ {{- '\n<tool_response>\n' }}
77
+ {{- content }}
78
+ {{- '\n</tool_response>' }}
79
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
80
+ {{- '<|im_end|>\n' }}
81
+ {%- endif %}
82
+ {%- endif %}
83
+ {%- endfor %}
84
+ {%- if add_generation_prompt %}
85
+ {{- '<|im_start|>assistant\n' }}
86
+ {%- if enable_thinking is defined and enable_thinking is false %}
87
+ {{- '<think>\n\n</think>\n\n' }}
88
+ {%- endif %}
89
+ {%- endif %}
qwen3-1.7b-teutonic-2e5/checkpoint-500/config.json ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "Qwen3ForCausalLM"
4
+ ],
5
+ "attention_bias": false,
6
+ "attention_dropout": 0.0,
7
+ "bos_token_id": null,
8
+ "dtype": "bfloat16",
9
+ "eos_token_id": 151645,
10
+ "head_dim": 128,
11
+ "hidden_act": "silu",
12
+ "hidden_size": 2048,
13
+ "initializer_range": 0.02,
14
+ "intermediate_size": 6144,
15
+ "layer_types": [
16
+ "full_attention",
17
+ "full_attention",
18
+ "full_attention",
19
+ "full_attention",
20
+ "full_attention",
21
+ "full_attention",
22
+ "full_attention",
23
+ "full_attention",
24
+ "full_attention",
25
+ "full_attention",
26
+ "full_attention",
27
+ "full_attention",
28
+ "full_attention",
29
+ "full_attention",
30
+ "full_attention",
31
+ "full_attention",
32
+ "full_attention",
33
+ "full_attention",
34
+ "full_attention",
35
+ "full_attention",
36
+ "full_attention",
37
+ "full_attention",
38
+ "full_attention",
39
+ "full_attention",
40
+ "full_attention",
41
+ "full_attention",
42
+ "full_attention",
43
+ "full_attention"
44
+ ],
45
+ "max_position_embeddings": 40960,
46
+ "max_window_layers": 28,
47
+ "model_type": "qwen3",
48
+ "num_attention_heads": 16,
49
+ "num_hidden_layers": 28,
50
+ "num_key_value_heads": 8,
51
+ "pad_token_id": 151643,
52
+ "rms_norm_eps": 1e-06,
53
+ "rope_parameters": {
54
+ "rope_theta": 1000000,
55
+ "rope_type": "default"
56
+ },
57
+ "sliding_window": null,
58
+ "tie_word_embeddings": true,
59
+ "transformers_version": "5.17.0",
60
+ "use_cache": false,
61
+ "use_sliding_window": false,
62
+ "vocab_size": 151936
63
+ }
qwen3-1.7b-teutonic-2e5/checkpoint-500/generation_config.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "do_sample": true,
3
+ "eos_token_id": [
4
+ 151645,
5
+ 151643
6
+ ],
7
+ "pad_token_id": 151643,
8
+ "temperature": 0.6,
9
+ "top_k": 20,
10
+ "top_p": 0.95,
11
+ "transformers_version": "5.17.0"
12
+ }
qwen3-1.7b-teutonic-2e5/checkpoint-500/global_step500/bf16_zero_pp_rank_0_mp_rank_00_optim_states.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:729d5481732775300f3678e55abd25181ac14249b2102bb960f3d12e0de8c1dd
3
+ size 10323466465
qwen3-1.7b-teutonic-2e5/checkpoint-500/global_step500/bf16_zero_pp_rank_1_mp_rank_00_optim_states.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:42810e16642c209d4e06c04f15001786db4ee9f99a890dfd7da8da2ad0a68cc1
3
+ size 10323469601
qwen3-1.7b-teutonic-2e5/checkpoint-500/global_step500/mp_rank_00_model_states.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8e3a2e69f57fd2c64c50cd6430722e31c6c0aa5e4bd3bae2ee2afd9aaefba424
3
+ size 3441239653
qwen3-1.7b-teutonic-2e5/checkpoint-500/latest ADDED
@@ -0,0 +1 @@
 
 
1
+ global_step500
qwen3-1.7b-teutonic-2e5/checkpoint-500/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:05699b742b2507f4eff84eafc1be8993c2ee2e467a5eaf97c9f506698cda6244
3
+ size 4063515640
qwen3-1.7b-teutonic-2e5/checkpoint-500/rng_state_0.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:958a6e27892fb703ed10a62b2ead762f94b60ec3bb4677c08b5468a57d8e339b
3
+ size 14917
qwen3-1.7b-teutonic-2e5/checkpoint-500/rng_state_1.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:378c8813b6f7f592a17b751f070068187707a01baf668eb0520492c2223e28e8
3
+ size 14917
qwen3-1.7b-teutonic-2e5/checkpoint-500/scheduler.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:de1d54e3a77abffcb08b973a58f94dc815bdaee26ce117745a3a339bb5263473
3
+ size 1465
qwen3-1.7b-teutonic-2e5/checkpoint-500/tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:be75606093db2094d7cd20f3c2f385c212750648bd6ea4fb2bf507a6a4c55506
3
+ size 11422650