tspersian commited on
Commit
be6798e
1 Parent(s): d786ff1
Files changed (3) hide show
  1. README.md +6 -1
  2. benchmark.py +52 -0
  3. mana_tokenizer.py +77 -5
README.md CHANGED
@@ -19,11 +19,16 @@ text = "سلام من یک متن تست برای تست این تست هستم.
19
  print(tokenizer.encode(text))
20
  print(tokenizer.decode(tokenizer.encode(text)))
21
  ```
22
- output should be:
23
  ```
24
  [216, 179, 217, 132, 216, 167, 217, 133, 32, 217, 133, 217, 134, 32, 219, 140, 218, 169, 32, 217, 133, 216, 170, 217, 134, 32, 216, 170, 216, 179, 216, 170, 32, 216, 168, 216, 177, 216, 167, 219, 140, 32, 216, 170, 216, 179, 216, 170, 32, 216, 167, 219, 140, 217, 134, 32, 216, 170, 216, 179, 216, 170, 32, 217, 135, 216, 179, 216, 170, 217, 133, 46]
25
  سلام من یک متن تست برای تست این تست هستم.
26
  ```
 
 
 
 
 
27
 
28
  You can also add special tokens:
29
  ```python
 
19
  print(tokenizer.encode(text))
20
  print(tokenizer.decode(tokenizer.encode(text)))
21
  ```
22
+ this is the normal encoding of this text:
23
  ```
24
  [216, 179, 217, 132, 216, 167, 217, 133, 32, 217, 133, 217, 134, 32, 219, 140, 218, 169, 32, 217, 133, 216, 170, 217, 134, 32, 216, 170, 216, 179, 216, 170, 32, 216, 168, 216, 177, 216, 167, 219, 140, 32, 216, 170, 216, 179, 216, 170, 32, 216, 167, 219, 140, 217, 134, 32, 216, 170, 216, 179, 216, 170, 32, 217, 135, 216, 179, 216, 170, 217, 133, 46]
25
  سلام من یک متن تست برای تست این تست هستم.
26
  ```
27
+ and here is what Mana tokenizer generate:
28
+ ```
29
+ [30318, 377, 363, 4340, 5828, 513, 5828, 378, 5828, 14471, 46]
30
+ سلام من یک متن تست برای تست این تست هستم.
31
+ ```
32
 
33
  You can also add special tokens:
34
  ```python
benchmark.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tracemalloc
2
+ import time
3
+ from datetime import datetime
4
+ from .mana_tokenizer import ManaTokenizer
5
+
6
+ tokenizer = ManaTokenizer()
7
+
8
+ # Example text for tokenization
9
+ sample_text = "شرکت آسا پرداز آریسا در سال 96 با استقرار در شهرک علمی و فناوری اصفهان فعالیت رسمی خود را در زمینه سامانه های پردازش سریع (hpc) و رایانش ابری (cloud) آغاز کرد. این شرکت اولین ارائه دهنده تخصصی کاملاً مبتنی بر شتاب دهنده های گرافیکی برای محاسبات پردازش سریع در ایران است. این شرکت توانست در سال 1400 آزمایشگاه پردازشی_گرافیکی خیام را در شهرک علمی تحقیقاتی اصفهان ایجاد و تجهیز کند.این آزمایشگاه مجهز به بیش از 8600 هسته پردازشی و بیش از 800 هزار هسته پردازش گرافیکی کودا می باشد که در اختیار محققان,معماران,مهندسان و … ,برای انجام تمامی تحقیقات و پروژهای علمیشان قرار داده میشود.این آزمایشگاه دارای فضای ذخیره سازی 1.5 پتابایت همچنین فضای رم 15 هزار گیگابایتی میباشد. این آزمایشگاه مجهز به جدید ترین سرورها و پردازنده های گرافیکی روز دنیا می باشد که از تمامی نرم افزار های پیشرفته ی طراحی,معماری,مهندسی,شبیه سازی,حل مسائل پیش بینی مالی,بازی و سرگرمی,پزشکی و درمان پشتیبانی می کند."
10
+
11
+ # Tokenize a sample text to verify tokenizer function
12
+ encoded_sample = tokenizer.encode(sample_text)
13
+ tokens2 = encoded_sample.tokens
14
+ vocab_size2 = len(tokenizer.get_vocab())
15
+ print(f"Mana Vocabulary: {vocab_size2}")
16
+ print(f"Mana Algorithm: {tokenizer.__class__.__name__}")
17
+
18
+ # Print current date and time
19
+ current_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
20
+ print(f"Current Date and Time: {current_date}")
21
+
22
+ # Batch benchmark function using batch_encode
23
+ def benchmark_tokenizer_batch(tokenizer, texts):
24
+ start_time = time.time()
25
+ tokenizer.batch_encode(texts) # Use batch encoding here
26
+ end_time = time.time()
27
+ return end_time - start_time
28
+
29
+ # Large texts for benchmarking
30
+ large_texts = ["سال 96 با استقرار در شهرک علمی و فناوری اصفهان فعالیت رسمی خود را در زمینه سامانه های پردازش سریع (hpc) و رایانش ابری (cloud) آغاز."] * 1000
31
+
32
+ # Run the batch benchmark
33
+ time2 = benchmark_tokenizer_batch(tokenizer, large_texts)
34
+ print(f"Mana Batch Encode Time: {time2} seconds")
35
+
36
+ # Batch memory usage function
37
+ def memory_usage_tokenizer_batch(tokenizer, texts):
38
+ tracemalloc.start()
39
+ tokenizer.batch_encode(texts) # Use batch encoding here
40
+ snapshot = tracemalloc.take_snapshot()
41
+ tracemalloc.stop()
42
+
43
+ top_stats = snapshot.statistics('lineno')
44
+ return top_stats[0].size / 1024
45
+
46
+ # Measure memory usage for batch encoding
47
+ memory2 = memory_usage_tokenizer_batch(tokenizer, large_texts)
48
+ print(f"Mana Batch Encode Memory Usage: {memory2} KB")
49
+
50
+ # Calculate and print the total character count for large_texts
51
+ total_chars_large_texts = sum(len(text) for text in large_texts)
52
+ print(f"Total characters in large_texts: {total_chars_large_texts}")
mana_tokenizer.py CHANGED
@@ -1,13 +1,14 @@
 
