CodeSoft commited on
Commit
249471c
·
verified ·
1 Parent(s): 96ef5f8

Upload 6 files

Browse files
config.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "hidden_size": 768,
3
+ "intermediate_size": 2112,
4
+ "num_hidden_layers": 16,
5
+ "num_attention_heads": 12,
6
+ "num_key_value_heads": 6,
7
+ "head_dim": 64,
8
+ "vocab_size": 32000,
9
+ "mask_vocab_size": 32001,
10
+ "max_position_embeddings": 5120,
11
+ "rope_theta": 10000.0,
12
+ "rms_norm_eps": 1e-06,
13
+ "hidden_act": "silu",
14
+ "timestep_emb_hidden": 768,
15
+ "mask_token_id": 32000,
16
+ "pad_token_id": 1,
17
+ "mask_ratio_min": 0.0,
18
+ "mask_ratio_max": 1.0,
19
+ "model_type": "metadiffusion",
20
+ "architectures": [
21
+ "MetaDiffusionForCausalLM"
22
+ ]
23
+ }
generation_config.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token_id": 0,
3
+ "eos_token_id": 2,
4
+ "pad_token_id": 1,
5
+ "mask_token_id": 32000,
6
+ "temperature": 0.6,
7
+ "repetition_penalty": 1.5,
8
+ "re_mask": 0.1,
9
+ "num_steps": 512,
10
+ "max_new_tokens": 512,
11
+ "use_cache": false,
12
+ "transformers_version": "4.40.0"
13
+ }
inference.py ADDED
@@ -0,0 +1,391 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+
3
+ import argparse
4
+ import json
5
+ import os
6
+ import sys
7
+ import math
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+ import torch.nn.functional as F
12
+ from safetensors.torch import load_file
13
+ from transformers import AutoTokenizer, AutoConfig
14
+
15
+
16
+ # ---------------------------------------------------------------------------
17
+ # Model definition
18
+ # ---------------------------------------------------------------------------
19
+
20
+ class MetaDiffusionConfig:
21
+ def __init__(self, **kwargs):
22
+ for k, v in kwargs.items():
23
+ setattr(self, k, v)
24
+
25
+
26
+ class RMSNorm(nn.Module):
27
+ def __init__(self, hidden_size, eps=1e-6):
28
+ super().__init__()
29
+ self.weight = nn.Parameter(torch.ones(hidden_size))
30
+ self.eps = eps
31
+
32
+ def forward(self, x):
33
+ var = x.pow(2).mean(-1, keepdim=True)
34
+ x = x * torch.rsqrt(var + self.eps)
35
+ return self.weight * x
36
+
37
+
38
+ class RotaryEmbedding(nn.Module):
39
+ def __init__(self, dim, max_position_embeddings=5120, base=10000.0):
40
+ super().__init__()
41
+ inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))
42
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
43
+
44
+ def forward(self, x, position_ids):
45
+ inv_freq_expanded = self.inv_freq[None, :, None].float().expand(
46
+ position_ids.shape[0], -1, 1
47
+ )
48
+ position_ids_expanded = position_ids[:, None, :].float()
49
+ freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(1, 2)
50
+ emb = torch.cat((freqs, freqs), dim=-1)
51
+ return emb.cos().to(dtype=x.dtype), emb.sin().to(dtype=x.dtype)
52
+
53
+
54
+ def rotate_half(x):
55
+ x1, x2 = x.chunk(2, dim=-1)
56
+ return torch.cat((-x2, x1), dim=-1)
57
+
58
+
59
+ def apply_rotary_pos_emb(q, k, cos, sin):
60
+ cos = cos.unsqueeze(1)
61
+ sin = sin.unsqueeze(1)
62
+ q_embed = (q * cos) + (rotate_half(q) * sin)
63
+ k_embed = (k * cos) + (rotate_half(k) * sin)
64
+ return q_embed, k_embed
65
+
66
+
67
+ class TimestepEmbedding(nn.Module):
68
+ def __init__(self, hidden_size):
69
+ super().__init__()
70
+ self.mlp = nn.Sequential(
71
+ nn.Linear(hidden_size, hidden_size * 4),
72
+ nn.SiLU(),
73
+ nn.Linear(hidden_size * 4, hidden_size),
74
+ )
75
+
76
+ def forward(self, t):
77
+ half_dim = self.mlp[0].in_features // 2
78
+ emb = math.log(10000.0) / (half_dim - 1)
79
+ emb = torch.exp(torch.arange(half_dim, device=t.device) * -emb)
80
+ emb = t[:, None].float() * emb[None, :]
81
+ emb = torch.cat([emb.sin(), emb.cos()], dim=-1)
82
+ return self.mlp(emb)
83
+
84
+
85
+ class TimestepResidual(nn.Module):
86
+ def __init__(self, hidden_size):
87
+ super().__init__()
88
+ self.proj = nn.Linear(hidden_size, hidden_size)
89
+
90
+ def forward(self, x, emb):
91
+ return x + self.proj(emb)[:, None, :]
92
+
93
+
94
+ class SelfAttention(nn.Module):
95
+ def __init__(self, config):
96
+ super().__init__()
97
+ self.hidden_size = config.hidden_size
98
+ self.num_heads = config.num_attention_heads
99
+ self.num_kv_heads = config.num_key_value_heads
100
+ self.head_dim = config.head_dim
101
+ self.num_kv_groups = self.num_heads // self.num_kv_heads
102
+
103
+ self.q_proj = nn.Linear(config.hidden_size, self.num_heads * self.head_dim, bias=False)
104
+ self.k_proj = nn.Linear(config.hidden_size, self.num_kv_heads * self.head_dim, bias=False)
105
+ self.v_proj = nn.Linear(config.hidden_size, self.num_kv_heads * self.head_dim, bias=False)
106
+ self.o_proj = nn.Linear(self.num_heads * self.head_dim, config.hidden_size, bias=False)
107
+ self.rotary_emb = RotaryEmbedding(
108
+ config.head_dim,
109
+ max_position_embeddings=config.max_position_embeddings,
110
+ base=config.rope_theta,
111
+ )
112
+
113
+ def forward(self, x, position_ids):
114
+ batch, seq, _ = x.shape
115
+ q = self.q_proj(x).view(batch, seq, self.num_heads, self.head_dim).transpose(1, 2)
116
+ k = self.k_proj(x).view(batch, seq, self.num_kv_heads, self.head_dim).transpose(1, 2)
117
+ v = self.v_proj(x).view(batch, seq, self.num_kv_heads, self.head_dim).transpose(1, 2)
118
+
119
+ cos, sin = self.rotary_emb(x, position_ids)
120
+ q, k = apply_rotary_pos_emb(q, k, cos, sin)
121
+
122
+ if self.num_kv_groups > 1:
123
+ k = k.repeat_interleave(self.num_kv_groups, dim=1)
124
+ v = v.repeat_interleave(self.num_kv_groups, dim=1)
125
+
126
+ out = F.scaled_dot_product_attention(q, k, v)
127
+ out = out.transpose(1, 2).contiguous().view(batch, seq, -1)
128
+ return self.o_proj(out)
129
+
130
+
131
+ class MLP(nn.Module):
132
+ def __init__(self, config):
133
+ super().__init__()
134
+ self.gate_proj = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
135
+ self.up_proj = nn.Linear(config.hidden_size, config.intermediate_size, bias=False)
136
+ self.down_proj = nn.Linear(config.intermediate_size, config.hidden_size, bias=False)
137
+
138
+ def forward(self, x):
139
+ return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x))
140
+
141
+
142
+ class TransformerBlock(nn.Module):
143
+ def __init__(self, config):
144
+ super().__init__()
145
+ self.input_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
146
+ self.self_attn = SelfAttention(config)
147
+ self.post_attention_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
148
+ self.mlp = MLP(config)
149
+ self.timestep_residual = TimestepResidual(config.hidden_size)
150
+
151
+ def forward(self, x, timestep_emb, position_ids):
152
+ residual = x
153
+ x = self.input_layernorm(x)
154
+ x = self.self_attn(x, position_ids)
155
+ x = residual + x
156
+ x = self.timestep_residual(x, timestep_emb)
157
+
158
+ residual = x
159
+ x = self.post_attention_layernorm(x)
160
+ x = self.mlp(x)
161
+ x = residual + x
162
+ x = self.timestep_residual(x, timestep_emb)
163
+
164
+ return x
165
+
166
+
167
+ class MetaDiffusionLM(nn.Module):
168
+ def __init__(self, config):
169
+ super().__init__()
170
+ self.config = config
171
+ self.mask_token_id = getattr(config, "mask_token_id", config.vocab_size)
172
+
173
+ self.embed_tokens = nn.Embedding(
174
+ config.mask_vocab_size, config.hidden_size,
175
+ padding_idx=getattr(config, "pad_token_id", 1)
176
+ )
177
+ self.timestep_emb = TimestepEmbedding(getattr(config, "timestep_emb_hidden", config.hidden_size))
178
+ self.layers = nn.ModuleList([TransformerBlock(config) for _ in range(config.num_hidden_layers)])
179
+ self.norm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
180
+ self.lm_head = nn.Linear(config.hidden_size, config.mask_vocab_size, bias=False)
181
+
182
+ def forward(self, input_ids, timesteps):
183
+ batch, seq = input_ids.shape
184
+ position_ids = torch.arange(seq, device=input_ids.device).unsqueeze(0).expand(batch, -1)
185
+ x = self.embed_tokens(input_ids)
186
+ t_emb = self.timestep_emb(timesteps)
187
+
188
+ for layer in self.layers:
189
+ x = layer(x, t_emb, position_ids)
190
+
191
+ x = self.norm(x)
192
+ logits = self.lm_head(x)
193
+ return logits
194
+
195
+
196
+ # ---------------------------------------------------------------------------
197
+ # Generation
198
+ # ---------------------------------------------------------------------------
199
+
200
+ def cumulative_unmask_frac(i, N, schedule="cosine"):
201
+ if schedule == "cosine":
202
+ return 0.5 * (1 - math.cos(math.pi * i / N))
203
+ return i / N
204
+
205
+
206
+ def generate(model, tokenizer, prompt, seq_len=256, num_steps=64, device="cuda",
207
+ temperature=0.6, repetition_penalty=1.5, watch=False,
208
+ watch_every=1, mask_token_id=32000):
209
+ model.eval()
210
+
211
+ # Tokenize prompt
212
+ prompt_ids = tokenizer.encode(prompt, add_special_tokens=False)
213
+ prompt_ids = torch.tensor([prompt_ids], device=device)
214
+
215
+ # Build input: prompt + [MASK] tokens
216
+ total_len = seq_len
217
+ gen_len = max(total_len - prompt_ids.shape[1], 0)
218
+
219
+ input_ids = torch.full((1, total_len), mask_token_id, device=device, dtype=torch.long)
220
+ input_ids[0, :prompt_ids.shape[1]] = prompt_ids
221
+
222
+ for i in range(num_steps):
223
+ frac_now = cumulative_unmask_frac(i, num_steps)
224
+ frac_next = cumulative_unmask_frac(i + 1, num_steps)
225
+
226
+ # How many tokens to unmask this step
227
+ n_masked = (input_ids == mask_token_id).sum().item()
228
+ n_total_to_unmask = int((frac_next - frac_now) * (total_len - prompt_ids.shape[1]) + 0.5)
229
+ if i == num_steps - 1:
230
+ n_unmask = n_masked
231
+ else:
232
+ n_unmask = max(n_total_to_unmask, 1) if n_masked > 0 else 0
233
+
234
+ t = 1.0 - frac_now
235
+ t_batch = torch.full((1,), t, device=device)
236
+
237
+ with torch.no_grad():
238
+ logits = model(input_ids, t_batch)
239
+
240
+ # Prevent model from predicting [MASK] token
241
+ logits[:, :, mask_token_id] = -1e9
242
+
243
+ if repetition_penalty != 1.0:
244
+ for tok in input_ids[0].unique():
245
+ tok_idx = tok.item()
246
+ logits[0, :, tok_idx] = torch.where(
247
+ logits[0, :, tok_idx] < 0,
248
+ logits[0, :, tok_idx] * repetition_penalty,
249
+ logits[0, :, tok_idx] / repetition_penalty
250
+ )
251
+
252
+ # Sample at masked positions
253
+ mask_positions = (input_ids == mask_token_id)
254
+ mask_logits = logits[mask_positions]
255
+
256
+ probs = F.softmax(mask_logits / temperature, dim=-1)
257
+ sampled = torch.multinomial(probs, 1).squeeze(-1)
258
+
259
+ # Select which masks to fill (by confidence)
260
+ if n_unmask < mask_positions.sum():
261
+ # Get entropy/confidence for each mask
262
+ log_probs = F.log_softmax(mask_logits, dim=-1)
263
+ confidence, _ = log_probs.max(dim=-1)
264
+ _, top_indices = confidence.topk(n_unmask)
265
+
266
+ # Only fill top-confidence positions
267
+ mask_flat = mask_positions.nonzero(as_tuple=False)
268
+ fill_positions = mask_flat[top_indices]
269
+ for idx, tok in zip(fill_positions, sampled[top_indices]):
270
+ input_ids[idx[0], idx[1]] = tok
271
+ else:
272
+ # Fill all remaining masks
273
+ input_ids[mask_positions] = sampled
274
+
275
+ if watch and i % watch_every == 0:
276
+ text = tokenizer.decode(input_ids[0], skip_special_tokens=True)
277
+ n_remaining = (input_ids == mask_token_id).sum().item()
278
+ print(f"Step {i+1}/{num_steps} | LR={t:.3f} | Masks remaining: {n_remaining}")
279
+ print(text[:200])
280
+ print()
281
+
282
+ # Decode
283
+ return tokenizer.decode(input_ids[0], skip_special_tokens=False)
284
+
285
+ def load_model(model_path, device="cuda"):
286
+ """Load model from safetensors file, directory, or HuggingFace Hub."""
287
+ # Check if it's a local path or HF hub id
288
+ is_file = os.path.isfile(model_path) and model_path.endswith(".safetensors")
289
+ is_dir = os.path.isdir(model_path)
290
+ is_local = is_file or is_dir
291
+
292
+ if is_local:
293
+ if is_file:
294
+ safetensors_path = model_path
295
+ config_path = os.path.join(os.path.dirname(model_path), "config.json")
296
+ else:
297
+ config_path = os.path.join(model_path, "config.json")
298
+ safetensors_path = os.path.join(model_path, "model.safetensors")
299
+
300
+ if not os.path.isfile(safetensors_path):
301
+ print(f"ERROR: model.safetensors not found in {model_path}")
302
+ sys.exit(1)
303
+ if not os.path.isfile(config_path):
304
+ print(f"ERROR: config.json not found next to {safetensors_path}")
305
+ sys.exit(1)
306
+
307
+ with open(config_path) as f:
308
+ config_dict = json.load(f)
309
+ else:
310
+ # Load from HuggingFace Hub
311
+ from huggingface_hub import hf_hub_download
312
+ config_path = hf_hub_download(model_path, "config.json")
313
+ safetensors_path = hf_hub_download(model_path, "model.safetensors")
314
+
315
+ with open(config_path) as f:
316
+ config_dict = json.load(f)
317
+
318
+ # Build config
319
+ config = MetaDiffusionConfig(**config_dict)
320
+ model = MetaDiffusionLM(config)
321
+ model = model.to(device)
322
+
323
+ # Load weights (remap HF names to model names)
324
+ state_dict = load_file(safetensors_path)
325
+
326
+ # Remap from HF naming to model naming
327
+ new_state_dict = {}
328
+ for key, value in state_dict.items():
329
+ if key.startswith("model."):
330
+ new_key = key[len("model."):]
331
+ else:
332
+ new_key = key
333
+ new_state_dict[new_key] = value
334
+
335
+ result = model.load_state_dict(new_state_dict, strict=False)
336
+ if result.missing_keys:
337
+ print(f" Warning: missing keys: {result.missing_keys[:5]}...")
338
+ if result.unexpected_keys:
339
+ print(f" Warning: unexpected keys: {result.unexpected_keys[:5]}...")
340
+
341
+ model = model.to(device)
342
+ print(f" Model loaded: {sum(p.numel() for p in model.parameters())/1e6:.1f}M params")
343
+
344
+ return model, config
345
+
346
+
347
+ def main():
348
+ parser = argparse.ArgumentParser(description="MetaDiffusion inference")
349
+ parser.add_argument("--model-path", required=True, help="Path to model directory or HF Hub ID")
350
+ parser.add_argument("--prompt", default="The cat sat on the", help="Input prompt")
351
+ parser.add_argument("--seq-len", type=int, default=256, help="Sequence length")
352
+ parser.add_argument("--num-steps", type=int, default=512, help="Denoising steps")
353
+ parser.add_argument("--temperature", type=float, default=0.6, help="Sampling temperature")
354
+ parser.add_argument("--repetition-penalty", type=float, default=1.5, help="Repetition penalty")
355
+ parser.add_argument("--device", default="cuda", help="Device (cuda/cpu)")
356
+ parser.add_argument("--watch", action="store_true", help="Show denoising progress")
357
+ parser.add_argument("--watch-every", type=int, default=4, help="Show progress every N steps")
358
+ parser.add_argument("--base-model", default="SupraLabs/Supra-1.5-50M-Base-exp",
359
+ help="HuggingFace model for tokenizer")
360
+ args = parser.parse_args()
361
+
362
+ if "cpu" in args.device:
363
+ device = torch.device("cpu")
364
+ else:
365
+ device = torch.device(args.device if torch.cuda.is_available() else "cpu")
366
+
367
+ model, config = load_model(args.model_path, device)
368
+
369
+ # Load tokenizer from base model
370
+ tokenizer = AutoTokenizer.from_pretrained(args.base_model)
371
+ mask_token_id = getattr(config, "mask_token_id", config.vocab_size)
372
+
373
+ print(f"\nPrompt: '{args.prompt}'")
374
+ print(f"Steps: {args.num_steps} | Temp: {args.temperature}")
375
+ print()
376
+
377
+ output = generate(
378
+ model, tokenizer, args.prompt,
379
+ seq_len=args.seq_len, num_steps=args.num_steps,
380
+ device=device, temperature=args.temperature,
381
+ repetition_penalty=args.repetition_penalty,
382
+ watch=args.watch,
383
+ watch_every=args.watch_every, mask_token_id=mask_token_id
384
+ )
385
+
386
+ print("Output:")
387
+ print(output)
388
+
389
+
390
+ if __name__ == "__main__":
391
+ main()
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5444f4b6b87d0db2bc93be91747ecd80fa2d306f5c793a52e6deabb5f6796cf3
3
+ size 339058560
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "bos_token": "<s>",
4
+ "clean_up_tokenization_spaces": false,
5
+ "eos_token": "</s>",
6
+ "is_local": false,
7
+ "local_files_only": false,
8
+ "model_max_length": 5120,
9
+ "pad_token": "<pad>",
10
+ "tokenizer_class": "TokenizersBackend",
11
+ "unk_token": "<unk>"
12
+ }