| import torch |
| import torch.nn as nn |
| from transformers import PreTrainedModel |
| from transformers.modeling_outputs import CausalLMOutputWithPast |
| from .configuration_approxdumb import ApproxDumbConfig |
|
|
| class ApproxDumbForCausalLM(PreTrainedModel): |
| config_class = ApproxDumbConfig |
|
|
| def __init__(self, config: ApproxDumbConfig): |
| super().__init__(config) |
| self.config = config |
| self.d_model = config.d_model |
|
|
| |
| self.token_emb = nn.Embedding(config.vocab_size, config.d_model) |
| self.pos_emb = nn.Embedding(config.max_len, config.d_model) |
|
|
| |
| self.q = nn.Linear(config.d_model, config.d_model) |
| self.k = nn.Linear(config.d_model, config.d_model) |
| self.v = nn.Linear(config.d_model, config.d_model) |
| self.out_proj = nn.Linear(config.d_model, config.d_model) |
|
|
| |
| self.ffn = nn.Sequential( |
| nn.Linear(config.d_model, 12), |
| nn.ReLU(), |
| nn.Linear(12, config.d_model) |
| ) |
|
|
| |
| self.lm_head = nn.Linear(config.d_model, config.vocab_size) |
|
|
| self.post_init() |
|
|
| def forward( |
| self, |
| input_ids=None, |
| labels=None, |
| output_attentions=None, |
| output_hidden_states=None, |
| return_dict=None, |
| **kwargs |
| ): |
| return_dict = return_dict if return_dict is not None else self.config.use_return_dict |
| B, T = input_ids.shape |
|
|
| pos = torch.arange(0, T, device=input_ids.device).unsqueeze(0) |
| h = self.token_emb(input_ids) + self.pos_emb(pos) |
|
|
| |
| q, k, v = self.q(h), self.k(h), self.v(h) |
| weights = (q @ k.transpose(-2, -1)) * (self.d_model ** -0.5) |
|
|
| mask = torch.tril(torch.ones(T, T, device=input_ids.device)) |
| weights = weights.masked_fill(mask == 0, float('-inf')) |
| weights = torch.softmax(weights, dim=-1) |
|
|
| attn_out = weights @ v |
| h = h + self.out_proj(attn_out) |
| h = h + self.ffn(h) |
|
|
| logits = self.lm_head(h) |
|
|
| loss = None |
| if labels is not None: |
| |
| shift_logits = logits[..., :-1, :].contiguous() |
| shift_labels = labels[..., 1:].contiguous() |
| loss_fct = nn.CrossEntropyLoss() |
| loss = loss_fct(shift_logits.view(-1, self.config.vocab_size), shift_labels.view(-1)) |
|
|
| if not return_dict: |
| output = (logits,) |
| return ((loss,) + output) if loss is not None else output |
|
|
| return CausalLMOutputWithPast( |
| loss=loss, |
| logits=logits, |
| ) |
|
|
| def prepare_inputs_for_generation(self, input_ids, **kwargs): |
| return {"input_ids": input_ids} |
|
|