Murali Chandran commited on
Commit
dd2fdf7
·
1 Parent(s): ea24b46

Add exact vocab.json (95 tokens); align model param names; add guard

Browse files
Files changed (2) hide show
  1. bot_model.py +24 -24
  2. export_vocab.py +137 -0
bot_model.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import math
2
  import torch
3
  import torch.nn as nn
@@ -9,51 +10,50 @@ class CausalSelfAttention(nn.Module):
9
  assert d_model % num_heads == 0
10
  self.num_heads = num_heads
11
  self.d_k = d_model // num_heads
12
- self.q = nn.Linear(d_model, d_model)
13
- self.k = nn.Linear(d_model, d_model)
14
- self.v = nn.Linear(d_model, d_model)
15
- self.o = nn.Linear(d_model, d_model)
16
- self.drop = nn.Dropout(dropout)
 
17
 
18
  def forward(self, x):
19
  B, T, C = x.size()
20
- q = self.q(x).view(B, T, self.num_heads, C//self.num_heads).transpose(1,2)
21
- k = self.k(x).view(B, T, self.num_heads, C//self.num_heads).transpose(1,2)
22
- v = self.v(x).view(B, T, self.num_heads, C//self.num_heads).transpose(1,2)
23
- att = (q @ k.transpose(-2,-1)) / math.sqrt(self.d_k)
24
  mask = torch.tril(torch.ones(T, T, device=x.device))
25
- att = att.masked_fill(mask==0, float('-inf'))
26
  att = F.softmax(att, dim=-1)
27
- att = self.drop(att)
28
  y = att @ v
29
- y = y.transpose(1,2).contiguous().view(B, T, C)
30
- return self.o(y)
31
 
32
  class GPTBlock(nn.Module):
33
- def __init__(self, d_model, num_heads, d_ff, dropout=0.1):
34
  super().__init__()
35
  self.ln1 = nn.LayerNorm(d_model)
36
  self.attn = CausalSelfAttention(d_model, num_heads, dropout)
37
  self.ln2 = nn.LayerNorm(d_model)
38
- self.ff = nn.Sequential(
39
- nn.Linear(d_model, d_ff),
40
- nn.ReLU(),
41
- nn.Linear(d_ff, d_model),
42
- nn.Dropout(dropout)
43
  )
44
  def forward(self, x):
45
  x = x + self.attn(self.ln1(x))
46
- x = x + self.ff(self.ln2(x))
47
  return x
48
 
49
  class GPT(nn.Module):
50
  def __init__(self, vocab_size, d_model=192, num_heads=6, num_layers=4, max_len=320, dropout=0.1):
51
  super().__init__()
52
  self.token_emb = nn.Embedding(vocab_size, d_model)
53
- self.pos_emb = nn.Embedding(max_len, d_model)
54
- self.blocks = nn.ModuleList([GPTBlock(d_model, num_heads, 4*d_model, dropout) for _ in range(num_layers)])
55
- self.ln_f = nn.LayerNorm(d_model)
56
- self.head = nn.Linear(d_model, vocab_size, bias=False)
57
  self.cfg = dict(vocab_size=vocab_size, d_model=d_model, num_heads=num_heads, num_layers=num_layers, max_len=max_len, dropout=dropout)
58
 
59
  def forward(self, idx):
 
1
+ # bot_model.py
2
  import math
3
  import torch
4
  import torch.nn as nn
 
10
  assert d_model % num_heads == 0
11
  self.num_heads = num_heads
12
  self.d_k = d_model // num_heads
13
+ # NOTE: match checkpoint names exactly
14
+ self.W_q = nn.Linear(d_model, d_model)
15
+ self.W_k = nn.Linear(d_model, d_model)
16
+ self.W_v = nn.Linear(d_model, d_model)
17
+ self.W_o = nn.Linear(d_model, d_model)
18
+ self.dropout = nn.Dropout(dropout)
19
 
20
  def forward(self, x):
21
  B, T, C = x.size()
22
+ q = self.W_q(x).view(B, T, self.num_heads, C//self.num_heads).transpose(1, 2)
23
+ k = self.W_k(x).view(B, T, self.num_heads, C//self.num_heads).transpose(1, 2)
24
+ v = self.W_v(x).view(B, T, self.num_heads, C//self.num_heads).transpose(1, 2)
25
+ att = (q @ k.transpose(-2, -1)) / math.sqrt(self.d_k)
26
  mask = torch.tril(torch.ones(T, T, device=x.device))
27
+ att = att.masked_fill(mask == 0, float('-inf'))
28
  att = F.softmax(att, dim=-1)
29
+ att = self.dropout(att)
30
  y = att @ v
31
+ y = y.transpose(1, 2).contiguous().view(B, T, C)
32
+ return self.W_o(y)
33
 
34
  class GPTBlock(nn.Module):
35
+ def __init__(self, d_model, num_heads, d_ff=768, dropout=0.1):
36
  super().__init__()
37
  self.ln1 = nn.LayerNorm(d_model)
38
  self.attn = CausalSelfAttention(d_model, num_heads, dropout)
39
  self.ln2 = nn.LayerNorm(d_model)
40
+ # NOTE: match checkpoint module name "ffn"
41
+ self.ffn = nn.Sequential(
42
+ nn.Linear(d_model, d_ff), nn.ReLU(), nn.Linear(d_ff, d_model), nn.Dropout(dropout)
 
 
43
  )
44
  def forward(self, x):
45
  x = x + self.attn(self.ln1(x))
46
+ x = x + self.ffn(self.ln2(x))
47
  return x
48
 
49
  class GPT(nn.Module):
50
  def __init__(self, vocab_size, d_model=192, num_heads=6, num_layers=4, max_len=320, dropout=0.1):
51
  super().__init__()
52
  self.token_emb = nn.Embedding(vocab_size, d_model)
53
+ self.pos_emb = nn.Embedding(max_len, d_model)
54
+ self.blocks = nn.ModuleList([GPTBlock(d_model, num_heads, 4*d_model, dropout) for _ in range(num_layers)])
55
+ self.ln_f = nn.LayerNorm(d_model)
56
+ self.head = nn.Linear(d_model, vocab_size, bias=False)
57
  self.cfg = dict(vocab_size=vocab_size, d_model=d_model, num_heads=num_heads, num_layers=num_layers, max_len=max_len, dropout=dropout)
58
 
59
  def forward(self, idx):
export_vocab.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # export_vocab.py
2
+ import json, random
3
+
4
+ # ---- Gen config (must mirror your training script that produced this checkpoint) ----
5
+ EXTRA_CHARSET = (
6
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
7
+ "abcdefghijklmnopqrstuvwxyz"
8
+ "0123456789"
9
+ " +-*/=?:.,'\"()[]"
10
+ "$£€₹¥₩₦"
11
+ )
12
+
13
+ ITEMS = ["apple","mango","banana","orange","pear","kiwi","pen","notebook","ticket","cookie","product"]
14
+ ASKS = [
15
+ "how much is {n} {item_plural}?",
16
+ "what's the cost of {n} {item_plural}?",
17
+ "price for {n} {item_plural}?",
18
+ "how much would {n} {item_plural} cost?",
19
+ "what do I pay for {n} {item_plural}?",
20
+ "total price of {n} {item_plural}?",
21
+ "what's {n} {item_plural} going to cost?"
22
+ ]
23
+ COPULA = ["is", "costs", "priced at", "= ", "comes to", "sells for"]
24
+
25
+ def s(x, w): return w if x == 1 else (w + "s")
26
+
27
+ def money(v: float) -> str:
28
+ return str(int(round(v))) if abs(v - round(v)) < 1e-9 else f"{v:.2f}"
29
+
30
+ CURRENCIES = [
31
+ {"prefix":"$", "name_sing":"dollar", "name_plur":"dollars"},
32
+ {"prefix":"£", "name_sing":"pound", "name_plur":"pounds"},
33
+ {"prefix":"€", "name_sing":"euro", "name_plur":"euros"},
34
+ {"prefix":"₹", "name_sing":"rupee", "name_plur":"rupees"},
35
+ {"prefix":"¥", "name_sing":"yen", "name_plur":"yen"},
36
+ {"prefix":"₩", "name_sing":"won", "name_plur":"won"},
37
+ {"prefix":"₦", "name_sing":"naira", "name_plur":"naira"},
38
+ {"prefix":"A$", "name_sing":"dollar", "name_plur":"dollars"},
39
+ {"prefix":"C$", "name_sing":"dollar", "name_plur":"dollars"},
40
+ {"prefix":"CHF","name_sing":"franc", "name_plur":"francs"},
41
+ {"prefix":"د.إ","name_sing":"dirham", "name_plur":"dirhams"},
42
+ {"prefix":"", "name_sing":"dollar", "name_plur":"dollars"},
43
+ {"prefix":"", "name_sing":"pound", "name_plur":"pounds"},
44
+ {"prefix":"", "name_sing":"rupee", "name_plur":"rupees"},
45
+ {"prefix":"", "name_sing":"euro", "name_plur":"euros"}
46
+ ]
47
+ EXTRA_CURRENCY_WORDS = [
48
+ ("peso","pesos"), ("dinar","dinars"), ("dirham","dirhams"), ("riyal","riyals"),
49
+ ("rial","rials"), ("krona","kronor"), ("krone","kroner"), ("koruna","koruny"),
50
+ ("rand","rand"), ("shekel","shekels"), ("lira","lire"), ("ruble","rubles"),
51
+ ("rouble","roubles"), ("yuan","yuan"), ("renminbi","renminbi"), ("ringgit","ringgit"),
52
+ ("baht","baht"), ("dong","dong"), ("taka","taka"), ("rupiah","rupiah"),
53
+ ("shilling","shillings"), ("kuna","kuna"), ("zloty","zlotys"), ("forint","forints"),
54
+ ("leu","lei"), ("riel","riel"), ("kyat","kyat"), ("quetzal","quetzales"),
55
+ ("bolivar","bolivares"), ("colon","colones"), ("sol","soles")
56
+ ]
57
+ SYNTHETIC_CURRENCY_WORDS = [
58
+ ("credit","credits"), ("token","tokens"), ("coin","coins"), ("unit","units"),
59
+ ("galactic credit","galactic credits"), ("space buck","space bucks")
60
+ ]
61
+ WORD_POOL = [{"prefix":"", "name_sing":a, "name_plur":b} for (a,b) in (EXTRA_CURRENCY_WORDS + SYNTHETIC_CURRENCY_WORDS)]
62
+
63
+ # We only need enough samples to surface all characters that occurred in training text
64
+ def cur_str(cur: dict, v: float) -> str:
65
+ if cur["prefix"]:
66
+ return f"{cur['prefix']}{money(v)}"
67
+ name = cur["name_sing"] if abs(v - 1.0) < 1e-9 else cur["name_plur"]
68
+ return f"{money(v)} {name}"
69
+
70
+ def make_addition():
71
+ k = random.randint(2, 6)
72
+ nums = [random.randint(0, 200) for _ in range(k)]
73
+ expr = " + ".join(map(str, nums))
74
+ s_ = sum(nums)
75
+ tail = random.choice(["", " = ?", " = ", "?"])
76
+ return f"q: {expr}{tail} a: step 1: take {nums[0]}. step 2: add {nums[1]}. step 3: {expr} = {s_}. final answer: {s_} <EOS>"
77
+
78
+ def make_subtraction():
79
+ a = random.randint(0,200); b = random.randint(0,a)
80
+ s_ = a - b
81
+ tail = random.choice(["", " = ?", " = ", "?"])
82
+ return f"q: {a} - {b}{tail} a: step 1: take {a}. step 2: subtract {b}. step 3: {a} - {b} = {s_}. final answer: {s_} <EOS>"
83
+
84
+ def make_multiplication():
85
+ a = random.randint(0,50); b = random.randint(0,20)
86
+ s_ = a*b
87
+ tail = random.choice(["", " = ?", " = ", "?"])
88
+ return f"q: {a} × {b}{tail} a: step 1: take {a}. step 2: multiply by {b}. step 3: {a} × {b} = {s_}. final answer: {s_} <EOS>"
89
+
90
+ def make_division():
91
+ b = random.randint(1, 20); qv = random.randint(0, 50); a = b*qv
92
+ tail = random.choice(["", " = ?", " = ", "?"])
93
+ return f"q: {a} ÷ {b}{tail} a: step 1: take {a}. step 2: divide by {b}. step 3: {a} ÷ {b} = {qv}. final answer: {qv} <EOS>"
94
+
95
+ def make_unit_price():
96
+ item = random.choice(ITEMS); qty = random.randint(1, 15)
97
+ unit_price = random.choice([0.39,0.5,0.75,1.2,1.5,2.25,3.4,4.99]) if (random.random()<0.5) else random.randint(1,30)
98
+ cost = unit_price * qty; target = random.randint(1, 30)
99
+ cur = random.choice(CURRENCIES) if random.random() < 0.7 else random.choice(WORD_POOL)
100
+ cop = random.choice(COPULA); ask = random.choice(ASKS)
101
+ if random.random() < 0.5:
102
+ q = f"{qty} {s(qty,item)} {cop} {cur_str(cur,cost)}, {ask.format(n=target, item_plural=s(target,item))}"
103
+ else:
104
+ q = f"{qty} {s(qty,item)} cost {cur_str(cur,cost)}. {ask.format(n=target, item_plural=s(target,item))}"
105
+ unit = cost/qty; total = unit*target
106
+ return f"q: {q} a: step 1: find unit price: {cur_str(cur,cost)} / {qty} = {cur_str(cur,unit)} per {item}. step 2: multiply by {target}: {cur_str(cur,unit)} × {target} = {cur_str(cur,total)}. final answer: {cur_str(cur,total)} <EOS>"
107
+
108
+ def make_group_price():
109
+ item = random.choice(ITEMS); group_qty = random.randint(2, 20)
110
+ price = random.choice([9.0,10.0,12.5,7.2,15.75,19.99,3.3,4.5,21.95]) if (random.random()<0.7) else float(random.randint(2,60))
111
+ target = random.randint(1,40); cur = random.choice(CURRENCIES)
112
+ q = f"{group_qty} {s(group_qty,item)} for {cur_str(cur,price)}, what's the price for {target} {s(target,item)}?"
113
+ unit = price/group_qty; total = unit*target
114
+ return f"q: {q} a: step 1: unit price = {cur_str(cur,price)} / {group_qty} = {cur_str(cur,unit)} per {item}. step 2: total = {cur_str(cur,unit)} × {target} = {cur_str(cur,total)}. final answer: {cur_str(cur,total)} <EOS>"
115
+
116
+ def build_seed_pool():
117
+ pool = []
118
+ for _ in range(200): pool.append(make_addition())
119
+ for _ in range(150): pool.append(make_subtraction())
120
+ for _ in range(150): pool.append(make_multiplication())
121
+ for _ in range(150): pool.append(make_division())
122
+ for _ in range(150): pool.append(make_unit_price())
123
+ for _ in range(100): pool.append(make_group_price())
124
+ random.shuffle(pool)
125
+ return pool
126
+
127
+ if __name__ == "__main__":
128
+ SEED_POOL = build_seed_pool()
129
+ seed_text = "\n".join(SEED_POOL)
130
+ base_chars = sorted(set(seed_text) | set(EXTRA_CHARSET))
131
+ # IMPORTANT: the older checkpoint DID NOT include <EOS> in the vocab
132
+ SPECIAL = ["<PAD>", "<UNK>"]
133
+ itos_list = SPECIAL + base_chars
134
+ print("len(itos) =", len(itos_list))
135
+ with open("vocab.json", "w", encoding="utf-8") as f:
136
+ json.dump({"itos": itos_list}, f, ensure_ascii=False, indent=2)
137
+ print("Wrote vocab.json")