Sherwinroger002 commited on
Commit
39ab78a
·
verified ·
1 Parent(s): 84a88f8

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ training_loss.png filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,3 +1,112 @@
1
  ---
 
 
 
 
 
 
 
 
 
2
  license: mit
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ language: en
3
+ tags:
4
+ - custom-gpt
5
+ - pytorch
6
+ - instruction-tuned
7
+ - from-scratch
8
+ datasets:
9
+ - HuggingFaceFW/fineweb-edu
10
+ - HuggingFaceH4/ultrachat_200k
11
  license: mit
12
  ---
13
+
14
+ # Luna-0.1b-Instruct
15
+
16
+ This is a **124 Million parameter** language model trained entirely from scratch on a consumer RTX 3060 Ti. Structurally identical to the original OpenAI GPT-2 Small, this model represents a complete end-to-end LLM training pipeline built independently.
17
+
18
+ ## 🧠 Training Details
19
+
20
+ The model was trained in two distinct phases to achieve "Compute-Optimal" performance for its size:
21
+
22
+ ### 1. Base Pretraining
23
+ - **Dataset:** [Fineweb-Edu](https://huggingface.co/datasets/HuggingFaceFW/fineweb-edu) (High-quality educational text).
24
+ - **Tokens:** ~2.6 Billion tokens.
25
+
26
+ ### 2. Supervised Fine-Tuning (SFT)
27
+ - **Dataset:** [UltraChat_200k](https://huggingface.co/datasets/HuggingFaceH4/ultrachat_200k) (Instruction / Q&A pairs).
28
+ - **Epochs:** 1 Epoch (~5,790 steps).
29
+ - **Final Train Loss:** 2.24
30
+ - **Best Validation Loss:** 2.10
31
+
32
+ ## 📉 Training Loss
33
+ Here is the training and validation loss curve during the 1-epoch Supervised Fine-Tuning phase:
34
+
35
+ ![Training Loss](training_loss.png)
36
+
37
+ ## 💻 How to Load and Run
38
+
39
+ Because this model uses a custom `model.py` architecture script (included in this repository), you don't load it using the standard `transformers` library pipeline. Instead, download the files from this repo and use the provided PyTorch script.
40
+
41
+ ```python
42
+ import torch
43
+ import tiktoken
44
+ import json
45
+ from model import GPTModel
46
+ from safetensors.torch import load_file
47
+
48
+ # 1. Load Config
49
+ with open("config.json") as f:
50
+ cfg = json.load(f)
51
+
52
+ # 2. Instantiate Model
53
+ model = GPTModel(cfg)
54
+
55
+ # 3. Load Safetensors
56
+ state_dict = load_file("model.safetensors")
57
+ model.load_state_dict(state_dict, strict=False)
58
+ model.cuda()
59
+ model.eval()
60
+
61
+ # 4. Tokenizer
62
+ tokenizer = tiktoken.get_encoding("gpt2")
63
+ eot_token_id = tokenizer.encode("<|endoftext|>", allowed_special={"<|endoftext|>"})[0]
64
+
65
+ # 5. Inference
66
+ prompt = (
67
+ "Below is an instruction that describes a task. "
68
+ "Write a response that appropriately completes the request.\n\n"
69
+ "### Instruction:\nWhat is the capital of France?\n\n### Response:\n"
70
+ )
71
+
72
+ input_ids = torch.tensor(tokenizer.encode(prompt)).unsqueeze(0).cuda()
73
+ generated = []
74
+
75
+ with torch.no_grad():
76
+ for _ in range(100):
77
+ logits = model(input_ids)
78
+ next_token_logits = logits[:, -1, :]
79
+
80
+ # Repetition Penalty
81
+ penalty = 1.2
82
+ for token_id in set(generated):
83
+ if next_token_logits[0, token_id] < 0:
84
+ next_token_logits[0, token_id] *= penalty
85
+ else:
86
+ next_token_logits[0, token_id] /= penalty
87
+
88
+ next_token_id = torch.argmax(next_token_logits, dim=-1).unsqueeze(0)
89
+
90
+ if next_token_id.item() == eot_token_id:
91
+ break
92
+
93
+ generated.append(next_token_id.item())
94
+ input_ids = torch.cat([input_ids, next_token_id], dim=-1)
95
+
96
+ print(tokenizer.decode(generated))
97
+ ```
98
+
99
+ ## 📝 Sample Output
100
+
101
+ When running inference with a repetition penalty of `1.2`, the model generates highly coherent text and follows instructions surprisingly well for its size:
102
+
103
+ **Prompt:**
104
+ > How can I stay motivated to exercise?
105
+
106
+ **Output:**
107
+ > 1. Set realistic goals and stick to them. This will help you feel more confident in your fitness level, which can lead to better results.
108
+ > 2. Practice mindfulness meditation or yoga regularly. Mindfulness meditation helps reduce stress levels and improve overall well-being.
109
+ > 3. Take breaks throughout the day to recharge and focus on your breath.
110
+ > 4. Exercise regularly. Regular physical activity can help boost energy levels and increase muscle mass.
111
+ > 5. Get enough sleep each night. Sleep is essential for maintaining good health and reducing stress levels.
112
+ > 6. Seek professional advice from a healthcare provider if you have any concerns about your fitness level.
config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "vocab_size": 50257,
3
+ "context_length": 512,
4
+ "emb_dim": 768,
5
+ "n_heads": 12,
6
+ "n_layers": 12,
7
+ "drop_rate": 0.1,
8
+ "qkv_bias": false
9
+ }
model.py ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from torch.utils.data import Dataset, DataLoader
3
+ import torch.nn as nn
4
+ import torch.nn.functional as F
5
+
6
+
7
+
8
+ class MultiHeadAttention(nn.Module):
9
+ def __init__(self,d_in,d_out,context_length,dropout,qkv_bias,n_heads):
10
+ super().__init__()
11
+ self.n_heads = n_heads
12
+ self.head_dim = d_out // n_heads
13
+ self.d_out = d_out
14
+ self.W_key = nn.Linear(d_in,d_out,bias=qkv_bias)
15
+ self.W_query = nn.Linear(d_in,d_out,bias=qkv_bias)
16
+ self.W_value = nn.Linear(d_in,d_out,bias=qkv_bias)
17
+ self.dropout = nn.Dropout(dropout)
18
+ self.proj = nn.Linear(d_out,d_out)
19
+ self.register_buffer(
20
+ 'mask',
21
+ torch.triu(torch.ones(context_length, context_length),
22
+ diagonal=1)
23
+ )
24
+
25
+ def forward(self,x):
26
+ b,n_tokens,d_out = x.shape
27
+ keys = self.W_key(x).view(b,n_tokens,self.n_heads,self.head_dim)
28
+ queries = self.W_query(x).view(b,n_tokens,self.n_heads,self.head_dim)
29
+ values = self.W_value(x).view(b,n_tokens,self.n_heads,self.head_dim)
30
+
31
+ keys = keys.transpose(1,2)
32
+ queries = queries.transpose(1,2)
33
+ values = values.transpose(1,2)
34
+
35
+ cntx_vec = F.scaled_dot_product_attention(
36
+ queries, keys, values,
37
+ attn_mask=None,
38
+ dropout_p=self.dropout.p if self.training else 0.0,
39
+ is_causal=True
40
+ )
41
+
42
+ cntx_vec = cntx_vec.transpose(1,2)
43
+
44
+ cntx_vec = cntx_vec.contiguous().view(b,n_tokens,self.d_out)
45
+
46
+ return self.proj(cntx_vec)
47
+
48
+
49
+
50
+
51
+ class NormLayer(nn.Module):
52
+ def __init__(self,emb_dim):
53
+ super().__init__()
54
+ self.eps = 1e-5
55
+ self.scale = nn.Parameter(torch.ones(emb_dim))
56
+ self.shift = nn.Parameter(torch.zeros(emb_dim))
57
+
58
+ def forward(self,x):
59
+ mean = x.mean(dim=-1,keepdim=True)
60
+ var = x.var(dim=-1,keepdim=True,unbiased=False)
61
+ return self.scale * ((x-mean)/torch.sqrt(var+self.eps)) + self.shift
62
+
63
+
64
+
65
+ class GELU(nn.Module):
66
+ def __init__(self):
67
+ super().__init__()
68
+
69
+ def forward(self, x):
70
+ return 0.5 * x * (1 + torch.tanh(
71
+ torch.sqrt(torch.tensor(2.0 / torch.pi)) *
72
+ (x + 0.044715 * torch.pow(x, 3))
73
+ ))
74
+
75
+
76
+
77
+ class FeedForward(nn.Module):
78
+ def __init__(self, cfg):
79
+ super().__init__()
80
+ self.layers = nn.Sequential(
81
+ nn.Linear(cfg["emb_dim"], 4 * cfg["emb_dim"]),
82
+ GELU(),
83
+ nn.Linear(4 * cfg["emb_dim"], cfg["emb_dim"]),
84
+ )
85
+
86
+ def forward(self, x):
87
+ return self.layers(x)
88
+
89
+
90
+ class TransformerBlock(nn.Module):
91
+ def __init__(self,cfg):
92
+ super().__init__()
93
+ self.attn = MultiHeadAttention(d_in=cfg["emb_dim"],d_out=cfg["emb_dim"],context_length=cfg["context_length"],dropout=cfg["drop_rate"],qkv_bias=cfg["qkv_bias"],n_heads=cfg["n_heads"])
94
+ self.ff = FeedForward(cfg)
95
+ self.norm1 = NormLayer(cfg["emb_dim"])
96
+ self.norm2 = NormLayer(cfg["emb_dim"])
97
+ self.drop_shortcut = nn.Dropout(cfg["drop_rate"])
98
+
99
+ def forward(self,x):
100
+ shortcut = x
101
+ x = self.norm1(x)
102
+ x = self.attn(x)
103
+ x = self.drop_shortcut(x)
104
+ x = x + shortcut
105
+
106
+ shortcut = x
107
+ x = self.norm2(x)
108
+ x = self.ff(x)
109
+ x = self.drop_shortcut(x)
110
+ x = x + shortcut
111
+
112
+ return x
113
+
114
+ vocab_size=50257
115
+
116
+ class GPTModel(nn.Module):
117
+ def __init__(self,cfg):
118
+ super().__init__()
119
+ self.tok_emb = nn.Embedding(vocab_size,cfg["emb_dim"])
120
+ self.pos_emb = nn.Embedding(cfg["context_length"],cfg["emb_dim"])
121
+ self.drop_emb = nn.Dropout(cfg["drop_rate"])
122
+ self.tranf_blocks = nn.Sequential(*[TransformerBlock(cfg) for _ in range(cfg["n_layers"])])
123
+ self.out_head = nn.Linear(cfg["emb_dim"],vocab_size)
124
+ self.final_norm = NormLayer(cfg["emb_dim"])
125
+
126
+ def forward(self,x):
127
+ b,n_inp = x.shape
128
+ tok_emb = self.tok_emb(x)
129
+ pos_emb = self.pos_emb(torch.arange(n_inp,device=x.device))
130
+ x = tok_emb + pos_emb
131
+ x= self.drop_emb(x)
132
+ x = self.tranf_blocks(x)
133
+ x = self.final_norm(x)
134
+ x = self.out_head(x)
135
+
136
+ return x
137
+
138
+ import torch.nn.functional as F
139
+
140
+
141
+ def top_k_top_p_filtering(logits, top_k=0, top_p=0.9):
142
+ if top_k > 0:
143
+ values, _ = torch.topk(logits, top_k)
144
+ min_values = values[:, -1].unsqueeze(-1)
145
+ logits = torch.where(
146
+ logits < min_values,
147
+ torch.tensor(float("-inf"), device=logits.device),
148
+ logits
149
+ )
150
+
151
+ if top_p < 1.0:
152
+ sorted_logits, sorted_indices = torch.sort(
153
+ logits,
154
+ descending=True
155
+ )
156
+
157
+ cumulative_probs = torch.cumsum(
158
+ F.softmax(sorted_logits, dim=-1),
159
+ dim=-1
160
+ )
161
+
162
+ sorted_indices_to_remove = cumulative_probs > top_p
163
+ sorted_indices_to_remove[:, 1:] = (
164
+ sorted_indices_to_remove[:, :-1].clone()
165
+ )
166
+
167
+ sorted_indices_to_remove[:, 0] = False
168
+
169
+ indices_to_remove = sorted_indices_to_remove.scatter(
170
+ 1,
171
+ sorted_indices,
172
+ sorted_indices_to_remove
173
+ )
174
+
175
+ logits = logits.masked_fill(
176
+ indices_to_remove,
177
+ float("-inf")
178
+ )
179
+
180
+ return logits
181
+
182
+
183
+ def apply_repetition_penalty(logits, generated_tokens, penalty=1.15):
184
+ for token in set(generated_tokens.tolist()):
185
+ logits[:, token] /= penalty
186
+
187
+ return logits
188
+
189
+
190
+ def generate_text(
191
+ model,
192
+ idx,
193
+ max_new_tokens,
194
+ context_size,
195
+ temperature=0.65,
196
+ top_k=30,
197
+ top_p=0.9,
198
+ repetition_penalty=1.15
199
+ ):
200
+
201
+ model.eval()
202
+
203
+ eos_token_id = 50256
204
+
205
+ with torch.no_grad():
206
+
207
+ for _ in range(max_new_tokens):
208
+
209
+ idx_cond = idx[:, -context_size:]
210
+
211
+ with torch.amp.autocast("cuda"):
212
+ logits = model(idx_cond)
213
+
214
+ logits = logits[:, -1, :]
215
+
216
+ logits = apply_repetition_penalty(
217
+ logits,
218
+ idx[0],
219
+ repetition_penalty
220
+ )
221
+
222
+ logits = logits / temperature
223
+
224
+ logits = top_k_top_p_filtering(
225
+ logits,
226
+ top_k=top_k,
227
+ top_p=top_p
228
+ )
229
+
230
+ probs = F.softmax(logits, dim=-1)
231
+
232
+ idx_next = torch.multinomial(
233
+ probs,
234
+ num_samples=1
235
+ )
236
+
237
+ idx = torch.cat(
238
+ (idx, idx_next),
239
+ dim=1
240
+ )
241
+
242
+ if idx_next.item() == eos_token_id:
243
+ break
244
+
245
+ return idx
246
+
247
+
248
+
249
+ def text_to_token_ids(text, tokenizer):
250
+ encoded = tokenizer.encode(text)
251
+ encoded_tensor = torch.tensor(encoded,device="cuda").unsqueeze(0) #1
252
+ return encoded_tensor
253
+
254
+ def token_ids_to_text(token_ids, tokenizer):
255
+ flat = token_ids.squeeze(0)
256
+ return tokenizer.decode(flat.tolist())
257
+
258
+
259
+
260
+ def generate_and_print_sample(
261
+ model,
262
+ tokenizer,
263
+ device,
264
+ start_context
265
+ ):
266
+
267
+ context_size = model.pos_emb.weight.shape[0]
268
+
269
+ encoded = text_to_token_ids(
270
+ start_context,
271
+ tokenizer
272
+ ).to(device)
273
+
274
+ token_ids = generate_text(
275
+ model=model,
276
+ idx=encoded,
277
+ max_new_tokens=512,
278
+ context_size=context_size,
279
+ temperature=0.65,
280
+ top_k=30,
281
+ top_p=0.9,
282
+ repetition_penalty=1.15
283
+ )
284
+
285
+ decoded_text = token_ids_to_text(
286
+ token_ids,
287
+ tokenizer
288
+ )
289
+
290
+ print(decoded_text.replace("\n", " "))
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d89cd8fd8817b76076893e841942284951a3f5c7bb43ed8146108b885314bc04
3
+ size 663266876
tokenizer/merges.txt ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer/special_tokens_map.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {
2
+ "bos_token": "<|endoftext|>",
3
+ "eos_token": "<|endoftext|>",
4
+ "unk_token": "<|endoftext|>"
5
+ }
tokenizer/tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer/tokenizer_config.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "added_tokens_decoder": {
4
+ "50256": {
5
+ "content": "<|endoftext|>",
6
+ "lstrip": false,
7
+ "normalized": true,
8
+ "rstrip": false,
9
+ "single_word": false,
10
+ "special": true
11
+ }
12
+ },
13
+ "bos_token": "<|endoftext|>",
14
+ "clean_up_tokenization_spaces": false,
15
+ "eos_token": "<|endoftext|>",
16
+ "extra_special_tokens": {},
17
+ "model_max_length": 1024,
18
+ "tokenizer_class": "GPT2Tokenizer",
19
+ "unk_token": "<|endoftext|>"
20
+ }
tokenizer/vocab.json ADDED
The diff for this file is too large to render. See raw diff
 
training_loss.png ADDED

Git LFS Details

  • SHA256: bdf625fea75d637424fa2095e6ef865e21103b12f92569d96f9bbf6ecffc8432
  • Pointer size: 131 Bytes
  • Size of remote file: 152 kB