hayder86al commited on
Commit
08ae84d
·
verified ·
1 Parent(s): 78f99a6

Upload folder using huggingface_hub

Browse files
README.md ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: transformers
3
+ tags:
4
+ - minigpt
5
+ - custom_code
6
+ - text-generation
7
+ license: mit
8
+ ---
9
+
10
+ # tinystories-50m-instruct
11
+
12
+ A ~50M-parameter GPT-style transformer (6 layers, 12 heads, 768 embd, 1024
13
+ context) trained from scratch on TinyStories and instruction-fine-tuned to
14
+ chat in a `User: ... / Assistant: ...` format.
15
+
16
+ ## Quick start
17
+
18
+ ```python
19
+ from transformers import AutoTokenizer, AutoModelForCausalLM
20
+
21
+ tokenizer = AutoTokenizer.from_pretrained("hayder86al/tinystories-50m-instruct")
22
+ model = AutoModelForCausalLM.from_pretrained("hayder86al/tinystories-50m-instruct", trust_remote_code=True)
23
+
24
+ def chat(prompt):
25
+ text = f"User: {prompt}\nAssistant:"
26
+ inputs = tokenizer(text, return_tensors="pt")
27
+ outputs = model.generate(
28
+ **inputs, max_new_tokens=120, do_sample=True, temperature=0.5,
29
+ top_k=40, use_cache=False,
30
+ pad_token_id=tokenizer.pad_token_id, eos_token_id=tokenizer.eos_token_id,
31
+ )
32
+ text_out = tokenizer.decode(outputs[0], skip_special_tokens=True)
33
+ return text_out.split("Assistant:")[-1].strip()
34
+
35
+ print(chat("What is 2+2?"))
36
+ ```
37
+
38
+ `trust_remote_code=True` is required because this repo defines a custom
39
+ architecture (`modeling_minigpt.py` / `configuration_minigpt.py`) — review
40
+ that code before running it.
41
+
42
+ ## Limitations
43
+
44
+ Single-turn only (no conversation memory), 1024-token context, small model —
45
+ expect simple, sometimes ungrammatical answers, not factual accuracy.
config.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "MiniGPTForCausalLM"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "configuration_minigpt.MiniGPTConfig",
7
+ "AutoModelForCausalLM": "modeling_minigpt.MiniGPTForCausalLM"
8
+ },
9
+ "context_len": 1024,
10
+ "dropout": 0.1,
11
+ "dtype": "float32",
12
+ "eos_token_id": 1,
13
+ "model_type": "minigpt",
14
+ "n_embd": 768,
15
+ "n_head": 12,
16
+ "n_layer": 6,
17
+ "pad_token_id": 0,
18
+ "transformers_version": "5.16.1",
19
+ "vocab_size": 8000
20
+ }
configuration_minigpt.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """HF config wrapper for MiniGPT (train_50M.py's CFG, made introspectable)."""
2
+
3
+ from transformers import PretrainedConfig
4
+
5
+
6
+ class MiniGPTConfig(PretrainedConfig):
7
+ model_type = "minigpt"
8
+
9
+ def __init__(
10
+ self,
11
+ vocab_size: int = 8_000,
12
+ n_embd: int = 768,
13
+ n_head: int = 12,
14
+ n_layer: int = 6,
15
+ context_len: int = 1024,
16
+ dropout: float = 0.1,
17
+ pad_token_id: int = 0,
18
+ eos_token_id: int = 1,
19
+ **kwargs,
20
+ ):
21
+ self.vocab_size = vocab_size
22
+ self.n_embd = n_embd
23
+ self.n_head = n_head
24
+ self.n_layer = n_layer
25
+ self.context_len = context_len
26
+ self.dropout = dropout
27
+ super().__init__(pad_token_id=pad_token_id, eos_token_id=eos_token_id, **kwargs)
generation_config.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "eos_token_id": 1,
4
+ "output_attentions": false,
5
+ "output_hidden_states": false,
6
+ "pad_token_id": 0,
7
+ "transformers_version": "5.16.1"
8
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c364d1109362057112581a4d8832f193981d794cb00158494b7fc5bc03b264ae
3
+ size 222345008
modeling_minigpt.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """HF-compatible MiniGPT — same architecture as train_50M.MiniGPT, wrapped as a
2
+ PreTrainedModel so it works with AutoModelForCausalLM / .generate() /
3
+ push_to_hub() (requires trust_remote_code=True, since this is a custom arch).
4
+
5
+ No KV cache, learned absolute positional embeddings: every forward re-crops the
6
+ sequence to the last `context_len` tokens and re-embeds positions from 0 —
7
+ that mirrors train_50M/chat.py exactly and is a correctness requirement, not
8
+ an optimization.
9
+ """
10
+
11
+ import torch
12
+ import torch.nn as nn
13
+ import torch.nn.functional as F
14
+ from transformers import GenerationMixin, PreTrainedModel
15
+ from transformers.modeling_outputs import CausalLMOutput
16
+
17
+ from .configuration_minigpt import MiniGPTConfig
18
+
19
+
20
+ class CausalSelfAttention(nn.Module):
21
+ def __init__(self, config):
22
+ super().__init__()
23
+ assert config.n_embd % config.n_head == 0
24
+ self.n_head = config.n_head
25
+ self.head_dim = config.n_embd // config.n_head
26
+ self.qkv = nn.Linear(config.n_embd, 3 * config.n_embd, bias=False)
27
+ self.proj = nn.Linear(config.n_embd, config.n_embd, bias=False)
28
+ self.dropout = config.dropout
29
+ self.resid_drop = nn.Dropout(config.dropout)
30
+
31
+ def forward(self, x):
32
+ B, T, C = x.shape
33
+ q, k, v = self.qkv(x).split(C, dim=2)
34
+
35
+ def split_heads(t):
36
+ return t.view(B, T, self.n_head, self.head_dim).transpose(1, 2)
37
+
38
+ q, k, v = split_heads(q), split_heads(k), split_heads(v)
39
+ out = F.scaled_dot_product_attention(
40
+ q, k, v, is_causal=True,
41
+ dropout_p=self.dropout if self.training else 0.0,
42
+ )
43
+ out = out.transpose(1, 2).contiguous().view(B, T, C)
44
+ return self.resid_drop(self.proj(out))
45
+
46
+
47
+ class FeedForward(nn.Module):
48
+ def __init__(self, config):
49
+ super().__init__()
50
+ self.fc = nn.Linear(config.n_embd, 4 * config.n_embd)
51
+ self.act = nn.GELU()
52
+ self.proj = nn.Linear(4 * config.n_embd, config.n_embd)
53
+ self.drop = nn.Dropout(config.dropout)
54
+
55
+ def forward(self, x):
56
+ return self.drop(self.proj(self.act(self.fc(x))))
57
+
58
+
59
+ class TransformerBlock(nn.Module):
60
+ def __init__(self, config):
61
+ super().__init__()
62
+ self.ln1 = nn.LayerNorm(config.n_embd)
63
+ self.attn = CausalSelfAttention(config)
64
+ self.ln2 = nn.LayerNorm(config.n_embd)
65
+ self.ff = FeedForward(config)
66
+
67
+ def forward(self, x):
68
+ x = x + self.attn(self.ln1(x))
69
+ x = x + self.ff(self.ln2(x))
70
+ return x
71
+
72
+
73
+ class MiniGPTForCausalLM(PreTrainedModel, GenerationMixin):
74
+ config_class = MiniGPTConfig
75
+ base_model_prefix = "minigpt"
76
+ main_input_name = "input_ids"
77
+
78
+ def __init__(self, config: MiniGPTConfig):
79
+ super().__init__(config)
80
+ self.token_emb = nn.Embedding(config.vocab_size, config.n_embd)
81
+ self.pos_emb = nn.Embedding(config.context_len, config.n_embd)
82
+ self.drop = nn.Dropout(config.dropout)
83
+ self.blocks = nn.Sequential(*[TransformerBlock(config) for _ in range(config.n_layer)])
84
+ self.ln_f = nn.LayerNorm(config.n_embd)
85
+ self.head = nn.Linear(config.n_embd, config.vocab_size, bias=False)
86
+ self.head.weight = self.token_emb.weight # weight tying, as in train_50M.MiniGPT
87
+ self.post_init()
88
+
89
+ def get_input_embeddings(self):
90
+ return self.token_emb
91
+
92
+ def set_input_embeddings(self, value):
93
+ self.token_emb = value
94
+
95
+ def get_output_embeddings(self):
96
+ return self.head
97
+
98
+ def set_output_embeddings(self, value):
99
+ self.head = value
100
+
101
+ def forward(self, input_ids=None, attention_mask=None, labels=None, **kwargs):
102
+ ctx = self.config.context_len
103
+ idx = input_ids[:, -ctx:]
104
+ pos = torch.arange(idx.size(1), device=idx.device)
105
+ x = self.drop(self.token_emb(idx) + self.pos_emb(pos))
106
+ x = self.blocks(x)
107
+ x = self.ln_f(x)
108
+ logits = self.head(x)
109
+
110
+ loss = None
111
+ if labels is not None:
112
+ labels = labels[:, -ctx:]
113
+ loss = F.cross_entropy(
114
+ logits.view(-1, logits.size(-1)), labels.view(-1), ignore_index=-100)
115
+ return CausalLMOutput(loss=loss, logits=logits)
116
+
117
+ # No KV cache exists for this architecture — every generation step resends
118
+ # the (cropped) full sequence, so there is nothing to thread through here.
119
+ def prepare_inputs_for_generation(self, input_ids, **kwargs):
120
+ return {"input_ids": input_ids}
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "eos_token": "<eos>",
4
+ "model_max_length": 1024,
5
+ "pad_token": "<pad>",
6
+ "tokenizer_class": "TokenizersBackend",
7
+ "unk_token": "<unk>"
8
+ }