1from transformers import AutoModelForCausalLM, AutoTokenizer, AutoConfig, PretrainedConfig, PreTrainedModel
2import torch
3import torch.nn as nn
4import torch.nn.functional as F
5import math
6from transformers.modeling_outputs import CausalLMOutputWithPast
7from transformers.generation import GenerationMixin
8import os
9
10class MeshConfig(PretrainedConfig):
11 model_type = "mesh"
12
13 def __init__(
14 self,
15 vocab_size=32000,
16 hidden_size=768,
17 intermediate_size=2048,
18 num_hidden_layers=12,
19 num_attention_heads=12,
20 num_key_value_heads=12,
21 max_position_embeddings=4096,
22 initializer_range=0.02,
23 rms_norm_eps=1e-6,
24 use_cache=True,
25 pad_token_id=0,
26 bos_token_id=1,
27 eos_token_id=2,
28 tie_word_embeddings=False,
29 mesh_grid_size=(2, 2),
30 expert_intermediate_size=256,
31 routing_k=2,
32 neighbor_exchange_enabled=True,
33 cross_expert_attention_enabled=True,
34 expert_scale_factor="sqrt_k",
35 load_in_8bit=False,
36 load_in_4bit=False,
37 **kwargs
38 ):
39 super().__init__(
40 vocab_size=vocab_size,
41 hidden_size=hidden_size,
42 intermediate_size=intermediate_size,
43 num_hidden_layers=num_hidden_layers,
44 num_attention_heads=num_attention_heads,
45 num_key_value_heads=num_key_value_heads,
46 max_position_embeddings=max_position_embeddings,
47 initializer_range=initializer_range,
48 rms_norm_eps=rms_norm_eps,
49 use_cache=use_cache,
50 pad_token_id=pad_token_id,
51 bos_token_id=bos_token_id,
52 eos_token_id=eos_token_id,
53 tie_word_embeddings=tie_word_embeddings,
54 **kwargs,
55 )
56 self.mesh_grid_size = mesh_grid_size
57 self.expert_intermediate_size = kwargs.pop("expert_intermediate_size", intermediate_size // (mesh_grid_size[0] * mesh_grid_size[1]))
58 self.routing_k = routing_k
59 self.neighbor_exchange_enabled = neighbor_exchange_enabled
60 self.cross_expert_attention_enabled = cross_expert_attention_enabled
61 self.expert_scale_factor = expert_scale_factor
62 self.load_in_8bit = load_in_8bit
63 self.load_in_4bit = load_in_4bit
64
65class MeshExpert(nn.Module):
66 def __init__(self, config: MeshConfig):
67 super().__init__()
68 self.fc1 = nn.Linear(config.hidden_size, config.expert_intermediate_size)
69 self.gelu = nn.GELU()
70 self.fc2 = nn.Linear(config.expert_intermediate_size, config.hidden_size)
71
72 def forward(self, x):
73 return self.fc2(self.gelu(self.fc1(x)))
74
75class MeshRouter(nn.Module):
76 def __init__(self, config: MeshConfig):
77 super().__init__()
78 self.gate = nn.Linear(config.hidden_size, config.mesh_grid_size[0] * config.mesh_grid_size[1])
79 self.softmax = nn.Softmax(dim=-1)
80 self.routing_k = config.routing_k
81
82 def forward(self, x):
83 gate_scores = self.gate(x)
84 gate_weights = self.softmax(gate_scores)
85 topk_weights, topk_indices = torch.topk(gate_weights, self.routing_k, dim=-1)
86 return topk_weights, topk_indices
87
88class NeighborExchange(nn.Module):
89 def __init__(self, config: MeshConfig):
90 super().__init__()
91 self.config = config
92 self.num_experts_x = config.mesh_grid_size[0]
93 self.num_experts_y = config.mesh_grid_size[1]
94 self.num_experts = self.num_experts_x * self.num_experts_y
95
96 self.exchange_projection = nn.Linear(config.hidden_size, config.hidden_size)
97
98 def forward(self, expert_outputs, expert_indices=None):
99 if not self.config.neighbor_exchange_enabled:
100 return expert_outputs
101
102 batch_size, seq_length, num_experts, hidden_size = expert_outputs.shape
103 reshaped_outputs = expert_outputs.view(batch_size, seq_length, self.num_experts_x, self.num_experts_y, hidden_size)
104 aggregated_neighbor_info = torch.zeros_like(reshaped_outputs)
105
106 for i in range(self.num_experts_x):
107 for j in range(self.num_experts_y):
108 current_expert_output = reshaped_outputs[:, :, i, j, :]
109 neighbor_info = torch.zeros_like(current_expert_output)
110 neighbors = []
111 if i > 0: neighbors.append(reshaped_outputs[:, :, i-1, j, :])
112 if i < self.num_experts_x - 1: neighbors.append(reshaped_outputs[:, :, i+1, j, :])
113 if j > 0: neighbors.append(reshaped_outputs[:, :, i, j-1, :])
114 if j < self.num_experts_y - 1: neighbors.append(reshaped_outputs[:, :, i, j+1, :])
115
116 if neighbors:
117 neighbor_stack = torch.stack(neighbors, dim=-2)
118 aggregated_info = torch.mean(neighbor_stack, dim=-2)
119 neighbor_info = aggregated_info
120
121 transformed_neighbor_info = self.exchange_projection(neighbor_info)
122 aggregated_neighbor_info[:, :, i, j, :] = transformed_neighbor_info
123
124 aggregated_neighbor_info = aggregated_neighbor_info.view(batch_size, seq_length, num_experts, hidden_size)
125 exchanged_expert_outputs = expert_outputs + aggregated_neighbor_info
126
127 return exchanged_expert_outputs
128
129class CrossExpertAttention(nn.Module):
130 def __init__(self, config: MeshConfig):
131 super().__init__()
132 self.config = config
133 self.cross_attention = nn.MultiheadAttention(
134 embed_dim=config.hidden_size,
135 num_heads=config.num_attention_heads,
136 batch_first=True
137 )
138
139 def forward(self, expert_outputs):
140 if not self.config.cross_expert_attention_enabled:
141 return expert_outputs
142
143 batch_seq_size = expert_outputs.shape[0] * expert_outputs.shape[1]
144 reshaped_outputs = expert_outputs.view(batch_seq_size, self.config.mesh_grid_size[0] * self.config.mesh_grid_size[1], self.config.hidden_size)
145 cross_attn_output, _ = self.cross_attention(reshaped_outputs, reshaped_outputs, reshaped_outputs)
146 cross_attn_output = cross_attn_output.view(
147 expert_outputs.shape[0], expert_outputs.shape[1], self.config.mesh_grid_size[0] * self.config.mesh_grid_size[1], self.config.hidden_size
148 )
149 return cross_attn_output
150
151class MeshLayer(nn.Module):
152 def __init__(self, config: MeshConfig):
153 super().__init__()
154 self.config = config
155 self.router = MeshRouter(config)
156 self.experts = nn.ModuleList([MeshExpert(config) for _ in range(config.mesh_grid_size[0] * config.mesh_grid_size[1])])
157 self.neighbor_exchange = NeighborExchange(config)
158 self.cross_expert_attention = CrossExpertAttention(config)
159
160 def forward(self, hidden_states):
161 topk_weights, topk_indices = self.router(hidden_states)
162 expanded_hidden_states = hidden_states.unsqueeze(2).expand(-1, -1, self.config.mesh_grid_size[0] * self.config.mesh_grid_size[1], -1)
163
164 if self.config.expert_scale_factor == "sqrt_k":
165 scaling_factor = math.sqrt(self.config.routing_k)
166 scaled_expert_inputs = expanded_hidden_states * scaling_factor
167 elif self.config.expert_scale_factor == "1_over_k":
168 scaling_factor = 1.0 / self.config.routing_k
169 scaled_expert_inputs = expanded_hidden_states * scaling_factor
170 else:
171 scaled_expert_inputs = expanded_hidden_states
172
173 expert_outputs_list = [expert(scaled_expert_inputs[:, :, i, :]) for i, expert in enumerate(self.experts)]
174 expert_outputs = torch.stack(expert_outputs_list, dim=2)
175
176 exchanged_expert_outputs = self.neighbor_exchange(expert_outputs, topk_indices)
177 cross_attned_expert_outputs = self.cross_expert_attention(exchanged_expert_outputs)
178
179 gathered_outputs = torch.gather(
180 cross_attned_expert_outputs,
181 dim=2,
182 index=topk_indices.unsqueeze(-1).expand(-1, -1, -1, self.config.hidden_size)
183 )
184
185 combined_output = (gathered_outputs * topk_weights.unsqueeze(-1)).sum(dim=2)
186
187 return combined_output, topk_indices
188
189class MeshModel(PreTrainedModel, GenerationMixin):
190 config_class = MeshConfig
191
192 def __init__(self, config: MeshConfig):
193 super().__init__(config)
194 self.config = config
195 self.embedding = nn.Embedding(config.vocab_size, config.hidden_size)
196 self.layers = nn.ModuleList([MeshLayer(config) for _ in range(config.num_hidden_layers)])
197 self.norm = nn.LayerNorm(config.hidden_size, eps=config.rms_norm_eps)
198 self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
199 self.post_init()
200
201 self._supports_gradient_checkpointing = True
202 self.gradient_checkpointing = False
203
204 def forward(
205 self,
206 input_ids=None,
207 attention_mask=None,
208 token_type_ids=None,
209 position_ids=None,
210 inputs_embeds=None,
211 labels=None,
212 return_dict=None,
213 output_attentions=None,
214 output_hidden_states=None,
215 past_key_values=None,
216 ):
217 return_dict = return_dict if return_dict is not None else self.config.use_return_dict
218
219 if input_ids is not None and inputs_embeds is not None:
220 raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
221 elif input_ids is not None:
222 inputs_embeds = self.embedding(input_ids)
223 elif inputs_embeds is not None:
224 pass
225 else:
226 raise ValueError("You have to specify either input_ids or inputs_embeds")
227
228 hidden_states = inputs_embeds
229
230 if self.gradient_checkpointing and self.training:
231 import torch.utils.checkpoint
232
233 for i, layer in enumerate(self.layers):
234 if hasattr(layer, 'forward') and callable(layer.forward):
235 if self.gradient_checkpointing and self.training:
236 checkpoint_output = torch.utils.checkpoint.checkpoint(
237 layer, hidden_states, use_reentrant=False
238 )
239 if isinstance(checkpoint_output, tuple):
240 hidden_states = checkpoint_output[0]
241 else:
242 hidden_states = checkpoint_output
243
244 else:
245 layer_output = layer(hidden_states)
246 hidden_states = layer_output[0]
247 else:
248 print(f"Warning: Layer {i} does not have a callable forward method. Skipping layer processing.")
249
250 hidden_states = self.norm(hidden_states)
251 logits = self.lm_head(hidden_states)
252
253 loss = None
254 if labels is not None:
255 loss_fct = nn.CrossEntropyLoss()
256 shift_logits = logits[..., :-1, :].contiguous()
257 shift_labels = labels[..., 1:].contiguous()
258 loss = loss_fct(shift_logits.view(-1, self.config.vocab_size), shift_labels.view(-1))
259
260 if return_dict:
261 return CausalLMOutputWithPast(
262 loss=loss,
263 logits=logits,
264 )
265 else:
266 return (loss, logits)
267
268 def prepare_inputs_for_generation(self, input_ids, past_key_values=None, inputs_embeds=None, **kwargs):
269 if past_key_values is not None:
270 input_ids = input_ids[:, -1].unsqueeze(-1)
271 if inputs_embeds is not None:
272 inputs_embeds = inputs_embeds[:, -1, :].unsqueeze(1)
273
274 if inputs_embeds is not None:
275 model_inputs = {"inputs_embeds": inputs_embeds}
276 else:
277 model_inputs = {"input_ids": input_ids}
278
279 if "attention_mask" in kwargs:
280 model_inputs["attention_mask"] = kwargs["attention_mask"]
281
282 return model_inputs
283
284 def gradient_checkpointing_enable(self, gradient_checkpointing_kwargs=None):
285 self.gradient_checkpointing = True
286 self.config.gradient_checkpointing = True
287 print("Gradient checkpointing enabled on MeshModel.")
288
289 def gradient_checkpointing_disable(self):
290 self.gradient_checkpointing = False
291 self.config.gradient_checkpointing = False
292 print("Gradient checkpointing disabled on MeshModel.")
293
294 def _set_gradient_checkpointing(self, enable=True):
295 if enable:
296 self.gradient_checkpointing_enable()
297 else:
298 self.gradient_checkpointing_disable()
299
300from transformers import AutoConfig
301AutoConfig.register("mesh", MeshConfig)
302AutoModelForCausalLM.register(MeshConfig, MeshModel)
303
304HF_MERGED_REPO_STAGE003 = "mesh-labs/v0.1-2x2-stage003"
305
306loaded_model_stage003 = None
307loaded_tokenizer_stage003 = None
308
309try:
310 print(f"Attempting to load Stage 003 merged model from HF: {HF_MERGED_REPO_STAGE003}...")
311 device_map = "auto"
312
313 loaded_model_stage003 = AutoModelForCausalLM.from_pretrained(
314 HF_MERGED_REPO_STAGE003,
315 trust_remote_code=True,
316 device_map=device_map,
317 torch_dtype=torch.float32
318 )
319
320 if torch.cuda.is_available():
321 loaded_model_stage003.to('cuda')
322 print("Stage 003 merged model moved to GPU.")
323 else:
324 print("Stage 003 merged model loaded on CPU.")
325
326 loaded_tokenizer_stage003 = AutoTokenizer.from_pretrained(
327 HF_MERGED_REPO_STAGE003,
328 trust_remote_code=True,
329 use_fast=False
330 )
331
332 print("Stage 003 merged model and tokenizer loaded successfully from Hugging Face Hub.")
333
334except Exception as e:
335 print(f"Error loading Stage 003 merged model or tokenizer from Hugging Face Hub: {e}")
336 loaded_model_stage003 = None
337 loaded_tokenizer_stage003 = None
338
339if loaded_model_stage003 is not None and loaded_tokenizer_stage003 is not None:
340 print("\n--- Starting Chat Interface ---")
341 print("Type your message and press Enter. Type 'quit' to exit.")
342
343 loaded_model_stage003.eval()
344
345 while True:
346 try:
347 user_input = input("You: ")
348 if user_input.lower() == 'quit':
349 break
350
351 prompt = f"Question: {user_input}\nAnswer:"
352
353 inputs = loaded_tokenizer_stage003(prompt, return_tensors="pt")
354
355 if torch.cuda.is_available():
356 inputs = {k: v.to('cuda') for k, v in inputs.items()}
357
358 with torch.no_grad():
359 outputs = loaded_model_stage003.generate(
360 **inputs,
361 max_new_tokens=128,
362 num_beams=1,
363 do_sample=False,
364 )
365
366 generated_sequence = loaded_tokenizer_stage003.decode(outputs[0], skip_special_tokens=True)
367
368 answer_prefix = "Answer:"
369 answer_start_index = generated_sequence.find(answer_prefix)
370
371 if answer_start_index != -1:
372 generated_answer = generated_sequence[answer_start_index + len(answer_prefix):].strip()
373 else:
374 print("Warning: 'Answer:' prefix not found in generated text. Showing full generated sequence.")
375 generated_answer = generated_sequence.strip()
376
377 print("Model:", generated_answer)
378
379 except Exception as e:
380 print(f"An error occurred: {e}")
381 print("Please try again or type 'quit' to exit.")
382
383else:
384 print("\nModel or tokenizer not loaded. Cannot start chat interface.")