OpenSoftware-World commited on
Commit
30b1619
ยท
verified ยท
1 Parent(s): d9d3b7c

Initialization code for the OpenSoftware-World-OSW1 AI model. (This code was written by Claude and edited by OpenSoftware-World.)

Browse files

Download one of our OpenSoftware-World-OSW1:5m, OpenSoftware-World-OSW1:10m, or OpenSoftware-World-OSW1:100m AI models and place it in the same folder as model_init.py. You can then start chatting with the OpenSoftware-World-OSW1 AI model.

Files changed (1) hide show
  1. model_init.py +237 -0
model_init.py ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import sys
4
+ import glob
5
+ import math
6
+
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)
13
+ try:
14
+ torch.set_num_interop_threads(max(1, NUM_THREADS // 2))
15
+ except RuntimeError:
16
+ pass
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, UNK, BOS, EOS = "<pad>", "<unk>", "<bos>", "<eos>"
27
+
28
+ def __init__(self):
29
+ self.stoi = {}
30
+ self.itos = []
31
+
32
+ def encode(self, text, add_bos=False, add_eos=False):
33
+ ids = [self.stoi.get(t, self.stoi[Vocab.UNK]) for t in tokenize(text)]
34
+ if add_bos:
35
+ ids = [self.stoi[Vocab.BOS]] + ids
36
+ if add_eos:
37
+ ids = ids + [self.stoi[Vocab.EOS]]
38
+ return ids
39
+
40
+ def decode(self, ids):
41
+ toks = [self.itos[i] for i in ids if 0 <= i < len(self.itos)]
42
+ toks = [t for t in toks if t != Vocab.PAD and t != Vocab.BOS]
43
+ out = []
44
+ for t in toks:
45
+ if t == Vocab.EOS:
46
+ break
47
+ out.append(t)
48
+ text = " ".join(out)
49
+ text = re.sub(r"\s+([.,!?;:])", r"\1", text)
50
+ return text
51
+
52
+ def __len__(self):
53
+ return len(self.itos)
54
+
55
+ class CausalSelfAttention(nn.Module):
56
+ def __init__(self, d_model, n_head, dropout):
57
+ super().__init__()
58
+ assert d_model % n_head == 0, "d_model must be evenly divisible by n_head"
59
+ self.n_head = n_head
60
+ self.head_dim = d_model // n_head
61
+ self.qkv = nn.Linear(d_model, 3 * d_model)
62
+ self.proj = nn.Linear(d_model, d_model)
63
+ self.attn_drop = nn.Dropout(dropout)
64
+ self.resid_drop = nn.Dropout(dropout)
65
+
66
+ def forward(self, x, attn_mask):
67
+ B, T, C = x.shape
68
+ qkv = self.qkv(x)
69
+ q, k, v = qkv.split(C, dim=2)
70
+ q = q.view(B, T, self.n_head, self.head_dim).transpose(1, 2)
71
+ k = k.view(B, T, self.n_head, self.head_dim).transpose(1, 2)
72
+ v = v.view(B, T, self.n_head, self.head_dim).transpose(1, 2)
73
+
74
+ att = (q @ k.transpose(-2, -1)) / math.sqrt(self.head_dim)
75
+ att = att.masked_fill(attn_mask, float("-inf"))
76
+ att = F.softmax(att, dim=-1)
77
+ att = self.attn_drop(att)
78
+ out = att @ v
79
+ out = out.transpose(1, 2).contiguous().view(B, T, C)
80
+ return self.resid_drop(self.proj(out))
81
+
82
+ class TransformerBlock(nn.Module):
83
+ def __init__(self, d_model, n_head, d_ff, dropout):
84
+ super().__init__()
85
+ self.ln1 = nn.LayerNorm(d_model)
86
+ self.attn = CausalSelfAttention(d_model, n_head, dropout)
87
+ self.ln2 = nn.LayerNorm(d_model)
88
+ self.mlp = nn.Sequential(
89
+ nn.Linear(d_model, d_ff),
90
+ nn.GELU(),
91
+ nn.Linear(d_ff, d_model),
92
+ nn.Dropout(dropout),
93
+ )
94
+
95
+ def forward(self, x, attn_mask):
96
+ x = x + self.attn(self.ln1(x), attn_mask)
97
+ x = x + self.mlp(self.ln2(x))
98
+ return x
99
+
100
+ class OSW1Model(nn.Module):
101
+ def __init__(self, vocab_size, cfg: dict, pad_id: int):
102
+ super().__init__()
103
+ self.cfg = cfg
104
+ self.pad_id = pad_id
105
+ self.block_size = cfg["block_size"]
106
+
107
+ self.tok_emb = nn.Embedding(vocab_size, cfg["d_model"])
108
+ self.pos_emb = nn.Embedding(cfg["block_size"], cfg["d_model"])
109
+ self.drop = nn.Dropout(cfg["dropout"])
110
+ self.blocks = nn.ModuleList([
111
+ TransformerBlock(cfg["d_model"], cfg["n_head"], cfg["d_ff"], cfg["dropout"])
112
+ for _ in range(cfg["n_layer"])
113
+ ])
114
+ self.ln_f = nn.LayerNorm(cfg["d_model"])
115
+ self.head = nn.Linear(cfg["d_model"], vocab_size, bias=False)
116
+ self.head.weight = self.tok_emb.weight # weight tying
117
+
118
+ def forward(self, idx):
119
+ B, T = idx.shape
120
+ pos = torch.arange(T, device=idx.device).unsqueeze(0)
121
+ x = self.drop(self.tok_emb(idx) + self.pos_emb(pos))
122
+
123
+ mask = torch.triu(torch.ones(T, T, dtype=torch.bool, device=idx.device), diagonal=1)
124
+ for block in self.blocks:
125
+ x = block(x, mask)
126
+ x = self.ln_f(x)
127
+ return self.head(x)
128
+
129
+ @torch.no_grad()
130
+ def generate(self, idx, max_new_tokens, temperature=0.85, top_k=40, eos_id=None):
131
+ self.eval()
132
+ for _ in range(max_new_tokens):
133
+ idx_cond = idx[:, -self.block_size:]
134
+ logits = self(idx_cond)
135
+ logits = logits[:, -1, :] / max(temperature, 1e-5)
136
+ if top_k is not None:
137
+ v, _ = torch.topk(logits, min(top_k, logits.size(-1)))
138
+ logits[logits < v[:, [-1]]] = float("-inf")
139
+ probs = F.softmax(logits, dim=-1)
140
+ next_id = torch.multinomial(probs, num_samples=1)
141
+ idx = torch.cat([idx, next_id], dim=1)
142
+ if eos_id is not None and next_id.item() == eos_id:
143
+ break
144
+ return idx
145
+
146
+ def find_checkpoint():
147
+ candidates = glob.glob("opensoftware_world_osw1_*.pth")
148
+ if not candidates:
149
+ return None
150
+ candidates.sort(key=os.path.getmtime, reverse=True)
151
+ return candidates[0]
152
+
153
+ def load_checkpoint(path: str):
154
+ print(f"๐Ÿ“ฆ Loading: {path}")
155
+ ckpt = torch.load(path, map_location="cpu")
156
+
157
+ cfg = ckpt["config"]
158
+ vocab = Vocab()
159
+ vocab.stoi = ckpt["vocab_stoi"]
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"])
165
+ model.eval()
166
+
167
+ param_count = ckpt.get("param_count", sum(p.numel() for p in model.parameters()))
168
+ training_time = ckpt.get("training_time_sec", None)
169
+ final_loss = ckpt.get("final_loss", None)
170
+
171
+ print("\n" + "=" * 64)
172
+ print("๐Ÿง  OpenSoftware-World OSW1 โ€” LOADED MODEL INFORMATION")
173
+ print("=" * 64)
174
+ print(f" File : {path}")
175
+ print(f" Vocab size : {len(vocab):,}")
176
+ print(f" Number of parameters : {param_count:,}")
177
+ print(f" d_model / n_layer : {cfg['d_model']} / {cfg['n_layer']}")
178
+ print(f" n_head / d_ff : {cfg['n_head']} / {cfg['d_ff']}")
179
+ print(f" Context window : {cfg['block_size']}")
180
+ if training_time is not None:
181
+ print(f" Training time : {training_time/60:.2f} minutes")
182
+ if final_loss is not None:
183
+ print(f" Final training loss : {final_loss:.4f}")
184
+ print("=" * 64 + "\n")
185
+
186
+ return model, vocab, cfg
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]
194
+ bos_id = vocab.stoi[Vocab.BOS]
195
+
196
+ while True:
197
+ try:
198
+ user_in = input("\nYou: ").strip()
199
+ except (EOFError, KeyboardInterrupt):
200
+ print("\n๐Ÿ‘‹ Goodbye!")
201
+ break
202
+
203
+ if user_in.lower() in ("exit", "quit"):
204
+ print("๐Ÿ‘‹ Goodbye!")
205
+ break
206
+ if not user_in:
207
+ continue
208
+
209
+ ids = [bos_id] + vocab.encode(user_in)
210
+ x = torch.tensor([ids], dtype=torch.long)
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:
218
+ ckpt_path = sys.argv[1]
219
+ if not os.path.isfile(ckpt_path):
220
+ print(f"โŒ File not found: {ckpt_path}")
221
+ sys.exit(1)
222
+ else:
223
+ ckpt_path = find_checkpoint()
224
+ if ckpt_path is None:
225
+ print(
226
+ "โŒ No checkpoint files found in the directory.\n"
227
+ " Please train a model using 'python train_osw1.py' or\n"
228
+ " specify a checkpoint file using 'python model_init.py <file_path>'."
229
+ )
230
+ sys.exit(1)
231
+
232
+ model, vocab, cfg = load_checkpoint(ckpt_path)
233
+ chat_loop(model, vocab)
234
+
235
+
236
+ if __name__ == "__main__":
237
+ main()