Taykhoom commited on
Commit
4a8d23e
·
verified ·
1 Parent(s): ebcf506

Upload folder using huggingface_hub

Browse files
README.md ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - rna
4
+ library_name: transformers
5
+ tags:
6
+ - RNA
7
+ - mRNA
8
+ - bert
9
+ - language-model
10
+ - flash-attention
11
+ license: apache-2.0
12
+ ---
13
+
14
+ # mRNABERT
15
+
16
+ An updated HuggingFace implementation of [mRNABERT](https://huggingface.co/YYLY66/mRNABERT)
17
+ (Xiong et al., Nature Communications 2025) with the three bugs fixed from
18
+ [MosaicBERT-updated](https://huggingface.co/Taykhoom/MosaicBERT-updated) and full
19
+ `attn_implementation` dispatch support (`eager`, `sdpa`, `flash_attention_2`).
20
+
21
+ mRNABERT is a language model pre-trained on 18 million mRNA sequences incorporating
22
+ contrastive learning to integrate semantic features of amino acids.
23
+
24
+ ## Architecture
25
+
26
+ mRNABERT uses the MosaicBERT architecture with an mRNA-specific vocabulary.
27
+
28
+ | Parameter | Value |
29
+ |---|---|
30
+ | Layers | 12 |
31
+ | Attention heads | 12 |
32
+ | Embedding dimension | 768 |
33
+ | Vocabulary size | 74 (5 special + 5 single-nt + 64 codons) |
34
+ | Positional encoding | ALiBi (no position embeddings) |
35
+ | Attention | Flash Attention (packed QKV) |
36
+ | FFN | Gated Linear Units (GeGLU) |
37
+ | Padding | Unpadding (tokens concatenated, no padding overhead) |
38
+ | Max sequence length | 1024 tokens |
39
+ | Parameters | ~114M |
40
+
41
+ ### Vocabulary
42
+
43
+ The tokenizer uses `BertTokenizer` with a hybrid vocabulary:
44
+
45
+ | Range | Tokens | Use |
46
+ |---|---|---|
47
+ | 0-4 | `[PAD]` `[UNK]` `[CLS]` `[SEP]` `[MASK]` | Special tokens |
48
+ | 5-9 | `A` `T` `C` `G` `N` | Single nucleotides (UTR regions) |
49
+ | 10-73 | `AAA` ... `GGG` | All 64 codons (CDS regions) |
50
+
51
+ ## Bugs Fixed
52
+
53
+ This port applies the same three fixes as
54
+ [Taykhoom/MosaicBERT-updated](https://huggingface.co/Taykhoom/MosaicBERT-updated):
55
+
56
+ 1. `attn_implementation` dispatch reads `config._attn_implementation` (underscore prefix) instead
57
+ of `config.attn_implementation` (no underscore, always `None`, silently fell back to eager).
58
+ 2. `extended_attention_mask` cast to `hidden_states.dtype` instead of `torch.float32`
59
+ (broke bfloat16 inference).
60
+ 3. `_supports_sdpa = True` and `_supports_flash_attn_2 = True` flags added to all model
61
+ classes so HF dispatch machinery activates correctly.
62
+
63
+ ## Parity Verification
64
+
65
+ Hidden states verified max abs diff < 2.4e-05 at all 13 representation levels
66
+ (embedding + 12 transformer layers) relative to the original implementation.
67
+ Both models use `flash_attn_varlen_qkvpacked_func` in this environment; the small
68
+ numerical differences are flash attention rounding, not a correctness issue.
69
+ SDPA vs eager max diff = 1.81e-05. Verified on GPU with PyTorch 2.7 / CUDA 11.8.
70
+
71
+ ## Pretraining
72
+
73
+ - **Objective:** Masked Language Modeling + contrastive learning (amino-acid semantic features)
74
+ - **Data:** 18 million curated mRNA sequences
75
+ - **Source checkpoint:** `pytorch_model.bin` from [YYLY66/mRNABERT](https://huggingface.co/YYLY66/mRNABERT)
76
+
77
+ ## Usage
78
+
79
+ Sequences must be pre-tokenized with spaces: single nucleotides for UTR regions,
80
+ three-letter codons for CDS regions.
81
+
82
+ ### Embedding generation
83
+
84
+ ```python
85
+ import torch
86
+ from transformers import AutoTokenizer, AutoModel
87
+
88
+ tokenizer = AutoTokenizer.from_pretrained("Taykhoom/mRNABERT", trust_remote_code=True)
89
+ model = AutoModel.from_pretrained("Taykhoom/mRNABERT", trust_remote_code=True)
90
+ model.eval()
91
+
92
+ # Space-separated: single nt for UTRs, codons for CDS
93
+ sequences = [
94
+ "A T C G G A GGG CCC TTT AAA", # mixed UTR + CDS
95
+ "ATG TTT CCC GAC TAA", # CDS only
96
+ ]
97
+ enc = tokenizer(sequences, return_tensors="pt", padding=True)
98
+
99
+ with torch.no_grad():
100
+ out = model(**enc)
101
+
102
+ # Mean pooling over non-padding tokens
103
+ mask = enc["attention_mask"].unsqueeze(-1).float()
104
+ mean_emb = (out.last_hidden_state * mask).sum(1) / mask.sum(1) # (batch, 768)
105
+ ```
106
+
107
+ ### MLM logits
108
+
109
+ ```python
110
+ from transformers import AutoTokenizer, AutoModelForMaskedLM
111
+
112
+ tokenizer = AutoTokenizer.from_pretrained("Taykhoom/mRNABERT", trust_remote_code=True)
113
+ model = AutoModelForMaskedLM.from_pretrained("Taykhoom/mRNABERT", trust_remote_code=True)
114
+ model.eval()
115
+
116
+ enc = tokenizer(["A T C G [MASK] CCC TTT"], return_tensors="pt")
117
+ with torch.no_grad():
118
+ logits = model(**enc).logits # (1, seq_len, 74)
119
+ ```
120
+
121
+ ### Attention implementation
122
+
123
+ ```python
124
+ # SDPA (default on PyTorch >= 2.0)
125
+ model = AutoModel.from_pretrained("Taykhoom/mRNABERT", trust_remote_code=True,
126
+ attn_implementation="sdpa")
127
+
128
+ # Flash Attention 2 (requires: pip install flash-attn --no-build-isolation)
129
+ model = AutoModel.from_pretrained("Taykhoom/mRNABERT", trust_remote_code=True,
130
+ attn_implementation="flash_attention_2")
131
+ ```
132
+
133
+ ### Fine-tuning
134
+
135
+ ```python
136
+ from transformers import AutoModel
137
+ import torch.nn as nn
138
+
139
+ class mRNABERTClassifier(nn.Module):
140
+ def __init__(self, num_labels):
141
+ super().__init__()
142
+ self.encoder = AutoModel.from_pretrained("Taykhoom/mRNABERT", trust_remote_code=True)
143
+ self.head = nn.Linear(768, num_labels)
144
+
145
+ def forward(self, input_ids, attention_mask):
146
+ out = self.encoder(input_ids, attention_mask=attention_mask)
147
+ mask = attention_mask.unsqueeze(-1).float()
148
+ pooled = (out.last_hidden_state * mask).sum(1) / mask.sum(1)
149
+ return self.head(pooled)
150
+ ```
151
+
152
+ ## Implementation Notes
153
+
154
+ The original implementation uses `flash_attn_varlen_qkvpacked_func`. This HF port
155
+ adds `attn_implementation="sdpa"` and `attn_implementation="flash_attention_2"` support,
156
+ which were not part of the original codebase.
157
+
158
+ ## Citation
159
+
160
+ ```bibtex
161
+ @article{xiong2025_mrnabert,
162
+ title = {{mRNABERT}: advancing {mRNA} sequence design with a universal language model and comprehensive dataset},
163
+ author = {Xiong, Ying and Wang, Aowen and Kang, Yu and Shen, Chao and Hsieh, Chang-Yu and Hou, Tingjun},
164
+ journal = {Nature Communications},
165
+ volume = {16},
166
+ number = {1},
167
+ pages = {10371},
168
+ year = {2025},
169
+ doi = {10.1038/s41467-025-65340-8}
170
+ }
171
+ ```
172
+
173
+ ## Credits
174
+
175
+ Original mRNABERT model and weights by Xiong et al. Source: [GitHub](https://github.com/yyly6/mRNABERT).
176
+ The HF conversion code was authored primarily by [Claude Code](https://claude.ai/code)
177
+ and reviewed manually by Taykhoom Dalal.
178
+
179
+ ## License
180
+
181
+ Apache 2.0, following the original repository.
bert_layers.py ADDED
@@ -0,0 +1,783 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2022 MosaicML Examples authors
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ # Copyright 2018 The Google AI Language Team Authors and The HuggingFace Inc. team.
5
+ # Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved.
6
+ # Copyright (c) 2022, Tri Dao.
7
+
8
+ import copy
9
+ import logging
10
+ import math
11
+ import warnings
12
+ from typing import List, Optional, Tuple, Union
13
+
14
+ import torch
15
+ import torch.nn as nn
16
+ import torch.nn.functional as F
17
+ from einops import rearrange
18
+ from transformers.activations import ACT2FN
19
+ from transformers.modeling_outputs import (BaseModelOutputWithPooling,
20
+ MaskedLMOutput,
21
+ SequenceClassifierOutput)
22
+ from transformers.models.bert.modeling_bert import BertPreTrainedModel
23
+
24
+ from .bert_padding import (index_first_axis,
25
+ index_put_first_axis, pad_input,
26
+ unpad_input, unpad_input_only)
27
+ from .configuration_bert import BertConfig
28
+
29
+ try:
30
+ from flash_attn import flash_attn_varlen_qkvpacked_func
31
+ except ImportError:
32
+ flash_attn_varlen_qkvpacked_func = None
33
+
34
+ logger = logging.getLogger(__name__)
35
+
36
+
37
+ class BertEmbeddings(nn.Module):
38
+
39
+ def __init__(self, config):
40
+ super().__init__()
41
+ self.word_embeddings = nn.Embedding(config.vocab_size,
42
+ config.hidden_size,
43
+ padding_idx=config.pad_token_id)
44
+ # ALiBi doesn't use position embeddings
45
+ self.token_type_embeddings = nn.Embedding(config.type_vocab_size,
46
+ config.hidden_size)
47
+
48
+ self.LayerNorm = nn.LayerNorm(config.hidden_size,
49
+ eps=config.layer_norm_eps)
50
+ self.dropout = nn.Dropout(config.hidden_dropout_prob)
51
+ self.register_buffer('token_type_ids',
52
+ torch.zeros(config.max_position_embeddings,
53
+ dtype=torch.long),
54
+ persistent=False)
55
+
56
+ def forward(
57
+ self,
58
+ input_ids: Optional[torch.LongTensor] = None,
59
+ token_type_ids: Optional[torch.LongTensor] = None,
60
+ position_ids: Optional[torch.LongTensor] = None,
61
+ inputs_embeds: Optional[torch.FloatTensor] = None,
62
+ past_key_values_length: int = 0,
63
+ ) -> torch.Tensor:
64
+ if (input_ids is not None) == (inputs_embeds is not None):
65
+ raise ValueError('Must specify either input_ids or input_embeds!')
66
+ if input_ids is not None:
67
+ input_shape = input_ids.size()
68
+ else:
69
+ assert inputs_embeds is not None
70
+ input_shape = inputs_embeds.size()[:-1]
71
+
72
+ seq_length = input_shape[1]
73
+
74
+ if token_type_ids is None:
75
+ if hasattr(self, 'token_type_ids'):
76
+ assert isinstance(self.token_type_ids, torch.LongTensor)
77
+ buffered_token_type_ids = self.token_type_ids[:, :seq_length]
78
+ buffered_token_type_ids_expanded = buffered_token_type_ids.expand(
79
+ input_shape[0], seq_length)
80
+ token_type_ids = buffered_token_type_ids_expanded
81
+ else:
82
+ token_type_ids = torch.zeros(input_shape,
83
+ dtype=torch.long,
84
+ device=self.word_embeddings.device)
85
+
86
+ if inputs_embeds is None:
87
+ inputs_embeds = self.word_embeddings(input_ids)
88
+ token_type_embeddings = self.token_type_embeddings(token_type_ids)
89
+
90
+ embeddings = inputs_embeds + token_type_embeddings
91
+ # no position embeddings -- ALiBi
92
+ embeddings = self.LayerNorm(embeddings)
93
+ embeddings = self.dropout(embeddings)
94
+ return embeddings
95
+
96
+
97
+ class BertUnpadSelfAttention(nn.Module):
98
+
99
+ def __init__(self, config):
100
+ super().__init__()
101
+ if config.hidden_size % config.num_attention_heads != 0 and not hasattr(
102
+ config, 'embedding_size'):
103
+ raise ValueError(
104
+ f'The hidden size ({config.hidden_size}) is not a multiple of the number of attention '
105
+ f'heads ({config.num_attention_heads})')
106
+
107
+ self.num_attention_heads = config.num_attention_heads
108
+ self.attention_head_size = int(config.hidden_size /
109
+ config.num_attention_heads)
110
+ self.all_head_size = self.num_attention_heads * self.attention_head_size
111
+ self.dropout = nn.Dropout(config.attention_probs_dropout_prob)
112
+ self.p_dropout = config.attention_probs_dropout_prob
113
+ self.Wqkv = nn.Linear(self.all_head_size, 3 * config.hidden_size)
114
+ # Read via HF's underscore convention (_attn_implementation is set by
115
+ # from_pretrained before __init__ when _supports_* flags are True).
116
+ self.attn_implementation = getattr(config, '_attn_implementation', 'eager')
117
+
118
+ if self.attn_implementation == 'flash_attention_2' and flash_attn_varlen_qkvpacked_func is None:
119
+ warnings.warn(
120
+ 'flash-attn not installed; falling back to eager attention. '
121
+ 'Install flash-attn to use flash_attention_2.'
122
+ )
123
+ self.attn_implementation = 'eager'
124
+
125
+ def forward(self, hidden_states: torch.Tensor, cu_seqlens: torch.Tensor,
126
+ max_seqlen_in_batch: int, indices: torch.Tensor,
127
+ attn_mask: torch.Tensor, bias: torch.Tensor,
128
+ alibi_slopes: Optional[torch.Tensor] = None,
129
+ return_attn_weights: bool = False) -> torch.Tensor:
130
+ qkv = self.Wqkv(hidden_states) # (nnz, 3 * hidden)
131
+
132
+ # flash_attention_2: work on unpadded tokens directly, skip pad/unpad
133
+ if self.attn_implementation == 'flash_attention_2' and not return_attn_weights:
134
+ qkv = rearrange(qkv, 'nnz (t h d) -> nnz t h d', t=3,
135
+ h=self.num_attention_heads)
136
+ orig_dtype = qkv.dtype
137
+ if orig_dtype not in (torch.float16, torch.bfloat16):
138
+ qkv = qkv.to(torch.bfloat16)
139
+ max_s_actual = int((cu_seqlens[1:] - cu_seqlens[:-1]).max())
140
+ attention = flash_attn_varlen_qkvpacked_func(
141
+ qkv,
142
+ cu_seqlens,
143
+ max_s_actual,
144
+ dropout_p=self.p_dropout if self.training else 0.0,
145
+ alibi_slopes=alibi_slopes,
146
+ ).to(orig_dtype) # (nnz, H, D)
147
+ return rearrange(attention, 'nnz h d -> nnz (h d)')
148
+
149
+ # eager and sdpa: pad back to (B, T, 3, H, D), compute, then unpad
150
+ batch = cu_seqlens.shape[0] - 1
151
+ qkv = pad_input(qkv, indices, batch, max_seqlen_in_batch)
152
+ qkv = rearrange(qkv, 'b s (t h d) -> b s t h d', t=3,
153
+ h=self.num_attention_heads)
154
+
155
+ if self.attn_implementation == 'sdpa' and not return_attn_weights:
156
+ q = qkv[:, :, 0].permute(0, 2, 1, 3) # B H T D
157
+ k = qkv[:, :, 1].permute(0, 2, 1, 3)
158
+ v = qkv[:, :, 2].permute(0, 2, 1, 3)
159
+ attention = F.scaled_dot_product_attention(
160
+ q, k, v, attn_mask=bias,
161
+ dropout_p=self.p_dropout if self.training else 0.0,
162
+ ).permute(0, 2, 1, 3) # B T H D
163
+ attention_probs = None
164
+ else:
165
+ # eager (also fallback when return_attn_weights=True)
166
+ q = qkv[:, :, 0, :, :].permute(0, 2, 1, 3) # b h s d
167
+ k = qkv[:, :, 1, :, :].permute(0, 2, 3, 1) # b h d s
168
+ v = qkv[:, :, 2, :, :].permute(0, 2, 1, 3) # b h s d
169
+ attention_scores = torch.matmul(q, k) / math.sqrt(
170
+ self.attention_head_size)
171
+ attention_scores = attention_scores + bias
172
+ attention_probs = nn.functional.softmax(attention_scores, dim=-1)
173
+ attention_probs = self.dropout(attention_probs)
174
+ attention = torch.matmul(attention_probs, v).permute(0, 2, 1, 3) # b s h d
175
+
176
+ # attn_mask is 1 for attend and 0 for don't
177
+ attention = unpad_input_only(attention, torch.squeeze(attn_mask) == 1)
178
+ out = rearrange(attention, 'nnz h d -> nnz (h d)')
179
+ if return_attn_weights:
180
+ return out, attention_probs
181
+ return out
182
+
183
+
184
+ class BertSelfOutput(nn.Module):
185
+
186
+ def __init__(self, config):
187
+ super().__init__()
188
+ self.dense = nn.Linear(config.hidden_size, config.hidden_size)
189
+ self.LayerNorm = nn.LayerNorm(config.hidden_size,
190
+ eps=config.layer_norm_eps)
191
+ self.dropout = nn.Dropout(config.hidden_dropout_prob)
192
+
193
+ def forward(self, hidden_states: torch.Tensor,
194
+ input_tensor: torch.Tensor) -> torch.Tensor:
195
+ hidden_states = self.dense(hidden_states)
196
+ hidden_states = self.dropout(hidden_states)
197
+ hidden_states = self.LayerNorm(hidden_states + input_tensor)
198
+ return hidden_states
199
+
200
+
201
+ class BertUnpadAttention(nn.Module):
202
+ """Chains attention, Dropout, and LayerNorm for Mosaic BERT."""
203
+
204
+ def __init__(self, config):
205
+ super().__init__()
206
+ self.self = BertUnpadSelfAttention(config)
207
+ self.output = BertSelfOutput(config)
208
+
209
+ def forward(
210
+ self,
211
+ input_tensor: torch.Tensor,
212
+ cu_seqlens: torch.Tensor,
213
+ max_s: int,
214
+ subset_idx: Optional[torch.Tensor] = None,
215
+ indices: Optional[torch.Tensor] = None,
216
+ attn_mask: Optional[torch.Tensor] = None,
217
+ bias: Optional[torch.Tensor] = None,
218
+ alibi_slopes: Optional[torch.Tensor] = None,
219
+ return_attn_weights: bool = False,
220
+ ) -> torch.Tensor:
221
+ if return_attn_weights:
222
+ self_output, attn_probs = self.self(
223
+ input_tensor, cu_seqlens, max_s, indices, attn_mask, bias,
224
+ alibi_slopes=alibi_slopes, return_attn_weights=True)
225
+ else:
226
+ self_output = self.self(input_tensor, cu_seqlens, max_s, indices,
227
+ attn_mask, bias, alibi_slopes=alibi_slopes)
228
+ attn_probs = None
229
+ if subset_idx is not None:
230
+ output = self.output(index_first_axis(self_output, subset_idx),
231
+ index_first_axis(input_tensor, subset_idx))
232
+ else:
233
+ output = self.output(self_output, input_tensor)
234
+ if return_attn_weights:
235
+ return output, attn_probs
236
+ return output
237
+
238
+
239
+ class BertGatedLinearUnitMLP(nn.Module):
240
+
241
+ def __init__(self, config):
242
+ super().__init__()
243
+ self.config = config
244
+ self.gated_layers = nn.Linear(config.hidden_size,
245
+ config.intermediate_size * 2,
246
+ bias=False)
247
+ self.act = nn.GELU(approximate='none')
248
+ self.wo = nn.Linear(config.intermediate_size, config.hidden_size)
249
+ self.dropout = nn.Dropout(config.hidden_dropout_prob)
250
+ self.layernorm = nn.LayerNorm(config.hidden_size,
251
+ eps=config.layer_norm_eps)
252
+
253
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
254
+ residual_connection = hidden_states
255
+ hidden_states = self.gated_layers(hidden_states)
256
+ gated = hidden_states[:, :self.config.intermediate_size]
257
+ non_gated = hidden_states[:, self.config.intermediate_size:]
258
+ hidden_states = self.act(gated) * non_gated
259
+ hidden_states = self.dropout(hidden_states)
260
+ hidden_states = self.wo(hidden_states)
261
+ hidden_states = self.layernorm(hidden_states + residual_connection)
262
+ return hidden_states
263
+
264
+
265
+ class BertLayer(nn.Module):
266
+
267
+ def __init__(self, config):
268
+ super(BertLayer, self).__init__()
269
+ self.attention = BertUnpadAttention(config)
270
+ self.mlp = BertGatedLinearUnitMLP(config)
271
+
272
+ def forward(
273
+ self,
274
+ hidden_states: torch.Tensor,
275
+ cu_seqlens: torch.Tensor,
276
+ seqlen: int,
277
+ subset_idx: Optional[torch.Tensor] = None,
278
+ indices: Optional[torch.Tensor] = None,
279
+ attn_mask: Optional[torch.Tensor] = None,
280
+ bias: Optional[torch.Tensor] = None,
281
+ alibi_slopes: Optional[torch.Tensor] = None,
282
+ return_attn_weights: bool = False,
283
+ ) -> torch.Tensor:
284
+ if return_attn_weights:
285
+ attention_output, attn_probs = self.attention(
286
+ hidden_states, cu_seqlens, seqlen, subset_idx, indices,
287
+ attn_mask, bias, alibi_slopes=alibi_slopes, return_attn_weights=True)
288
+ else:
289
+ attention_output = self.attention(hidden_states, cu_seqlens, seqlen,
290
+ subset_idx, indices, attn_mask, bias,
291
+ alibi_slopes=alibi_slopes)
292
+ attn_probs = None
293
+ layer_output = self.mlp(attention_output)
294
+ if return_attn_weights:
295
+ return layer_output, attn_probs
296
+ return layer_output
297
+
298
+
299
+ class BertEncoder(nn.Module):
300
+
301
+ def __init__(self, config):
302
+ super().__init__()
303
+ layer = BertLayer(config)
304
+ self.layer = nn.ModuleList(
305
+ [copy.deepcopy(layer) for _ in range(config.num_hidden_layers)])
306
+
307
+ self.num_attention_heads = config.num_attention_heads
308
+ # Read via HF's underscore convention.
309
+ self.attn_implementation = getattr(config, '_attn_implementation', 'eager')
310
+
311
+ self._current_alibi_size = int(config.alibi_starting_size)
312
+ self.alibi = torch.zeros(
313
+ (1, self.num_attention_heads, self._current_alibi_size,
314
+ self._current_alibi_size))
315
+ self.alibi_slopes = torch.zeros(self.num_attention_heads)
316
+ self.rebuild_alibi_tensor(size=config.alibi_starting_size)
317
+
318
+ def rebuild_alibi_tensor(self,
319
+ size: int,
320
+ device: Optional[Union[torch.device, str]] = None):
321
+ n_heads = self.num_attention_heads
322
+
323
+ def _get_alibi_head_slopes(n_heads: int) -> List[float]:
324
+
325
+ def get_slopes_power_of_2(n_heads: int) -> List[float]:
326
+ start = (2**(-2**-(math.log2(n_heads) - 3)))
327
+ ratio = start
328
+ return [start * ratio**i for i in range(n_heads)]
329
+
330
+ if math.log2(n_heads).is_integer():
331
+ return get_slopes_power_of_2(n_heads)
332
+
333
+ closest_power_of_2 = 2**math.floor(math.log2(n_heads))
334
+ slopes_a = get_slopes_power_of_2(closest_power_of_2)
335
+ slopes_b = _get_alibi_head_slopes(2 * closest_power_of_2)
336
+ slopes_b = slopes_b[0::2][:n_heads - closest_power_of_2]
337
+ return slopes_a + slopes_b
338
+
339
+ context_position = torch.arange(size, device=device)[:, None]
340
+ memory_position = torch.arange(size, device=device)[None, :]
341
+ relative_position = torch.abs(memory_position - context_position)
342
+ relative_position = relative_position.unsqueeze(0).expand(n_heads, -1, -1)
343
+ slopes = torch.Tensor(_get_alibi_head_slopes(n_heads)).to(device)
344
+ alibi = slopes.unsqueeze(1).unsqueeze(1) * -relative_position
345
+ alibi = alibi.unsqueeze(0)
346
+ assert alibi.shape == torch.Size([1, n_heads, size, size])
347
+
348
+ self._current_alibi_size = size
349
+ self.alibi = alibi
350
+ self.alibi_slopes = slopes
351
+
352
+ def forward(
353
+ self,
354
+ hidden_states: torch.Tensor,
355
+ attention_mask: torch.Tensor,
356
+ output_all_encoded_layers: Optional[bool] = True,
357
+ subset_mask: Optional[torch.Tensor] = None,
358
+ output_attentions: bool = False,
359
+ ) -> Tuple[List[torch.Tensor], Optional[Tuple[torch.Tensor, ...]]]:
360
+
361
+ extended_attention_mask = attention_mask.unsqueeze(1).unsqueeze(2)
362
+ # Cast to match hidden_states dtype for SDPA/eager compatibility.
363
+ extended_attention_mask = extended_attention_mask.to(dtype=hidden_states.dtype)
364
+ extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0
365
+
366
+ attention_mask_bool = attention_mask.bool()
367
+ batch, seqlen = hidden_states.shape[:2]
368
+
369
+ # Capture padded embedding (B, T, D) before unpadding for HF
370
+ # hidden_states convention: index 0 = embedding, index i+1 = layer i.
371
+ padded_embedding = hidden_states
372
+
373
+ hidden_states, indices, cu_seqlens, _ = unpad_input(
374
+ hidden_states, attention_mask_bool)
375
+
376
+ if self._current_alibi_size < seqlen:
377
+ warnings.warn(
378
+ f'Increasing alibi size from {self._current_alibi_size} to {seqlen}'
379
+ )
380
+ self.rebuild_alibi_tensor(size=seqlen, device=hidden_states.device)
381
+ elif self.alibi.device != hidden_states.device:
382
+ self.alibi = self.alibi.to(hidden_states.device)
383
+ self.alibi_slopes = self.alibi_slopes.to(hidden_states.device)
384
+
385
+ # Cast ALiBi bias to match hidden_states dtype.
386
+ alibi_bias = self.alibi[:, :, :seqlen, :seqlen].to(dtype=hidden_states.dtype)
387
+ attn_bias = extended_attention_mask[:, :, :seqlen, :seqlen]
388
+ alibi_attn_mask = attn_bias + alibi_bias
389
+ alibi_slopes = (
390
+ self.alibi_slopes if self.attn_implementation == 'flash_attention_2'
391
+ else None
392
+ )
393
+
394
+ all_encoder_layers = []
395
+ all_attention_probs: List[torch.Tensor] = []
396
+ if subset_mask is None:
397
+ for layer_module in self.layer:
398
+ if output_attentions:
399
+ hidden_states, attn_probs = layer_module(
400
+ hidden_states, cu_seqlens, seqlen, None, indices,
401
+ attn_mask=attention_mask, bias=alibi_attn_mask,
402
+ alibi_slopes=alibi_slopes, return_attn_weights=True)
403
+ all_attention_probs.append(attn_probs)
404
+ else:
405
+ hidden_states = layer_module(hidden_states,
406
+ cu_seqlens,
407
+ seqlen,
408
+ None,
409
+ indices,
410
+ attn_mask=attention_mask,
411
+ bias=alibi_attn_mask,
412
+ alibi_slopes=alibi_slopes)
413
+ if output_all_encoded_layers:
414
+ all_encoder_layers.append(
415
+ pad_input(hidden_states, indices, batch, seqlen))
416
+ hidden_states = pad_input(hidden_states, indices, batch, seqlen)
417
+ else:
418
+ for i in range(len(self.layer) - 1):
419
+ layer_module = self.layer[i]
420
+ hidden_states = layer_module(hidden_states,
421
+ cu_seqlens,
422
+ seqlen,
423
+ None,
424
+ indices,
425
+ attn_mask=attention_mask,
426
+ bias=alibi_attn_mask,
427
+ alibi_slopes=alibi_slopes)
428
+ if output_all_encoded_layers:
429
+ all_encoder_layers.append(hidden_states)
430
+ subset_idx = torch.nonzero(subset_mask[attention_mask_bool],
431
+ as_tuple=False).flatten()
432
+ hidden_states = self.layer[-1](hidden_states,
433
+ cu_seqlens,
434
+ seqlen,
435
+ subset_idx=subset_idx,
436
+ indices=indices,
437
+ attn_mask=attention_mask,
438
+ bias=alibi_attn_mask,
439
+ alibi_slopes=alibi_slopes)
440
+
441
+ if not output_all_encoded_layers:
442
+ all_encoder_layers.append(hidden_states)
443
+ else:
444
+ # Prepend padded embedding as index 0 (HF convention).
445
+ all_encoder_layers.insert(0, padded_embedding)
446
+
447
+ attn_out = tuple(all_attention_probs) if output_attentions else None
448
+ return all_encoder_layers, attn_out
449
+
450
+
451
+ class BertPooler(nn.Module):
452
+
453
+ def __init__(self, config):
454
+ super(BertPooler, self).__init__()
455
+ self.dense = nn.Linear(config.hidden_size, config.hidden_size)
456
+ self.activation = nn.Tanh()
457
+
458
+ def forward(self,
459
+ hidden_states: torch.Tensor,
460
+ pool: Optional[bool] = True) -> torch.Tensor:
461
+ first_token_tensor = hidden_states[:, 0] if pool else hidden_states
462
+ pooled_output = self.dense(first_token_tensor)
463
+ pooled_output = self.activation(pooled_output)
464
+ return pooled_output
465
+
466
+
467
+ class BertPredictionHeadTransform(nn.Module):
468
+
469
+ def __init__(self, config):
470
+ super().__init__()
471
+ self.dense = nn.Linear(config.hidden_size, config.hidden_size)
472
+ if isinstance(config.hidden_act, str):
473
+ self.transform_act_fn = ACT2FN[config.hidden_act]
474
+ else:
475
+ self.transform_act_fn = config.hidden_act
476
+ self.LayerNorm = torch.nn.LayerNorm(config.hidden_size, eps=1e-12)
477
+
478
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
479
+ hidden_states = self.dense(hidden_states)
480
+ hidden_states = self.transform_act_fn(hidden_states)
481
+ hidden_states = self.LayerNorm(hidden_states)
482
+ return hidden_states
483
+
484
+
485
+ class BertModel(BertPreTrainedModel):
486
+ config_class = BertConfig
487
+ _supports_sdpa = True
488
+ _supports_flash_attn_2 = True
489
+
490
+ def __init__(self, config, add_pooling_layer=True):
491
+ super(BertModel, self).__init__(config)
492
+ self.embeddings = BertEmbeddings(config)
493
+ self.encoder = BertEncoder(config)
494
+ self.pooler = BertPooler(config) if add_pooling_layer else None
495
+ self.post_init()
496
+
497
+ def get_input_embeddings(self):
498
+ return self.embeddings.word_embeddings
499
+
500
+ def set_input_embeddings(self, value):
501
+ self.embeddings.word_embeddings = value
502
+
503
+ def forward(
504
+ self,
505
+ input_ids: torch.Tensor,
506
+ token_type_ids: Optional[torch.Tensor] = None,
507
+ attention_mask: Optional[torch.Tensor] = None,
508
+ position_ids: Optional[torch.Tensor] = None,
509
+ output_all_encoded_layers: Optional[bool] = False,
510
+ masked_tokens_mask: Optional[torch.Tensor] = None,
511
+ output_hidden_states: bool = False,
512
+ output_attentions: bool = False,
513
+ **kwargs
514
+ ) -> BaseModelOutputWithPooling:
515
+ if attention_mask is None:
516
+ attention_mask = torch.ones_like(input_ids)
517
+ if token_type_ids is None:
518
+ token_type_ids = torch.zeros_like(input_ids)
519
+
520
+ embedding_output = self.embeddings(input_ids, token_type_ids,
521
+ position_ids)
522
+
523
+ subset_mask = None
524
+ if masked_tokens_mask is not None:
525
+ first_col_mask = torch.zeros_like(masked_tokens_mask)
526
+ first_col_mask[:, 0] = True
527
+ subset_mask = masked_tokens_mask | first_col_mask
528
+
529
+ encoder_outputs, all_attentions = self.encoder(
530
+ embedding_output,
531
+ attention_mask,
532
+ output_all_encoded_layers=output_hidden_states,
533
+ subset_mask=subset_mask,
534
+ output_attentions=output_attentions)
535
+
536
+ if masked_tokens_mask is None:
537
+ sequence_output = encoder_outputs[-1]
538
+ pooled_output = self.pooler(
539
+ sequence_output) if self.pooler is not None else None
540
+ else:
541
+ attention_mask_bool = attention_mask.bool()
542
+ subset_idx = subset_mask[attention_mask_bool]
543
+ sequence_output = encoder_outputs[-1][
544
+ masked_tokens_mask[attention_mask_bool][subset_idx]]
545
+ if self.pooler is not None:
546
+ first_col_mask = torch.zeros_like(masked_tokens_mask)
547
+ first_col_mask[:, 0] = True
548
+ pool_input = encoder_outputs[-1][
549
+ first_col_mask[attention_mask_bool][subset_idx]]
550
+ pooled_output = self.pooler(pool_input, pool=False)
551
+ else:
552
+ pooled_output = None
553
+
554
+ return BaseModelOutputWithPooling(
555
+ last_hidden_state=sequence_output,
556
+ pooler_output=pooled_output,
557
+ hidden_states=tuple(encoder_outputs) if output_hidden_states else None,
558
+ attentions=all_attentions,
559
+ )
560
+
561
+
562
+ ###################
563
+ # Bert Heads
564
+ ###################
565
+ class BertLMPredictionHead(nn.Module):
566
+
567
+ def __init__(self, config, bert_model_embedding_weights):
568
+ super().__init__()
569
+ self.transform = BertPredictionHeadTransform(config)
570
+ self.decoder = nn.Linear(bert_model_embedding_weights.size(1),
571
+ bert_model_embedding_weights.size(0))
572
+ self.decoder.weight = bert_model_embedding_weights
573
+
574
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
575
+ hidden_states = self.transform(hidden_states)
576
+ hidden_states = self.decoder(hidden_states)
577
+ return hidden_states
578
+
579
+
580
+ class BertOnlyMLMHead(nn.Module):
581
+
582
+ def __init__(self, config, bert_model_embedding_weights):
583
+ super().__init__()
584
+ self.predictions = BertLMPredictionHead(config,
585
+ bert_model_embedding_weights)
586
+
587
+ def forward(self, sequence_output: torch.Tensor) -> torch.Tensor:
588
+ prediction_scores = self.predictions(sequence_output)
589
+ return prediction_scores
590
+
591
+
592
+ class BertForMaskedLM(BertPreTrainedModel):
593
+ config_class = BertConfig
594
+ _supports_sdpa = True
595
+ _supports_flash_attn_2 = True
596
+
597
+ def __init__(self, config):
598
+ super().__init__(config)
599
+
600
+ if config.is_decoder:
601
+ warnings.warn(
602
+ 'If you want to use `BertForMaskedLM` make sure `config.is_decoder=False` for '
603
+ 'bi-directional self-attention.')
604
+
605
+ self.bert = BertModel(config, add_pooling_layer=False)
606
+ self.cls = BertOnlyMLMHead(config,
607
+ self.bert.embeddings.word_embeddings.weight)
608
+ self.post_init()
609
+
610
+ def get_output_embeddings(self):
611
+ return self.cls.predictions.decoder
612
+
613
+ def set_output_embeddings(self, new_embeddings):
614
+ self.cls.predictions.decoder = new_embeddings
615
+
616
+ def forward(
617
+ self,
618
+ input_ids: Optional[torch.Tensor] = None,
619
+ attention_mask: Optional[torch.Tensor] = None,
620
+ token_type_ids: Optional[torch.Tensor] = None,
621
+ position_ids: Optional[torch.Tensor] = None,
622
+ head_mask: Optional[torch.Tensor] = None,
623
+ inputs_embeds: Optional[torch.Tensor] = None,
624
+ encoder_hidden_states: Optional[torch.Tensor] = None,
625
+ encoder_attention_mask: Optional[torch.Tensor] = None,
626
+ labels: Optional[torch.Tensor] = None,
627
+ output_attentions: Optional[bool] = None,
628
+ output_hidden_states: Optional[bool] = None,
629
+ return_dict: Optional[bool] = None,
630
+ ) -> Union[Tuple[torch.Tensor], MaskedLMOutput]:
631
+ if (input_ids is not None) == (inputs_embeds is not None):
632
+ raise ValueError('Must specify either input_ids or input_embeds!')
633
+
634
+ if labels is None:
635
+ masked_tokens_mask = None
636
+ else:
637
+ masked_tokens_mask = labels > 0
638
+
639
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
640
+
641
+ outputs = self.bert(
642
+ input_ids,
643
+ attention_mask=attention_mask,
644
+ token_type_ids=token_type_ids,
645
+ position_ids=position_ids,
646
+ inputs_embeds=inputs_embeds,
647
+ output_attentions=output_attentions,
648
+ output_hidden_states=output_hidden_states,
649
+ masked_tokens_mask=masked_tokens_mask,
650
+ )
651
+
652
+ sequence_output = outputs.last_hidden_state
653
+ prediction_scores = self.cls(sequence_output)
654
+
655
+ loss = None
656
+ if labels is not None:
657
+ loss_fct = nn.CrossEntropyLoss()
658
+ masked_token_idx = torch.nonzero(labels.flatten() > 0,
659
+ as_tuple=False).flatten()
660
+ loss = loss_fct(prediction_scores,
661
+ labels.flatten()[masked_token_idx])
662
+
663
+ assert input_ids is not None, 'Coding error; please open an issue'
664
+ batch, seqlen = input_ids.shape[:2]
665
+ prediction_scores = rearrange(index_put_first_axis(
666
+ prediction_scores, masked_token_idx, batch * seqlen),
667
+ '(b s) d -> b s d',
668
+ b=batch)
669
+
670
+ if not return_dict:
671
+ output = (prediction_scores,) + outputs[2:]
672
+ return ((loss,) + output) if loss is not None else output
673
+
674
+ return MaskedLMOutput(
675
+ loss=loss,
676
+ logits=prediction_scores,
677
+ hidden_states=outputs.hidden_states,
678
+ attentions=outputs.attentions,
679
+ )
680
+
681
+ def prepare_inputs_for_generation(self, input_ids: torch.Tensor,
682
+ attention_mask: torch.Tensor,
683
+ **model_kwargs):
684
+ input_shape = input_ids.shape
685
+ effective_batch_size = input_shape[0]
686
+
687
+ if self.config.pad_token_id is None:
688
+ raise ValueError('The PAD token should be defined for generation')
689
+
690
+ attention_mask = torch.cat([
691
+ attention_mask,
692
+ attention_mask.new_zeros((attention_mask.shape[0], 1))
693
+ ], dim=-1)
694
+ dummy_token = torch.full((effective_batch_size, 1),
695
+ self.config.pad_token_id,
696
+ dtype=torch.long,
697
+ device=input_ids.device)
698
+ input_ids = torch.cat([input_ids, dummy_token], dim=1)
699
+
700
+ return {'input_ids': input_ids, 'attention_mask': attention_mask}
701
+
702
+
703
+ class BertForSequenceClassification(BertPreTrainedModel):
704
+ config_class = BertConfig
705
+ _supports_sdpa = True
706
+ _supports_flash_attn_2 = True
707
+
708
+ def __init__(self, config):
709
+ super().__init__(config)
710
+ self.num_labels = config.num_labels
711
+ self.config = config
712
+
713
+ self.bert = BertModel(config)
714
+ classifier_dropout = (config.classifier_dropout
715
+ if config.classifier_dropout is not None else
716
+ config.hidden_dropout_prob)
717
+ self.dropout = nn.Dropout(classifier_dropout)
718
+ self.classifier = nn.Linear(config.hidden_size, config.num_labels)
719
+ self.post_init()
720
+
721
+ def forward(
722
+ self,
723
+ input_ids: Optional[torch.Tensor] = None,
724
+ attention_mask: Optional[torch.Tensor] = None,
725
+ token_type_ids: Optional[torch.Tensor] = None,
726
+ position_ids: Optional[torch.Tensor] = None,
727
+ head_mask: Optional[torch.Tensor] = None,
728
+ inputs_embeds: Optional[torch.Tensor] = None,
729
+ labels: Optional[torch.Tensor] = None,
730
+ output_attentions: Optional[bool] = None,
731
+ output_hidden_states: Optional[bool] = None,
732
+ return_dict: Optional[bool] = None,
733
+ ) -> Union[Tuple[torch.Tensor], SequenceClassifierOutput]:
734
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
735
+
736
+ outputs = self.bert(
737
+ input_ids,
738
+ attention_mask=attention_mask,
739
+ token_type_ids=token_type_ids,
740
+ position_ids=position_ids,
741
+ inputs_embeds=inputs_embeds,
742
+ output_attentions=output_attentions,
743
+ output_hidden_states=output_hidden_states,
744
+ )
745
+
746
+ pooled_output = outputs.pooler_output
747
+ pooled_output = self.dropout(pooled_output)
748
+ logits = self.classifier(pooled_output)
749
+
750
+ loss = None
751
+ if labels is not None:
752
+ if self.config.problem_type is None:
753
+ if self.num_labels == 1:
754
+ self.config.problem_type = 'regression'
755
+ elif self.num_labels > 1 and (labels.dtype == torch.long or
756
+ labels.dtype == torch.int):
757
+ self.config.problem_type = 'single_label_classification'
758
+ else:
759
+ self.config.problem_type = 'multi_label_classification'
760
+
761
+ if self.config.problem_type == 'regression':
762
+ loss_fct = nn.MSELoss()
763
+ if self.num_labels == 1:
764
+ loss = loss_fct(logits.squeeze(), labels.squeeze())
765
+ else:
766
+ loss = loss_fct(logits, labels)
767
+ elif self.config.problem_type == 'single_label_classification':
768
+ loss_fct = nn.CrossEntropyLoss()
769
+ loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
770
+ elif self.config.problem_type == 'multi_label_classification':
771
+ loss_fct = nn.BCEWithLogitsLoss()
772
+ loss = loss_fct(logits, labels)
773
+
774
+ if not return_dict:
775
+ output = (logits,) + outputs[2:]
776
+ return ((loss,) + output) if loss is not None else output
777
+
778
+ return SequenceClassifierOutput(
779
+ loss=loss,
780
+ logits=logits,
781
+ hidden_states=outputs.hidden_states,
782
+ attentions=outputs.attentions,
783
+ )
bert_padding.py ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2022 MosaicML Examples authors
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ # Adapted from https://github.com/HazyResearch/flash-attention/blob/main/flash_attn/bert_padding.py
5
+ # Which was adapted from https://github.com/mlcommons/training_results_v1.1/blob/main/NVIDIA/benchmarks/bert/implementations/pytorch/padding.py
6
+
7
+
8
+ from typing import Tuple, cast
9
+
10
+ import torch
11
+ import torch.nn.functional as F
12
+ from einops import rearrange, repeat
13
+
14
+
15
+ class IndexFirstAxis(torch.autograd.Function):
16
+
17
+ @staticmethod
18
+ def forward(ctx, input: torch.Tensor,
19
+ indices: torch.Tensor) -> torch.Tensor:
20
+ """Get just the values of `input` which are at `indices`.
21
+
22
+ Arguments:
23
+ ctx: the autograd context object
24
+ input: (b, ...) 2+ dimensional tensor
25
+ indices: (num_idx) 1D tensor
26
+ """
27
+ ctx.save_for_backward(indices)
28
+ assert input.ndim >= 2
29
+ ctx.first_axis_dim, other_shape = input.shape[0], input.shape[
30
+ 1:] # type: ignore
31
+ second_dim = other_shape.numel(
32
+ ) # product of sizes of all but first dimension
33
+ # TD [2022-03-04] For some reason torch.gather is a bit faster than indexing.
34
+ return torch.gather(
35
+ rearrange(input, 'b ... -> b (...)'), # (b, ...) -> (b, second_dim)
36
+ 0,
37
+ repeat(indices, 'z -> z d',
38
+ d=second_dim) # (indices,) -> (indices, second_dim)
39
+ ).reshape(-1, *other_shape) # (num_idx, ...)
40
+
41
+ @staticmethod
42
+ def backward(ctx, grad_output: torch.Tensor) -> Tuple[torch.Tensor, None]:
43
+ indices, = ctx.saved_tensors
44
+ assert grad_output.ndim >= 2
45
+ other_shape = grad_output.shape[1:]
46
+ grad_output = rearrange(grad_output, 'b ... -> b (...)')
47
+ grad_input = torch.zeros([ctx.first_axis_dim, grad_output.shape[1]],
48
+ device=grad_output.device,
49
+ dtype=grad_output.dtype)
50
+ # TD [2022-03-04] For some reason torch.scatter is a bit faster than indexing.
51
+ # grad_input[indices] = grad_output
52
+ grad_input.scatter_(0,
53
+ repeat(indices, 'z -> z d', d=grad_output.shape[1]),
54
+ grad_output)
55
+ return grad_input.reshape(ctx.first_axis_dim, *other_shape), None
56
+
57
+
58
+ index_first_axis = IndexFirstAxis.apply
59
+
60
+
61
+ class IndexPutFirstAxis(torch.autograd.Function):
62
+
63
+ @staticmethod
64
+ def forward(ctx, values: torch.Tensor, indices: torch.Tensor,
65
+ first_axis_dim) -> torch.Tensor:
66
+ ctx.save_for_backward(indices)
67
+ assert indices.ndim == 1
68
+ assert values.ndim >= 2
69
+ output = torch.zeros(first_axis_dim,
70
+ *values.shape[1:],
71
+ device=values.device,
72
+ dtype=values.dtype)
73
+ output[indices] = values
74
+ return output
75
+
76
+ @staticmethod
77
+ def backward(ctx,
78
+ grad_output: torch.Tensor) -> Tuple[torch.Tensor, None, None]:
79
+ indices, = ctx.saved_tensors
80
+ grad_values = grad_output[indices]
81
+ return grad_values, None, None
82
+
83
+
84
+ index_put_first_axis = IndexPutFirstAxis.apply
85
+
86
+
87
+ def unpad_input(
88
+ hidden_states: torch.Tensor,
89
+ attention_mask: torch.Tensor,
90
+ ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor, int]:
91
+ """Remove padding from input sequences.
92
+
93
+ Arguments:
94
+ hidden_states: (batch, seqlen, ...)
95
+ attention_mask: (batch, seqlen), bool / int, 1 means valid and 0 means not valid.
96
+
97
+ Returns:
98
+ hidden_states: (total_nnz, ...), where total_nnz = number of tokens in selected in attention_mask.
99
+ indices: (total_nnz)
100
+ cu_seqlens: (batch + 1), the cumulative sequence lengths, used to index into hidden_states.
101
+ max_seqlen_in_batch: int ()
102
+ """
103
+ seqlens_in_batch = attention_mask.sum(dim=-1, dtype=torch.int32)
104
+ indices = torch.nonzero(attention_mask.flatten(), as_tuple=False).flatten()
105
+ max_seqlen_in_batch = int(seqlens_in_batch.max().item())
106
+ cu_seqlens = F.pad(torch.cumsum(seqlens_in_batch, dim=0, dtype=torch.int32),
107
+ (1, 0))
108
+ # TD [2022-03-04] We don't want to index with a bool mask, because Pytorch will expand the
109
+ # bool mask, then call nonzero to get the indices, then index with those. The indices is @dim
110
+ # times larger than it needs to be, wasting memory. It's faster and more memory-efficient to
111
+ # index with integer indices. Moreover, torch's index is a bit slower than it needs to be,
112
+ # so we write custom forward and backward to make it a bit faster.
113
+ hidden_states = cast(
114
+ torch.Tensor,
115
+ index_first_axis(rearrange(hidden_states, 'b s ... -> (b s) ...'),
116
+ indices))
117
+ return hidden_states, indices, cu_seqlens, max_seqlen_in_batch
118
+
119
+
120
+ def unpad_input_only(
121
+ hidden_states: torch.Tensor,
122
+ attention_mask: torch.Tensor,
123
+ ) -> torch.Tensor:
124
+ """Like unpad_input, but only return the unpadded first tensor.
125
+
126
+ Save a small amount of overhead.
127
+
128
+ Arguments:
129
+ hidden_states: (batch, seqlen, ...)
130
+ attention_mask: (batch, seqlen), bool / int, 1 means valid and 0 means not valid.
131
+
132
+ Returns:
133
+ hidden_states: (total_nnz, ...), where total_nnz = number of tokens in selected in attention_mask.
134
+ """
135
+ indices = torch.nonzero(attention_mask.flatten(), as_tuple=False).flatten()
136
+ return index_first_axis(rearrange(hidden_states, 'b s ... -> (b s) ...'),
137
+ indices)
138
+
139
+
140
+ def pad_input(hidden_states: torch.Tensor, indices: torch.Tensor, batch: int,
141
+ seqlen: int) -> torch.Tensor:
142
+ """Add padding to sequences.
143
+
144
+ Arguments:
145
+ hidden_states: (total_nnz, ...), where total_nnz = number of tokens in selected in attention_mask.
146
+ indices: (total_nnz)
147
+ batch: int batch_size
148
+ seqlen: int max sequence length
149
+
150
+ Returns:
151
+ hidden_states: (batch, seqlen, ...)
152
+ """
153
+ output = index_put_first_axis(hidden_states, indices, batch * seqlen)
154
+ return rearrange(output, '(b s) ... -> b s ...', b=batch)
config.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "alibi_starting_size": 1024,
3
+ "architectures": [
4
+ "BertForMaskedLM"
5
+ ],
6
+ "attention_probs_dropout_prob": 0.0,
7
+ "classifier_dropout": null,
8
+ "dtype": "float32",
9
+ "hidden_act": "gelu",
10
+ "hidden_dropout_prob": 0.1,
11
+ "hidden_size": 768,
12
+ "initializer_range": 0.02,
13
+ "intermediate_size": 3072,
14
+ "layer_norm_eps": 1e-12,
15
+ "max_position_embeddings": 512,
16
+ "model_max_length": 1024,
17
+ "model_type": "bert",
18
+ "num_attention_heads": 12,
19
+ "num_hidden_layers": 12,
20
+ "pad_token_id": 0,
21
+ "position_embedding_type": "absolute",
22
+ "transformers_version": "4.57.6",
23
+ "type_vocab_size": 2,
24
+ "use_cache": true,
25
+ "vocab_size": 74
26
+ }
configuration_bert.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2022 MosaicML Examples authors
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ from transformers import BertConfig as TransformersBertConfig
5
+
6
+
7
+ class BertConfig(TransformersBertConfig):
8
+
9
+ auto_map = {
10
+ "AutoConfig": "configuration_bert.BertConfig",
11
+ "AutoModel": "bert_layers.BertModel",
12
+ "AutoModelForMaskedLM": "bert_layers.BertForMaskedLM",
13
+ "AutoModelForSequenceClassification": "bert_layers.BertForSequenceClassification",
14
+ }
15
+
16
+ def __init__(
17
+ self,
18
+ alibi_starting_size: int = 1024,
19
+ attention_probs_dropout_prob: float = 0.0,
20
+ **kwargs,
21
+ ):
22
+ super().__init__(
23
+ attention_probs_dropout_prob=attention_probs_dropout_prob,
24
+ **kwargs,
25
+ )
26
+ self.alibi_starting_size = alibi_starting_size
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:44f40d1c7df2a140860df1647ce087313b84406e5694ca66c21df90302bf057b
3
+ size 456168656
special_tokens_map.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "cls_token": "[CLS]",
3
+ "mask_token": "[MASK]",
4
+ "pad_token": "[PAD]",
5
+ "sep_token": "[SEP]",
6
+ "unk_token": "[UNK]"
7
+ }
tokenizer_config.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "clean_up_tokenization_spaces": true,
3
+ "cls_token": "[CLS]",
4
+ "do_basic_tokenize": true,
5
+ "do_lower_case": false,
6
+ "mask_token": "[MASK]",
7
+ "max_len": 1024,
8
+ "max_length": 1024,
9
+ "model_max_length": 1024,
10
+ "never_split": null,
11
+ "pad_to_multiple_of": null,
12
+ "pad_token": "[PAD]",
13
+ "pad_token_type_id": 0,
14
+ "padding_side": "right",
15
+ "sep_token": "[SEP]",
16
+ "stride": 0,
17
+ "strip_accents": null,
18
+ "tokenize_chinese_chars": true,
19
+ "tokenizer_class": "BertTokenizer",
20
+ "truncation_side": "right",
21
+ "truncation_strategy": "longest_first",
22
+ "unk_token": "[UNK]"
23
+ }
vocab.txt ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [PAD]
2
+ [UNK]
3
+ [CLS]
4
+ [SEP]
5
+ [MASK]
6
+ A
7
+ T
8
+ C
9
+ G
10
+ N
11
+ AAA
12
+ AAT
13
+ AAC
14
+ AAG
15
+ ATA
16
+ ATT
17
+ ATC
18
+ ATG
19
+ ACA
20
+ ACT
21
+ ACC
22
+ ACG
23
+ AGA
24
+ AGT
25
+ AGC
26
+ AGG
27
+ TAA
28
+ TAT
29
+ TAC
30
+ TAG
31
+ TTA
32
+ TTT
33
+ TTC
34
+ TTG
35
+ TCA
36
+ TCT
37
+ TCC
38
+ TCG
39
+ TGA
40
+ TGT
41
+ TGC
42
+ TGG
43
+ CAA
44
+ CAT
45
+ CAC
46
+ CAG
47
+ CTA
48
+ CTT
49
+ CTC
50
+ CTG
51
+ CCA
52
+ CCT
53
+ CCC
54
+ CCG
55
+ CGA
56
+ CGT
57
+ CGC
58
+ CGG
59
+ GAA
60
+ GAT
61
+ GAC
62
+ GAG
63
+ GTA
64
+ GTT
65
+ GTC
66
+ GTG
67
+ GCA
68
+ GCT
69
+ GCC
70
+ GCG
71
+ GGA
72
+ GGT
73
+ GGC
74
+ GGG