fynnsu commited on
Commit
81ad4cb
·
verified ·
1 Parent(s): 1ee0137

Create README.md

Browse files
Files changed (1) hide show
  1. README.md +129 -0
README.md ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Smoke model using Qwen3 architecture. Used for testing purposes only, model outputs random text.
2
+
3
+ Creating using the below script (note script has not been cleaned up):
4
+ ```python
5
+ import json
6
+ import os
7
+ import tempfile
8
+
9
+ import torch
10
+ from tokenizers import Tokenizer
11
+ from transformers import (
12
+ AutoModelForCausalLM,
13
+ AutoTokenizer,
14
+ Qwen2TokenizerFast,
15
+ Qwen3Config,
16
+ Qwen3ForCausalLM,
17
+ )
18
+
19
+ source_model = "Qwen/Qwen3-8B"
20
+ output_path = "./scrap/qwen3_smoke"
21
+ vocab_keep_items = 1024
22
+
23
+
24
+ ##### Tokenizer ######
25
+ # Reduce vocabulary size, while maintaining special tokens
26
+
27
+ num_added_tokens_to_keep = 26
28
+ tokenizer = AutoTokenizer.from_pretrained(
29
+ source_model, use_fast=True, model_max_length=2048
30
+ )
31
+ assert tokenizer.is_fast, "This only works for fast tokenizers."
32
+ tokenizer_json = json.loads(tokenizer._tokenizer.to_str())
33
+ vocab = tokenizer_json["model"]["vocab"]
34
+
35
+ assert tokenizer_json["model"]["type"] == "BPE"
36
+ new_vocab = {token: i for token, i in vocab.items() if i < vocab_keep_items}
37
+ merges = tokenizer_json["model"]["merges"]
38
+ new_merges = []
39
+ for i in range(len(merges)):
40
+ a, b = merges[i]
41
+ new_token = "".join((a, b))
42
+ if a in new_vocab and b in new_vocab and new_token in new_vocab:
43
+ new_merges.append(merges[i])
44
+ tokenizer_json["model"]["merges"] = new_merges
45
+ tokenizer_json["model"]["vocab"] = new_vocab
46
+
47
+ new_added_tokens = []
48
+ for i in range(num_added_tokens_to_keep):
49
+ added_token = tokenizer_json["added_tokens"][i]
50
+ added_token["id"] = vocab_keep_items + i
51
+ new_added_tokens.append(added_token)
52
+
53
+
54
+ tokenizer_json["added_tokens"] = new_added_tokens
55
+
56
+ added_map = {token["content"]: token["id"] for token in new_added_tokens}
57
+
58
+ if "processors" in tokenizer_json["post_processor"]:
59
+ tokenizer_json["post_processor"]["processors"][-1]["special_tokens"][
60
+ "<|begin_of_text|>"
61
+ ]["ids"] = [vocab_keep_items]
62
+
63
+ dir = tempfile.mkdtemp()
64
+ vocab_file = dir + "/vocab.json"
65
+ merges_file = dir + "/merges.txt"
66
+
67
+ with open(vocab_file, "wt") as f:
68
+ json.dump(new_vocab, f)
69
+
70
+ with open(merges_file, "wt") as f:
71
+ for a, b in new_merges:
72
+ f.write(f"{a} {b}\n")
73
+
74
+ tokenizer = Qwen2TokenizerFast(
75
+ vocab_file, merges_file, added_tokens_decoder=tokenizer.added_tokens_decoder
76
+ )
77
+
78
+
79
+ # tokenizer = AutoTokenizer.from_pretrained(source_model)
80
+ tokenizer.save_pretrained(output_path)
81
+
82
+ ##### Model #####
83
+ # Reduce weight size and copy weights from a real llama model, so that weight distribution matches
84
+
85
+ weight_source_llama = AutoModelForCausalLM.from_pretrained(source_model)
86
+
87
+ weight_source_llama_dict = dict(weight_source_llama.named_parameters())
88
+
89
+ new_config = Qwen3Config(
90
+ vocab_size=vocab_keep_items + num_added_tokens_to_keep,
91
+ hidden_size=64,
92
+ num_attention_heads=16,
93
+ num_hidden_layers=6,
94
+ num_key_value_heads=8,
95
+ intermediate_size=128,
96
+ tie_word_embeddings=True,
97
+ )
98
+
99
+
100
+ def rec_setattr(obj, key, value):
101
+ if "." in key:
102
+ attr, rem_key = key.split(".", 1)
103
+ rec_setattr(getattr(obj, attr), rem_key, value)
104
+ else:
105
+ setattr(obj, key, value)
106
+
107
+
108
+ new_model = Qwen3ForCausalLM(new_config)
109
+
110
+ for w_name, w_value in list(new_model.named_parameters()):
111
+ if w_name == "lm_head.weight":
112
+ continue
113
+ # w_name = "model.embed_tokens.weight"
114
+ elif w_name not in weight_source_llama_dict:
115
+ raise ValueError(f"Couldn't find weight ref {w_name}")
116
+
117
+ w = weight_source_llama_dict[w_name]
118
+
119
+ slices = tuple(slice(0, n) for n in w_value.shape)
120
+ if any(x < y for x, y in zip(w.shape, w_value.shape)):
121
+ raise RuntimeError(f"Can't slice to size {w_name}")
122
+ sliced_weight = w[slices].detach().clone()
123
+ rec_setattr(new_model, w_name, torch.nn.Parameter(sliced_weight))
124
+
125
+ # Tie lm head to embed weights
126
+ # new_model.lm_head.weight = new_model.model.embed_tokens.weight
127
+
128
+ new_model.save_pretrained(output_path)
129
+ ```