sol-pro / modeling_sol_pro_hf.py
j0no12's picture
Add Transformers adapter for official evaluation harness
a22f353 verified
Raw History Blame Contribute Delete
3.31 kB
import torch
from torch.nn import functional as F
from transformers import PreTrainedModel, GenerationMixin
from transformers.modeling_outputs import CausalLMOutput
from .configuration_sol_pro import SolProHFConfig
from .modeling_sol_pro import SolProConfig, SolProForCausalLM
class SolProHFForCausalLM(PreTrainedModel, GenerationMixin):
config_class = SolProHFConfig
base_model_prefix = ""
main_input_name = "input_ids"
_no_split_modules = ["Block"]
def __init__(self, config):
super().__init__(config)
fields = SolProConfig.__dataclass_fields__
core = SolProForCausalLM(SolProConfig(**{k: getattr(config, k) for k in fields}))
# Keep original checkpoint names, including the single tied embedding.
for name, module in core.named_children():
self.add_module(name, module)
for name, parameter in core.named_parameters(recurse=False):
self.register_parameter(name, parameter)
for name, buffer in core.named_buffers(recurse=False):
self.register_buffer(name, buffer)
self.post_init()
def get_input_embeddings(self):
return self.embedding
def set_input_embeddings(self, value):
self.embedding = value
def get_output_embeddings(self):
return self.embedding
def set_output_embeddings(self, value):
self.embedding = value
def prepare_inputs_for_generation(self, input_ids, attention_mask=None, **kwargs):
return {"input_ids": input_ids, "attention_mask": attention_mask, "use_cache": False}
def forward(self, input_ids=None, attention_mask=None, labels=None,
return_dict=None, use_cache=False, past_key_values=None, **kwargs):
if input_ids is None:
raise ValueError("input_ids are required")
if past_key_values is not None:
raise ValueError("KV caching is not implemented")
if attention_mask is None or bool(attention_mask.bool().all()):
logits = SolProForCausalLM.forward(self, input_ids)
else:
# Strip padding so n-gram memory and recurrent conditioning see the
# same sequence as an unpadded standalone inference call.
rows = []
for ids, mask in zip(input_ids, attention_mask):
keep = mask.bool()
positions = keep.nonzero(as_tuple=True)[0]
if positions.numel() == 0:
raise ValueError("An attention mask cannot be empty")
values = SolProForCausalLM.forward(self, ids[keep][None])[0]
row = values.new_zeros((ids.numel(), self.config.vocab_size))
rows.append(row.index_copy(0, positions, values))
logits = torch.stack(rows)
loss = None
if labels is not None:
targets = labels[:, 1:].clone()
if attention_mask is not None:
targets.masked_fill_(~attention_mask[:, 1:].bool(), -100)
loss = F.cross_entropy(logits[:, :-1].float().reshape(-1, logits.shape[-1]),
targets.reshape(-1), ignore_index=-100)
if return_dict is False:
return ((loss,) if loss is not None else ()) + (logits,)
return CausalLMOutput(loss=loss, logits=logits)