chenbhao commited on
Commit
1909c9c
·
1 Parent(s): c6b1b88

Add tokenizer training script and save trained tokenizer into checkpoint dir

Browse files
runs/train_tokenizer.sh ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # Tokenizer 训练启动脚本(仅供学习和参考,不建议重复训练 tokenizer)
3
+ # 用法: bash runs/train_tokenizer.sh [额外参数...]
4
+ set -e
5
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
6
+ cd "$ROOT"
7
+ export PYTHONPATH="$ROOT/src:${PYTHONPATH}"
8
+ exec python -m trainers.lm.train_tokenizer --config "$ROOT/configs/model/lm.yaml" "$@"
src/trainers/lm/train_tokenizer.py CHANGED
@@ -2,10 +2,11 @@
2
  # Note: It is not recommended to re-train the tokenizer. MiniMind already includes one. This script is for learning and reference only. Training models with different tokenizers will lead to inconsistent outputs and reduce model reusability in the community.
3
  import os
4
  import json
 
5
  from tokenizers import decoders, models, pre_tokenizers, trainers, Tokenizer
6
 
7
  DATA_PATH = '../dataset/sft_t2t_mini.jsonl'
8
- TOKENIZER_DIR = '../model_learn_tokenizer/'
9
  VOCAB_SIZE = 6400
10
  SPECIAL_TOKENS_NUM = 36
11
 
@@ -21,25 +22,30 @@ def get_texts(data_path):
21
  except json.JSONDecodeError:
22
  continue
23
 
24
- def train_tokenizer(data_path, tokenizer_dir, vocab_size, special_tokens_num=SPECIAL_TOKENS_NUM):
25
- tokenizer = Tokenizer(models.BPE())
26
- tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False)
27
-
28
  special_tokens_list = [
29
- "<|endoftext|>", "<|im_start|>", "<|im_end|>",
30
- "<|object_ref_start|>", "<|object_ref_end|>", "<|box_start|>", "<|box_end|>", "<|quad_start|>", "<|quad_end|>",
31
- "<|vision_start|>", "<|vision_end|>", "<|vision_pad|>", "<|image_pad|>", "<|video_pad|>",
32
  "<|audio_start|>", "<|audio_end|>", "<|audio_pad|>", "<tts_pad>", "<tts_text_bos>", "<tts_text_eod>", "<tts_text_bos_single>"
33
  ]
34
-
35
  additional_tokens_list = [
36
  "<tool_call>", "</tool_call>",
37
  "<tool_response>", "</tool_response>",
38
  "<think>", "</think>"
39
  ]
40
  num_buffer = special_tokens_num - len(special_tokens_list + additional_tokens_list)
41
- buffer_tokens = [f"<|buffer{i}|>" for i in range(1, num_buffer + 1)] # 预留一定数量的token位置
42
  all_special_tokens = special_tokens_list + additional_tokens_list + buffer_tokens
 
 
 
 
 
 
 
 