1
  from .base import Tokenizer
2
  from .helper import get_stats, merge_batch_get_stats
3
  from heapq import nlargest
4
  import time
5
 
6
  MANA_SPECIAL_TOKENS = {
7
- '<|end|>': 100257,
8
- '<|user|>': 100258,
9
- '<|assistant|>': 100259,
10
- '<|system|>': 100260
11
  }
12
 
13
  class ManaTokenizer(Tokenizer):
@@ -17,9 +18,80 @@ class ManaTokenizer(Tokenizer):
17
  - special_tokens: str -> int dictionary of special tokens
18
  example: {'<|endoftext|>': 100257}
19
  """
20
- self.register_special_tokens(MANA_SPECIAL_TOKENS)
21
  super().__init__(pattern, multiprocess, store_dict, stop_list_size, freq_cutoff)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
 
 
 
 
 
 
 
 
 
 
23
  def train(self, data, vocab_size, cap_divisor=2, max_batch_size=0, verbose=False):
24
  t0 = time.time()
25
  ids = self._import_data(data) # [(bytes, int)] -> text chunks and their counts
 
1
+ import torch
2
  from .base import Tokenizer
3
  from .helper import get_stats, merge_batch_get_stats
4
  from heapq import nlargest
5
  import time
6
 
7
  MANA_SPECIAL_TOKENS = {
8
+ '<|end|>': 265712,
9
+ '<|user|>': 265713,
10
+ '<|assistant|>': 265714,
11
+ '<|system|>': 265715
12
  }
13
 
14
  class ManaTokenizer(Tokenizer):
 
18
  - special_tokens: str -> int dictionary of special tokens
19
  example: {'<|endoftext|>': 100257}
20
  """
 
21
  super().__init__(pattern, multiprocess, store_dict, stop_list_size, freq_cutoff)
22
+ self.register_special_tokens(MANA_SPECIAL_TOKENS)
23
+ self.load("mana_tokenizer/mana.model")
24
+ self.padding_side = "right"
25
+ self.pad_token_id = self.special_tokens.get('<|end|>')
26
+
27
+ @property
28
+ def tokens(self):
29
+ """Property to retrieve token IDs for a given text."""
30
+ return self._tokens
31
+
32
+ @property
33
+ def attention_masks(self):
34
+ """Property to retrieve attention masks for a given text."""
35
+ return self._attention_masks
36
+
37
+ def encode(self, text, allowed_special="none_raise"):
38
+ """Override encode to include attention masks."""
39
+ encoded_ids = super().encode(text, allowed_special=allowed_special)
40
+ self._tokens = encoded_ids
41
+ self._attention_masks = torch.ones(len(encoded_ids), dtype=torch.int32)
42
+ return self
43
+
44
+ def batch_encode(self, texts, padding=True):
45
+ """
46
+ Encode a list of texts with dynamic padding and attention masks.
47
+ Handles left padding and attention masking.
48
+
49
+ Parameters:
50
+ texts (list of str): List of texts to encode.
51
+ padding (bool): If True, pad sequences to the max length in the batch.
52
+
53
+ Returns:
54
+ dict: A dictionary containing input_ids and attention_mask tensors.
55
+ """
56
+ # Ensure encode method returns a dict with 'input_ids' and 'attention_mask'
57
+ encoded_texts = [{"input_ids": self.encode(text).tokens, "attention_mask": [1] * len(self.encode(text).tokens)}
58
+ for text in texts]
59
+
60
+ max_len = max(len(t["input_ids"]) for t in encoded_texts) if padding else None
61
+
62
+ # Apply padding with left alignment
63
+ input_ids = []
64
+ attention_masks = []
65
+ for encoding in encoded_texts:
66
+ ids = encoding["input_ids"]
67
+ attn_mask = encoding["attention_mask"]
68
+ if padding and len(ids) < max_len:
69
+ pad_len = max_len - len(ids)
70
+ if self.padding_side == "left":
71
+ ids = [self.pad_token_id] * pad_len + ids
72
+ attn_mask = [0] * pad_len + attn_mask
73
+ else:
74
+ ids = ids + [self.pad_token_id] * pad_len
75
+ attn_mask = attn_mask + [0] * pad_len
76
+ input_ids.append(ids)
77
+ attention_masks.append(attn_mask)
78
+
79
+ # Convert to tensors
80
+ input_ids = torch.tensor(input_ids, dtype=torch.long)
81
+ attention_masks = torch.tensor(attention_masks, dtype=torch.long)
82
+
83
+ return {"input_ids": input_ids, "attention_mask": attention_masks}
84
 
85
+
86
+ def get_vocab(self):
87
+ """Function to return the vocabulary dictionary."""
88
+ return self.vocab
89
+
90
+ @property
91
+ def vocab_size(self):
92
+ """Property to return the vocabulary size."""
93
+ return len(self.vocab)
94
+
95
  def train(self, data, vocab_size, cap_divisor=2, max_batch_size=0, verbose=False):
96
  t0 = time.time()
97
  ids = self._import_data(data) # [(bytes, int)] -> text chunks and their counts