We have switched from the Regex tokenizer to the SentencePiece tokenizer. (The updated code was written by OpenSoftware-World and corrected by ChatGPT.)
Browse filesSentencePiece is much more effective than the Regex tokenizer and is also used in large language models. At OpenSoftware-World, we have switched to the SentencePiece tokenizer for our OpenSoftware-World-OSW1 AI model so that it can produce high-quality and accurate results, just like other large language models.
- model_init.py +51 -30
model_init.py
CHANGED
|
@@ -7,6 +7,7 @@ import math
|
|
| 7 |
import torch
|
| 8 |
import torch.nn as nn
|
| 9 |
import torch.nn.functional as F
|
|
|
|
| 10 |
|
| 11 |
NUM_THREADS = os.cpu_count() or 4
|
| 12 |
torch.set_num_threads(NUM_THREADS)
|
|
@@ -17,40 +18,62 @@ except RuntimeError:
|
|
| 17 |
|
| 18 |
DEVICE = torch.device("cpu")
|
| 19 |
print(f"🧵 Number of CPU threads : {NUM_THREADS}")
|
| 20 |
-
TOKEN_RE = re.compile(r"\w+|[^\w\s]", re.UNICODE)
|
| 21 |
-
|
| 22 |
-
def tokenize(text: str):
|
| 23 |
-
return TOKEN_RE.findall(text.lower())
|
| 24 |
|
| 25 |
class Vocab:
|
| 26 |
-
PAD
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
-
|
| 29 |
-
self.
|
| 30 |
-
self.
|
|
|
|
| 31 |
|
| 32 |
def encode(self, text, add_bos=False, add_eos=False):
|
| 33 |
-
ids =
|
|
|
|
| 34 |
if add_bos:
|
| 35 |
-
ids = [self.
|
|
|
|
| 36 |
if add_eos:
|
| 37 |
-
ids = ids + [self.
|
|
|
|
| 38 |
return ids
|
| 39 |
|
| 40 |
def decode(self, ids):
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
return text
|
| 51 |
|
| 52 |
def __len__(self):
|
| 53 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
|
| 55 |
class CausalSelfAttention(nn.Module):
|
| 56 |
def __init__(self, d_model, n_head, dropout):
|
|
@@ -155,10 +178,8 @@ def load_checkpoint(path: str):
|
|
| 155 |
ckpt = torch.load(path, map_location="cpu")
|
| 156 |
|
| 157 |
cfg = ckpt["config"]
|
| 158 |
-
vocab = Vocab()
|
| 159 |
-
|
| 160 |
-
vocab.itos = ckpt["vocab_itos"]
|
| 161 |
-
pad_id = ckpt["pad_id"]
|
| 162 |
|
| 163 |
model = OSW1Model(len(vocab), cfg, pad_id=pad_id).to(DEVICE)
|
| 164 |
model.load_state_dict(ckpt["model_state_dict"])
|
|
@@ -187,7 +208,7 @@ def load_checkpoint(path: str):
|
|
| 187 |
|
| 188 |
def chat_loop(model: OSW1Model, vocab: Vocab):
|
| 189 |
print("=" * 64)
|
| 190 |
-
print("💬 OSW1 ready! You can start chatting. Type 'exit' to quit.")
|
| 191 |
print("=" * 64)
|
| 192 |
|
| 193 |
eos_id = vocab.stoi[Vocab.EOS]
|
|
@@ -211,7 +232,7 @@ def chat_loop(model: OSW1Model, vocab: Vocab):
|
|
| 211 |
out = model.generate(x, max_new_tokens=60, temperature=0.85, top_k=40, eos_id=eos_id)
|
| 212 |
answer_ids = out[0, len(ids):].tolist()
|
| 213 |
answer = vocab.decode(answer_ids)
|
| 214 |
-
print(f"OSW1: {answer if answer else '(...silence...)'}")
|
| 215 |
|
| 216 |
def main():
|
| 217 |
if len(sys.argv) > 1:
|
|
@@ -224,8 +245,8 @@ def main():
|
|
| 224 |
if ckpt_path is None:
|
| 225 |
print(
|
| 226 |
"❌ No checkpoint files found in the directory.\n"
|
| 227 |
-
" Please train a model using '
|
| 228 |
-
" specify a checkpoint file using '
|
| 229 |
)
|
| 230 |
sys.exit(1)
|
| 231 |
|
|
|
|
| 7 |
import torch
|
| 8 |
import torch.nn as nn
|
| 9 |
import torch.nn.functional as F
|
| 10 |
+
import sentencepiece as spm
|
| 11 |
|
| 12 |
NUM_THREADS = os.cpu_count() or 4
|
| 13 |
torch.set_num_threads(NUM_THREADS)
|
|
|
|
| 18 |
|
| 19 |
DEVICE = torch.device("cpu")
|
| 20 |
print(f"🧵 Number of CPU threads : {NUM_THREADS}")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
class Vocab:
|
| 23 |
+
PAD = "<pad>"
|
| 24 |
+
UNK = "<unk>"
|
| 25 |
+
BOS = "<bos>"
|
| 26 |
+
EOS = "<eos>"
|
| 27 |
+
|
| 28 |
+
def __init__(self, model_path="opensoftware_world_osw1_tokenizer.model"):
|
| 29 |
+
self.sp = spm.SentencePieceProcessor()
|
| 30 |
+
self.sp.load(model_path)
|
| 31 |
|
| 32 |
+
self.pad_id = self.sp.pad_id()
|
| 33 |
+
self.unk_id = self.sp.unk_id()
|
| 34 |
+
self.bos_id = self.sp.bos_id()
|
| 35 |
+
self.eos_id = self.sp.eos_id()
|
| 36 |
|
| 37 |
def encode(self, text, add_bos=False, add_eos=False):
|
| 38 |
+
ids = self.sp.encode(text, out_type=int)
|
| 39 |
+
|
| 40 |
if add_bos:
|
| 41 |
+
ids = [self.bos_id] + ids
|
| 42 |
+
|
| 43 |
if add_eos:
|
| 44 |
+
ids = ids + [self.eos_id]
|
| 45 |
+
|
| 46 |
return ids
|
| 47 |
|
| 48 |
def decode(self, ids):
|
| 49 |
+
ids = [
|
| 50 |
+
i for i in ids
|
| 51 |
+
if i not in (self.pad_id, self.bos_id)
|
| 52 |
+
]
|
| 53 |
+
|
| 54 |
+
if self.eos_id in ids:
|
| 55 |
+
ids = ids[:ids.index(self.eos_id)]
|
| 56 |
+
|
| 57 |
+
return self.sp.decode(ids)
|
|
|
|
| 58 |
|
| 59 |
def __len__(self):
|
| 60 |
+
return self.sp.get_piece_size()
|
| 61 |
+
|
| 62 |
+
@property
|
| 63 |
+
def stoi(self):
|
| 64 |
+
return {
|
| 65 |
+
self.PAD: self.pad_id,
|
| 66 |
+
self.UNK: self.unk_id,
|
| 67 |
+
self.BOS: self.bos_id,
|
| 68 |
+
self.EOS: self.eos_id,
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
@property
|
| 72 |
+
def itos(self):
|
| 73 |
+
return [
|
| 74 |
+
self.sp.id_to_piece(i)
|
| 75 |
+
for i in range(self.sp.get_piece_size())
|
| 76 |
+
]
|
| 77 |
|
| 78 |
class CausalSelfAttention(nn.Module):
|
| 79 |
def __init__(self, d_model, n_head, dropout):
|
|
|
|
| 178 |
ckpt = torch.load(path, map_location="cpu")
|
| 179 |
|
| 180 |
cfg = ckpt["config"]
|
| 181 |
+
vocab = Vocab("opensoftware_world_osw1_tokenizer.model")
|
| 182 |
+
pad_id = vocab.sp.pad_id()
|
|
|
|
|
|
|
| 183 |
|
| 184 |
model = OSW1Model(len(vocab), cfg, pad_id=pad_id).to(DEVICE)
|
| 185 |
model.load_state_dict(ckpt["model_state_dict"])
|
|
|
|
| 208 |
|
| 209 |
def chat_loop(model: OSW1Model, vocab: Vocab):
|
| 210 |
print("=" * 64)
|
| 211 |
+
print("💬 OpenSoftware-World-OSW1 ready! You can start chatting. Type 'exit' to quit.")
|
| 212 |
print("=" * 64)
|
| 213 |
|
| 214 |
eos_id = vocab.stoi[Vocab.EOS]
|
|
|
|
| 232 |
out = model.generate(x, max_new_tokens=60, temperature=0.85, top_k=40, eos_id=eos_id)
|
| 233 |
answer_ids = out[0, len(ids):].tolist()
|
| 234 |
answer = vocab.decode(answer_ids)
|
| 235 |
+
print(f"OpenSoftware-World-OSW1: {answer if answer else '(...silence...)'}")
|
| 236 |
|
| 237 |
def main():
|
| 238 |
if len(sys.argv) > 1:
|
|
|
|
| 245 |
if ckpt_path is None:
|
| 246 |
print(
|
| 247 |
"❌ No checkpoint files found in the directory.\n"
|
| 248 |
+
" Please train a model using 'python3 model_training.py' or\n"
|
| 249 |
+
" specify a checkpoint file using 'python3 model_init.py <file_path>'."
|
| 250 |
)
|
| 251 |
sys.exit(1)
|
| 252 |
|