import torch from transformers import PreTrainedTokenizerBase def fix_pad_token(tokenizer: PreTrainedTokenizerBase) -> None: if tokenizer.pad_token_id is None: tokenizer.pad_token = tokenizer.eos_token def find_attention_start_and_end_positions( attention_mask: torch.Tensor, ) -> tuple[torch.Tensor, torch.Tensor]: # convoluted, and generated by ChatGPT, but seems to work indices = torch.arange(attention_mask.size(1)).to(attention_mask.device) # use broadcasting to expand indices to the shape of attention_mask indices = indices[None, :].expand_as(attention_mask) # set indices where attention_mask is 0 to -1 indices = torch.where(attention_mask == 1, indices, -1) max_indices = indices.max(dim=1).values # set indices where attention_mask is 0 to a large number # TODO: there's probably a more efficient way to get the min and the max in one go indices = torch.where(attention_mask == 1, indices, attention_mask.size(1) + 1) min_indices = indices.min(dim=1).values return min_indices, max_indices def adjust_read_indices_for_padding( read_indices: torch.Tensor, attention_mask: torch.Tensor ) -> torch.Tensor: """ Adjust read indices to account for padding in the input """ start_positions, end_positions = find_attention_start_and_end_positions( attention_mask ) tokenized_lengths = end_positions - start_positions + 1 # turn negative indices into positive indices fixed_read_indices = torch.where( read_indices < 0, read_indices + tokenized_lengths, read_indices ) return fixed_read_indices + start_positions