Collision-1B / modeling_collision.py
collision-10M's picture
Fix AutoTokenizer configuration schema warning and update modeling_collision.py
ace9fce verified
Raw History Blame Contribute Delete
15.4 kB
"""
COLLISION Modeling for Hugging Face Transformers Integration.
Enables AutoModelForCausalLM.from_pretrained("collision-10M/Collision-1B", trust_remote_code=True)
and pipeline("text-generation", model="collision-10M/Collision-1B", trust_remote_code=True).
"""
import math
from typing import Optional, Tuple, Union, List
import torch
import torch.nn as nn
import torch.nn.functional as F
try:
from transformers.modeling_utils import PreTrainedModel
from transformers.modeling_outputs import CausalLMOutputWithPast, BaseModelOutputWithPast
from transformers.generation import GenerationMixin
except ImportError:
class PreTrainedModel(nn.Module):
config_class = None
base_model_prefix = "model"
def __init__(self, config, *inputs, **kwargs):
super().__init__()
self.config = config
class GenerationMixin:
pass
class CausalLMOutputWithPast:
def __init__(self, loss=None, logits=None, past_key_values=None, hidden_states=None, attentions=None):
self.loss = loss
self.logits = logits
self.past_key_values = past_key_values
self.hidden_states = hidden_states
self.attentions = attentions
class BaseModelOutputWithPast:
def __init__(self, last_hidden_state=None, past_key_values=None, hidden_states=None, attentions=None):
self.last_hidden_state = last_hidden_state
self.past_key_values = past_key_values
self.hidden_states = hidden_states
self.attentions = attentions
try:
from .configuration_collision import CollisionConfig
except (ImportError, ValueError):
from configuration_collision import CollisionConfig
class TokenEmbedding(nn.Module):
def __init__(self, vocab_size: int, d_model: int):
super().__init__()
self.emb = nn.Embedding(vocab_size, d_model)
def forward(self, x: torch.Tensor) -> torch.Tensor:
return self.emb(x)
class PositionalEmbedding(nn.Module):
def __init__(self, max_seq_len: int, d_model: int):
super().__init__()
self.emb = nn.Embedding(max_seq_len, d_model)
def forward(self, x: torch.Tensor) -> torch.Tensor:
seq_len = x.size(1)
positions = torch.arange(seq_len, device=x.device).unsqueeze(0)
return self.emb(positions)
class CausalSelfAttention(nn.Module):
def __init__(self, d_model: int, n_head: int, max_seq_len: int, dropout: float = 0.1):
super().__init__()
assert d_model % n_head == 0, "d_model must be divisible by n_head"
self.d_model = d_model
self.n_head = n_head
self.d_k = d_model // n_head
self.qkv_proj = nn.Linear(d_model, 3 * d_model)
self.o_proj = nn.Linear(d_model, d_model)
self.attn_dropout = nn.Dropout(dropout)
self.resid_dropout = nn.Dropout(dropout)
self.register_buffer(
"bias",
torch.tril(torch.ones(max_seq_len, max_seq_len)).view(1, 1, max_seq_len, max_seq_len),
persistent=False
)
def forward(
self,
x: torch.Tensor,
attention_mask: Optional[torch.Tensor] = None,
output_attentions: bool = False
) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
B, T, C = x.size()
q, k, v = self.qkv_proj(x).split(self.d_model, dim=2)
q = q.view(B, T, self.n_head, self.d_k).transpose(1, 2)
k = k.view(B, T, self.n_head, self.d_k).transpose(1, 2)
v = v.view(B, T, self.n_head, self.d_k).transpose(1, 2)
scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(self.d_k)
scores = scores.masked_fill(self.bias[:, :, :T, :T] == 0, -1e4)
if attention_mask is not None:
if attention_mask.dim() == 2:
# (B, T) -> (B, 1, 1, T)
mask = attention_mask[:, None, None, :]
scores = scores.masked_fill(mask == 0, -1e4)
elif attention_mask.dim() == 4:
scores = scores + attention_mask
attn_weights = torch.softmax(scores, dim=-1)
attn_weights = torch.nan_to_num(attn_weights, nan=0.0)
attn_weights = self.attn_dropout(attn_weights)
out = torch.matmul(attn_weights, v)
out = out.transpose(1, 2).contiguous().view(B, T, C)
out = self.o_proj(out)
out = self.resid_dropout(out)
outputs = (out,)
if output_attentions:
outputs = outputs + (attn_weights,)
return outputs
class FeedForward(nn.Module):
def __init__(self, d_model: int, d_ff: int, dropout: float = 0.1):
super().__init__()
self.net = nn.Sequential(
nn.Linear(d_model, d_ff),
nn.GELU(),
nn.Linear(d_ff, d_model),
nn.Dropout(dropout)
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
return self.net(x)
class TransformerBlock(nn.Module):
def __init__(self, d_model: int, n_head: int, max_seq_len: int, d_ff: int, dropout: float = 0.1):
super().__init__()
self.ln1 = nn.LayerNorm(d_model)
self.attn = CausalSelfAttention(d_model, n_head, max_seq_len, dropout)
self.ln2 = nn.LayerNorm(d_model)
self.ffn = FeedForward(d_model, d_ff, dropout)
def forward(
self,
x: torch.Tensor,
attention_mask: Optional[torch.Tensor] = None,
output_attentions: bool = False
) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
attn_outputs = self.attn(self.ln1(x), attention_mask=attention_mask, output_attentions=output_attentions)
x = x + attn_outputs[0]
x = x + self.ffn(self.ln2(x))
outputs = (x,) + attn_outputs[1:]
return outputs
class CollisionPreTrainedModel(PreTrainedModel):
config_class = CollisionConfig
base_model_prefix = "transformer"
supports_gradient_checkpointing = True
_no_split_modules = ["TransformerBlock"]
def _init_weights(self, module):
if isinstance(module, nn.Linear):
torch.nn.init.normal_(module.weight, mean=0.0, std=self.config.initializer_range)
if module.bias is not None:
torch.nn.init.zeros_(module.bias)
elif isinstance(module, nn.Embedding):
emb_weight = module.emb.weight if hasattr(module, "emb") else module.weight
torch.nn.init.normal_(emb_weight, mean=0.0, std=self.config.initializer_range)
elif isinstance(module, nn.LayerNorm):
torch.nn.init.ones_(module.weight)
torch.nn.init.zeros_(module.bias)
def post_init(self):
self.apply(self._init_weights)
class CollisionModel(CollisionPreTrainedModel):
def __init__(self, config: CollisionConfig):
super().__init__(config)
self.config = config
self.token_emb = TokenEmbedding(config.vocab_size, config.d_model)
self.pos_emb = PositionalEmbedding(config.max_seq_len, config.d_model)
self.drop = nn.Dropout(config.dropout)
self.blocks = nn.ModuleList([
TransformerBlock(
d_model=config.d_model,
n_head=config.n_head,
max_seq_len=config.max_seq_len,
d_ff=config.d_ff,
dropout=config.dropout
) for _ in range(config.n_layer)
])
self.ln_f = nn.LayerNorm(config.d_model, eps=config.layer_norm_epsilon)
self.post_init()
def get_input_embeddings(self):
return self.token_emb.emb
def set_input_embeddings(self, value):
self.token_emb.emb = value
def forward(
self,
input_ids: torch.LongTensor = None,
attention_mask: Optional[torch.Tensor] = None,
position_ids: Optional[torch.LongTensor] = None,
inputs_embeds: Optional[torch.FloatTensor] = None,
output_attentions: Optional[bool] = None,
output_hidden_states: Optional[bool] = None,
return_dict: Optional[bool] = None,
**kwargs
) -> Union[Tuple, BaseModelOutputWithPast]:
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions if hasattr(self.config, "output_attentions") else False
output_hidden_states = output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states if hasattr(self.config, "output_hidden_states") else False
return_dict = return_dict if return_dict is not None else self.config.use_return_dict if hasattr(self.config, "use_return_dict") else True
if input_ids is not None:
batch_size, seq_length = input_ids.shape
device = input_ids.device
x = self.token_emb(input_ids)
if position_ids is None:
x = x + self.pos_emb(input_ids)
else:
x = x + self.pos_emb.emb(position_ids)
elif inputs_embeds is not None:
batch_size, seq_length, _ = inputs_embeds.shape
device = inputs_embeds.device
x = inputs_embeds
if position_ids is None:
positions = torch.arange(seq_length, device=device).unsqueeze(0)
x = x + self.pos_emb.emb(positions)
else:
x = x + self.pos_emb.emb(position_ids)
else:
raise ValueError("You have to specify either input_ids or inputs_embeds")
x = self.drop(x)
all_hidden_states = () if output_hidden_states else None
all_self_attns = () if output_attentions else None
for block in self.blocks:
if output_hidden_states:
all_hidden_states = all_hidden_states + (x,)
layer_outputs = block(x, attention_mask=attention_mask, output_attentions=output_attentions)
x = layer_outputs[0]
if output_attentions:
all_self_attns = all_self_attns + (layer_outputs[1],)
x = self.ln_f(x)
if output_hidden_states:
all_hidden_states = all_hidden_states + (x,)
if not return_dict:
return tuple(v for v in [x, all_hidden_states, all_self_attns] if v is not None)
return BaseModelOutputWithPast(
last_hidden_state=x,
past_key_values=None,
hidden_states=all_hidden_states,
attentions=all_self_attns
)
class CollisionForCausalLM(CollisionPreTrainedModel, GenerationMixin):
_tied_weights_keys = ["lm_head.weight"]
_keys_to_ignore_on_load_unexpected = {r"blocks\.\d+\.attn\.bias"}
_keys_to_ignore_on_load_missing = set()
@property
def all_tied_weights_keys(self):
return {"lm_head.weight": "token_emb.emb.weight"}
def __init__(self, config: CollisionConfig):
super().__init__(config)
self.config = config
# Direct embedding and transformer layers matching state_dict
self.token_emb = TokenEmbedding(config.vocab_size, config.d_model)
self.pos_emb = PositionalEmbedding(config.max_seq_len, config.d_model)
self.drop = nn.Dropout(config.dropout)
self.blocks = nn.ModuleList([
TransformerBlock(
d_model=config.d_model,
n_head=config.n_head,
max_seq_len=config.max_seq_len,
d_ff=config.d_ff,
dropout=config.dropout
) for _ in range(config.n_layer)
])
self.ln_f = nn.LayerNorm(config.d_model, eps=config.layer_norm_epsilon)
self.lm_head = nn.Linear(config.d_model, config.vocab_size, bias=True)
if config.tie_embeddings:
self.lm_head.weight = self.token_emb.emb.weight
self.post_init()
def get_input_embeddings(self):
return self.token_emb.emb
def set_input_embeddings(self, value):
self.token_emb.emb = value
def get_output_embeddings(self):
return self.lm_head
def set_output_embeddings(self, new_embeddings):
self.lm_head = new_embeddings
def prepare_inputs_for_generation(self, input_ids, past_key_values=None, **kwargs):
attention_mask = kwargs.get("attention_mask", None)
position_ids = kwargs.get("position_ids", None)
if input_ids.shape[1] > self.config.max_seq_len:
input_ids = input_ids[:, -self.config.max_seq_len:]
return {
"input_ids": input_ids,
"attention_mask": attention_mask,
"position_ids": position_ids,
}
def forward(
self,
input_ids: torch.LongTensor = None,
attention_mask: Optional[torch.Tensor] = None,
position_ids: Optional[torch.LongTensor] = None,
inputs_embeds: Optional[torch.FloatTensor] = None,
labels: Optional[torch.LongTensor] = None,
output_attentions: Optional[bool] = None,
output_hidden_states: Optional[bool] = None,
return_dict: Optional[bool] = None,
**kwargs
) -> Union[Tuple, CausalLMOutputWithPast]:
return_dict = return_dict if return_dict is not None else self.config.use_return_dict if hasattr(self.config, "use_return_dict") else True
if input_ids is not None:
B, T = input_ids.size()
x = self.token_emb(input_ids)
if position_ids is None:
x = x + self.pos_emb(input_ids)
else:
x = x + self.pos_emb.emb(position_ids)
elif inputs_embeds is not None:
B, T, _ = inputs_embeds.size()
x = inputs_embeds
if position_ids is None:
positions = torch.arange(T, device=inputs_embeds.device).unsqueeze(0)
x = x + self.pos_emb.emb(positions)
else:
x = x + self.pos_emb.emb(position_ids)
else:
raise ValueError("You must specify either input_ids or inputs_embeds")
x = self.drop(x)
all_hidden_states = () if output_hidden_states else None
all_self_attns = () if output_attentions else None
for block in self.blocks:
if output_hidden_states:
all_hidden_states = all_hidden_states + (x,)
layer_outputs = block(x, attention_mask=attention_mask, output_attentions=output_attentions)
x = layer_outputs[0]
if output_attentions:
all_self_attns = all_self_attns + (layer_outputs[1],)
hidden_states = self.ln_f(x)
logits = self.lm_head(hidden_states)
logits = torch.nan_to_num(logits, nan=0.0)
loss = None
if labels is not None:
# Shift so that tokens < n predict n
shift_logits = logits[..., :-1, :].contiguous()
shift_labels = labels[..., 1:].contiguous()
loss = F.cross_entropy(
shift_logits.view(-1, shift_logits.size(-1)),
shift_labels.view(-1),
ignore_index=-100
)
if not return_dict:
output = (logits,) + (all_hidden_states, all_self_attns)
return ((loss,) + output) if loss is not None else output
return CausalLMOutputWithPast(
loss=loss,
logits=logits,
past_key_values=None,
hidden_states=all_hidden_states,
attentions=all_self_attns
)
# Compatibility alias
CollisionTransformer = CollisionForCausalLM