OpenLab-NLP commited on
Commit
872e441
ยท
verified ยท
1 Parent(s): 98d43a4

Upload 4 files

Browse files
Files changed (4) hide show
  1. openlm.weights.h5 +3 -0
  2. tokenizer.model +3 -0
  3. tokenizer.vocab +0 -0
  4. ์ถ”๋ก .py +198 -0
openlm.weights.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5db6b49d3d0ba41030b618650f72874a2ebf8150ebcac0371cc611e40f3d81ef
3
+ size 32381304
tokenizer.model ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:46f7f887c9d36c6bde12637bc280a8a121c57a1ef6a3034e0e8f417ac4bfa6e1
3
+ size 517610
tokenizer.vocab ADDED
The diff for this file is too large to render. See raw diff
 
์ถ”๋ก .py ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import tensorflow as tf
3
+ import sentencepiece as spm
4
+ from tensorflow.keras import layers, Model
5
+
6
+ # 1. ํ† ํฌ๋‚˜์ด์ € ๋กœ๋“œ
7
+ TOKENIZER_PATH = "tokenizer.model"
8
+ sp = spm.SentencePieceProcessor(TOKENIZER_PATH)
9
+ pad_id = sp.piece_to_id("<pad>") if sp.piece_to_id("<pad>") != -1 else 0
10
+ bos_id = sp.piece_to_id("<s>") if sp.piece_to_id("<s>") != -1 else 1
11
+ eos_id = sp.piece_to_id("</s>")
12
+ vocab_size = sp.get_piece_size()
13
+
14
+ # 2. ๋ชจ๋ธ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ (ํ•™์Šต ๋•Œ์™€ ๋™์ผํ•œ ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ํ•„์ˆ˜)
15
+ # ํ•˜๋“œ์›จ์–ด ์‚ฌ์–‘์— ๋งž์ถฐ Strategy ๋ฒ”์œ„ ๋ฐ–์—์„œ ๋‹จ์ผ ์žฅ์น˜(CPU/GPU)์šฉ์œผ๋กœ ์ƒ์„ฑ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
16
+ d_model = 256
17
+ n_layers = 6
18
+ max_len = 1024
19
+
20
+
21
+ class RotaryPositionalEmbedding(layers.Layer):
22
+ def __init__(self, dim, max_seq_len=2048):
23
+ super().__init__()
24
+ self.dim = dim
25
+ self.max_seq_len = max_seq_len
26
+ # ๋ฏธ๋ฆฌ ์ฃผํŒŒ์ˆ˜ ์ •๋ณด๋ฅผ ๊ณ„์‚ฐํ•ด ๋‘ก๋‹ˆ๋‹ค.
27
+ inv_freq = 1.0 / (10000 ** (tf.range(0, dim, 2, dtype=tf.float32) / dim))
28
+ t = tf.range(max_seq_len, dtype=tf.float32)
29
+ freqs = tf.einsum('i,j->ij', t, inv_freq)
30
+ self.emb_sin = tf.exp(1.0) # ๋”๋ฏธ ์ดˆ๊ธฐํ™”
31
+ self.emb_cos = tf.exp(1.0)
32
+
33
+ # ์ƒ์ˆ˜๋กœ ์ €์žฅํ•˜์—ฌ ๋งค๋ฒˆ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๊ฒŒ ํ•จ
34
+ self.sin_cached = tf.sin(freqs)[tf.newaxis, tf.newaxis, :, :]
35
+ self.cos_cached = tf.cos(freqs)[tf.newaxis, tf.newaxis, :, :]
36
+
37
+ def call(self, x):
38
+ seq_len = tf.shape(x)[2]
39
+ t_type = x.dtype
40
+
41
+ # ์บ์‹ฑ๋œ ํ…Œ์ด๋ธ”์—์„œ ํ˜„์žฌ ์‹œํ€€์Šค ๊ธธ์ด๋งŒํผ๋งŒ ์ž˜๋ผ์„œ ์‚ฌ์šฉ
42
+ emb_sin = tf.cast(self.sin_cached[:, :, :seq_len, :], t_type)
43
+ emb_cos = tf.cast(self.cos_cached[:, :, :seq_len, :], t_type)
44
+
45
+ x1 = x[..., ::2]
46
+ x2 = x[..., 1::2]
47
+ out = tf.stack([x1 * emb_cos - x2 * emb_sin,
48
+ x1 * emb_sin + x2 * emb_cos], axis=-1)
49
+ return tf.reshape(out, tf.shape(x))
50
+
51
+ class SwiGLU(layers.Layer):
52
+ def __init__(self, d_model, d_ff):
53
+ super().__init__()
54
+
55
+ self.w12 = layers.Dense(d_ff, use_bias=False)
56
+ self.w3 = layers.Dense(d_model, use_bias=False)
57
+
58
+ def call(self, x):
59
+ x_proj = self.w12(x)
60
+ x_gate, x_val = tf.split(x_proj, 2, axis=-1)
61
+ return self.w3(tf.nn.silu(x_gate) * x_val)
62
+
63
+ class TransformerBlock(layers.Layer):
64
+ def __init__(self, d_model, d_ff, num_heads=4, dropout_rate=0.1):
65
+ super().__init__()
66
+ self.ln1 = layers.LayerNormalization(epsilon=1e-5)
67
+ self.mha = layers.MultiHeadAttention(num_heads=num_heads, key_dim=d_model // num_heads)
68
+ self.rope = RotaryPositionalEmbedding(d_model // num_heads)
69
+
70
+ self.ln2 = layers.LayerNormalization(epsilon=1e-5)
71
+ self.ffn = SwiGLU(d_model, d_ff)
72
+ self.dropout = layers.Dropout(dropout_rate)
73
+
74
+ def call(self, x, training=False):
75
+ # Attention Path
76
+ skip = x
77
+ x = self.ln1(x)
78
+
79
+ b, s, d = tf.unstack(tf.shape(x))
80
+ h = self.mha._num_heads
81
+ dh = d // h
82
+
83
+ qkv = tf.reshape(x, [b, s, h, dh])
84
+ qkv = tf.transpose(qkv, [0, 2, 1, 3]) # [b, h, s, dh]
85
+ qkv_rope = self.rope(qkv)
86
+ qkv_rope = tf.transpose(qkv_rope, [0, 2, 1, 3])
87
+ qkv_rope = tf.reshape(qkv_rope, [b, s, d])
88
+
89
+ attn_out = self.mha(query=qkv_rope, value=x, key=qkv_rope, use_causal_mask=True, training=training)
90
+ attn_out = attn_out
91
+ x = skip + self.dropout(attn_out, training=training)
92
+
93
+ # FFN Path
94
+ x = x + self.dropout(self.ffn(self.ln2(x)), training=training)
95
+ return x
96
+
97
+ class OpenLM(tf.keras.Model):
98
+ def __init__(self, vocab_size, d_model=256, n_layers=6, d_ff=1024, dropout_rate=0.1):
99
+ super().__init__()
100
+ self.d_model = d_model
101
+ # 1. ์ž„๋ฒ ๋”ฉ ๋ ˆ์ด์–ด ์ •์˜
102
+ self.token_embedding = layers.Embedding(vocab_size, d_model)
103
+
104
+ self.blocks = [TransformerBlock(d_model, d_ff, dropout_rate=dropout_rate) for _ in range(n_layers)]
105
+ self.ln_f = layers.LayerNormalization(epsilon=1e-5)
106
+ # lm_head ๋ ˆ์ด์–ด๋Š” ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.
107
+
108
+ def call(self, x, training=False):
109
+ # ์ž…๋ ฅ ์ž„๋ฒ ๋”ฉ
110
+ x = self.token_embedding(x)
111
+
112
+ for block in self.blocks:
113
+ x = block(x, training=training)
114
+
115
+ # ์ตœ์ข… ๋…ธ๋ฉ€๋ผ์ด์ œ์ด์…˜
116
+ x = self.ln_f(x)
117
+
118
+ # 2. ๊ฐ€์ค‘์น˜ ๊ณต์œ  (Weight Tying) ๊ตฌํ˜„
119
+ # embedding ๊ฐ€์ค‘์น˜๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. shape: [vocab_size, d_model]
120
+ weights = self.token_embedding.embeddings
121
+
122
+ # ์—ฐ์‚ฐ์„ ์œ„ํ•ด x๋ฅผ float32๋กœ ์˜ฌ๋ฆฌ๊ฑฐ๋‚˜, ๊ฐ€์ค‘์น˜๋ฅผ x์˜ ํƒ€์ž…์— ๋งž์ถฅ๋‹ˆ๋‹ค.
123
+ # ์—ฌ๊ธฐ์„œ๋Š” ์•ˆ์ •์„ฑ์„ ์œ„ํ•ด x์™€ ๊ฐ€์ค‘์น˜๋ฅผ ๋ชจ๋‘ float32๋กœ ์บ์ŠคํŒ…ํ•˜์—ฌ ์—ฐ์‚ฐํ•ฉ๋‹ˆ๋‹ค.
124
+ x = tf.cast(x, tf.float32)
125
+ weights = tf.cast(weights, tf.float32)
126
+
127
+ # 3. ํ–‰๋ ฌ๊ณฑ ์ˆ˜ํ–‰: [batch, seq, d_model] @ [d_model, vocab_size]
128
+ # transpose_b=True ์˜ต์…˜์„ ์ฃผ๋ฉด weights๋ฅผ [vocab_size, d_model]์—์„œ [d_model, vocab_size]๋กœ ๊ฐ„์ฃผํ•ด ๊ณฑํ•ฉ๋‹ˆ๋‹ค.
129
+ logits = tf.matmul(x, weights, transpose_b=True)
130
+
131
+ return logits # ์ด๋ฏธ float32์ด๋ฏ€๋กœ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜
132
+
133
+ lm = OpenLM(vocab_size=vocab_size, d_model=d_model, n_layers=n_layers)
134
+
135
+ # ๊ฐ€์ค‘์น˜ ๋กœ๋“œ๋ฅผ ์œ„ํ•ด ๋”๋ฏธ ์ž…๋ ฅ์œผ๋กœ ๋นŒ๋“œ
136
+ dummy_input = tf.zeros((1, 1), dtype=tf.int32)
137
+ _ = lm(dummy_input)
138
+
139
+ # 3. ๊ฐ€์ค‘์น˜ ๋กœ๋“œ
140
+ lm.load_weights("openlm.weights.h5")
141
+ print("โœ… ๋ชจ๋ธ ๊ฐ€์ค‘์น˜ ๋กœ๋“œ ์™„๋ฃŒ")
142
+
143
+ def generate_text(model, tokenizer, prompt, max_new_tokens=100, temperature=0.8, top_p=0.9):
144
+ input_ids = tokenizer.encode_as_ids(prompt)
145
+ input_ids = tf.expand_dims(tf.convert_to_tensor(input_ids, dtype=tf.int32), 0)
146
+
147
+ for _ in range(max_new_tokens):
148
+ # 1. ๋ชจ๋ธ ์˜ˆ์ธก
149
+ curr_input = input_ids[:, -max_len:]
150
+ logits = model(curr_input, training=False)
151
+ next_token_logits = logits[:, -1, :] # [Batch, Vocab]
152
+
153
+ # 2. Temperature ์ ์šฉ
154
+ if temperature > 0:
155
+ next_token_logits = next_token_logits / temperature
156
+ else:
157
+ # temperature๊ฐ€ 0์ด๋ฉด ๊ฐ€์žฅ ๋†’์€ ํ™•๋ฅ ๋งŒ ์„ ํƒ(Greedy)
158
+ next_token = tf.argmax(next_token_logits, axis=-1, output_type=tf.int32)
159
+ next_token = tf.reshape(next_token, [1, 1])
160
+ input_ids = tf.concat([input_ids, next_token], axis=-1)
161
+ if next_token[0, 0].numpy() == eos_id: break
162
+ continue
163
+
164
+ # 3. Top-p (Nucleus) Filtering
165
+ # ๋‚ด๋ฆผ์ฐจ์ˆœ ์ •๋ ฌ
166
+ sorted_logits = tf.sort(next_token_logits, direction='DESCENDING', axis=-1)
167
+ sorted_probs = tf.nn.softmax(sorted_logits, axis=-1)
168
+ cumulative_probs = tf.cumsum(sorted_probs, axis=-1)
169
+
170
+ # ๋ˆ„์  ํ™•๋ฅ ์ด top_p๋ฅผ ๋„˜๋Š” ๋กœ์ง“๋“ค์„ ์ฐพ์•„ ๋งค์šฐ ๋‚ฎ์€ ๊ฐ’์œผ๋กœ ๋งˆ์Šคํ‚น
171
+ # (์ฒซ ๋ฒˆ์งธ ํ† ํฐ์€ ์ œ์™ธํ•˜๊ธฐ ์œ„ํ•ด 1์นธ shift)
172
+ sorted_indices_to_remove = cumulative_probs > top_p
173
+ # ์ฒซ ๋ฒˆ์งธ(๊ฐ€์žฅ ๋†’์€ ํ™•๋ฅ ) ํ† ํฐ์€ ๋ฌด์กฐ๊ฑด ์œ ์ง€
174
+ mask_shifted = tf.concat([tf.zeros_like(sorted_indices_to_remove[:, :1]),
175
+ sorted_indices_to_remove[:, :-1]], axis=-1)
176
+
177
+ # ์ •๋ ฌ๋œ ์ƒํƒœ์—์„œ ๋งˆ์Šคํ‚น ๊ธฐ์ค€์ด ๋˜๋Š” '์ตœ์†Œ ๋กœ์ง“ ๊ฐ’' ๊ฒฐ์ •
178
+ # ๋งˆ์Šคํ‚น๋  ์œ„์น˜์˜ ๋กœ์ง“ ์ค‘ ๊ฐ€์žฅ ํฐ ๊ฐ’์„ ์ฐพ์•„ ๊ทธ๋ณด๋‹ค ์ž‘์€ ๋กœ์ง“์€ ๋‹ค ์ œ๊ฑฐ
179
+ min_logit_to_keep = tf.reduce_min(tf.where(mask_shifted, 1e10, sorted_logits), axis=-1, keepdims=True)
180
+
181
+ # ์›๋ณธ ๋กœ์ง“์— ๋งˆ์Šคํฌ ์ ์šฉ
182
+ next_token_logits = tf.where(next_token_logits < min_logit_to_keep, -1e10, next_token_logits)
183
+
184
+ # 4. ์ƒ˜ํ”Œ๋ง
185
+ next_token = tf.random.categorical(next_token_logits, num_samples=1)
186
+ next_token = tf.cast(next_token, tf.int32)
187
+
188
+ input_ids = tf.concat([input_ids, next_token], axis=-1)
189
+
190
+ if next_token[0, 0].numpy() == eos_id:
191
+ break
192
+
193
+ return tokenizer.decode_ids(input_ids[0].numpy().tolist())
194
+
195
+ # --- ์‹คํ–‰ ์˜ˆ์‹œ ---
196
+ prompt_text = "Question: What is AI?\nAnswer:"
197
+ result = generate_text(lm, sp, prompt_text, max_new_tokens=50, temperature=0.7)
198
+ print(f"\n๐Ÿš€ ์ƒ์„ฑ ๊ฒฐ๊ณผ:\n{result}")