43
  trainer = trainers.BpeTrainer(
44
  vocab_size=vocab_size,
45
  show_progress=True,
@@ -51,6 +57,12 @@ def train_tokenizer(data_path, tokenizer_dir, vocab_size, special_tokens_num=SPE
51
  tokenizer.decoder = decoders.ByteLevel()
52
  tokenizer.add_special_tokens(special_tokens_list)
53
 
 
 
 
 
 
 
54
  os.makedirs(tokenizer_dir, exist_ok=True)
55
  tokenizer.save(os.path.join(tokenizer_dir, "tokenizer.json"))
56
  tokenizer.model.save(tokenizer_dir)
@@ -103,7 +115,7 @@ def train_tokenizer(data_path, tokenizer_dir, vocab_size, special_tokens_num=SPE
103
 
104
  with open(os.path.join(tokenizer_dir, "tokenizer_config.json"), "w", encoding="utf-8") as f:
105
  json.dump(config, f, ensure_ascii=False, indent=4)
106
- print("Tokenizer training completed.")
107
 
108
  def eval_tokenizer(tokenizer_dir):
109
  from transformers import AutoTokenizer
@@ -164,5 +176,20 @@ def eval_tokenizer(tokenizer_dir):
164
  token_cache = []
165
 
166
  if __name__ == '__main__':
167
- train_tokenizer(DATA_PATH, TOKENIZER_DIR, VOCAB_SIZE)
168
- eval_tokenizer(TOKENIZER_DIR)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  # Note: It is not recommended to re-train the tokenizer. MiniMind already includes one. This script is for learning and reference only. Training models with different tokenizers will lead to inconsistent outputs and reduce model reusability in the community.
3
  import os
4
  import json
5
+ import argparse
6
  from tokenizers import decoders, models, pre_tokenizers, trainers, Tokenizer
7
 
8
  DATA_PATH = '../dataset/sft_t2t_mini.jsonl'
9
+ CHECKPOINT_DIR = '../checkpoint/'
10
  VOCAB_SIZE = 6400
11
  SPECIAL_TOKENS_NUM = 36
12
 
 
22
  except json.JSONDecodeError:
23
  continue
24
 
25
+ def build_special_tokens(special_tokens_num=SPECIAL_TOKENS_NUM):
 
 
 
26
  special_tokens_list = [
27
+ "<|endoftext|>", "<|im_start|>", "<|im_end|>",
28
+ "<|object_ref_start|>", "<|object_ref_end|>", "<|box_start|>", "<|box_end|>", "<|quad_start|>", "<|quad_end|>",
29
+ "<|vision_start|>", "<|vision_end|>", "<|vision_pad|>", "<|image_pad|>", "<|video_pad|>",
30
  "<|audio_start|>", "<|audio_end|>", "<|audio_pad|>", "<tts_pad>", "<tts_text_bos>", "<tts_text_eod>", "<tts_text_bos_single>"
31
  ]
32
+
33
  additional_tokens_list = [
34
  "<tool_call>", "</tool_call>",
35
  "<tool_response>", "</tool_response>",
36
  "<think>", "</think>"
37
  ]
38
  num_buffer = special_tokens_num - len(special_tokens_list + additional_tokens_list)
39
+ buffer_tokens = [f"<|buffer{i}|>" for i in range(1, num_buffer + 1)] # 预留一定数量的token位置
40
  all_special_tokens = special_tokens_list + additional_tokens_list + buffer_tokens
41
+ return special_tokens_list, all_special_tokens
42
+
43
+
44
+ def train_tokenizer(data_path, vocab_size, special_tokens_num=SPECIAL_TOKENS_NUM, checkpoint_dir=None):
45
+ tokenizer = Tokenizer(models.BPE())
46
+ tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False)
47
+
48
+ special_tokens_list, all_special_tokens = build_special_tokens(special_tokens_num)
49
  trainer = trainers.BpeTrainer(
50
  vocab_size=vocab_size,
51
  show_progress=True,
 
57
  tokenizer.decoder = decoders.ByteLevel()
58
  tokenizer.add_special_tokens(special_tokens_list)
59
 
60
+ if checkpoint_dir:
61
+ ckpt_tokenizer_dir = os.path.join(checkpoint_dir, "tokenizer")
62
+ save_tokenizer(tokenizer, ckpt_tokenizer_dir, special_tokens_list, all_special_tokens)
63
+
64
+
65
+ def save_tokenizer(tokenizer, tokenizer_dir, special_tokens_list, all_special_tokens):
66
  os.makedirs(tokenizer_dir, exist_ok=True)
67
  tokenizer.save(os.path.join(tokenizer_dir, "tokenizer.json"))
68
  tokenizer.model.save(tokenizer_dir)
 
115
 
116
  with open(os.path.join(tokenizer_dir, "tokenizer_config.json"), "w", encoding="utf-8") as f:
117
  json.dump(config, f, ensure_ascii=False, indent=4)
118
+ print(f"Tokenizer saved to {tokenizer_dir}.")
119
 
120
  def eval_tokenizer(tokenizer_dir):
121
  from transformers import AutoTokenizer
 
176
  token_cache = []
177
 
178
  if __name__ == '__main__':
179
+ parser = argparse.ArgumentParser(description="MiniMind Tokenizer Training (学习用)")
180
+ parser.add_argument("--data_path", type=str, default=DATA_PATH, help="训练语料路径 (.jsonl)")
181
+ parser.add_argument("--checkpoint_dir", type=str, default=CHECKPOINT_DIR, help="tokenizer 保存到该 checkpoint 目录下的 tokenizer/ 子目录")
182
+ parser.add_argument("--vocab_size", type=int, default=VOCAB_SIZE, help="词表大小")
183
+ parser.add_argument("--special_tokens_num", type=int, default=SPECIAL_TOKENS_NUM, help="特殊 token 预留数量")
184
+ parser.add_argument("--no_eval", action="store_true", help="训练后跳过评估")
185
+ args = parser.parse_args()
186
+
187
+ ckpt_tokenizer_dir = os.path.join(args.checkpoint_dir, "tokenizer")
188
+ train_tokenizer(
189
+ args.data_path,
190
+ args.vocab_size,
191
+ special_tokens_num=args.special_tokens_num,
192
+ checkpoint_dir=args.checkpoint_dir,
193
+ )
194
+ if not args.no_eval:
195
+ eval_tokenizer(ckpt_tokenizer_dir)