gijl commited on
Commit
8a0f059
·
verified ·
1 Parent(s): b804389

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -246
app.py DELETED
@@ -1,246 +0,0 @@
1
- import os
2
- import time
3
- import math
4
- import jax
5
- import jax.numpy as jnp
6
- import flax.linen as nn
7
- import orbax.checkpoint as ocp
8
- from transformers import AutoTokenizer
9
- from huggingface_hub import snapshot_download
10
-
11
- # ════════════════════════════════════════════════════════════════════════
12
- # 1. إعدادات النموذج والمتغيرات
13
- # ════════════════════════════════════════════════════════════════════════
14
- REPO_ID = "gijl/G2-Model-350m"
15
- TOKENIZER_NAME = "bert-base-multilingual-cased"
16
-
17
- D_MODEL = 1024
18
- D_U = 512
19
- D_V = 512
20
- HIDDEN_REACT = 3072
21
- N_ATTRACTORS = 22_000
22
- NUM_HEADS = 8
23
- NUM_LAYERS = 4
24
- MAX_LEN = 64
25
- COMPUTE_DTYPE = jnp.float16
26
-
27
- # ════════════════════════════════════════════════════════════════════════
28
- # 2. معمارية HTDN الدقيقة المطابقة للأوزان
29
- # ════════════════════════════════════════════════════════════════════════
30
- def rope_frequencies(d_head: int, base: float = 10000.0) -> jnp.ndarray:
31
- inv_freq = 1.0 / (base ** (jnp.arange(0, d_head, 2, dtype=jnp.float32) / d_head))
32
- return inv_freq
33
-
34
- def apply_rope(x: jnp.ndarray, positions: jnp.ndarray, inv_freq: jnp.ndarray) -> jnp.ndarray:
35
- freqs = jnp.einsum("l,d->ld", positions.astype(jnp.float32), inv_freq)
36
- cos = jnp.cos(freqs)[None, None, :, :]
37
- sin = jnp.sin(freqs)[None, None, :, :]
38
- x1, x2 = jnp.split(x.astype(jnp.float32), 2, axis=-1)
39
- return jnp.concatenate([x1 * cos - x2 * sin, x2 * cos + x1 * sin], axis=-1).astype(x.dtype)
40
-
41
- def _linear_recurrence_combine(l, r):
42
- a_l, b_l = l
43
- a_r, b_r = r
44
- return a_l * a_r, a_r * b_l + b_r
45
-
46
- class DynamicsLayer(nn.Module):
47
- d_u: int
48
- d_v: int
49
- n_attractors: int
50
- num_heads: int
51
-
52
- @nn.compact
53
- def __call__(self, x: jnp.ndarray, steps: int) -> jnp.ndarray:
54
- u = nn.Dense(self.d_u, dtype=COMPUTE_DTYPE)(x)
55
- v = nn.Dense(self.d_v, dtype=COMPUTE_DTYPE)(x)
56
-
57
- log_Du = self.param("log_Du", nn.initializers.normal(stddev=0.01), (self.num_heads,))
58
- log_Dv = self.param("log_Dv", nn.initializers.normal(stddev=0.01), (self.num_heads,))
59
- Du = nn.softplus(log_Du).mean()
60
- Dv = nn.softplus(log_Dv).mean()
61
-
62
- attr_u = nn.Dense(self.n_attractors, dtype=COMPUTE_DTYPE)(u)
63
- attr_v = nn.Dense(self.n_attractors, dtype=COMPUTE_DTYPE)(v)
64
- back_u = nn.Dense(self.d_u, dtype=COMPUTE_DTYPE)(attr_u)
65
- back_v = nn.Dense(self.d_v, dtype=COMPUTE_DTYPE)(attr_v)
66
-
67
- SAFE_BOUND = 30.0
68
- u0 = jnp.clip(u.astype(jnp.float32), -SAFE_BOUND, SAFE_BOUND)
69
- v0 = jnp.clip(v.astype(jnp.float32), -SAFE_BOUND, SAFE_BOUND)
70
- back_u = jnp.clip(back_u.astype(jnp.float32), -SAFE_BOUND, SAFE_BOUND)
71
- back_v = jnp.clip(back_v.astype(jnp.float32), -SAFE_BOUND, SAFE_BOUND)
72
-
73
- dt = 0.1 / max(1, steps)
74
- a_u = jnp.clip(1.0 - dt * Du.astype(jnp.float32), -0.99, 1.0)
75
- a_v = jnp.clip(1.0 - dt * Dv.astype(jnp.float32), -0.99, 1.0)
76
- b_u = dt * back_u
77
- b_v = dt * back_v
78
-
79
- A_u_seq = jnp.broadcast_to(a_u, (steps,) + u0.shape)
80
- B_u_seq = jnp.broadcast_to(b_u, (steps,) + u0.shape)
81
- A_v_seq = jnp.broadcast_to(a_v, (steps,) + v0.shape)
82
- B_v_seq = jnp.broadcast_to(b_v, (steps,) + v0.shape)
83
-
84
- cumA_u, cumB_u = jax.lax.associative_scan(_linear_recurrence_combine, (A_u_seq, B_u_seq), axis=0)
85
- cumA_v, cumB_v = jax.lax.associative_scan(_linear_recurrence_combine, (A_v_seq, B_v_seq), axis=0)
86
-
87
- u_final = jnp.clip(cumA_u[-1] * u0 + cumB_u[-1], -SAFE_BOUND, SAFE_BOUND)
88
- v_final = jnp.clip(cumA_v[-1] * v0 + cumB_v[-1], -SAFE_BOUND, SAFE_BOUND)
89
-
90
- return jnp.concatenate([u_final, v_final], axis=-1).astype(COMPUTE_DTYPE)
91
-
92
- class CausalSelfAttention(nn.Module):
93
- num_heads: int
94
- d_model: int
95
-
96
- @nn.compact
97
- def __call__(self, x: jnp.ndarray) -> jnp.ndarray:
98
- B, L, D = x.shape
99
- d_head = self.d_model // self.num_heads
100
- Q = nn.Dense(self.d_model, dtype=COMPUTE_DTYPE)(x).reshape(B, L, self.num_heads, d_head).transpose(0, 2, 1, 3)
101
- K = nn.Dense(self.d_model, dtype=COMPUTE_DTYPE)(x).reshape(B, L, self.num_heads, d_head).transpose(0, 2, 1, 3)
102
- V = nn.Dense(self.d_model, dtype=COMPUTE_DTYPE)(x).reshape(B, L, self.num_heads, d_head).transpose(0, 2, 1, 3)
103
-
104
- inv_freq = rope_frequencies(d_head)
105
- positions = jnp.arange(L)
106
- Q = apply_rope(Q, positions, inv_freq)
107
- K = apply_rope(K, positions, inv_freq)
108
-
109
- scores = jnp.matmul(Q, K.transpose(0, 1, 3, 2)) / math.sqrt(d_head)
110
- idx = jnp.arange(L)
111
- causal_mask = jnp.where(idx[:, None] >= idx[None, :], 0.0, -1e9)
112
- scores = scores + causal_mask[None, None, :, :]
113
- attn = nn.softmax(scores, axis=-1)
114
- out = jnp.matmul(attn, V).transpose(0, 2, 1, 3).reshape(B, L, self.d_model)
115
-
116
- return nn.Dense(self.d_model, dtype=COMPUTE_DTYPE)(out)
117
-
118
- class SwiGLUFFN(nn.Module):
119
- d_model: int
120
- hidden_dim: int
121
-
122
- @nn.compact
123
- def __call__(self, x: jnp.ndarray) -> jnp.ndarray:
124
- swiglu_hidden = max(1, int(self.hidden_dim * 2 / 3))
125
- gate = nn.Dense(swiglu_hidden, dtype=COMPUTE_DTYPE)(x)
126
- up = nn.Dense(swiglu_hidden, dtype=COMPUTE_DTYPE)(x)
127
- return nn.Dense(self.d_model, dtype=COMPUTE_DTYPE)(nn.swish(gate) * up)
128
-
129
- class HTDNBlock(nn.Module):
130
- d_model: int
131
- d_u: int
132
- d_v: int
133
- hidden_react: int
134
- n_attractors: int
135
- num_heads: int
136
-
137
- @nn.compact
138
- def __call__(self, x: jnp.ndarray, steps: int) -> jnp.ndarray:
139
- x = x + DynamicsLayer(self.d_u, self.d_v, self.n_attractors, self.num_heads)(nn.RMSNorm(dtype=COMPUTE_DTYPE)(x), steps)
140
- x = x + CausalSelfAttention(self.num_heads, self.d_model)(nn.RMSNorm(dtype=COMPUTE_DTYPE)(x))
141
- x = x + SwiGLUFFN(self.d_model, self.hidden_react)(nn.RMSNorm(dtype=COMPUTE_DTYPE)(x))
142
- return x
143
-
144
- class HTDNModel(nn.Module):
145
- vocab_size: int
146
- d_model: int
147
- d_u: int
148
- d_v: int
149
- hidden_react: int
150
- n_attractors: int
151
- num_heads: int
152
- num_layers: int
153
- max_len: int
154
-
155
- @nn.compact
156
- def __call__(self, input_ids: jnp.ndarray, steps: int) -> jnp.ndarray:
157
- embed = nn.Embed(self.vocab_size, self.d_model, dtype=COMPUTE_DTYPE)
158
- x = embed(input_ids)
159
- for _ in range(self.num_layers):
160
- x = HTDNBlock(self.d_model, self.d_u, self.d_v, self.hidden_react, self.n_attractors, self.num_heads)(x, steps)
161
- x = nn.RMSNorm(dtype=COMPUTE_DTYPE)(x)
162
- logits = jnp.matmul(x.astype(jnp.float32), embed.embedding.astype(jnp.float32).T)
163
- return logits
164
-
165
- # ════════════════════════════════════════════════════════════════════════
166
- # 3. التحميل الآمن والأستدلال
167
- # ════════════════════════════════════════════════════════════════════════
168
- print("⏳ جاري تنزيل أوزان المستودع من Hugging Face Hub...")
169
- repo_path = snapshot_download(repo_id=REPO_ID)
170
-
171
- print("⏳ جاري إعداد التوكنايزر والهيكل البرمجي...")
172
- tokenizer = AutoTokenizer.from_pretrained(TOKENIZER_NAME)
173
- PAD_ID = tokenizer.pad_token_id if tokenizer.pad_token_id is not None else 0
174
-
175
- model = HTDNModel(
176
- vocab_size=tokenizer.vocab_size,
177
- d_model=D_MODEL,
178
- d_u=D_U,
179
- d_v=D_V,
180
- hidden_react=HIDDEN_REACT,
181
- n_attractors=N_ATTRACTORS,
182
- num_heads=NUM_HEADS,
183
- num_layers=NUM_LAYERS,
184
- max_len=MAX_LEN
185
- )
186
-
187
- print("⏳ جاري استعادة أوزان Orbax من المسار المحلي...")
188
-
189
- # 💡 التعديل المحوري لتفادي أخطاء واجهة برمجة Orbax (API Mismatch)
190
- try:
191
- # الطريقة المضمونة 1: استخدام PyTreeCheckpointer مباشرة (مدعوم في أغلب الإصدارات)
192
- checkpointer = ocp.PyTreeCheckpointer()
193
- raw_restored = checkpointer.restore(repo_path)
194
- except AttributeError:
195
- # الطريقة المضمونة 2: في حال تم إزالة PyTreeCheckpointer في أحدث إصدار
196
- handler = ocp.PyTreeCheckpointHandler()
197
- checkpointer = ocp.Checkpointer(handler)
198
- raw_restored = checkpointer.restore(repo_path)
199
-
200
- # استخراج القاموس الداخلي بذكاء أياً كان شكل التغليف الذي حُفظ به
201
- if "params" in raw_restored:
202
- restored_params = raw_restored["params"]
203
- elif "model" in raw_restored:
204
- restored_params = raw_restored["model"]
205
- else:
206
- restored_params = raw_restored
207
-
208
- print("✅ تم استعادة أوزان النموذج بنجاح!")
209
-
210
- def generate_text(prompt: str, max_new_tokens: int = 25):
211
- ids = tokenizer(prompt, add_special_tokens=True, return_tensors="np")["input_ids"][0].tolist()
212
- ids = ids[:MAX_LEN]
213
-
214
- print(f"\n📝 النص المدخل: {prompt}")
215
- print("🤖 التوليد: ", end="", flush=True)
216
-
217
- for _ in range(max_new_tokens):
218
- if len(ids) >= MAX_LEN:
219
- break
220
- cur_len = len(ids)
221
- padded = ids + [PAD_ID] * (MAX_LEN - cur_len)
222
- input_arr = jnp.array(padded, dtype=jnp.int32)[None, :]
223
-
224
- # تطبيق النموذج باستخدام الأوزان المستخرجة
225
- logits = model.apply({"params": restored_params}, input_arr, steps=24)
226
- next_id = int(jnp.argmax(logits[0, cur_len - 1]))
227
-
228
- if next_id == PAD_ID:
229
- break
230
- ids.append(next_id)
231
-
232
- token_str = tokenizer.decode([next_id], skip_special_tokens=True)
233
- if token_str.startswith("##"):
234
- print(token_str[2:], end="", flush=True)
235
- else:
236
- print(" " + token_str, end="", flush=True)
237
- time.sleep(0.03)
238
- print("\n" + "─" * 50)
239
-
240
- if __name__ == "__main__":
241
- prompts = [
242
- "تعتبر معمارية الذكاء الاصطناعي",
243
- "تطوير النماذج باستخدام بايثون"
244
- ]
245
- for p in prompts:
246
- generate_text(p)