HawkLabofficial commited on
Commit
eab9950
·
verified ·
1 Parent(s): 930247b

Upload tokenizer_module.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. tokenizer_module.py +70 -0
tokenizer_module.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """HawkGPT 0.3 — Digit-aware BPE tokenizer.
2
+
3
+ Key improvement: numbers are split into individual digits.
4
+ "123" → ["1", "2", "3"] — model can learn arithmetic digit-by-digit.
5
+ """
6
+
7
+ import os
8
+ from tokenizers import Tokenizer, models, pre_tokenizers, trainers
9
+
10
+ import config
11
+
12
+
13
+ def train_tokenizer(text_path: str, vocab_size: int = None) -> Tokenizer:
14
+ """Train digit-aware BPE tokenizer."""
15
+ if vocab_size is None:
16
+ vocab_size = config.VOCAB_SIZE
17
+
18
+ tokenizer = Tokenizer(models.BPE())
19
+
20
+ # Digit-aware: Whitespace + individual digits
21
+ tokenizer.pre_tokenizer = pre_tokenizers.Sequence([
22
+ pre_tokenizers.Whitespace(),
23
+ pre_tokenizers.Digits(individual_digits=True),
24
+ ])
25
+
26
+ trainer = trainers.BpeTrainer(
27
+ vocab_size=vocab_size,
28
+ special_tokens=["[PAD]", "[BOS]", "[EOS]", "[UNK]", "[MASK]"],
29
+ min_frequency=3,
30
+ )
31
+
32
+ def line_iterator():
33
+ with open(text_path, "r", encoding="utf-8") as f:
34
+ for line in f:
35
+ yield line
36
+
37
+ tokenizer.train_from_iterator(line_iterator(), trainer=trainer)
38
+
39
+ tokenizer.enable_padding(length=config.MAX_SEQ_LEN, pad_id=tokenizer.token_to_id("[PAD]"))
40
+ tokenizer.enable_truncation(max_length=config.MAX_SEQ_LEN)
41
+
42
+ os.makedirs(config.DATA_DIR, exist_ok=True)
43
+ tokenizer.save(config.TOKENIZER_PATH)
44
+
45
+ # Verify digit splitting
46
+ tok_test = Tokenizer.from_file(config.TOKENIZER_PATH)
47
+ tok_test.no_padding()
48
+ tok_test.no_truncation()
49
+ enc = tok_test.encode("123 + 456 = 579")
50
+ print(f"Digit test: {'123 + 456 = 579'}")
51
+ print(f" Tokens: {enc.tokens}")
52
+ print(f" Digit-aware: {'1' in enc.tokens and '2' in enc.tokens and '3' in enc.tokens}")
53
+
54
+ print(f"Tokenizer saved: {config.TOKENIZER_PATH} | vocab={tokenizer.get_vocab_size()}")
55
+ return tokenizer
56
+
57
+
58
+ def load_tokenizer() -> Tokenizer:
59
+ if not os.path.exists(config.TOKENIZER_PATH):
60
+ raise FileNotFoundError(f"Tokenizer not found at {config.TOKENIZER_PATH}")
61
+ return Tokenizer.from_file(config.TOKENIZER_PATH)
62
+
63
+
64
+ if __name__ == "__main__":
65
+ tok = train_tokenizer(config.DATA_TEXT_PATH)
66
+ tok.no_padding()
67
+ tok.no_truncation()
68
+ for test in ["123 + 456 = 579", "Привет! Как дела?", "Реши: 3x + 5 = 20"]:
69
+ enc = tok.encode(test)
70
+ print(f" {test} → {enc.tokens}")