David Arps commited on
Commit
0bbc3d8
·
1 Parent(s): 68f7559

update model

Browse files
LICENSE ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
generative_r2d2_fast.py CHANGED
@@ -10,9 +10,10 @@ from dataclasses import dataclass
10
  from typing import Optional
11
  from transformers import PreTrainedModel, PretrainedConfig, GPT2Config
12
  from transformers.modeling_outputs import MaskedLMOutput
13
- from lmup.gpst.gpt2_flash_attn import GPT2Model
14
- #from lmup.gpst.config import *
15
- from lmup.gpst.r2d2_insideoutside import *
 
16
  import copy
17
 
18
  def load_model(model, model_path, strict=True):
@@ -186,46 +187,9 @@ class FastGenerativeR2D2(nn.Module):
186
  next_token_indices = next_token_indices[:, :max_input_len + 1]
187
  return next_token_indices, chunk_input_ids
188
 
189
- def gpst_prep(self, input_ids, attention_mask, max_len=96):
190
- """
191
- - `input_ids`: token ids, with padding id 0, such that 2048 tokens are reached (example shape: 66x81) for 66 sentences with max length 81
192
- - `chunk_input_ids`: The same tokens, but without padding
193
- - `chunk_masks`: Shape 2x1024, and in each row values 1-something to indicate the sentence in `input_ids`. Starting with 1!
194
- - `masks`: Same shape as the input ids, 1 for input tokens, 0 for padding
195
- - `group_ids`: One-dim with length 66 (num sents), values 0 and 1 to indicate which sentence goes in which row of the `chunk_input_ids` and `chunk_masks`
196
- - `atom_spans` is None, `span_ids` is an empty list, `external_vocab_ids` is None
197
- """
198
- device = attention_mask.device
199
- max_batch_len = attention_mask.sum(dim=1).max().item() # old for formal language, depends on pad_token_id==0 batch["input_ids"].nonzero()[:,1].max()
200
- #chunk_input_ids = batch["input_ids"].view(-1) # old version, removes padding
201
- #chunk_input_ids = chunk_input_ids[chunk_input_ids != 0].unsqueeze(0)
202
- input_ids = input_ids[:,:max_batch_len]
203
- attention_mask = attention_mask[:,:max_batch_len]
204
- chunk_input_ids = input_ids # when the assertion is true
205
- #group_ids = model_inputs["input_ids"].nonzero()[:,0]
206
- group_ids = torch.arange(input_ids.shape[0], dtype=int, device=device)
207
- #chunk_masks = (batch["input_ids"].nonzero()[:,0].unsqueeze(0))+1
208
- chunk_masks = attention_mask * (group_ids+1).unsqueeze(1)
209
- gpst_batch = {
210
- "input_ids": input_ids, # batch_size (sents) x max_seq_length
211
- "masks": attention_mask,
212
- "chunk_input_ids": chunk_input_ids, #
213
- "group_ids": group_ids.cpu().numpy(),
214
- "chunk_masks": chunk_masks
215
- }
216
- return gpst_batch
217
-
218
  def forward(self, chunk_input_ids= None, chunk_masks=None, input_ids=None, masks=None, eos_labels=None, group_ids=None,
219
- atom_spans=None, span_ids=None, external_vocab_ids=None, attention_mask=None,
220
  coeff=1.0, temperature=1.0, past_key_values=None):
221
-
222
- gpst_batch = self.gpst_prep(input_ids, attention_mask)
223
- input_ids = gpst_batch["input_ids"]
224
- masks = gpst_batch["masks"]
225
- chunk_input_ids = gpst_batch["chunk_input_ids"]
226
- group_ids = gpst_batch["group_ids"]
227
- chunk_masks = gpst_batch["chunk_masks"]
228
-
229
  batch_size = max(group_ids) + 1
230
  r2d2_input_ids = torch.where(chunk_input_ids == -100, 0, chunk_input_ids)
231
  input_embeddings = self.embeddings(r2d2_input_ids)
 
10
  from typing import Optional
11
  from transformers import PreTrainedModel, PretrainedConfig, GPT2Config
12
  from transformers.modeling_outputs import MaskedLMOutput
13
+ from gpst.gpt2_flash_attn import GPT2Model
14
+ from gpst.backend_loader import load_cpp_backend
15
+ cppbackend = load_cpp_backend()
16
+ from gpst.r2d2_insideoutside import *
17
  import copy
18
 
19
  def load_model(model, model_path, strict=True):
 
187
  next_token_indices = next_token_indices[:, :max_input_len + 1]
188
  return next_token_indices, chunk_input_ids
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  def forward(self, chunk_input_ids= None, chunk_masks=None, input_ids=None, masks=None, eos_labels=None, group_ids=None,
191
+ atom_spans=None, span_ids=None, external_vocab_ids=None,
192
  coeff=1.0, temperature=1.0, past_key_values=None):
 
 
 
 
 
 
 
 
193
  batch_size = max(group_ids) + 1
194
  r2d2_input_ids = torch.where(chunk_input_ids == -100, 0, chunk_input_ids)
195
  input_embeddings = self.embeddings(r2d2_input_ids)
gpst/Llama_flash_attn.py ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # This software may be used and distributed according to the terms of the GNU General Public License version 3.
3
+
4
+ from typing import Optional, Tuple, Type
5
+ from dataclasses import dataclass
6
+ import math
7
+
8
+ import torch
9
+ from torch import nn
10
+ import torch.nn.functional as F
11
+
12
+
13
+ @dataclass
14
+ class ModelArgs:
15
+ dim: int = 512
16
+ n_layers: int = 8
17
+ n_heads: int = 8
18
+ vocab_size: int = -1 # defined later by tokenizer
19
+ multiple_of: int = 256 # make SwiGLU hidden layer size multiple of large power of 2
20
+ norm_eps: float = 1e-5
21
+
22
+ max_seq_len: int = 1024
23
+ apply_norm: bool = True
24
+
25
+
26
+ class RMSNorm(torch.nn.Module):
27
+ def __init__(self, dim: int, eps: float = 1e-6):
28
+ super().__init__()
29
+ self.eps = eps
30
+ self.weight = nn.Parameter(torch.ones(dim))
31
+
32
+ def forward(self, hidden_states):
33
+ input_dtype = hidden_states.dtype
34
+ hidden_states = hidden_states.to(torch.float32)
35
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
36
+ hidden_states = hidden_states * torch.rsqrt(variance + self.eps)
37
+ return self.weight * hidden_states.to(input_dtype)
38
+
39
+
40
+ # def precompute_freqs_cis(dim: int, end: int, theta: float = 10000.0):
41
+ # freqs = 1.0 / (theta ** (torch.arange(0, dim, 2)[: (dim // 2)] / dim))
42
+ # t = torch.arange(end, device=freqs.device) # type: ignore
43
+ # freqs = torch.outer(t, freqs) # type: ignore
44
+ # freqs_cis = torch.polar(torch.ones_like(freqs), freqs) # complex64
45
+ # return freqs_cis
46
+
47
+
48
+ def reshape_for_broadcast(freqs_cis: torch.Tensor, x: torch.Tensor):
49
+ ndim = x.ndim
50
+ assert 0 <= 1 < ndim
51
+ assert freqs_cis.shape == (x.shape[1], x.shape[-1]), f'{freqs_cis.shape},{(x.shape[1], x.shape[-1])}'
52
+ shape = [d if i == 1 or i == ndim - 1 else 1 for i, d in enumerate(x.shape)]
53
+ return freqs_cis.view(*shape)
54
+
55
+
56
+ def rotate_half(x):
57
+ """Rotates half the hidden dims of the input."""
58
+ x1 = x[..., : x.shape[-1] // 2]
59
+ x2 = x[..., x.shape[-1] // 2 :]
60
+ return torch.cat((-x2, x1), dim=-1)
61
+
62
+ def apply_rotary_emb(
63
+ xq: torch.Tensor,
64
+ xk: torch.Tensor,
65
+ freqs_cis: torch.Tensor,
66
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
67
+ # xq_ = torch.view_as_complex(xq.reshape(*xq.shape[:-1], -1, 2))
68
+ # xk_ = torch.view_as_complex(xk.reshape(*xk.shape[:-1], -1, 2))
69
+ # freqs_cis = reshape_for_broadcast(freqs_cis, xq_)
70
+ # xq_out = torch.view_as_real(xq_ * freqs_cis).flatten(3)
71
+ # xk_out = torch.view_as_real(xk_ * freqs_cis).flatten(3)
72
+ # return xq_out.type_as(xq), xk_out.type_as(xk)
73
+
74
+ cos, sin = freqs_cis
75
+ cos = cos.unsqueeze(1)
76
+ sin = sin.unsqueeze(1)
77
+ q_embed = (xq * cos) + (rotate_half(xq) * sin)
78
+ k_embed = (xk * cos) + (rotate_half(xk) * sin)
79
+ return q_embed, k_embed
80
+
81
+
82
+ class Attention(nn.Module):
83
+ def __init__(self, args: ModelArgs):
84
+ super().__init__()
85
+
86
+ self.n_local_heads = args.n_heads
87
+ self.head_dim = args.dim // args.n_heads
88
+
89
+ self.wq = nn.Linear(
90
+ args.dim,
91
+ args.n_heads * self.head_dim,
92
+ bias=False,
93
+ )
94
+ self.wk = nn.Linear(
95
+ args.dim,
96
+ args.n_heads * self.head_dim,
97
+ bias=False,
98
+ )
99
+ self.wv = nn.Linear(
100
+ args.dim,
101
+ args.n_heads * self.head_dim,
102
+ bias=False,
103
+ )
104
+ self.wo = nn.Linear(
105
+ args.dim,
106
+ args.n_heads * self.head_dim,
107
+ bias=False,
108
+ )
109
+
110
+ def forward(
111
+ self,
112
+ x: torch.Tensor,
113
+ freqs_cis: torch.Tensor,
114
+ attn_mask: Optional[torch.Tensor],
115
+ ):
116
+ bsz, seqlen, _ = x.shape
117
+ xq, xk, xv = self.wq(x), self.wk(x), self.wv(x)
118
+
119
+ xq = xq.view(bsz, seqlen, self.n_local_heads, self.head_dim)
120
+ xk = xk.view(bsz, seqlen, self.n_local_heads, self.head_dim)
121
+ xv = xv.view(bsz, seqlen, self.n_local_heads, self.head_dim)
122
+
123
+ xq = xq.transpose(1, 2)
124
+ xk = xk.transpose(1, 2)
125
+ values = xv.transpose(1, 2)
126
+
127
+ xq, xk = apply_rotary_emb(xq, xk, freqs_cis=freqs_cis)
128
+ if True:
129
+ #with torch.backends.cuda.sdpa_kernel():
130
+ if attn_mask is not None:
131
+ if len(attn_mask.shape) == 2:
132
+ output = F.scaled_dot_product_attention(xq, xk, values, attn_mask=attn_mask.unsqueeze(1).unsqueeze(1))
133
+ elif len(attn_mask.shape) == 3:
134
+ output = F.scaled_dot_product_attention(xq, xk, values, attn_mask=attn_mask.unsqueeze(1).to(xq.dtype))
135
+ else:
136
+ raise Exception("Unsupported mask format")
137
+ else:
138
+ output = F.scaled_dot_product_attention(xq, xk, values, is_causal=True)
139
+
140
+ # L, S = xq.size(-2), keys.size(-2)
141
+ # scale_factor = 1 / math.sqrt(xq.size(-1))
142
+ # attn_weight = xq @ keys.transpose(-2, -1) * scale_factor
143
+ # attn_weight += attn_mask.unsqueeze(1).unsqueeze(1)
144
+ # attn_weight = torch.softmax(attn_weight, dim=-1)
145
+ # output = attn_weight @ values
146
+
147
+ output = output.transpose(1, 2).reshape(bsz, seqlen, -1)
148
+
149
+ return self.wo(output)
150
+
151
+
152
+ class FeedForward(nn.Module):
153
+ def __init__(
154
+ self,
155
+ dim: int,
156
+ hidden_dim: int,
157
+ multiple_of: int,
158
+ ):
159
+ super().__init__()
160
+ hidden_dim = int(2 * hidden_dim / 3)
161
+ hidden_dim = multiple_of * ((hidden_dim + multiple_of - 1) // multiple_of)
162
+
163
+ self.w1 = nn.Linear(dim, hidden_dim, bias=False)
164
+ self.w2 = nn.Linear(
165
+ hidden_dim,
166
+ dim,
167
+ bias=False,
168
+ )
169
+ self.w3 = nn.Linear(
170
+ dim,
171
+ hidden_dim,
172
+ bias=False,
173
+ )
174
+
175
+ def forward(self, x):
176
+ return self.w2(F.silu(self.w1(x)) * self.w3(x))
177
+
178
+
179
+ class TransformerBlock(nn.Module):
180
+ def __init__(self, layer_id: int, args: ModelArgs):
181
+ super().__init__()
182
+ self.n_heads = args.n_heads
183
+ self.dim = args.dim
184
+ self.head_dim = args.dim // args.n_heads
185
+ self.attention = Attention(args)
186
+ self.feed_forward = FeedForward(
187
+ dim=args.dim, hidden_dim=4 * args.dim, multiple_of=args.multiple_of
188
+ )
189
+ self.layer_id = layer_id
190
+ self.attention_norm = RMSNorm(args.dim, eps=args.norm_eps)
191
+ self.ffn_norm = RMSNorm(args.dim, eps=args.norm_eps)
192
+
193
+ def forward(
194
+ self,
195
+ x: torch.Tensor,
196
+ freqs_cis: torch.Tensor,
197
+ mask: Optional[torch.Tensor],
198
+ ):
199
+ h = x + self.attention.forward(
200
+ self.attention_norm(x), freqs_cis, mask
201
+ )
202
+ out = h + self.feed_forward.forward(self.ffn_norm(h))
203
+ return out
204
+
205
+
206
+ def convert_linear_to_bnb(float_linear):
207
+ new_layer = InferenceQuantizedLinear(
208
+ float_linear.in_features,
209
+ float_linear.out_features,
210
+ bias=float_linear.bias is not None,
211
+ )
212
+ new_layer._parameters["weight"] = bnb.nn.Int8Params(
213
+ float_linear.weight.data.cpu(),
214
+ requires_grad=False,
215
+ has_fp16_weights=False,
216
+ )
217
+ if float_linear.bias is not None:
218
+ new_layer._parameters["bias"] = float_linear.bias
219
+ return new_layer
220
+
221
+
222
+ class Transformer(nn.Module):
223
+ def __init__(self, params: ModelArgs):
224
+ super().__init__()
225
+ self.params = params
226
+ self.vocab_size = params.vocab_size
227
+ self.n_layers = params.n_layers
228
+
229
+ self.tok_embeddings = torch.nn.Embedding(params.vocab_size, params.dim)
230
+
231
+ self.layers = torch.nn.ModuleList()
232
+ for layer_id in range(params.n_layers):
233
+ self.layers.append(TransformerBlock(layer_id, params))
234
+
235
+ if params.apply_norm:
236
+ self.norm = RMSNorm(params.dim, eps=params.norm_eps)
237
+ else:
238
+ self.norm = lambda x: x
239
+
240
+ # self._freqs_cis = None
241
+ self._init_sin_cos()
242
+
243
+ def _init_sin_cos(self, base=10000.0):
244
+ device=next(self.parameters()).device
245
+ dim = self.params.dim // self.params.n_heads
246
+ inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float().to(device) / dim))
247
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
248
+
249
+ t = torch.arange(self.params.max_seq_len, device=device, dtype=self.inv_freq.dtype)
250
+
251
+ freqs = torch.einsum("i,j->ij", t, self.inv_freq)
252
+ # Different from paper, but it uses a different permutation in order to obtain the same calculation
253
+ emb = torch.cat((freqs, freqs), dim=-1)
254
+ dtype=torch.get_default_dtype()
255
+ self.register_buffer("cos_cached", emb.cos().to(dtype), persistent=False)
256
+ self.register_buffer("sin_cached", emb.sin().to(dtype), persistent=False)
257
+
258
+ def freqs_cis(self, position_ids, h):
259
+ # if self._freqs_cis is None:
260
+ # self._freqs_cis = precompute_freqs_cis(
261
+ # self.params.dim // self.params.n_heads, self.params.max_seq_len
262
+ # )
263
+ # self._freqs_cis = self._freqs_cis.to(next(self.parameters()).device)
264
+
265
+ # return self._freqs_cis
266
+
267
+ return (
268
+ self.cos_cached[position_ids].to(dtype=h.dtype),
269
+ self.sin_cached[position_ids].to(dtype=h.dtype),
270
+ )
271
+
272
+ def forward(self, tokens: torch.Tensor, attn_mask: torch.Tensor, position_ids: torch.Tensor):
273
+ _bsz, seqlen = tokens.shape
274
+ h = self.tok_embeddings(tokens)
275
+ if len(position_ids.shape) == 1:
276
+ position_ids = position_ids.unsqueeze(0).repeat(_bsz, 1)
277
+ freqs_cis = self.freqs_cis(position_ids, h)
278
+
279
+ for layer in self.layers:
280
+ h = layer(h, freqs_cis, mask=attn_mask)
281
+
282
+ h = self.norm(h)
283
+ # output = self.output(h)
284
+ return h
gpst/backend_loader.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import importlib
2
+ import pathlib
3
+ import sys
4
+ import subprocess
5
+
6
+ # gpst/backend_loader.py
7
+ import os
8
+ import glob
9
+ import torch
10
+ from torch.utils.cpp_extension import load
11
+ from setuptools import setup
12
+ from torch.utils.cpp_extension import BuildExtension, CUDAExtension, CppExtension
13
+
14
+ def load_cpp_backend2():
15
+ include_dirs = os.path.dirname(os.path.abspath(__file__))
16
+ source_files = glob.glob(os.path.join(include_dirs, "cpp_extension", "*.cpp"))
17
+
18
+ if not source_files:
19
+ raise FileNotFoundError("No C++ source files found in cpp_extension/")
20
+
21
+ print("[INFO] Building cppbackend...")
22
+ cppbackend = load(
23
+ name="cppbackend",
24
+ sources=source_files,
25
+ extra_include_paths=[include_dirs], # same as include_dirs in setup.py
26
+ verbose=True
27
+ )
28
+ return cppbackend
29
+
30
+
31
+ def load_cpp_backend():
32
+ try:
33
+ # Try importing the compiled module
34
+ import gpst.cppbackend
35
+ #return importlib.import_module("cppbackend")
36
+ except ModuleNotFoundError:
37
+ print("[INFO] C++ backend not found. Building now...")
38
+ repo_root = pathlib.Path(__file__).parent.resolve()
39
+ setup_script = repo_root / "setup.py"
40
+ subprocess.check_call([sys.executable, str(setup_script), "build_ext", "--inplace"])
41
+
42
+ import gpst.cppbackend
gpst/config.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import PretrainedConfig
2
+
3
+ class GPSTConfig(PretrainedConfig):
4
+ model_type = "gpst"
5
+
6
+ def __init__(self, r2d2=None, gpt=None, **kwargs):#, gptconfig, r2d2config, **kwargs):
7
+
8
+ self.gptconfig = gpt
9
+ self.r2d2config = r2d2
10
+ super().__init__(**kwargs)
gpst/cpp_extension/binding.cpp ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <torch/torch.h>
2
+ #include "py_backend.h"
3
+ #include <pybind11/pybind11.h>
4
+ #include <pybind11/numpy.h>
5
+ #include <pybind11/stl.h>
6
+
7
+
8
+ PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
9
+ std::string name = std::string("TableManager");
10
+ py::class_<TableManager>(m, name.c_str())
11
+ .def(py::init([](const py::array_t<int>& seq_lens, const py::array_t<int>& group_ids,
12
+ const py::array_t<int>& merge_orders,
13
+ size_t window_size, size_t cache_id_offset, size_t detach_cache_id_offset,
14
+ vector<py::array_t<int>>& span_ids)
15
+ { return new TableManager(seq_lens, group_ids, merge_orders, window_size,
16
+ cache_id_offset, detach_cache_id_offset, span_ids); }))
17
+ .def("step", &TableManager::step)
18
+ .def("root_ids", &TableManager::root_ids)
19
+ .def("is_finished", &TableManager::is_finished)
20
+ .def("prepare_bilm", &TableManager::prepare_bilm)
21
+ .def("prepare_generation", &TableManager::prepare_generation)
22
+ .def("batch_size", &TableManager::batch_size);
23
+ name = std::string("SpanTokenizer");
24
+ py::class_<SpanTokenizer>(m, name.c_str())
25
+ .def(py::init([](vector<py::array_t<int>>& dictionary, int max_entry_id) {
26
+ return new SpanTokenizer(dictionary, max_entry_id);
27
+ }))
28
+ .def("tokenize", &SpanTokenizer::tokenize);
29
+ }
gpst/cpp_extension/py_backend.cpp ADDED
@@ -0,0 +1,1100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2024 Ant Group
2
+ // Author: Xiang Hu
3
+ // #undef NDEBUG
4
+ #include <stdexcept>
5
+ #include <cstring>
6
+ #include <numeric>
7
+ #include "py_backend.h"
8
+ #include <cassert>
9
+ #include <cmath>
10
+ #include <functional>
11
+ using namespace torch::indexing;
12
+
13
+ #ifndef NDEBUG
14
+ # define ASSERT(condition, message) \
15
+ do { \
16
+ if (! (condition)) { \
17
+ std::cerr << "Assertion `" #condition "` failed in " << __FILE__ \
18
+ << " line " << __LINE__ << ": " << message << std::endl; \
19
+ std::terminate(); \
20
+ } \
21
+ } while (false)
22
+ #else
23
+ # define ASSERT(condition, message) do { } while (false)
24
+ #endif
25
+
26
+ LinkedNode::LinkedNode(Cell * value):m_pLeft{NULL}, m_pRight{NULL}, m_pLeftup{NULL},
27
+ m_pRightup{NULL}, m_pLeftdown{NULL}, m_pRightdown{NULL}, m_pCell{value} {
28
+ }
29
+
30
+ LinkedNode::~LinkedNode(){
31
+ this->m_pCell->setNode(NULL);
32
+ }
33
+
34
+ Cell * LinkedNode::getCell() const {
35
+ return this->m_pCell;
36
+ }
37
+
38
+ LinkedNode * LinkedNode::left() const {
39
+ return this->m_pLeft;
40
+ }
41
+
42
+ LinkedNode * LinkedNode::right() const {
43
+ return this->m_pRight;
44
+ }
45
+
46
+ LinkedNode * LinkedNode::leftup() const {
47
+ return this->m_pLeftup;
48
+ }
49
+
50
+ LinkedNode * LinkedNode::rightup() const {
51
+ return this->m_pRightup;
52
+ }
53
+
54
+ LinkedNode * LinkedNode::leftdown() const {
55
+ return this->m_pLeftdown;
56
+ }
57
+
58
+ LinkedNode * LinkedNode::rightdown() const {
59
+ return this->m_pRightdown;
60
+ }
61
+
62
+ void LinkedNode::setLeft(LinkedNode * other) {
63
+ if (this->m_pLeft != other) {
64
+ this->m_pLeft = other;
65
+ if (other != NULL) {
66
+ other->setRight(this);
67
+ }
68
+ }
69
+ }
70
+
71
+ void LinkedNode::setRight(LinkedNode * other) {
72
+ if (this->m_pRight != other) {
73
+ this->m_pRight = other;
74
+ if (other != NULL) {
75
+ other->setLeft(this);
76
+ }
77
+ }
78
+ }
79
+
80
+ void LinkedNode::setLeftup(LinkedNode * other) {
81
+ if (this->m_pLeftup != other) {
82
+ this->m_pLeftup = other;
83
+ if (other != NULL) {
84
+ assert(this->getCell()->j == other->getCell()->j);
85
+ other->setRightdown(this);
86
+ }
87
+ }
88
+ }
89
+
90
+ void LinkedNode::setRightup(LinkedNode * other) {
91
+ if (this->m_pRightup != other) {
92
+ this->m_pRightup = other;
93
+ if (other != NULL) {
94
+ assert(this->getCell()->i == other->getCell()->i);
95
+ other->setLeftdown(this);
96
+ }
97
+ }
98
+ }
99
+
100
+ void LinkedNode::setLeftdown(LinkedNode * other) {
101
+ if (this->m_pLeftdown != other) {
102
+ this->m_pLeftdown = other;
103
+ if (other != NULL) {
104
+ assert(this->getCell()->i == other->getCell()->i);
105
+ other->setRightup(this);
106
+ }
107
+ }
108
+ }
109
+
110
+ void LinkedNode::setRightdown(LinkedNode * other) {
111
+ if (this->m_pRightdown != other) {
112
+ this->m_pRightdown = other;
113
+ if (other != NULL) {
114
+ assert(this->getCell()->j == other->getCell()->j);
115
+ other->setLeftup(this);
116
+ }
117
+ }
118
+ }
119
+
120
+ Cell::Cell(int i, int j, int window_size, TableManager * mgr, int batch_id, bool is_root):i{i}, j{j}, detached{false},
121
+ best_split{-1}, a_ij_split{-1}, cache_id{-1}, batch_id(batch_id), m_pReadyChild(0), m_pMgr(mgr), m_bIsRoot(is_root), ext_vocab_id(0) {
122
+ this->m_pNode = NULL;
123
+ if (j > i) {
124
+ this->split_size = j - i < window_size ? j - i : window_size;
125
+ this->splits = new int[this->split_size];
126
+ memset(this->splits, 0, this->split_size * sizeof(int));
127
+ } else {
128
+ this->split_size = 0;
129
+ this->splits = 0;
130
+ }
131
+ }
132
+
133
+ Cell::~Cell() {
134
+ if (this->splits != NULL) {
135
+ delete this->splits;
136
+ }
137
+ if (this->m_pNode != NULL) {
138
+ delete this->m_pNode;
139
+ }
140
+ }
141
+
142
+ int Cell::getDetachedCacheID(int detach_offset) const {
143
+ if (this->detached || this->i == this->j) {
144
+ return detach_offset + this->cache_id;
145
+ } else {
146
+ return this->cache_id;
147
+ }
148
+ }
149
+
150
+ LinkedNode * Cell::getNode() const {
151
+ return this->m_pNode;
152
+ }
153
+
154
+ void Cell::setNode(LinkedNode * target) {
155
+ assert(this->m_pNode == NULL || target == NULL);
156
+ assert(this->m_pNode != NULL || target != NULL);
157
+ this->m_pNode = target;
158
+ }
159
+
160
+ void Cell::addParent(Cell * parent) {
161
+ this->m_lParents.push_back(parent);
162
+ }
163
+
164
+ void Cell::onReady() {
165
+ for (auto const & cell : this->m_lParents) {
166
+ cell->notifyChildReady();
167
+ }
168
+ }
169
+
170
+ void Cell::notifyChildReady() {
171
+ ++this->m_pReadyChild;
172
+ assert(this->m_pReadyChild <= 2 * this->split_size);
173
+ if (this->m_pReadyChild == 2 * this->split_size && (m_bIsRoot || this->m_lParents.size() > 0)) {
174
+ // not root and has parents
175
+ this->m_pMgr->on_cell_ready(this);
176
+ }
177
+ }
178
+
179
+
180
+ int Cell::getBestSplit() const {
181
+ int k = this->best_split;
182
+ assert(k >= 0);
183
+ assert(k < this->split_size);
184
+ return this->splits[k];
185
+ }
186
+
187
+ int Cell::getGumbelSplit() const {
188
+ int k = this->a_ij_split;
189
+ assert(k >= 0);
190
+ assert(k < this->split_size);
191
+ return this->splits[k];
192
+ }
193
+
194
+ CellTable::CellTable(int seq_len, int window_size, int batch_i, TableManager * mgr):m_iCellOffset{0}, m_iMaxCreatedCells{2 * (window_size + 1) * seq_len},
195
+ m_iSeqLen{seq_len}, m_iWindowSize{window_size}, m_iBatchId(batch_i), m_pMgr(mgr) {
196
+ this->m_pCells = new Cell*[seq_len * seq_len];
197
+ memset(this->m_pCells, 0, seq_len * seq_len * sizeof(Cell*));
198
+
199
+ this->m_pCreatedCells = new Cell*[this->m_iMaxCreatedCells];
200
+ memset(this->m_pCreatedCells, 0, this->m_iMaxCreatedCells * sizeof(Cell*));
201
+ }
202
+
203
+ CellTable::~CellTable() {
204
+ for (int i = 0; i < this->m_iCellOffset; ++i) {
205
+ assert(this->m_pCreatedCells[i] != NULL);
206
+ delete this->m_pCreatedCells[i];
207
+ }
208
+ delete this->m_pCreatedCells;
209
+ delete this->m_pCells;
210
+ }
211
+
212
+ Cell * CellTable::get(const int i, const int j) {
213
+ assert(i <= j);
214
+ assert(j < this->m_iSeqLen);
215
+ if (this->m_pCells[i * this->m_iSeqLen + j] == NULL) {
216
+ bool is_root = j - i + 1 == this->m_iSeqLen && i == 0;
217
+ Cell * new_cell = new Cell(i, j, this->m_iWindowSize, this->m_pMgr, this->m_iBatchId, is_root);
218
+ this->m_pCreatedCells[this->m_iCellOffset++] = new_cell;
219
+ this->m_pCells[i * this->m_iSeqLen + j] = new_cell;
220
+ }
221
+ return this->m_pCells[i * this->m_iSeqLen + j];
222
+ }
223
+
224
+ bool CellTable::isEmpty(const int i, const int j) {
225
+ return this->m_pCells[i * this->m_iSeqLen + j] == NULL;
226
+ }
227
+
228
+ int CellTable::getLen() const {
229
+ return this->m_iSeqLen;
230
+ }
231
+
232
+ void init_active_cells(int window_size, int seq_len, CellTable * cell_table) {
233
+ for (int layer_i = 0; layer_i <= window_size; ++layer_i) {
234
+ LinkedNode * left_previous = NULL;
235
+ for (int pos_i = 0; pos_i < seq_len - layer_i; ++pos_i) {
236
+ Cell * cell_ij = cell_table->get(pos_i, pos_i + layer_i);
237
+ if (layer_i > 0) {
238
+ for (int split_idx = 0; split_idx < layer_i; ++split_idx) {
239
+ cell_ij->splits[split_idx] = pos_i + split_idx;
240
+ }
241
+ }
242
+ LinkedNode * node = new LinkedNode(cell_ij);
243
+ cell_ij->setNode(node);
244
+ node->setLeft(left_previous);
245
+ left_previous = node;
246
+ LinkedNode * leftdown = NULL;
247
+ LinkedNode * rightdown = NULL;
248
+ if (layer_i > 0) {
249
+ leftdown = cell_table->get(pos_i, pos_i + layer_i - 1)->getNode();
250
+ rightdown = cell_table->get(pos_i + 1, pos_i + layer_i)->getNode();
251
+ }
252
+ node->setLeftdown(leftdown);
253
+ node->setRightdown(rightdown);
254
+ }
255
+ }
256
+ }
257
+
258
+ LinkedNode * create_new_node(LinkedNode * leftdown, LinkedNode * rightdown, LinkedNode * left,
259
+ LinkedNode * right, LinkedNode * ld_most, LinkedNode * rd_most, CellTable * table) {
260
+ int i = leftdown->getCell()->i;
261
+ int j = rightdown->getCell()->j;
262
+ Cell * new_cell = table->get(i, j);
263
+ LinkedNode * new_node = new LinkedNode(new_cell);
264
+ LinkedNode * current = ld_most;
265
+
266
+ int idx = 0;
267
+ while (current != rd_most->right()) {
268
+ assert(idx < new_cell->split_size);
269
+ new_cell->splits[idx++] = current->getCell()->j;
270
+ current = current->right();
271
+ }
272
+
273
+ new_cell->setNode(new_node);
274
+ new_node->setLeftdown(leftdown);
275
+ new_node->setRightdown(rightdown);
276
+ new_node->setLeft(left);
277
+ new_node->setRight(right);
278
+ return new_node;
279
+ }
280
+
281
+ void prune(LinkedNode * node, std::function<void(Cell*)> on_new_cell, CellTable * table) {
282
+ node->getCell()->detached = true;
283
+ LinkedNode * leftdown = node->leftdown();
284
+ LinkedNode * rightdown = node->rightdown();
285
+
286
+ LinkedNode * left_node = leftdown;
287
+ LinkedNode * tmp = NULL;
288
+
289
+ int left_steps = 0;
290
+ while (left_node != NULL) {
291
+ if (left_node->left() != NULL) {
292
+ left_node->left()->setRight(left_node->rightup());
293
+ }
294
+ if (left_node->rightup() != NULL) {
295
+ left_node->rightup()->setLeftdown(left_node->leftdown());
296
+ }
297
+ left_steps += 1;
298
+
299
+ if (left_node->leftup() != NULL) {
300
+ tmp = left_node->leftup();
301
+ delete left_node;
302
+ left_node = tmp;
303
+ } else {
304
+ if (left_node->rightup() != NULL) {
305
+ tmp = left_node->rightup();
306
+ left_steps += 1;
307
+ } else {
308
+ tmp = left_node->right();
309
+ }
310
+ // std::cout << "delete: " << left_node->getCell()->i << "," << left_node->getCell()->j << std::endl;
311
+ delete left_node;
312
+ left_node = tmp;
313
+ break;
314
+ }
315
+ }
316
+
317
+ // std::cout << "left_node: " << left_node->getCell()->i << "," << left_node->getCell()->j << std::endl;
318
+
319
+ while (left_node->rightup() != NULL) {
320
+ left_node = left_node->rightup();
321
+ // std::cout << "left_node: " << left_node->getCell()->i << "," << left_node->getCell()->j << std::endl;
322
+ left_steps += 1;
323
+ }
324
+ // std::cout << "pb" << std::endl;
325
+
326
+ LinkedNode * right_node = rightdown;
327
+ assert(rightdown != NULL);
328
+ int right_steps = 0;
329
+ while (right_node != NULL) {
330
+ // std::cout << "right_node: " << right_node->getCell()->i << "," << right_node->getCell()->j << std::endl;
331
+ if (right_node->right() != NULL) {
332
+ right_node->right()->setLeft(right_node->leftup());
333
+ }
334
+ if (right_node->leftup() != NULL) {
335
+ right_node->leftup()->setRightdown(right_node->rightdown());
336
+ }
337
+ right_steps += 1;
338
+
339
+ if (right_node->rightup() != NULL) {
340
+ tmp = right_node->rightup();
341
+ delete right_node;
342
+ right_node = tmp;
343
+ } else {
344
+ if (right_node->leftup() != NULL) {
345
+ tmp = right_node->leftup();
346
+ right_steps += 1;
347
+ } else {
348
+ tmp = right_node->left();
349
+ }
350
+ // std::cout << "delete : " << right_node->getCell()->i << "," << right_node->getCell()->j << std::endl;
351
+ delete right_node;
352
+ right_node = tmp;
353
+ break;
354
+ }
355
+ }
356
+ // std::cout << "right_node: " << right_node->getCell()->i << "," << right_node->getCell()->j << std::endl;
357
+ while (right_node->leftup() != NULL) {
358
+ // std::cout << "right_node: " << right_node->getCell()->i << "," << right_node->getCell()->j << std::endl;
359
+ right_node = right_node->leftup();
360
+ right_steps += 1;
361
+ }
362
+
363
+ // std::cout << "pc" << std::endl;
364
+
365
+ LinkedNode * current = left_node->left() != NULL ? left_node->left() : left_node;
366
+ LinkedNode * end = right_node->right() != NULL ? right_node->right() : right_node;
367
+
368
+ LinkedNode * current_ld_most = current;
369
+ while (current_ld_most->leftdown() != NULL) {
370
+ current_ld_most = current_ld_most->leftdown();
371
+ }
372
+
373
+ LinkedNode * current_rd_most = current;
374
+ while (current_rd_most->rightdown() != NULL) {
375
+ current_rd_most = current_rd_most->rightdown();
376
+ }
377
+
378
+ // std::cout << "pd" << std::endl;
379
+ while (current != end) {
380
+ LinkedNode * node_left = current->leftup();
381
+ LinkedNode * node_right = current->right()->rightup();
382
+ // std::cout << "pcreate" << std::endl;
383
+ LinkedNode * node = create_new_node(current, current->right(), node_left, node_right,
384
+ current_ld_most, current_rd_most, table);
385
+ // std::cout << "pcreate over" << std::endl;
386
+ on_new_cell(node->getCell());
387
+ current = current->right();
388
+ current_ld_most = current_ld_most->right();
389
+ current_rd_most = current_rd_most->right();
390
+
391
+ }
392
+ }
393
+
394
+
395
+ TableManager::TableManager(const py::array_t<int>& seq_lens, const py::array_t<int>& group_ids, const py::array_t<int>& merge_orders, const int window_size,
396
+ const int cache_id_offset, const int detach_id_offset, vector<py::array_t<int>>& span_ids): m_iBatchSize{seq_lens.shape()[0]}, m_iWindowSize{window_size},
397
+ m_iCacheOffset{cache_id_offset}, m_iCurrentStep{1}, m_iDetachCacheOffset(detach_id_offset), m_iCellNum{0} {
398
+ this->m_pCellTables = new CellTable*[this->m_iBatchSize];
399
+ // this->m_pMergeOrders = new Span*[this->m_iBatchSize];
400
+ auto pMergeOrders = new Span*[this->m_iBatchSize];
401
+
402
+ auto buf = seq_lens.request();
403
+ int * seq_lens_ptr = (int*)buf.ptr;
404
+ int max_seq_len = 0;
405
+ int seq_len_sum = 0;
406
+ for (int batch_i = 0; batch_i < this->m_iBatchSize; ++batch_i) {
407
+ int seq_len = seq_lens_ptr[batch_i];
408
+ CellTable * table = new CellTable(seq_len, window_size, batch_i, this);
409
+ this->m_pCellTables[batch_i] = table;
410
+ init_active_cells(window_size, seq_len, table);
411
+ for (int pos = 0; pos < seq_len; ++pos) {
412
+ table->get(pos, pos)->cache_id = this->m_iCacheOffset + this->m_iCellNum++;
413
+ }
414
+
415
+ if (span_ids.size() > 0) {
416
+ buf = span_ids[batch_i].request();
417
+ int total_size = span_ids[batch_i].shape(0) / 3;
418
+ // std::cout << "batch: " << batch_i << " total size: " << total_size << std::endl;
419
+ // std::cout << "table seq len: " << table->getLen() << std::endl;
420
+ int * span_ids_ptr = (int*)buf.ptr;
421
+ for (int span_idx = 0; span_idx < total_size; ++span_idx) {
422
+ // std::cout << span_ids_ptr[span_idx * 3] << ", " << span_ids_ptr[span_idx * 3 + 1] << "->" << span_ids_ptr[span_idx * 3 + 2] << ";";
423
+ if (!table->isEmpty(span_ids_ptr[span_idx * 3], span_ids_ptr[span_idx * 3 + 1])) {
424
+ table->get(span_ids_ptr[span_idx * 3], span_ids_ptr[span_idx * 3 + 1])->ext_vocab_id = span_ids_ptr[span_idx * 3 + 2];
425
+ }
426
+ }
427
+ }
428
+
429
+ max_seq_len = seq_len > max_seq_len ? seq_len : max_seq_len;
430
+ seq_len_sum += seq_len;
431
+ }
432
+
433
+ buf = group_ids.request();
434
+ int * merge_order_ptr = 0;
435
+ int merge_order_L = 0;
436
+ int * group_ids_ptr = (int*)buf.ptr;
437
+ int max_group_size = group_ids_ptr[m_iBatchSize - 1] + 1;
438
+
439
+ if (m_iBatchSize != max_group_size) {
440
+ merge_order_L = max_seq_len - 1;
441
+ merge_order_ptr = new int[m_iBatchSize * merge_order_L];
442
+ std::fill_n(merge_order_ptr, m_iBatchSize * merge_order_L, -1);
443
+ buf = merge_orders.request();
444
+ int * chunk_merge_order_ptr = (int*)buf.ptr;
445
+ int chunk_size = merge_orders.shape(1); // sum(seq_lens) - 1
446
+
447
+ int prev_group_id = -1;
448
+ int offset = 0;
449
+ int * pos_chunk2sent = new int[max_group_size * chunk_size];
450
+ int * bid_chunk2sent = new int[max_group_size * chunk_size];
451
+ std::fill_n(bid_chunk2sent, max_group_size * chunk_size, -1);
452
+ std::fill_n(pos_chunk2sent, max_group_size * chunk_size, -1);
453
+ for (int batch_i = 0; batch_i < this->m_iBatchSize; ++batch_i) {
454
+ if (group_ids_ptr[batch_i] != prev_group_id) {
455
+ prev_group_id = group_ids_ptr[batch_i];
456
+ offset = 0;
457
+ }
458
+
459
+ for (int sent_idx = 0; sent_idx < seq_lens_ptr[batch_i] - 1; ++sent_idx) {
460
+ if (offset + sent_idx < chunk_size) {
461
+ pos_chunk2sent[prev_group_id * chunk_size + offset + sent_idx] = sent_idx;
462
+ bid_chunk2sent[prev_group_id * chunk_size + offset + sent_idx] = batch_i;
463
+ }
464
+ }
465
+ offset += seq_lens_ptr[batch_i];
466
+ }
467
+
468
+ int * sent_offset = new int[m_iBatchSize];
469
+ std::fill_n(sent_offset, m_iBatchSize, 0);
470
+ for (int group_i = 0; group_i < max_group_size; ++group_i) {
471
+ for (int pos = 0; pos < chunk_size; ++pos) {
472
+ assert(chunk_merge_order_ptr[group_i * chunk_size + pos] >= 0 && chunk_merge_order_ptr[group_i * chunk_size + pos] < chunk_size);
473
+ int sent_id = bid_chunk2sent[group_i * chunk_size + chunk_merge_order_ptr[group_i * chunk_size + pos]];
474
+ int split_pos = pos_chunk2sent[group_i * chunk_size + chunk_merge_order_ptr[group_i * chunk_size + pos]];
475
+ // std::cout << "sent_id" << sent_id << ", " << split_pos << std::endl;
476
+ if (sent_id != -1 && split_pos < seq_lens_ptr[sent_id] - 1) {
477
+ // std::cout << sent_id << "|" << sent_offset[sent_id] << "|" << split_pos << ", " << std::endl;
478
+ assert(sent_offset[sent_id] < merge_order_L);
479
+ assert(sent_id >= 0 && sent_id < m_iBatchSize);
480
+ merge_order_ptr[sent_id * merge_order_L + sent_offset[sent_id]++] = split_pos;
481
+ }
482
+ }
483
+ }
484
+ delete pos_chunk2sent;
485
+ delete bid_chunk2sent;
486
+ delete sent_offset;
487
+ } else {
488
+ buf = merge_orders.request();
489
+ merge_order_ptr = (int*)buf.ptr;
490
+ merge_order_L = merge_orders.shape()[1];
491
+ }
492
+ // std::cout << "B" << std::endl;
493
+
494
+ //convert merge order to cell i,j
495
+ int left_i = 0;
496
+ int right_j = 0;
497
+ int merge_pos = 0;
498
+ // assert(seq_lens.shape()[0] == merge_orders.shape()[0]);
499
+
500
+
501
+ int * current_merge_orders = 0;
502
+ for (int batch_i = 0; batch_i < this->m_iBatchSize; ++batch_i) {
503
+ int seq_len = seq_lens_ptr[batch_i];
504
+ Span * left_splits = new Span[seq_len - 1];
505
+ Span * right_splits = new Span[seq_len - 1];
506
+ current_merge_orders = merge_order_ptr + batch_i * merge_order_L;
507
+ for (int split = 0; split < seq_len - 1; ++split) {
508
+ left_splits[split].i = split;
509
+ left_splits[split].j = split;
510
+ right_splits[split].i = split + 1;
511
+ right_splits[split].j = split + 1;
512
+ }
513
+
514
+ Span * merge_orders = new Span[seq_len - 1];
515
+ for (int action_i = 0; action_i < seq_len - 1; ++action_i) {
516
+ merge_pos = current_merge_orders[action_i];
517
+ assert(merge_pos < seq_len - 1);
518
+ left_i = left_splits[merge_pos].i;
519
+ right_j = right_splits[merge_pos].j;
520
+
521
+ merge_orders[action_i].i = left_i;
522
+ merge_orders[action_i].j = right_j;
523
+ if (left_i >= 1) {
524
+ right_splits[left_i - 1].i = left_i;
525
+ right_splits[left_i - 1].j = right_j;
526
+ }
527
+ if (right_j < seq_len - 1) {
528
+ left_splits[right_j].i = left_i;
529
+ left_splits[right_j].j = right_j;
530
+ }
531
+ // std::cout << "merge span: " << left_i << ", " << right_j << std::endl;
532
+ }
533
+ pMergeOrders[batch_i] = merge_orders;
534
+
535
+ delete left_splits;
536
+ delete right_splits;
537
+ }
538
+ // std::cout << "C" << std::endl;
539
+
540
+ // int max_seq_len = *max_element(seq_lens.begin(), seq_lens.end());
541
+ // int seq_len_sum = accumulate(seq_lens.begin(), seq_lens.end(), 0);
542
+ this->m_iMaxSeqLen = max_seq_len;
543
+ this->m_pCellOrders = new Cell**[max_seq_len - 1];
544
+ this->m_pCellNums = new int[max_seq_len - 1];
545
+ this->m_pTargetCacheIds = new long*[max_seq_len - 1];
546
+ this->m_pGroupCacheIds = new long*[max_seq_len - 1];
547
+ this->m_pTargetExtIds = new long*[max_seq_len - 1];
548
+ this->m_pDetachGroupCacheIds = new long*[max_seq_len - 1];
549
+
550
+ this->m_pLDRCache_ids = 0;
551
+ this->m_pExtIds = 0;
552
+ this->m_pPositionIds = 0;
553
+ this->m_pTgtIds = 0;
554
+
555
+ this->m_pSpanMasks = 0;
556
+ this->m_pSplitTargets = 0;
557
+ this->m_pSpanGatherIds = 0;
558
+ this->m_pTokenPositions = 0;
559
+
560
+ for (int step = 1; step < max_seq_len; ++step) {
561
+ this->m_pCellOrders[step - 1] = 0;
562
+ this->m_pCellNums[step - 1] = 0;
563
+ this->m_pTargetCacheIds[step - 1] = 0;
564
+ this->m_pGroupCacheIds[step - 1] = 0;
565
+ this->m_pTargetExtIds[step - 1] = 0;
566
+ this->m_pDetachGroupCacheIds[step - 1] = 0;
567
+ }
568
+
569
+ this->build_cell_dependencies(pMergeOrders);
570
+ for (int batch_i = 0; batch_i < this->m_iBatchSize; ++batch_i) {
571
+ int seq_len = seq_lens_ptr[batch_i];
572
+ CellTable * table = this->m_pCellTables[batch_i];
573
+ for (int pos = 0; pos < seq_len; ++pos) {
574
+ table->get(pos, pos)->onReady();
575
+ }
576
+ }
577
+
578
+ if (m_iBatchSize != max_group_size) {
579
+ delete merge_order_ptr;
580
+ }
581
+ for (int batch_i = 0; batch_i < this->m_iBatchSize; ++batch_i) {
582
+ delete pMergeOrders[batch_i];
583
+ }
584
+ delete pMergeOrders;
585
+ }
586
+
587
+ TableManager::~TableManager() {
588
+ for (int batch_i = 0; batch_i < this->m_iBatchSize; ++batch_i) {
589
+ delete this->m_pCellTables[batch_i];
590
+ // delete this->m_pMergeOrders[batch_i];
591
+ }
592
+ for (int step = 0; step < this->m_iMaxSeqLen - 1; ++step) {
593
+ if (this->m_pCellOrders[step] != 0)
594
+ delete this->m_pCellOrders[step];
595
+ if (this->m_pTargetCacheIds[step] != 0)
596
+ delete this->m_pTargetCacheIds[step];
597
+ if (this->m_pGroupCacheIds[step] != 0)
598
+ delete this->m_pGroupCacheIds[step];
599
+ if (this->m_pTargetExtIds[step] != 0)
600
+ delete this->m_pTargetExtIds[step];
601
+ if (this->m_pDetachGroupCacheIds[step] != 0)
602
+ delete this->m_pDetachGroupCacheIds[step];
603
+ }
604
+
605
+
606
+ if (m_pLDRCache_ids != 0)
607
+ delete m_pLDRCache_ids;
608
+ if (m_pExtIds != 0)
609
+ delete m_pExtIds;
610
+ if (m_pPositionIds != 0)
611
+ delete m_pPositionIds;
612
+ if (m_pTgtIds != 0)
613
+ delete m_pTgtIds;
614
+ if (m_pSpanMasks != 0)
615
+ delete m_pSpanMasks;
616
+ if (m_pSplitTargets != 0)
617
+ delete m_pSplitTargets;
618
+ if (m_pSpanGatherIds != 0)
619
+ delete m_pSpanGatherIds;
620
+ if (m_pTokenPositions != 0)
621
+ delete m_pTokenPositions;
622
+
623
+ delete this->m_pCellNums;
624
+ delete this->m_pCellOrders;
625
+ delete this->m_pCellTables;
626
+ // delete this->m_pMergeOrders;
627
+ delete this->m_pTargetCacheIds;
628
+ delete this->m_pTargetExtIds;
629
+ delete this->m_pGroupCacheIds;
630
+ delete this->m_pDetachGroupCacheIds;
631
+ }
632
+
633
+ void TableManager::push_cell(Cell * cell) {
634
+ int current_cache_id = this->m_iCacheOffset + this->m_iCellNum++;
635
+ cell->cache_id = current_cache_id;
636
+ }
637
+
638
+ void TableManager::build_cell_dependencies(Span ** pMergeOrders) {
639
+ for (int step = 1; step < this->m_iMaxSeqLen; ++step) {
640
+ // #pragma omp parallel for
641
+ for (int batch_i = 0; batch_i < this->m_iBatchSize; ++batch_i) {
642
+ CellTable * table = this->m_pCellTables[batch_i];
643
+ int seq_len = table->getLen();
644
+ // printf("batch_i: %d, seq_len: %d\n", batch_i, seq_len);
645
+ if (step < seq_len) {
646
+ if (step <= this->m_iWindowSize) {
647
+ for (int i = 0; i < seq_len - step; ++i) {
648
+ int j = i + step;
649
+ assert(j < seq_len);
650
+ Cell * current_cell = table->get(i, j);
651
+ for (int split_idx = 0; split_idx < current_cell->split_size; ++split_idx) {
652
+ int k = current_cell->splits[split_idx];
653
+ assert(i <= k);
654
+ assert(k < j);
655
+ Cell * cell_ik = table->get(i, k);
656
+ Cell * cell_kj = table->get(k + 1, j);
657
+ cell_ik->addParent(current_cell);
658
+ cell_kj->addParent(current_cell);
659
+ }
660
+ }
661
+ } else {
662
+ Span & merge_span = pMergeOrders[batch_i][step - this->m_iWindowSize - 1];
663
+ int i = merge_span.i;
664
+ int j = merge_span.j;
665
+ // printf("(%d, %d)\n", i, j);
666
+ prune(table->get(i, j)->getNode(), [&](Cell * cell) {
667
+ for (int sp_idx = 0; sp_idx < cell->split_size; ++sp_idx) {
668
+ int k = cell->splits[sp_idx];
669
+ assert(cell->i <= k);
670
+ assert(k < cell->j);
671
+ Cell * cell_ik = table->get(cell->i, k);
672
+ Cell * cell_kj = table->get(k + 1, cell->j);
673
+ cell_ik->addParent(cell);
674
+ cell_kj->addParent(cell);
675
+ }
676
+
677
+ }, table);
678
+ }
679
+ }
680
+ }
681
+ }
682
+ }
683
+
684
+ void TableManager::on_cell_ready(Cell * ready_cell) {
685
+ this->m_lReadyCells.push_back(ready_cell);
686
+ }
687
+
688
+ bool TableManager::is_finished() {
689
+ return this->m_lReadyCells.size() == 0;
690
+ }
691
+
692
+ vector<at::Tensor> TableManager::step() {
693
+ int current_step = this->m_iCurrentStep;
694
+
695
+ int total_size = this->m_lReadyCells.size();
696
+ int group_size = this->m_iCurrentStep <= this->m_iWindowSize ? this->m_iCurrentStep : this->m_iWindowSize;
697
+ this->m_pCellNums[current_step - 1] = total_size;
698
+ this->m_pCellOrders[current_step - 1] = new Cell*[total_size];
699
+
700
+ // at::Tensor target_cache_ids_ = torch::zeros({total_size}, at::kLong);
701
+ // at::Tensor group_cache_ids_ = torch::zeros({total_size, group_size, 2}, at::kLong);
702
+ // at::Tensor detach_group_cache_ids_ = torch::zeros({total_size, group_size, 2}, at::kLong);
703
+
704
+ this->m_pTargetCacheIds[current_step - 1] = new long[total_size];
705
+ this->m_pGroupCacheIds[current_step - 1] = new long[total_size * group_size * 2];
706
+ this->m_pTargetExtIds[current_step - 1] = new long[total_size];
707
+ this->m_pDetachGroupCacheIds[current_step - 1] = new long[total_size * group_size * 2];
708
+
709
+ auto tgt_cache_ids_ptr = this->m_pTargetCacheIds[current_step - 1];
710
+ auto tgt_ext_id_ptr = this->m_pTargetExtIds[current_step - 1];
711
+ auto group_ids_ptr = this->m_pGroupCacheIds[current_step - 1];
712
+ auto detach_group_ids_ptr = this->m_pDetachGroupCacheIds[current_step - 1];
713
+
714
+ int idx_offset = 0;
715
+ for (int cell_idx = 0; cell_idx < total_size; ++cell_idx) {
716
+ Cell * cell_ptr = this->m_lReadyCells.front();
717
+ this->m_lReadyCells.pop_front();
718
+ CellTable * table = this->m_pCellTables[cell_ptr->batch_id];
719
+ int i = cell_ptr->i;
720
+ int j = cell_ptr->j;
721
+ cell_ptr->onReady();
722
+ this->push_cell(cell_ptr);
723
+ this->m_pCellOrders[this->m_iCurrentStep - 1][cell_idx] = cell_ptr;
724
+ tgt_cache_ids_ptr[cell_idx] = cell_ptr->cache_id;
725
+ tgt_ext_id_ptr[cell_idx] = cell_ptr->ext_vocab_id;
726
+ for (int split_idx = 0; split_idx < cell_ptr->split_size; ++split_idx) {
727
+ int k = cell_ptr->splits[split_idx];
728
+ assert(i <= k);
729
+ assert(k < j);
730
+ Cell * cell_ik = table->get(i, k);
731
+ Cell * cell_kj = table->get(k + 1, j);
732
+ // group_cache_ids_.index({cell_idx, split_idx, 0}) = cell_ik->cache_id;
733
+ // group_cache_ids_.index({cell_idx, split_idx, 1}) = cell_kj->cache_id;
734
+ // detach_group_cache_ids_.index({cell_idx, split_idx, 0}) = cell_ik->getDetachedCacheID(this->m_iDetachCacheOffset);
735
+ // detach_group_cache_ids_.index({cell_idx, split_idx, 1}) = cell_kj->getDetachedCacheID(this->m_iDetachCacheOffset);
736
+ group_ids_ptr[idx_offset] = cell_ik->cache_id;
737
+ group_ids_ptr[idx_offset + 1] = cell_kj->cache_id;
738
+ detach_group_ids_ptr[idx_offset] = cell_ik->getDetachedCacheID(this->m_iDetachCacheOffset);
739
+ detach_group_ids_ptr[idx_offset + 1] = cell_kj->getDetachedCacheID(this->m_iDetachCacheOffset);
740
+
741
+ idx_offset += 2;
742
+ }
743
+ }
744
+
745
+ at::Tensor target_cache_ids_ = torch::from_blob(tgt_cache_ids_ptr, {total_size}, at::kLong);
746
+ at::Tensor group_cache_ids_ = torch::from_blob(group_ids_ptr, {total_size, group_size, 2}, at::kLong);
747
+ at::Tensor ext_id_cache_ids_ = torch::from_blob(tgt_ext_id_ptr, {total_size}, at::kLong);
748
+ at::Tensor detach_group_cache_ids_ = torch::from_blob(detach_group_ids_ptr, {total_size, group_size, 2}, at::kLong);
749
+
750
+ this->m_iCurrentStep += 1;
751
+ return {target_cache_ids_, ext_id_cache_ids_, group_cache_ids_, detach_group_cache_ids_};
752
+ // return {target_cache_ids_, group_cache_ids_, detach_group_cache_ids_};
753
+ }
754
+
755
+ bool hit_span(int i, int k, int j, py::array_t<int>& atom_spans) {
756
+ auto atom_span_pt = atom_spans.unchecked<2>();
757
+ int atom_span_st = 0, atom_span_ed = 0;
758
+ for (int atom_i = 0; atom_i < atom_spans.shape(0); ++atom_i) {
759
+ atom_span_st = atom_span_pt(atom_i, 0);
760
+ atom_span_ed = atom_span_pt(atom_i, 1);
761
+
762
+ if (j < atom_span_st || i > atom_span_ed || (i >= atom_span_st && j <= atom_span_ed)) {
763
+ // no overlap
764
+ continue;
765
+ }
766
+ if ((k < atom_span_st && j >= atom_span_ed) || (k + 1 > atom_span_ed && i <= atom_span_st)) {
767
+ continue;
768
+ }
769
+ return true;
770
+ }
771
+ return false;
772
+ }
773
+
774
+ void induce_best_splits(int max_seq_len, int * cell_nums, Cell *** cell_orders, vector<py::array_t<int>> &best_splits,
775
+ vector<py::array_t<int>> &a_ij_splits, vector<py::array_t<int>> &atom_spans) {
776
+ // a_ij after gumbel_softmax maybe different from best_splits
777
+ for (int step = 0; step < max_seq_len - 1; ++step) {
778
+ for (int cell_idx = 0; cell_idx < cell_nums[step]; ++cell_idx) {
779
+ Cell * current_cell = cell_orders[step][cell_idx];
780
+ assert(current_cell->i <= current_cell->j);
781
+ // atom_spans[current_cell->batch_id]
782
+ auto best_splits_mat = best_splits[step].unchecked<2>();
783
+ auto a_ij_np = a_ij_splits[step].unchecked<2>();
784
+ current_cell->a_ij_split = a_ij_np(cell_idx, 0);
785
+ if (atom_spans.size() > 0 && atom_spans[current_cell->batch_id].shape(0) > 0) {
786
+ for (int split_idx = 0; split_idx < best_splits[step].shape(1); ++split_idx) {
787
+ int split = best_splits_mat(cell_idx, split_idx);
788
+ int k = current_cell->splits[split];
789
+ if (!hit_span(current_cell->i, k, current_cell->j, atom_spans[current_cell->batch_id])) {
790
+ current_cell->best_split = split;
791
+ break;
792
+ }
793
+ }
794
+ // assert(current_cell->best_split != -1);
795
+ } else {
796
+ current_cell->best_split = best_splits_mat(cell_idx, 0);
797
+ }
798
+ }
799
+ }
800
+ }
801
+
802
+ at::Tensor TableManager::root_ids() {
803
+ at::Tensor t = torch::zeros(this->m_iBatchSize, torch::kLong);
804
+ for (int batch_i = 0; batch_i < this->m_iBatchSize; ++batch_i) {
805
+ CellTable * tbl = this->m_pCellTables[batch_i];
806
+ t[batch_i] = tbl->get(0, tbl->getLen() - 1)->cache_id;
807
+ }
808
+ return t;
809
+ }
810
+
811
+ const int TableManager::batch_size() const {
812
+ return this->m_iBatchSize;
813
+ }
814
+
815
+ int left_most(CellTable * table, int idx, int bos_id, int eos_id) {
816
+ if (idx < 0) {
817
+ return bos_id;
818
+ }
819
+ assert (idx < table->getLen() - 1);
820
+ for (int start = 0; start <= idx; ++start) {
821
+ if (!table->isEmpty(start, idx)) {
822
+ return table->get(start, idx)->cache_id;
823
+ }
824
+ }
825
+ assert (false);
826
+ }
827
+
828
+ int right_most(CellTable * table, int idx, int bos_id, int eos_id) {
829
+ if (idx >= table->getLen()) {
830
+ return eos_id;
831
+ }
832
+ assert (idx > 0);
833
+ for (int end = table->getLen() - 1; end >= idx; --end) {
834
+ if (!table->isEmpty(idx, end)) {
835
+ return table->get(idx, end)->cache_id;
836
+ }
837
+ }
838
+ assert (false);
839
+ }
840
+
841
+ at::Tensor TableManager::prepare_bilm(int total_len, int bos_id, int eos_id) {
842
+ at::Tensor cache_ids = torch::zeros({total_len, 2}, torch::kLong);
843
+ int offset = 0;
844
+ for (int batch_i = 0; batch_i < this->m_iBatchSize; ++batch_i) {
845
+ CellTable * tbl = this->m_pCellTables[batch_i];
846
+ for (int idx = 0; idx < tbl->getLen(); ++idx) {
847
+ cache_ids.index({offset, 0}) = left_most(tbl, idx - 1, bos_id, eos_id);
848
+ cache_ids.index({offset, 1}) = right_most(tbl, idx + 1, bos_id, eos_id);
849
+ ++offset;
850
+ }
851
+ }
852
+ assert(offset == total_len);
853
+ return cache_ids;
854
+ }
855
+
856
+ vector<at::Tensor> TableManager::prepare_generation(vector<py::array_t<int>>& score_splits,
857
+ vector<py::array_t<int>>& a_ij_splits,
858
+ vector<py::array_t<int>>& atom_spans,
859
+ const py::array_t<int>& input_ids,
860
+ const py::array_t<int>& group_ids,
861
+ const py::array_t<int>& eos_labels,
862
+ const int reduce_id,
863
+ const int max_input_len) {
864
+ // RETURN: span_mask, split_targets: for the top-down parser to fit
865
+ // ldr_cache_ids : input embeddings for GPT
866
+ // position ids: position id for GPT
867
+ // tgt_ids for generation: cross entropy targets for GPT
868
+ auto buf = group_ids.request();
869
+ size_t buf_sz = buf.size;
870
+ int * group_ids_ptr = (int*)buf.ptr;
871
+ int group_size = group_ids_ptr[buf_sz - 1] + 1;
872
+
873
+ int max_seq_len = max_input_len * 2 - 1;
874
+ int max_ids_len = input_ids.shape(1);
875
+ auto input_ids_ptr = input_ids.unchecked<2>();
876
+
877
+ // assign best split to each cell
878
+ induce_best_splits(this->m_iMaxSeqLen, this->m_pCellNums, m_pCellOrders, score_splits, a_ij_splits, atom_spans);
879
+
880
+ int max_node_size = 2 * this->m_iMaxSeqLen - 1;
881
+
882
+ this->m_pLDRCache_ids = new long[group_size * max_seq_len];
883
+ std::fill_n(this->m_pLDRCache_ids, group_size * max_seq_len, 0);
884
+ this->m_pExtIds = new long[group_size * max_seq_len];
885
+ std::fill_n(this->m_pExtIds, group_size * max_seq_len, -1);
886
+ this->m_pPositionIds = new long[group_size * (max_seq_len + 1)];
887
+ std::fill_n(this->m_pPositionIds, group_size * (max_seq_len + 1), 0);
888
+ this->m_pTgtIds = new long[group_size * (max_seq_len + 1)];
889
+ std::fill_n(this->m_pTgtIds, group_size * (max_seq_len + 1), -1);
890
+
891
+ int mask_mat_size = (max_input_len - 1) * (max_input_len - 1);
892
+
893
+ // this->m_pSpanGatherIds = new long[group_size * max_input_len];
894
+ // std::fill_n(this->m_pSpanGatherIds, group_size * max_input_len, 0);
895
+ this->m_pSpanMasks = new long[group_size * mask_mat_size];
896
+ std::fill_n(this->m_pSpanMasks, group_size * mask_mat_size, 0);
897
+ this->m_pSplitTargets = new long[group_size * (max_input_len - 1)];
898
+ std::fill_n(this->m_pSplitTargets, group_size * (max_input_len - 1), -1);
899
+ this->m_pTokenPositions = new long[group_size * max_input_len];
900
+ std::fill_n(this->m_pTokenPositions, group_size * max_input_len, max_seq_len - 1);
901
+
902
+
903
+ Cell * queue[max_node_size];
904
+ int prev_group_id = -1;
905
+ int ldr_offset = 0;
906
+ int sent_offset = 1;
907
+ auto eos_labels_arr = eos_labels.unchecked<1>();
908
+ for (int batch_i = 0; batch_i < this->m_iBatchSize; ++batch_i) {
909
+ CellTable * tbl = this->m_pCellTables[batch_i];
910
+ Cell * root = tbl->get(0, tbl->getLen() - 1);
911
+ int sent_len = root->j - root->i + 1;
912
+
913
+ int index_bias = sent_len * 2 - 1;
914
+ int queue_offset = 0;
915
+ int split_idx = 0;
916
+ int group_id = group_ids_ptr[batch_i];
917
+ if (group_id != prev_group_id) {
918
+ ldr_offset = 0;
919
+ sent_offset = 1;
920
+ prev_group_id = group_id;
921
+ }
922
+
923
+ Cell * current = NULL;
924
+ queue[queue_offset++] = root;
925
+ while (queue_offset > 0) {
926
+ current = queue[--queue_offset];
927
+
928
+ if (current->split_size > 0) {
929
+ // non-terminal
930
+ int k = current->getBestSplit();
931
+
932
+ std::fill_n(m_pSpanMasks + group_id * mask_mat_size + (sent_offset - 1 + split_idx) * (max_input_len - 1) + sent_offset - 1 + current->i, current->j - current->i, 1);
933
+ assert(current->i <= k && current->j > k);
934
+ m_pSplitTargets[group_id * (max_input_len - 1) + sent_offset + split_idx - 1] = sent_offset - 1 + k;
935
+ ++split_idx;
936
+ queue[queue_offset++] = tbl->get(current->i, k);
937
+ queue[queue_offset++] = tbl->get(k + 1, current->j);
938
+ }
939
+ }
940
+
941
+ queue_offset = 0;
942
+ queue[queue_offset++] = root;
943
+ current = NULL;
944
+ // If there is appending sentence, eos_id will be overrided.
945
+ // tgt_ids.index({group_id, ldr_offset + index_bias}) = eos_id;
946
+ this->m_pTgtIds[group_id * (max_seq_len + 1) + ldr_offset + index_bias] = eos_labels_arr[group_id];
947
+ // for (int idx = 0; idx < sent_len - 1; ++idx) {
948
+ // m_pSpanGatherIds[group_id * max_input_len + sent_offset + idx - 1] = batch_i * (max_ids_len - 1) + idx;
949
+ // }
950
+ while (queue_offset > 0) {
951
+ current = queue[--queue_offset];
952
+
953
+ // ldr_cache_ids.index({group_id, ldr_offset + index_bias - 1}) = current->cache_id;
954
+ // position_ids.index({group_id, ldr_offset + index_bias}) = current->j + sent_offset;
955
+ m_pLDRCache_ids[group_id * max_seq_len + ldr_offset + index_bias - 1] = current->cache_id;
956
+ m_pPositionIds[group_id * (max_seq_len + 1) + ldr_offset + index_bias] = current->j + sent_offset;
957
+ m_pExtIds[group_id * max_seq_len + ldr_offset + index_bias - 1] = current->ext_vocab_id;
958
+ if (current->split_size > 0) {
959
+ // non-terminal
960
+ int k = current->getBestSplit();
961
+
962
+ assert(current->i <= k && current->j > k);
963
+ queue[queue_offset++] = tbl->get(current->i, k);
964
+ queue[queue_offset++] = tbl->get(k + 1, current->j);
965
+ //The right node will be visited first
966
+
967
+ // input will be shift right during training, so just keep id same
968
+ // tgt_ids.index({group_id, ldr_offset + index_bias - 1}) = reduce_id;
969
+ m_pTgtIds[group_id * (max_seq_len + 1) + ldr_offset + index_bias - 1] = reduce_id;
970
+ } else {
971
+ // terminal
972
+ m_pTgtIds[group_id * (max_seq_len + 1) + ldr_offset + index_bias - 1] = \
973
+ input_ids_ptr(batch_i, current->i);
974
+ m_pTokenPositions[group_id * max_input_len + sent_offset - 1 + current->i] = \
975
+ ldr_offset + index_bias - 1;
976
+ }
977
+ --index_bias;
978
+ }
979
+ ldr_offset += 2 * sent_len - 1;
980
+ sent_offset += sent_len;
981
+ }
982
+
983
+ //torch::zeros({group_size, max_seq_len}, at::kLong);
984
+ at::Tensor ldr_cache_ids = torch::from_blob(m_pLDRCache_ids, {group_size, max_seq_len}, at::kLong);
985
+ // at::Tensor position_ids = torch::zeros({group_size, max_seq_len + 1}, at::kLong);
986
+ at::Tensor position_ids = torch::from_blob(m_pPositionIds, {group_size, max_seq_len + 1}, at::kLong);
987
+ // at::Tensor tgt_ids = torch::full({group_size, max_seq_len + 1}, -1, at::kLong);
988
+ at::Tensor tgt_ids = torch::from_blob(m_pTgtIds, {group_size, max_seq_len + 1}, at::kLong);
989
+
990
+ at::Tensor span_masks = torch::from_blob(m_pSpanMasks, {group_size, max_input_len - 1, max_input_len - 1}, at::kLong);
991
+
992
+ at::Tensor split_targets = torch::from_blob(m_pSplitTargets, {group_size, max_input_len - 1}, at::kLong);
993
+
994
+ // at::Tensor gather_ids = torch::from_blob(m_pSpanGatherIds, {group_size, max_input_len}, at::kLong);
995
+ at::Tensor ext_vocab_ids_ = torch::from_blob(m_pExtIds, {group_size, max_seq_len}, at::kLong);
996
+
997
+ at::Tensor token_indices = torch::from_blob(m_pTokenPositions, {group_size, max_input_len}, at::kLong);
998
+
999
+ return {span_masks, split_targets, ldr_cache_ids, position_ids, tgt_ids, token_indices, ext_vocab_ids_};
1000
+ }
1001
+
1002
+ WordTreeNode::WordTreeNode(int entry_id, int total_size, int depth): m_iValue(entry_id), m_iTotalSize(total_size), m_iWordId(-1), m_iDepth(depth){
1003
+ }
1004
+
1005
+ WordTreeNode::~WordTreeNode() {
1006
+ for (auto iter = m_mSubNodes.begin(); iter != m_mSubNodes.end(); ++iter) {
1007
+ delete iter->second;
1008
+ }
1009
+ }
1010
+
1011
+ void WordTreeNode::add_ids(int * ids_ptr, int ids_len, int entry_id, int offset) {
1012
+ int current_id = ids_ptr[offset];
1013
+ if (m_mSubNodes.find(current_id) == m_mSubNodes.end()) {
1014
+ m_mSubNodes[current_id] = new WordTreeNode(-1, m_iTotalSize, m_iDepth + 1);
1015
+ }
1016
+
1017
+ if (offset + 1 < ids_len) {
1018
+ m_mSubNodes[current_id]->add_ids(ids_ptr, ids_len, entry_id, offset + 1);
1019
+ } else if(offset + 1 == ids_len) {
1020
+ m_mSubNodes[current_id]->setWordId(entry_id);
1021
+ }
1022
+ }
1023
+
1024
+ WordTreeNode * WordTreeNode::next_node(int current_id) {
1025
+ // assert(current_id >= 0 && current_id < m_iTotalSize);
1026
+ if (m_mSubNodes.find(current_id) != m_mSubNodes.end()) {
1027
+ return m_mSubNodes[current_id];
1028
+ } else {
1029
+ return NULL;
1030
+ }
1031
+ }
1032
+
1033
+ void WordTreeNode::setWordId(const int wordId) {
1034
+ m_iWordId = wordId;
1035
+ }
1036
+
1037
+ int WordTreeNode::getWordId() const {
1038
+ return m_iWordId;
1039
+ }
1040
+
1041
+ int WordTreeNode::getDepth() const {
1042
+ return m_iDepth;
1043
+ }
1044
+
1045
+ bool WordTreeNode::isWord() const {
1046
+ return m_iWordId != -1;
1047
+ }
1048
+
1049
+ SpanTokenizer::SpanTokenizer(vector<py::array_t<int>>& dictionary, int max_entry_id) {
1050
+ m_pRoot = new WordTreeNode(-1, max_entry_id, false);
1051
+ int entry_id = 0;
1052
+ for (py::array_t<int>& ids : dictionary) {
1053
+ auto buf = ids.request();
1054
+ int * ids_ptr = (int*)buf.ptr;
1055
+ int ids_len = ids.shape(0);
1056
+ m_pRoot->add_ids(ids_ptr, ids_len, entry_id);
1057
+ ++entry_id;
1058
+ }
1059
+ }
1060
+
1061
+ SpanTokenizer::~SpanTokenizer() {
1062
+ delete m_pRoot;
1063
+ }
1064
+
1065
+ vector<int> SpanTokenizer::tokenize(py::array_t<int>& ids_arr) {
1066
+ auto buf = ids_arr.request();
1067
+ int * ids_ptr = (int*)buf.ptr;
1068
+ int size = ids_arr.shape(0);
1069
+
1070
+ list<WordTreeNode*> * current_nodes = new list<WordTreeNode*>();
1071
+ list<WordTreeNode*> * next_nodes = new list<WordTreeNode*>();
1072
+ list<WordTreeNode*> * temp_nodes = 0;
1073
+ current_nodes->push_back(m_pRoot);
1074
+ WordTreeNode * temp = NULL;
1075
+ vector<int> results;
1076
+ for (int idx = 0; idx < size; ++idx) {
1077
+ next_nodes->push_back(m_pRoot);
1078
+ for (WordTreeNode * activated_node : *current_nodes) {
1079
+ temp = activated_node->next_node(ids_ptr[idx]);
1080
+ if (temp != NULL) {
1081
+ next_nodes->push_back(temp);
1082
+ if (temp->isWord()) {
1083
+ // TODO: record span position and word id
1084
+ results.push_back(idx);
1085
+ results.push_back(temp->getDepth());
1086
+ results.push_back(temp->getWordId());
1087
+ // temp->getWordId();
1088
+ }
1089
+ }
1090
+ }
1091
+
1092
+ temp_nodes = current_nodes;
1093
+ current_nodes = next_nodes;
1094
+ next_nodes = temp_nodes;
1095
+ next_nodes->clear();
1096
+ }
1097
+ delete current_nodes;
1098
+ delete next_nodes;
1099
+ return results;
1100
+ }
gpst/cpp_extension/py_backend.h ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2024 Ant Group
2
+ // Author: Xiang Hu
3
+ #pragma once
4
+ #include <vector>
5
+ #include <torch/extension.h>
6
+ #include <pybind11/pybind11.h>
7
+ #include <pybind11/numpy.h>
8
+ #include <pybind11/stl.h>
9
+ #include <list>
10
+ #include <map>
11
+ using namespace std;
12
+ namespace py = pybind11;
13
+
14
+
15
+ class Cell;
16
+ class TableManager;
17
+
18
+ struct Span {
19
+ int i;
20
+ int j;
21
+ };
22
+
23
+ class LinkedNode {
24
+ private:
25
+ Cell * m_pCell;
26
+ LinkedNode * m_pLeft;
27
+ LinkedNode * m_pRight;
28
+ LinkedNode * m_pLeftup;
29
+ LinkedNode * m_pRightup;
30
+ LinkedNode * m_pLeftdown;
31
+ LinkedNode * m_pRightdown;
32
+ public:
33
+ LinkedNode(Cell * value);
34
+ ~LinkedNode();
35
+
36
+ Cell * getCell() const;
37
+ LinkedNode * left() const;
38
+ LinkedNode * right() const;
39
+ LinkedNode * leftup() const;
40
+ LinkedNode * rightup() const;
41
+ LinkedNode * leftdown() const;
42
+ LinkedNode * rightdown() const;
43
+
44
+ void setLeft(LinkedNode * other);
45
+ void setRight(LinkedNode * other);
46
+ void setLeftup(LinkedNode * other);
47
+ void setRightup(LinkedNode * other);
48
+ void setLeftdown(LinkedNode * other);
49
+ void setRightdown(LinkedNode * other);
50
+ };
51
+
52
+
53
+ class Cell {
54
+ private:
55
+ LinkedNode * m_pNode;
56
+ list<Cell*> m_lParents;
57
+ TableManager * m_pMgr;
58
+ bool m_bIsRoot;
59
+ int m_pReadyChild;
60
+
61
+ void notifyChildReady(); // notify when one of its inside cell is ready
62
+ public:
63
+ const int i;
64
+ const int j;
65
+ const int batch_id;
66
+ int ext_vocab_id;
67
+ int cache_id;
68
+ int * splits;
69
+ int split_size;
70
+ int best_split;
71
+ int a_ij_split;
72
+ bool detached;
73
+
74
+ Cell(int i, int j, int window_size, TableManager * mgr, const int batch_id, const bool is_root);
75
+ ~Cell();
76
+
77
+ int getDetachedCacheID(int detach_offset) const;
78
+ LinkedNode * getNode() const;
79
+ void setNode(LinkedNode * target);
80
+ int getBestSplit() const ;
81
+ int getGumbelSplit() const ;
82
+ void addParent(Cell * parent);
83
+ void onReady(); // call when a cell is ready to encode
84
+ };
85
+
86
+ class CellTable {
87
+ private:
88
+ Cell ** m_pCells;
89
+ Cell ** m_pCreatedCells;
90
+ TableManager * m_pMgr;
91
+ const int m_iSeqLen;
92
+ const int m_iBatchId;
93
+ const int m_iMaxCreatedCells;
94
+ const int m_iWindowSize;
95
+ int m_iCellOffset;
96
+ public:
97
+ CellTable(int seq_len, int window_size, int batch_i, TableManager * mgr);
98
+ ~CellTable();
99
+
100
+ int getLen() const;
101
+
102
+ Cell * get(const int i, const int j); // get cell at i,j, if null then create one
103
+ bool isEmpty(const int i, const int j);
104
+ };
105
+
106
+ // class ActiveCells {
107
+ // public:
108
+ // ActiveCells(int window_size, int seq_len, CellTable * cell_table);
109
+ // ~ActiveCells(); //delete memory
110
+
111
+ // vector<LinkedNode*> prune(LinkedNode * node); //return created Nodes
112
+ // }
113
+
114
+ // init_active_cells(int window_size, int seq_len, CellTable * cell_table);
115
+ // vector<LinkedNode*> prune(LinkedNode * node); //return created Nodes
116
+
117
+ class TableManager {
118
+ private:
119
+ CellTable ** m_pCellTables;
120
+ // Span ** m_pMergeOrders;
121
+ int m_iCurrentStep;
122
+ int m_iCellNum;
123
+ const int m_iCacheOffset;
124
+ const int m_iDetachCacheOffset;
125
+ const int m_iWindowSize;
126
+ const int m_iBatchSize;
127
+ int m_iMaxSeqLen;
128
+
129
+ Cell *** m_pCellOrders;
130
+ int * m_pCellNums;
131
+ long ** m_pTargetCacheIds;
132
+ long ** m_pGroupCacheIds;
133
+ long ** m_pTargetExtIds;
134
+ long ** m_pDetachGroupCacheIds;
135
+
136
+ long * m_pLDRCache_ids;
137
+ long * m_pPositionIds;
138
+ long * m_pExtIds; // external vocab id for each position
139
+ long * m_pTgtIds;
140
+
141
+ long * m_pSpanMasks;
142
+ long * m_pSplitTargets;
143
+ long * m_pSpanGatherIds;
144
+ long * m_pTokenPositions;
145
+
146
+ list<Cell*> m_lReadyCells;
147
+ private:
148
+ void push_cell(Cell * cell);
149
+ void build_cell_dependencies(Span ** pMergeOrders);
150
+ public:
151
+ TableManager(const py::array_t<int>& seq_lens, const py::array_t<int>& group_ids,
152
+ const py::array_t<int>& merge_orders, const int window_size,
153
+ const int cache_id_offset, const int detach_cache_id_offset,
154
+ vector<py::array_t<int>>& span_ids);
155
+ ~TableManager();
156
+ bool is_finished();
157
+ vector<at::Tensor> step();
158
+ // vector<at::Tensor> best_trees(py::array_t<int>& best_splits);
159
+
160
+ vector<at::Tensor> prepare_generation(vector<py::array_t<int>>& score_splits,
161
+ vector<py::array_t<int>>& a_ij_splits,
162
+ vector<py::array_t<int>>& atom_spans,
163
+ const py::array_t<int>& input_ids,
164
+ const py::array_t<int>& groups_ids,
165
+ const py::array_t<int>& eos_labels,
166
+ const int reduce_id,
167
+ const int max_input_len);
168
+ at::Tensor root_ids();
169
+ at::Tensor prepare_bilm(int total_len, int bos_id, int eos_id);
170
+ const int batch_size() const;
171
+ void on_cell_ready(Cell* cell);
172
+ };
173
+
174
+ class WordTreeNode;
175
+
176
+ class WordTreeNode {
177
+ private:
178
+ // WordTreeNode ** m_pSubNodes;
179
+ map<int, WordTreeNode*> m_mSubNodes;
180
+ const int m_iTotalSize;
181
+ const int m_iValue;
182
+ int m_iWordId;
183
+ const int m_iDepth;
184
+ public:
185
+ WordTreeNode(int entry_id, int total_size, int depth=0);
186
+ void add_ids(int * ids_ptr, int ids_len, int entry_id, int offset=0);
187
+ WordTreeNode * next_node(int current_id);
188
+ ~WordTreeNode();
189
+ void setWordId(const int wordId);
190
+ int getWordId() const;
191
+ int getDepth() const;
192
+ bool isWord() const;
193
+ void print_path() const;
194
+ };
195
+
196
+ class SpanTokenizer {
197
+ private:
198
+ WordTreeNode * m_pRoot;
199
+ public:
200
+ SpanTokenizer(vector<py::array_t<int>>& dictionary, int max_entry_id);
201
+ ~SpanTokenizer();
202
+
203
+ vector<int> tokenize(py::array_t<int>& ids_arr);
204
+ };
gpst/data_structure/py_backend.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright (c) 2024 Ant Group
3
+ # Author: Xiang Hu
4
+ from typing import List
5
+ import torch
6
+ import numpy as np
7
+ from gpst import cppbackend
8
+
9
+ class CPPChartTableManager:
10
+ def __init__(self, seq_lens, window_size, merge_orders, cache_id_offset, detach_cache_id_offset, group_ids=None, span_ids=None):
11
+ # seq_lens: np array
12
+ # merge_orders: np array
13
+ self.seq_lens = seq_lens
14
+
15
+ if group_ids is None:
16
+ group_ids = [i for i in range(len(seq_lens))]
17
+ if span_ids is None:
18
+ span_ids = []
19
+ assert len(group_ids) == len(seq_lens)
20
+ self.cpp_tbl_mgr = cppbackend.TableManager(seq_lens, group_ids, merge_orders, window_size,
21
+ cache_id_offset, detach_cache_id_offset, span_ids)
22
+ self._root_ids = None
23
+
24
+ @property
25
+ def root_ids(self):
26
+ return self._root_ids
27
+
28
+ def construct_inside_groups(self, device):
29
+ target_cache_ids_list = []
30
+ span_ids_batch_list = []
31
+ cache_groups_batch_list = []
32
+ detach_cache_groups_batch_list = []
33
+ total_time = None
34
+ while not self.cpp_tbl_mgr.is_finished():
35
+ tgt_cache_ids, span_ids, cache_ids, detach_cache_ids = self.cpp_tbl_mgr.step()
36
+ target_cache_ids_list.append(tgt_cache_ids.to(device, non_blocking=True))
37
+ span_ids_batch_list.append(span_ids.to(device, non_blocking=True))
38
+ cache_groups_batch_list.append(cache_ids.to(device, non_blocking=True))
39
+ detach_cache_groups_batch_list.append(detach_cache_ids.to(device, non_blocking=True))
40
+
41
+ self._root_ids = self.cpp_tbl_mgr.root_ids().to(device, non_blocking=True)
42
+ return target_cache_ids_list, span_ids_batch_list, cache_groups_batch_list, detach_cache_groups_batch_list
43
+
44
+ # def best_trees(self, best_splits, atom_spans=None, terminal_only=False):
45
+ # if atom_spans is None:
46
+ # atom_spans = [torch.zeros((0,2))] * self.cpp_tbl_mgr.batch_size()
47
+ # else:
48
+ # atom_spans = [torch.tensor(spans) if len(spans) > 0 else torch.zeros((0, 2)) for spans in atom_spans]
49
+ # assert len(atom_spans) == self.cpp_tbl_mgr.batch_size()
50
+ # # np_arr = [t.data.numpy() for t in best_splits]
51
+ # # best_splits = np.concatenate(np_arr)
52
+ # # return targets, cache_ids
53
+ # splits, cache_ids = self.cpp_tbl_mgr.best_trees(best_splits, atom_spans, terminal_only)
54
+ # return splits, cache_ids
55
+
56
+ def prepare_generation(self, score_orders, split_orders, atom_spans, input_ids, groups_ids, eos_id, reduce_id, max_input_len,
57
+ eos_labels=None):
58
+ if atom_spans is None:
59
+ atom_spans = [np.zeros((0,2))] * self.cpp_tbl_mgr.batch_size()
60
+ else:
61
+ atom_spans = [np.array(spans) if len(spans) > 0 else np.zeros((0, 2)) for spans in atom_spans]
62
+ assert len(atom_spans) == self.cpp_tbl_mgr.batch_size()
63
+ score_orders = [order.data.numpy() for order in score_orders]
64
+ split_orders = [order.data.numpy() for order in split_orders]
65
+ if eos_labels is None:
66
+ eos_labels = np.full((groups_ids[-1] + 1), fill_value=eos_id)
67
+ assert len(eos_labels) == groups_ids[-1] + 1
68
+ span_masks, split_targets, ldr_cache_ids, position_ids, tgt_ids, token_indices, ext_ids = \
69
+ self.cpp_tbl_mgr.prepare_generation(score_orders, split_orders, atom_spans, input_ids, groups_ids,
70
+ eos_labels, reduce_id, max_input_len)
71
+ return span_masks, split_targets, ldr_cache_ids, position_ids, tgt_ids, token_indices, ext_ids
72
+
73
+ def prepare_bilm(self, total_len, bos_id, eos_id):
74
+ return self.cpp_tbl_mgr.prepare_bilm(total_len, bos_id, eos_id)
gpst/data_structure/tensor_cache.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright (c) 2024 Ant Group
3
+ # Author: Xiang Hu
4
+ from enum import Enum
5
+ import torch
6
+
7
+
8
+ class CacheType(Enum):
9
+ NORMAL = 0
10
+ DETACH = 1
11
+
12
+
13
+ class TensorCache:
14
+ def __init__(self, max_window,
15
+ seq_lens,
16
+ cache_types,
17
+ dims,
18
+ placeholder_num,
19
+ device,
20
+ iter_times=1,
21
+ total_cache_size=-1):
22
+ self.placeholder_num = placeholder_num #
23
+ self.total_block_size = placeholder_num
24
+ self.iter_times = iter_times
25
+
26
+ if total_cache_size == -1:
27
+ self.block_sizes = [0] * len(seq_lens)
28
+ self._init_blocks_size(seq_lens, max_window)
29
+ for i in range(len(seq_lens)):
30
+ self.total_block_size += self.block_sizes[i]
31
+ else:
32
+ self.total_block_size += total_cache_size
33
+
34
+ self._max_lengths = [placeholder_num] * len(cache_types)
35
+ self._cache_num = len(cache_types)
36
+ self.cache_types = cache_types
37
+ self.caches = [None] * self._cache_num
38
+ self.dims = dims
39
+ self.device = device
40
+ # dtype = torch.float16 if torch.is_autocast_enabled() else torch.float
41
+ for i, cache_type in enumerate(cache_types):
42
+ if cache_type == CacheType.NORMAL:
43
+ self.caches[i] = torch.full((self.total_block_size, dims[i]), 0.0, dtype=torch.float32, device=device)
44
+ elif cache_type == CacheType.DETACH:
45
+ self.caches[i] = torch.full((self.total_block_size * 2, dims[i]), 0.0, dtype=torch.float32, device=device)
46
+
47
+ @property
48
+ def capacity(self):
49
+ return self.total_block_size
50
+
51
+ @property
52
+ def detach_offset(self):
53
+ return self.total_block_size
54
+
55
+ def init_placeholders(self, cache_ids, values):
56
+ for cache_id, value in zip(cache_ids, values):
57
+ self.caches[cache_id][:self.placeholder_num] = value
58
+
59
+ def _init_blocks_size(self, seq_lens, max_window):
60
+ seq_num = len(seq_lens)
61
+ for seq_i in range(seq_num):
62
+ seq_len = seq_lens[seq_i]
63
+ block_max_len = 0
64
+ for layer_i in range(seq_len):
65
+ if layer_i <= max_window:
66
+ block_max_len += (seq_len - layer_i) * (layer_i + 1)
67
+ else:
68
+ block_max_len += (max_window + 1) * max_window
69
+ self.block_sizes[seq_i] = block_max_len * self.iter_times
70
+
71
+ def gather(self, indices, cache_ids):
72
+ # Gather tensors according to CacheItem pairs
73
+ tensors_gathered = []
74
+ if isinstance(indices, torch.Tensor):
75
+ gather_indices = indices
76
+ else:
77
+ gather_indices = torch.tensor(indices, dtype=torch.long, device=self.device)
78
+ for cache_id in cache_ids:
79
+ tensor_block = self.caches[cache_id]
80
+ tensor_gather = tensor_block.index_select(dim=0, index=gather_indices)
81
+ tensors_gathered.append(tensor_gather)
82
+ return tensors_gathered
83
+
84
+ def fill(self, cache_id_offset, cache_id_len, cache_ids, values):
85
+ if len(cache_ids) != len(values):
86
+ raise Exception('TensorCache::fill names and values mismatch')
87
+ # cdef PyObject ** tensor_block
88
+ for cache_id, value in zip(cache_ids, values):
89
+ tensor_block = self.caches[cache_id]
90
+ tensor_block[cache_id_offset: cache_id_offset + cache_id_len] = value
91
+ if self.cache_types[cache_id] == CacheType.DETACH:
92
+ detach_offset = self.total_block_size + cache_id_offset
93
+ tensor_block[detach_offset: detach_offset + cache_id_len] = value.detach()
94
+
95
+ def get(self, cache_id, idx):
96
+ assert self.caches[cache_id] is not None
97
+ return self.caches[cache_id][idx]
98
+
99
+ def get_tensor_cache(self, cache_id):
100
+ return self.caches[cache_id]
101
+
102
+ def detach(self, idx):
103
+ detach_idx = self.total_block_size + idx
104
+ for cache_i, cache_type in enumerate(self.cache_types):
105
+ if cache_type == CacheType.DETACH:
106
+ self.caches[cache_i][detach_idx] = self.caches[cache_i][idx].detach()
107
+ return detach_idx
108
+
109
+ def scatter(self, indices, cache_ids, values):
110
+ if isinstance(indices, torch.Tensor):
111
+ scatter_indices = indices
112
+ else:
113
+ scatter_indices = torch.tensor(indices, dtype=torch.long, device=self.device)
114
+
115
+ for cache_id, value in zip(cache_ids, values):
116
+ tensor_block = self.caches[cache_id]
117
+ dim = value.shape[-1]
118
+ scatter_indices_ = scatter_indices.unsqueeze(1).repeat(1, dim)
119
+ if value.dtype != tensor_block.dtype:
120
+ value = value.to(tensor_block.dtype)
121
+ tensor_block.scatter_(dim=0, index=scatter_indices_, src=value)
gpst/fast_parser.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright (c) 2024 Ant Group
3
+ # Author: Xiang Hu
4
+ from gpst.topdown_parser import BasicParser
5
+ from gpst.Llama_flash_attn import *
6
+ import torch.nn as nn
7
+ import torch
8
+ import numpy as np
9
+
10
+
11
+ class TransformerParser(BasicParser):
12
+ def __init__(self, config) -> None:
13
+ super().__init__()
14
+ self.legacy_mode = False
15
+ self.hidden_dim = config.parser_hidden_dim
16
+ self.input_dim = config.parser_input_dim
17
+
18
+ self.score_mlp = nn.Sequential(nn.Linear(2 * self.input_dim, self.hidden_dim),
19
+ nn.GELU(),
20
+ nn.Dropout(config.hidden_dropout_prob),
21
+ nn.Linear(self.hidden_dim, 1))
22
+ # self.score_mlp = nn.Sequential(nn.Linear(self.input_dim, self.hidden_dim),
23
+ # nn.GELU(),
24
+ # nn.Dropout(config.hidden_dropout_prob),
25
+ # nn.Linear(self.hidden_dim, 1))
26
+
27
+ # args = ModelArgs(config.parser_input_dim, config.parser_num_layers, config.parser_nhead,
28
+ # config.vocab_size, max_seq_len=config.parser_max_len, apply_norm=False)
29
+ args = ModelArgs(config.parser_input_dim, config.parser_num_layers, config.parser_nhead,
30
+ config.vocab_size, max_seq_len=config.parser_max_len, apply_norm=True)
31
+
32
+
33
+ # layer = nn.TransformerEncoderLayer(self.input_dim, nhead=config.parser_nhead,
34
+ # dim_feedforward=self.hidden_dim, activation='gelu',
35
+ # batch_first=True)
36
+ # self.encoder = nn.TransformerEncoder(layer, config.parser_num_layers)
37
+ self.encoder = Transformer(args)
38
+
39
+ def _generate_flatten_input_ids(self, input_ids, attn_mask, group_ids):
40
+ seq_lens = attn_mask.sum(dim=1).cpu().data.numpy()
41
+ batch_size = group_ids[-1] + 1
42
+ group_lengths = [0] * batch_size
43
+ for sent_id, group_id in enumerate(group_ids):
44
+ group_lengths[group_id] += seq_lens[sent_id]
45
+
46
+ max_length = max(group_lengths)
47
+
48
+ prev_group_id = -1
49
+ flatten_ids = input_ids.new_zeros((batch_size, max_length))
50
+ flatten_masks = attn_mask.new_zeros([batch_size, max_length])
51
+ for sent_id, group_id in enumerate(group_ids):
52
+ if prev_group_id != group_id:
53
+ offset = 0
54
+ prev_group_id = group_id
55
+ flatten_ids[group_id, offset: offset + seq_lens[sent_id]] = input_ids[sent_id, :seq_lens[sent_id]]
56
+ flatten_masks[group_id, offset: offset + seq_lens[sent_id]] = 1
57
+ offset += seq_lens[sent_id]
58
+ return flatten_ids, flatten_masks, seq_lens
59
+
60
+ def _recover_score_chunks(self, org_shape, scores, seq_lens, group_ids):
61
+ rev_scores = scores.new_zeros((org_shape[0], org_shape[1] - 1)) # (N, L)
62
+ offset = 0
63
+ prev_group_id = -1
64
+ for sent_id, group_id in enumerate(group_ids):
65
+ if group_id != prev_group_id:
66
+ prev_group_id = group_id
67
+ offset = 0
68
+ sent_len = seq_lens[sent_id]
69
+ rev_scores[sent_id, : sent_len - 1] = scores[group_id, offset: offset + sent_len - 1]
70
+ offset += sent_len
71
+ return rev_scores
72
+
73
+ def _split_point_scores(self, input_ids, attn_mask, group_ids=None):
74
+ # attn_mask: (N, L) recording segment ids
75
+ # if group_ids is not None:
76
+ # # reorgniaze input_ids
77
+ # org_input_ids, org_mask = input_ids, attn_mask
78
+ # input_ids, attn_mask, seq_lens = self._generate_flatten_input_ids(input_ids, attn_mask, group_ids)
79
+ if attn_mask is None:
80
+ attn_mask = torch.ones_like(input_ids)
81
+ # print(attn_mask.shape)
82
+ attn_mask = attn_mask.unsqueeze(2) == attn_mask.unsqueeze(1) # (N, L, L) or (L, L)
83
+ # print(attn_mask.shape)
84
+ mask = torch.zeros_like(attn_mask, dtype=torch.float)
85
+ mask.masked_fill_(attn_mask == 0, -np.inf)
86
+ # if len(attn_mask.shape) == 3:
87
+ # eye_mask = torch.eye(attn_mask.shape[1], device=input_ids.device)
88
+ # mask.masked_fill_(attn_mask + eye_mask.unsqueeze(0) == 0, -np.inf)
89
+ # else:
90
+ # mask.masked_fill_(attn_mask == 0, -np.inf)
91
+ # seq_lens = attn_mask.sum(dim=-1) # (N)
92
+ N = input_ids.shape[0]
93
+ pos_ids = torch.arange(input_ids.shape[1], device=input_ids.device)
94
+ outputs = self.encoder(input_ids, attn_mask=mask, position_ids=pos_ids)
95
+ split_logits = torch.cat([outputs[:, :-1, :], outputs[:, 1:, :]], dim=-1) # (N, L - 1, 2 * dim)
96
+ # dim = outputs.shape[-1]
97
+ # split_logits = torch.cat([outputs[:, :-1, dim//2:], outputs[:, 1:, :dim//2]], dim=-1)
98
+ scores = self.score_mlp(split_logits)
99
+ scores = scores.squeeze(-1)
100
+ # if group_ids is not None:
101
+ # # split scores
102
+ # scores = self._recover_score_chunks(org_input_ids.shape, scores, seq_lens, group_ids)
103
+ return scores
gpst/generative_r2d2_fast.py ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright (c) 2024 Ant Group
3
+ # Author: Xiang Hu
4
+ import torch.nn as nn
5
+ import torch
6
+ import torch.nn.functional as F
7
+ from datetime import datetime
8
+ from concurrent.futures import ThreadPoolExecutor
9
+ from dataclasses import dataclass
10
+ from typing import Optional
11
+ from transformers import PreTrainedModel, PretrainedConfig, GPT2Config
12
+ from transformers.modeling_outputs import MaskedLMOutput
13
+ from gpst.gpt2_flash_attn import GPT2Model
14
+ from gpst.r2d2_insideoutside import *
15
+ import copy
16
+
17
+ def load_model(model, model_path, strict=True):
18
+ state_dict = torch.load(model_path, map_location=lambda a, b: a)
19
+ transfered_state_dict = {}
20
+ for k, v in state_dict.items():
21
+ new_k = k.replace('module.', '')
22
+ transfered_state_dict[new_k] = v
23
+ model.load_state_dict(transfered_state_dict, strict=strict)
24
+
25
+ def index_sanity_hook(module, input, output):
26
+ def check(tensor):
27
+ if isinstance(tensor, torch.Tensor):
28
+ if tensor.dtype == torch.long or "int" in str(tensor.dtype):
29
+ if tensor.max() > 10000 or tensor.min() < -10000: # change threshold if needed
30
+ print(f"[!] Suspicious index in {module.__class__.__name__}: min={tensor.min().item()}, max={tensor.max().item()}, shape={tensor.shape}")
31
+
32
+ # Check all inputs
33
+ for item in input:
34
+ if isinstance(item, (tuple, list)):
35
+ for sub in item:
36
+ check(sub)
37
+ else:
38
+ check(item)
39
+
40
+ @dataclass(kw_only=True)
41
+ class R2D2GenOutput():
42
+ struct_loss: Optional[torch.FloatTensor] = None,
43
+ non_struct_loss: Optional[torch.FloatTensor] = None,
44
+ non_struct_loss_fullscale: Optional[torch.FloatTensor] = None,
45
+ action_logits: Optional[torch.FloatTensor] = None,
46
+ hidden_states: Optional[torch.FloatTensor] = None,
47
+ cls_hidden_states: Optional[torch.FloatTensor] = None,
48
+ tgt_ids: Optional[torch.LongTensor] = None,
49
+ pred: Optional[torch.FloatTensor] = None,
50
+ splits: Optional[torch.LongTensor] = None,
51
+ gpt_loss: Optional[torch.FloatTensor] = None,
52
+ action_loss: Optional[torch.FloatTensor] = None,
53
+ inside_outside_loss: Optional[torch.FloatTensor] = None,
54
+ parser_loss: Optional[torch.FloatTensor] = None,
55
+ glue_finetune_loss: Optional[torch.FloatTensor] = None,
56
+ past_kv: Optional[torch.FloatTensor] = None
57
+ logits: Optional[torch.FloatTensor] = None,
58
+ loss: Optional[torch.FloatTensor] = None,
59
+
60
+
61
+ class GPSTConfig(PretrainedConfig):
62
+ model_type = "gpst"
63
+
64
+ def __init__(self, r2d2=None, gpt=None, **kwargs):#, gptconfig, r2d2config, **kwargs):
65
+
66
+ self.gptconfig = gpt
67
+ self.r2d2config = r2d2
68
+ super().__init__(**kwargs)
69
+
70
+ class GPST(PreTrainedModel):
71
+ config_class = GPSTConfig
72
+
73
+ def __init__(self, config, gradient_checkpoint=False):
74
+ super().__init__(config)
75
+ self.config = config
76
+ self.r2d2_config = PretrainedConfig.from_dict(config.r2d2config)
77
+ self.gpt_config = GPT2Config.from_dict(config.gptconfig)
78
+
79
+ self.vocab_size = self.gpt_config.vocab_size
80
+
81
+ total_layer = self.gpt_config.n_layer
82
+ action_transformers = GPT2Model(copy.deepcopy(self.gpt_config), no_embedding=True, no_layer_norm=True, n_layers_manual=self.gpt_config.action_layer_num)
83
+ action_transformers.gradient_checkpointing = gradient_checkpoint
84
+ self.gpt_config.n_layer = total_layer - self.gpt_config.action_layer_num
85
+ self.gpt_config.num_hidden_layers = total_layer - self.gpt_config.action_layer_num
86
+ gpt_transformers = GPT2Model(self.gpt_config, no_embedding=True, no_extra_embedding=True)
87
+ gpt_transformers.gradient_checkpointing = gradient_checkpoint
88
+
89
+ r2d2 = InsideOutsideModule(self.r2d2_config)
90
+ self.model = FastGenerativeR2D2(
91
+ r2d2=r2d2,
92
+ action_layers=action_transformers,
93
+ generation_layers=gpt_transformers,
94
+ vocab_size=self.vocab_size,
95
+ r2d2_input_dim=r2d2.input_dim,
96
+ embedding_dim=self.gpt_config.n_embd,
97
+ ext_vocab_size=self.r2d2_config.ext_vocab_size,
98
+ dense_hidden_factor=self.gpt_config.dense_hidden_factor
99
+ )
100
+
101
+ #for name, module in self.model.named_modules():
102
+ # #module.register_forward_hook(index_sanity_hook)
103
+ # module.register_full_backward_hook(index_sanity_hook)
104
+
105
+ def get_input_embeddings(self):
106
+ return self.model.embeddings
107
+
108
+ def forward(self, **kwargs):
109
+ return self.model(**kwargs)
110
+
111
+ class FastGenerativeR2D2(nn.Module):
112
+ def __init__(self, r2d2, action_layers, generation_layers, vocab_size,
113
+ r2d2_input_dim, embedding_dim, dropout_rate=0.2, ext_vocab_size=0,
114
+ fix_embeddings=False, dense_hidden_factor=4):
115
+ # embedding dim is used to feed to r2d2
116
+ # input dim is sued to feed to GPT
117
+ super().__init__()
118
+ self.embedding_dim = embedding_dim # embedding_dim > r2d2_input_dim
119
+ self.r2d2_input_dim = r2d2_input_dim
120
+ self.r2d2 = r2d2
121
+
122
+ self.vocab_size = vocab_size
123
+
124
+ # self.action_ln = nn.Linear(self.embedding_dim, 2) # judge reduce or predict next token
125
+
126
+ self.enable_gpt = False
127
+ if action_layers is not None and generation_layers is not None:
128
+ self.dense_hidden_factor = dense_hidden_factor
129
+ self.action_layers = action_layers
130
+ self.generation_layers = generation_layers
131
+ self.bos_embedding = nn.Parameter(torch.rand(self.embedding_dim))
132
+ self.up_scale = nn.Linear(self.r2d2_input_dim, self.embedding_dim)
133
+ self.dense = nn.Sequential(nn.Linear(self.embedding_dim, self.dense_hidden_factor * self.embedding_dim),
134
+ nn.GELU(),
135
+ nn.Dropout(dropout_rate),
136
+ nn.Linear(self.dense_hidden_factor * self.embedding_dim, self.embedding_dim))
137
+ self.action_mlp = nn.Sequential(nn.LayerNorm(self.embedding_dim),
138
+ nn.Linear(self.embedding_dim, self.embedding_dim),
139
+ nn.GELU(),
140
+ nn.Dropout(dropout_rate),
141
+ nn.Linear(self.embedding_dim, 2))
142
+ self.enable_gpt = True
143
+
144
+ self.classifier = nn.Linear(self.embedding_dim, vocab_size, bias=False)
145
+ self.embeddings = nn.Embedding(vocab_size, self.embedding_dim)
146
+ self.embeddings.requires_grad = not fix_embeddings
147
+ self.down_scale = nn.Linear(self.embedding_dim, self.r2d2_input_dim)
148
+
149
+ self.insideoutside_dense = nn.Sequential(
150
+ nn.Linear(r2d2_input_dim, self.dense_hidden_factor * r2d2_input_dim),
151
+ nn.GELU(),
152
+ nn.Dropout(dropout_rate),
153
+ nn.Linear(self.dense_hidden_factor * r2d2_input_dim, self.embedding_dim)
154
+ )
155
+
156
+ # self.parallel_stream = torch.cuda.Stream()
157
+
158
+ self._init_weights()
159
+ self._tie_weights()
160
+
161
+ def _init_weights(self):
162
+ if self.enable_gpt:
163
+ self.bos_embedding.data.normal_(mean=0, std=0.02)
164
+ self.embeddings.weight.data.normal_(mean=0, std=0.02)
165
+
166
+ def _tie_weights(self):
167
+ self.classifier.weight = self.embeddings.weight
168
+
169
+ def get_parser(self):
170
+ return self.r2d2.parser
171
+
172
+ def from_pretrain(self, model_path, strict=True):
173
+ load_model(self, model_path, strict=strict)
174
+ self._tie_weights()
175
+
176
+ def _append_eos_label(self, eos_labels, chunk_input_ids, chunk_masks, next_token_indices, max_input_len):
177
+ chunk_masks = (chunk_masks.sum(dim=1) > 0).to(int)
178
+ seq_lens = chunk_masks.sum(dim=1) # (N)
179
+ temp_ids = torch.zeros((chunk_input_ids.shape[0], chunk_input_ids.shape[1] + 1), dtype=chunk_input_ids.dtype, device=chunk_input_ids.device)
180
+ temp_ids.fill_(-100)
181
+ temp_ids[:, :-1] = chunk_input_ids
182
+ # comment this line to support discriminant way
183
+ temp_ids.scatter_(1, seq_lens.unsqueeze(1), torch.tensor(eos_labels, device=chunk_input_ids.device).unsqueeze(1))
184
+ chunk_input_ids = temp_ids
185
+ next_token_indices = next_token_indices[:, :max_input_len + 1]
186
+ return next_token_indices, chunk_input_ids
187
+
188
+ def forward(self, chunk_input_ids= None, chunk_masks=None, input_ids=None, masks=None, eos_labels=None, group_ids=None,
189
+ atom_spans=None, span_ids=None, external_vocab_ids=None,
190
+ coeff=1.0, temperature=1.0, past_key_values=None):
191
+ batch_size = max(group_ids) + 1
192
+ r2d2_input_ids = torch.where(chunk_input_ids == -100, 0, chunk_input_ids)
193
+ input_embeddings = self.embeddings(r2d2_input_ids)
194
+ r2d2_embeddings = self.down_scale(input_embeddings)
195
+ # max_input_len = chunk_input_ids.shape[1]
196
+ max_input_len = (chunk_masks != 0).sum(dim=1).max().to('cpu', non_blocking=True)
197
+
198
+ ctx, outside_tgt, ldr_repr, position_ids, tgt_ids, token_indices, ext_ids, split_targets, l_height = \
199
+ self.r2d2(r2d2_input_ids, chunk_masks, input_ids, masks, r2d2_embeddings, group_ids,
200
+ max_input_len, atom_spans=atom_spans, coeff=coeff, temperature=temperature, span_ids=span_ids,
201
+ eos_labels=eos_labels, external_vocab_ids=external_vocab_ids)
202
+
203
+
204
+ if self.training:
205
+ # with torch.cuda.stream(self.parallel_stream):
206
+ parser_loss = self.r2d2.parser_loss(ctx)
207
+ outside_embeddings = self.r2d2.outside_embeddings(ctx) # (num non-padding tokens in batch) x embedding_dim
208
+ io_dense = self.insideoutside_dense(outside_embeddings) # (num non-padding tokens in batch) x embedding_dim
209
+ outside_logits = self.classifier(io_dense) # (num non-padding tokens in batch) x voc_size
210
+ insideoutside_loss = F.cross_entropy(outside_logits, outside_tgt)
211
+ else:
212
+ parser_loss = insideoutside_loss = 0
213
+
214
+ logits = action_logits = None
215
+ gpt_loss = action_loss = 0
216
+ past_kv = None
217
+ hidden_states = None
218
+
219
+ if self.enable_gpt:
220
+ if past_key_values is not None:
221
+ action_past_kv, gen_past_kv = past_key_values
222
+ else:
223
+ action_past_kv = gen_past_kv = None
224
+ gpt_input = self.up_scale(ldr_repr).clone() # ldr_repr: batch_size x (2*max_seq_len - 1) x HP dim; gpt_input: batch_size x (2*max_seq_len - 1) x emb_dim
225
+ gpt_input.scatter_(1, token_indices.unsqueeze(2).repeat(1, 1, input_embeddings.shape[-1]).clone(),
226
+ input_embeddings.to(gpt_input.dtype)) # inserting values of input_embeddings at token_indices
227
+
228
+ # ext_embedding = self.ext_embeds(ext_ids)
229
+ # gpt_input = gpt_input + ext_embedding
230
+ bos_emb = self.bos_embedding.unsqueeze(0).repeat(batch_size, 1)
231
+ # position ids already considered <bos>
232
+ cat_input = torch.cat([bos_emb.unsqueeze(1), gpt_input], dim=1) # batch_size x 2*max_seq_len x emb_dim # old comment: (group_size, L + 1, dim) where L is (2*max_seq_len - 1)
233
+ # cat_input = self.layer_norm(cat_input)
234
+ # cat_input = self.norm(cat_input)
235
+ outputs = self.action_layers(inputs_embeds=cat_input, position_ids=position_ids, past_key_values=action_past_kv) # (B, L, dim)
236
+ action_logits = self.action_mlp(outputs.last_hidden_state) # (batch_size x 2*max_seq_len x emb_dim) to (B, 2*max_seq_len, 2)
237
+ # before, tgt_ids has shape (batch_size x 2*max_seq_len) and has the reduce_token_id (default: 50257) in some placdse. Paddingn: -1
238
+ # first where expression: action_tgt has shape (batch_size x 2*max_seq_len), 0 and 1 values for generate/reduce. Padding is still zero
239
+ # second where: padding with -1
240
+ action_tgt = torch.where(tgt_ids == self.r2d2.reduce_id, 1, 0) # REDUCE: 1, SHIFT:0
241
+ action_tgt = torch.where(tgt_ids != -1, action_tgt, -1)
242
+ # print(action_tgt)
243
+
244
+ next_token_indices = (tgt_ids != self.r2d2.reduce_id).int().argsort(dim=-1, descending=True, stable=True) # (B, L)
245
+ if eos_labels is None:
246
+ #truncated_len = max_input_len if self.training else max_input_len + 1
247
+ truncated_len = max_input_len
248
+ next_token_indices = next_token_indices[:, :truncated_len] # batch_size x longest_sequence;
249
+ else:
250
+ next_token_indices, chunk_input_ids = self._append_eos_label(eos_labels, chunk_input_ids, chunk_masks, next_token_indices, max_input_len)
251
+ # outputs.last_hidden_state: batch_size x 2*max_seq_len x HP dim
252
+ # generation_inputs: batch_size x max_seq_len x HP dim
253
+ # next_token_indices_reformat: batch_size x max_seq_len x HP dim
254
+ next_token_indices_reformat = next_token_indices.unsqueeze(2).repeat(1, 1, self.embedding_dim)
255
+ generation_inputs = outputs.last_hidden_state.gather(1, next_token_indices_reformat)
256
+ # token_pos_ids = position_ids.gather(1, next_token_indices)
257
+ # gather outputs to predict the next token
258
+ # token_outputs: LM output. Last hidden_state has batch_size x max_seq_len x HP dim
259
+ token_outputs = self.generation_layers(inputs_embeds=generation_inputs, past_key_values=gen_past_kv)
260
+
261
+ hidden_states = token_outputs.last_hidden_state
262
+ logits = self.classifier(self.dense(hidden_states)) # new: batch_size x max_seq_len x voc_size old: (group_size, L + 1, vocab)
263
+ # predict token loss + action loss
264
+ # print("chunk_input_ids: ", chunk_input_ids)
265
+ #if self.training:
266
+ gpt_loss = F.cross_entropy(logits.permute(0, 2, 1), chunk_input_ids, ignore_index=-100)
267
+ action_loss = F.cross_entropy(action_logits.permute(0, 2, 1), action_tgt, ignore_index=-1)
268
+ past_kv = (outputs.past_key_values, token_outputs.past_key_values)
269
+
270
+ # torch.cuda.synchronize()
271
+ # return loss + lm_loss + parser_loss, split_targets
272
+ return R2D2GenOutput(struct_loss=insideoutside_loss + l_height,
273
+ non_struct_loss=0.5 * gpt_loss + action_loss + parser_loss,
274
+ non_struct_loss_fullscale=gpt_loss + action_loss + parser_loss,
275
+ logits=logits,
276
+ action_logits=action_logits,
277
+ hidden_states=hidden_states,
278
+ tgt_ids=chunk_input_ids,
279
+ gpt_loss=gpt_loss,
280
+ action_loss=action_loss,
281
+ inside_outside_loss=insideoutside_loss,
282
+ parser_loss=parser_loss,
283
+ past_kv=past_kv,
284
+ splits=split_targets,
285
+ loss=action_loss+gpt_loss+parser_loss+insideoutside_loss+l_height)
286
+ # parser_loss should be fine
287
+
288
+ class FastGenerativeR2D2_discriminant_glue(FastGenerativeR2D2):
289
+
290
+ def _append_eos_label(self, eos_labels, chunk_input_ids, chunk_masks, next_token_indices, max_input_len):
291
+ chunk_masks = (chunk_masks.sum(dim=1) > 0).to(int)
292
+ seq_lens = chunk_masks.sum(dim=1) # (N)
293
+ temp_ids = torch.zeros((chunk_input_ids.shape[0], chunk_input_ids.shape[1] + 1), dtype=chunk_input_ids.dtype, device=chunk_input_ids.device)
294
+ temp_ids.fill_(-100)
295
+ temp_ids[:, :-1] = chunk_input_ids
296
+ # temp_ids.scatter_(1, seq_lens.unsqueeze(1), torch.tensor(eos_labels, device=chunk_input_ids.device).unsqueeze(1))
297
+ chunk_input_ids = temp_ids
298
+ next_token_indices = next_token_indices[:, :max_input_len + 1]
299
+ return next_token_indices, chunk_input_ids
gpst/gpt2_flash_attn.py ADDED
@@ -0,0 +1,1625 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """PyTorch OpenAI GPT-2 model."""
2
+
3
+ import math
4
+ import os
5
+ import warnings
6
+ from dataclasses import dataclass
7
+ from typing import Optional, Tuple, Union
8
+
9
+ import torch
10
+ import torch.utils.checkpoint
11
+ from torch import nn
12
+ from torch.cuda.amp import autocast
13
+ from torch.nn import BCEWithLogitsLoss, CrossEntropyLoss, MSELoss
14
+ import torch.nn.functional as F
15
+
16
+ from transformers.activations import ACT2FN
17
+ from transformers.modeling_outputs import (
18
+ BaseModelOutputWithPastAndCrossAttentions,
19
+ CausalLMOutputWithCrossAttentions,
20
+ QuestionAnsweringModelOutput,
21
+ SequenceClassifierOutputWithPast,
22
+ TokenClassifierOutput,
23
+ )
24
+ from transformers.modeling_utils import PreTrainedModel, SequenceSummary
25
+ from transformers.pytorch_utils import Conv1D, find_pruneable_heads_and_indices, prune_conv1d_layer
26
+ from transformers.utils import (
27
+ ModelOutput,
28
+ add_code_sample_docstrings,
29
+ add_start_docstrings,
30
+ add_start_docstrings_to_model_forward,
31
+ logging,
32
+ replace_return_docstrings,
33
+ )
34
+ from transformers.utils.model_parallel_utils import assert_device_map, get_device_map
35
+ from transformers import GPT2Config
36
+
37
+
38
+ logger = logging.get_logger(__name__)
39
+
40
+ _CHECKPOINT_FOR_DOC = "gpt2"
41
+ _CONFIG_FOR_DOC = "GPT2Config"
42
+
43
+ GPT2_PRETRAINED_MODEL_ARCHIVE_LIST = [
44
+ "gpt2",
45
+ "gpt2-medium",
46
+ "gpt2-large",
47
+ "gpt2-xl",
48
+ "distilgpt2",
49
+ # See all GPT-2 models at https://huggingface.co/models?filter=gpt2
50
+ ]
51
+
52
+
53
+ def load_tf_weights_in_gpt2(model, config, gpt2_checkpoint_path):
54
+ """Load tf checkpoints in a pytorch model"""
55
+ try:
56
+ import re
57
+
58
+ import tensorflow as tf
59
+ except ImportError:
60
+ logger.error(
61
+ "Loading a TensorFlow model in PyTorch, requires TensorFlow to be installed. Please see "
62
+ "https://www.tensorflow.org/install/ for installation instructions."
63
+ )
64
+ raise
65
+ tf_path = os.path.abspath(gpt2_checkpoint_path)
66
+ logger.info(f"Converting TensorFlow checkpoint from {tf_path}")
67
+ # Load weights from TF model
68
+ init_vars = tf.train.list_variables(tf_path)
69
+ names = []
70
+ arrays = []
71
+ for name, shape in init_vars:
72
+ logger.info(f"Loading TF weight {name} with shape {shape}")
73
+ array = tf.train.load_variable(tf_path, name)
74
+ names.append(name)
75
+ arrays.append(array.squeeze())
76
+
77
+ for name, array in zip(names, arrays):
78
+ name = name[6:] # skip "model/"
79
+ name = name.split("/")
80
+ pointer = model
81
+ for m_name in name:
82
+ if re.fullmatch(r"[A-Za-z]+\d+", m_name):
83
+ scope_names = re.split(r"(\d+)", m_name)
84
+ else:
85
+ scope_names = [m_name]
86
+ if scope_names[0] == "w" or scope_names[0] == "g":
87
+ pointer = getattr(pointer, "weight")
88
+ elif scope_names[0] == "b":
89
+ pointer = getattr(pointer, "bias")
90
+ elif scope_names[0] == "wpe" or scope_names[0] == "wte":
91
+ pointer = getattr(pointer, scope_names[0])
92
+ pointer = getattr(pointer, "weight")
93
+ else:
94
+ pointer = getattr(pointer, scope_names[0])
95
+ if len(scope_names) >= 2:
96
+ num = int(scope_names[1])
97
+ pointer = pointer[num]
98
+ try:
99
+ if pointer.shape != array.shape:
100
+ raise ValueError(f"Pointer shape {pointer.shape} and array shape {array.shape} mismatched")
101
+ except ValueError as e:
102
+ e.args += (pointer.shape, array.shape)
103
+ raise
104
+ logger.info(f"Initialize PyTorch weight {name}")
105
+ pointer.data = torch.from_numpy(array)
106
+ return model
107
+
108
+
109
+ class GPT2Attention(nn.Module):
110
+ def __init__(self, config, is_cross_attention=False, layer_idx=None):
111
+ super().__init__()
112
+
113
+ max_positions = config.max_position_embeddings
114
+ self.register_buffer(
115
+ "bias",
116
+ torch.tril(torch.ones((2 * max_positions, 2 * max_positions), dtype=torch.bool)).view(
117
+ 1, 1, 2 * max_positions, 2 * max_positions
118
+ ),
119
+ persistent=False,
120
+ )
121
+ self.register_buffer("masked_bias", torch.tensor(-1e4), persistent=False)
122
+
123
+ self.embed_dim = config.hidden_size
124
+ self.num_heads = config.num_attention_heads
125
+ self.head_dim = self.embed_dim // self.num_heads
126
+ self.split_size = self.embed_dim
127
+ if self.head_dim * self.num_heads != self.embed_dim:
128
+ raise ValueError(
129
+ f"`embed_dim` must be divisible by num_heads (got `embed_dim`: {self.embed_dim} and `num_heads`:"
130
+ f" {self.num_heads})."
131
+ )
132
+
133
+ self.scale_attn_weights = config.scale_attn_weights
134
+ self.is_cross_attention = is_cross_attention
135
+
136
+ # Layer-wise attention scaling, reordering, and upcasting
137
+ self.scale_attn_by_inverse_layer_idx = config.scale_attn_by_inverse_layer_idx
138
+ self.layer_idx = layer_idx
139
+ self.reorder_and_upcast_attn = config.reorder_and_upcast_attn
140
+
141
+ if self.is_cross_attention:
142
+ self.c_attn = Conv1D(2 * self.embed_dim, self.embed_dim)
143
+ self.q_attn = Conv1D(self.embed_dim, self.embed_dim)
144
+ else:
145
+ self.c_attn = Conv1D(3 * self.embed_dim, self.embed_dim)
146
+ self.c_proj = Conv1D(self.embed_dim, self.embed_dim)
147
+
148
+ # self.attn_dropout = nn.Dropout(config.attn_pdrop)
149
+ self.attn_dropout = config.attn_pdrop
150
+ self.resid_dropout = nn.Dropout(config.resid_pdrop)
151
+
152
+ self.pruned_heads = set()
153
+
154
+ def prune_heads(self, heads):
155
+ if len(heads) == 0:
156
+ return
157
+ heads, index = find_pruneable_heads_and_indices(heads, self.num_heads, self.head_dim, self.pruned_heads)
158
+ index_attn = torch.cat([index, index + self.split_size, index + (2 * self.split_size)])
159
+
160
+ # Prune conv1d layers
161
+ self.c_attn = prune_conv1d_layer(self.c_attn, index_attn, dim=1)
162
+ self.c_proj = prune_conv1d_layer(self.c_proj, index, dim=0)
163
+
164
+ # Update hyper params
165
+ self.split_size = (self.split_size // self.num_heads) * (self.num_heads - len(heads))
166
+ self.num_heads = self.num_heads - len(heads)
167
+ self.pruned_heads = self.pruned_heads.union(heads)
168
+
169
+ def _attn(self, query, key, value, attention_mask=None, head_mask=None):
170
+ # print(f'query input: {query[:, 0, :, :3]}')
171
+ # L, S = query.size(-2), key.size(-2)
172
+ # temp_mask = torch.ones(L, S, dtype=torch.bool).tril(diagonal=0)
173
+ # attn_bias = torch.zeros(L, S, dtype=query.dtype)
174
+ # attn_bias.masked_fill_(temp_mask.logical_not(), float("-inf"))
175
+ # print(attn_bias)
176
+ with torch.backends.cuda.sdp_kernel():
177
+ dropout_p = self.attn_dropout if self.training else 0
178
+ L, S = query.size(-2), key.size(-2)
179
+ if attention_mask is None:
180
+ if L == S:
181
+ attn_outputs = F.scaled_dot_product_attention(query, key, value, dropout_p=dropout_p, is_causal=True)
182
+ else:
183
+ attn_mask = torch.ones(L, S, dtype=torch.bool, device=query.device).tril(diagonal=S - L)
184
+ # # print(attn_mask)
185
+ attn_outputs = F.scaled_dot_product_attention(query, key, value, dropout_p=dropout_p, attn_mask=attn_mask)
186
+ else:
187
+ attn_outputs = F.scaled_dot_product_attention(query, key, value, dropout_p=dropout_p, attn_mask=attention_mask)
188
+ # elif query.size(-2) == 1:
189
+ # # inference mode
190
+ # attn_outputs = F.scaled_dot_product_attention(query, key, value, dropout_p=dropout_p, attn_mask=attention_mask)
191
+ # else:
192
+ # raise Exception('unsupported mode')
193
+ # print(attn_outputs[:, :, :3])
194
+ # print(attn_outputs[:, 0, :, :3])
195
+ return attn_outputs
196
+ # attn_weights = torch.matmul(query, key.transpose(-1, -2))
197
+
198
+ # if self.scale_attn_weights:
199
+ # attn_weights = attn_weights / torch.full(
200
+ # [], value.size(-1) ** 0.5, dtype=attn_weights.dtype, device=attn_weights.device
201
+ # )
202
+
203
+ # # Layer-wise attention scaling
204
+ # if self.scale_attn_by_inverse_layer_idx:
205
+ # attn_weights = attn_weights / float(self.layer_idx + 1)
206
+
207
+ # if not self.is_cross_attention:
208
+ # # if only "normal" attention layer implements causal mask
209
+ # query_length, key_length = query.size(-2), key.size(-2)
210
+ # causal_mask = self.bias[:, :, key_length - query_length : key_length, :key_length]
211
+ # mask_value = torch.finfo(attn_weights.dtype).min
212
+ # # Need to be a tensor, otherwise we get error: `RuntimeError: expected scalar type float but found double`.
213
+ # # Need to be on the same device, otherwise `RuntimeError: ..., x and y to be on the same device`
214
+ # mask_value = torch.full([], mask_value, dtype=attn_weights.dtype).to(attn_weights.device)
215
+ # attn_weights = torch.where(causal_mask, attn_weights.to(attn_weights.dtype), mask_value)
216
+
217
+ # if attention_mask is not None:
218
+ # # Apply the attention mask
219
+ # attn_weights = attn_weights + attention_mask
220
+
221
+ # attn_weights = nn.functional.softmax(attn_weights, dim=-1)
222
+
223
+ # # Downcast (if necessary) back to V's dtype (if in mixed-precision) -- No-Op otherwise
224
+ # attn_weights = attn_weights.type(value.dtype)
225
+ # attn_weights = self.attn_dropout(attn_weights)
226
+
227
+ # # Mask heads if we want to
228
+ # if head_mask is not None:
229
+ # attn_weights = attn_weights * head_mask
230
+
231
+ # attn_output = torch.matmul(attn_weights, value)
232
+
233
+ # return attn_output, attn_weights
234
+
235
+ def _upcast_and_reordered_attn(self, query, key, value, attention_mask=None, head_mask=None):
236
+ # Use `torch.baddbmm` (a bit more efficient w/ alpha param for scaling -- from Megatron-LM)
237
+ raise Exception('not implemented for GPT2WithFlashAttn')
238
+
239
+ def _split_heads(self, tensor, num_heads, attn_head_size):
240
+ """
241
+ Splits hidden_size dim into attn_head_size and num_heads
242
+ """
243
+ new_shape = tensor.size()[:-1] + (num_heads, attn_head_size)
244
+ tensor = tensor.view(new_shape)
245
+ return tensor.permute(0, 2, 1, 3) # (batch, head, seq_length, head_features)
246
+
247
+ def _merge_heads(self, tensor, num_heads, attn_head_size):
248
+ """
249
+ Merges attn_head_size dim and num_attn_heads dim into hidden_size
250
+ """
251
+ tensor = tensor.permute(0, 2, 1, 3).contiguous()
252
+ new_shape = tensor.size()[:-2] + (num_heads * attn_head_size,)
253
+ return tensor.view(new_shape)
254
+
255
+ def forward(
256
+ self,
257
+ hidden_states: Optional[Tuple[torch.FloatTensor]],
258
+ layer_past: Optional[Tuple[torch.Tensor]] = None,
259
+ attention_mask: Optional[torch.FloatTensor] = None,
260
+ head_mask: Optional[torch.FloatTensor] = None,
261
+ encoder_hidden_states: Optional[torch.Tensor] = None,
262
+ encoder_attention_mask: Optional[torch.FloatTensor] = None,
263
+ use_cache: Optional[bool] = False,
264
+ output_attentions: Optional[bool] = False,
265
+ ) -> Tuple[Union[torch.Tensor, Tuple[torch.Tensor]], ...]:
266
+ if encoder_hidden_states is not None:
267
+ if not hasattr(self, "q_attn"):
268
+ raise ValueError(
269
+ "If class is used as cross attention, the weights `q_attn` have to be defined. "
270
+ "Please make sure to instantiate class with `GPT2Attention(..., is_cross_attention=True)`."
271
+ )
272
+
273
+ query = self.q_attn(hidden_states)
274
+ key, value = self.c_attn(encoder_hidden_states).split(self.split_size, dim=2)
275
+ attention_mask = encoder_attention_mask
276
+ else:
277
+ query, key, value = self.c_attn(hidden_states).split(self.split_size, dim=2)
278
+
279
+ query = self._split_heads(query, self.num_heads, self.head_dim)
280
+ key = self._split_heads(key, self.num_heads, self.head_dim)
281
+ value = self._split_heads(value, self.num_heads, self.head_dim)
282
+
283
+ if layer_past is not None:
284
+ past_key, past_value = layer_past
285
+ key = torch.cat((past_key, key), dim=-2)
286
+ value = torch.cat((past_value, value), dim=-2)
287
+
288
+ if use_cache is True:
289
+ present = (key, value)
290
+ else:
291
+ present = None
292
+
293
+ attn_output = self._attn(query, key, value, attention_mask, head_mask)
294
+
295
+ attn_output = self._merge_heads(attn_output, self.num_heads, self.head_dim)
296
+ attn_output = self.c_proj(attn_output)
297
+ attn_output = self.resid_dropout(attn_output)
298
+
299
+ outputs = (attn_output, present)
300
+
301
+ return outputs # a, present, (attentions)
302
+
303
+
304
+ class GPT2MLP(nn.Module):
305
+ def __init__(self, intermediate_size, config):
306
+ super().__init__()
307
+ embed_dim = config.hidden_size
308
+ self.c_fc = Conv1D(intermediate_size, embed_dim)
309
+ self.c_proj = Conv1D(embed_dim, intermediate_size)
310
+ self.act = ACT2FN[config.activation_function]
311
+ self.dropout = nn.Dropout(config.resid_pdrop)
312
+
313
+ def forward(self, hidden_states: Optional[Tuple[torch.FloatTensor]]) -> torch.FloatTensor:
314
+ hidden_states = self.c_fc(hidden_states)
315
+ hidden_states = self.act(hidden_states)
316
+ hidden_states = self.c_proj(hidden_states)
317
+ hidden_states = self.dropout(hidden_states)
318
+ return hidden_states
319
+
320
+
321
+ class GPT2Block(nn.Module):
322
+ def __init__(self, config, layer_idx=None):
323
+ super().__init__()
324
+ hidden_size = config.hidden_size
325
+ inner_dim = config.n_inner if config.n_inner is not None else 4 * hidden_size
326
+
327
+ self.ln_1 = nn.LayerNorm(hidden_size, eps=config.layer_norm_epsilon)
328
+ self.attn = GPT2Attention(config, layer_idx=layer_idx)
329
+ self.ln_2 = nn.LayerNorm(hidden_size, eps=config.layer_norm_epsilon)
330
+
331
+ if config.add_cross_attention:
332
+ self.crossattention = GPT2Attention(config, is_cross_attention=True, layer_idx=layer_idx)
333
+ self.ln_cross_attn = nn.LayerNorm(hidden_size, eps=config.layer_norm_epsilon)
334
+
335
+ self.mlp = GPT2MLP(inner_dim, config)
336
+
337
+ def forward(
338
+ self,
339
+ hidden_states: Optional[Tuple[torch.FloatTensor]],
340
+ layer_past: Optional[Tuple[torch.Tensor]] = None,
341
+ attention_mask: Optional[torch.FloatTensor] = None,
342
+ head_mask: Optional[torch.FloatTensor] = None,
343
+ encoder_hidden_states: Optional[torch.Tensor] = None,
344
+ encoder_attention_mask: Optional[torch.FloatTensor] = None,
345
+ use_cache: Optional[bool] = False,
346
+ output_attentions: Optional[bool] = False,
347
+ ) -> Union[Tuple[torch.Tensor], Optional[Tuple[torch.Tensor, Tuple[torch.FloatTensor, ...]]]]:
348
+ residual = hidden_states
349
+ hidden_states = self.ln_1(hidden_states)
350
+ attn_outputs = self.attn(
351
+ hidden_states,
352
+ layer_past=layer_past,
353
+ attention_mask=attention_mask,
354
+ head_mask=head_mask,
355
+ use_cache=use_cache,
356
+ output_attentions=output_attentions,
357
+ )
358
+ attn_output = attn_outputs[0] # output_attn: a, present, (attentions)
359
+ outputs = attn_outputs[1:]
360
+ # residual connection
361
+ hidden_states = attn_output + residual
362
+
363
+ if encoder_hidden_states is not None:
364
+ # add one self-attention block for cross-attention
365
+ if not hasattr(self, "crossattention"):
366
+ raise ValueError(
367
+ f"If `encoder_hidden_states` are passed, {self} has to be instantiated with "
368
+ "cross-attention layers by setting `config.add_cross_attention=True`"
369
+ )
370
+ residual = hidden_states
371
+ hidden_states = self.ln_cross_attn(hidden_states)
372
+ cross_attn_outputs = self.crossattention(
373
+ hidden_states,
374
+ attention_mask=attention_mask,
375
+ head_mask=head_mask,
376
+ encoder_hidden_states=encoder_hidden_states,
377
+ encoder_attention_mask=encoder_attention_mask,
378
+ output_attentions=output_attentions,
379
+ )
380
+ attn_output = cross_attn_outputs[0]
381
+ # residual connection
382
+ hidden_states = residual + attn_output
383
+ outputs = outputs + cross_attn_outputs[2:] # add cross attentions if we output attention weights
384
+
385
+ residual = hidden_states
386
+ hidden_states = self.ln_2(hidden_states)
387
+ feed_forward_hidden_states = self.mlp(hidden_states)
388
+ # residual connection
389
+ hidden_states = residual + feed_forward_hidden_states
390
+
391
+ if use_cache:
392
+ outputs = (hidden_states,) + outputs
393
+ else:
394
+ outputs = (hidden_states,) + outputs[1:]
395
+
396
+ return outputs # hidden_states, present, (attentions, cross_attentions)
397
+
398
+
399
+ class GPT2PreTrainedModel(PreTrainedModel):
400
+ """
401
+ An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained
402
+ models.
403
+ """
404
+
405
+ config_class = GPT2Config
406
+ load_tf_weights = load_tf_weights_in_gpt2
407
+ base_model_prefix = "transformer"
408
+ is_parallelizable = True
409
+ supports_gradient_checkpointing = True
410
+ _no_split_modules = ["GPT2Block"]
411
+ _skip_keys_device_placement = "past_key_values"
412
+
413
+ def __init__(self, *inputs, **kwargs):
414
+ super().__init__(*inputs, **kwargs)
415
+
416
+ def _init_weights(self, module):
417
+ """Initialize the weights."""
418
+ if isinstance(module, (nn.Linear, Conv1D)):
419
+ # Slightly different from the TF version which uses truncated_normal for initialization
420
+ # cf https://github.com/pytorch/pytorch/pull/5617
421
+ module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
422
+ if module.bias is not None:
423
+ module.bias.data.zero_()
424
+ elif isinstance(module, nn.Embedding):
425
+ module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
426
+ if module.padding_idx is not None:
427
+ module.weight.data[module.padding_idx].zero_()
428
+ elif isinstance(module, nn.LayerNorm):
429
+ module.bias.data.zero_()
430
+ module.weight.data.fill_(1.0)
431
+
432
+ # Reinitialize selected weights subject to the OpenAI GPT-2 Paper Scheme:
433
+ # > A modified initialization which accounts for the accumulation on the residual path with model depth. Scale
434
+ # > the weights of residual layers at initialization by a factor of 1/√N where N is the # of residual layers.
435
+ # > -- GPT-2 :: https://openai.com/blog/better-language-models/
436
+ #
437
+ # Reference (Megatron-LM): https://github.com/NVIDIA/Megatron-LM/blob/main/megatron/model/gpt_model.py
438
+ for name, p in module.named_parameters():
439
+ if name == "c_proj.weight":
440
+ # Special Scaled Initialization --> There are 2 Layer Norms per Transformer Block
441
+ p.data.normal_(mean=0.0, std=(self.config.initializer_range / math.sqrt(2 * self.config.n_layer)))
442
+
443
+ def _set_gradient_checkpointing(self, module, value=False):
444
+ if isinstance(module, GPT2Model):
445
+ module.gradient_checkpointing = value
446
+
447
+
448
+ @dataclass
449
+ class GPT2DoubleHeadsModelOutput(ModelOutput):
450
+ """
451
+ Base class for outputs of models predicting if two sentences are consecutive or not.
452
+
453
+ Args:
454
+ loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `labels` is provided):
455
+ Language modeling loss.
456
+ mc_loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `mc_labels` is provided):
457
+ Multiple choice classification loss.
458
+ logits (`torch.FloatTensor` of shape `(batch_size, num_choices, sequence_length, config.vocab_size)`):
459
+ Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).
460
+ mc_logits (`torch.FloatTensor` of shape `(batch_size, num_choices)`):
461
+ Prediction scores of the multiple choice classification head (scores for each choice before SoftMax).
462
+ past_key_values (`Tuple[Tuple[torch.Tensor]]`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
463
+ Tuple of length `config.n_layers`, containing tuples of tensors of shape `(batch_size, num_heads,
464
+ sequence_length, embed_size_per_head)`).
465
+
466
+ Contains pre-computed hidden-states (key and values in the attention blocks) that can be used (see
467
+ `past_key_values` input) to speed up sequential decoding.
468
+ hidden_states (`tuple(torch.FloatTensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
469
+ Tuple of `torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer) of
470
+ shape `(batch_size, sequence_length, hidden_size)`.
471
+
472
+ Hidden-states of the model at the output of each layer plus the initial embedding outputs.
473
+ attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
474
+ Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
475
+ sequence_length)`.
476
+
477
+ GPT2Attentions weights after the attention softmax, used to compute the weighted average in the
478
+ self-attention heads.
479
+ """
480
+
481
+ loss: Optional[torch.FloatTensor] = None
482
+ mc_loss: Optional[torch.FloatTensor] = None
483
+ logits: torch.FloatTensor = None
484
+ mc_logits: torch.FloatTensor = None
485
+ past_key_values: Optional[Tuple[Tuple[torch.FloatTensor]]] = None
486
+ hidden_states: Optional[Tuple[torch.FloatTensor]] = None
487
+ attentions: Optional[Tuple[torch.FloatTensor]] = None
488
+
489
+
490
+ GPT2_START_DOCSTRING = r"""
491
+
492
+ This model inherits from [`PreTrainedModel`]. Check the superclass documentation for the generic methods the
493
+ library implements for all its model (such as downloading or saving, resizing the input embeddings, pruning heads
494
+ etc.)
495
+
496
+ This model is also a PyTorch [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) subclass.
497
+ Use it as a regular PyTorch Module and refer to the PyTorch documentation for all matter related to general usage
498
+ and behavior.
499
+
500
+ Parameters:
501
+ config ([`GPT2Config`]): Model configuration class with all the parameters of the model.
502
+ Initializing with a config file does not load the weights associated with the model, only the
503
+ configuration. Check out the [`~PreTrainedModel.from_pretrained`] method to load the model weights.
504
+ """
505
+
506
+ GPT2_INPUTS_DOCSTRING = r"""
507
+ Args:
508
+ input_ids (`torch.LongTensor` of shape `(batch_size, input_ids_length)`):
509
+ `input_ids_length` = `sequence_length` if `past_key_values` is `None` else
510
+ `past_key_values[0][0].shape[-2]` (`sequence_length` of input past key value states). Indices of input
511
+ sequence tokens in the vocabulary.
512
+
513
+ If `past_key_values` is used, only `input_ids` that do not have their past calculated should be passed as
514
+ `input_ids`.
515
+
516
+ Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
517
+ [`PreTrainedTokenizer.__call__`] for details.
518
+
519
+ [What are input IDs?](../glossary#input-ids)
520
+ past_key_values (`Tuple[Tuple[torch.Tensor]]` of length `config.n_layers`):
521
+ Contains precomputed hidden-states (key and values in the attention blocks) as computed by the model (see
522
+ `past_key_values` output below). Can be used to speed up sequential decoding. The `input_ids` which have
523
+ their past given to this model should not be passed as `input_ids` as they have already been computed.
524
+ attention_mask (`torch.FloatTensor` of shape `(batch_size, sequence_length)`, *optional*):
525
+ Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
526
+
527
+ - 1 for tokens that are **not masked**,
528
+ - 0 for tokens that are **masked**.
529
+
530
+ If `past_key_values` is used, `attention_mask` needs to contain the masking strategy that was used for
531
+ `past_key_values`. In other words, the `attention_mask` always has to have the length:
532
+ `len(past_key_values) + len(input_ids)`
533
+
534
+ [What are attention masks?](../glossary#attention-mask)
535
+ token_type_ids (`torch.LongTensor` of shape `(batch_size, input_ids_length)`, *optional*):
536
+ Segment token indices to indicate first and second portions of the inputs. Indices are selected in `[0,
537
+ 1]`:
538
+
539
+ - 0 corresponds to a *sentence A* token,
540
+ - 1 corresponds to a *sentence B* token.
541
+
542
+ [What are token type IDs?](../glossary#token-type-ids)
543
+ position_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
544
+ Indices of positions of each input sequence tokens in the position embeddings. Selected in the range `[0,
545
+ config.max_position_embeddings - 1]`.
546
+
547
+ [What are position IDs?](../glossary#position-ids)
548
+ head_mask (`torch.FloatTensor` of shape `(num_heads,)` or `(num_layers, num_heads)`, *optional*):
549
+ Mask to nullify selected heads of the self-attention modules. Mask values selected in `[0, 1]`:
550
+
551
+ - 1 indicates the head is **not masked**,
552
+ - 0 indicates the head is **masked**.
553
+
554
+ inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`, *optional*):
555
+ Optionally, instead of passing `input_ids` you can choose to directly pass an embedded representation. This
556
+ is useful if you want more control over how to convert `input_ids` indices into associated vectors than the
557
+ model's internal embedding lookup matrix.
558
+
559
+ If `past_key_values` is used, optionally only the last `inputs_embeds` have to be input (see
560
+ `past_key_values`).
561
+ use_cache (`bool`, *optional*):
562
+ If set to `True`, `past_key_values` key value states are returned and can be used to speed up decoding (see
563
+ `past_key_values`).
564
+ output_attentions (`bool`, *optional*):
565
+ Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned
566
+ tensors for more detail.
567
+ output_hidden_states (`bool`, *optional*):
568
+ Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors for
569
+ more detail.
570
+ return_dict (`bool`, *optional*):
571
+ Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
572
+ """
573
+ PARALLELIZE_DOCSTRING = r"""
574
+ This is an experimental feature and is a subject to change at a moment's notice.
575
+
576
+ Uses a device map to distribute attention modules of the model across several devices. If no device map is given,
577
+ it will evenly distribute blocks across all devices.
578
+
579
+ Args:
580
+ device_map (`Dict[int, list]`, optional, defaults to None):
581
+ A dictionary that maps attention modules to devices. Note that the embedding module and LMHead are always
582
+ automatically mapped to the first device (for esoteric reasons). That means that the first device should
583
+ have fewer attention modules mapped to it than other devices. For reference, the gpt2 models have the
584
+ following number of attention modules:
585
+
586
+ - gpt2: 12
587
+ - gpt2-medium: 24
588
+ - gpt2-large: 36
589
+ - gpt2-xl: 48
590
+
591
+ Example:
592
+
593
+ ```python
594
+ # Here is an example of a device map on a machine with 4 GPUs using gpt2-xl, which has a total of 48 attention modules:
595
+ model = GPT2LMHeadModel.from_pretrained("gpt2-xl")
596
+ device_map = {
597
+ 0: [0, 1, 2, 3, 4, 5, 6, 7, 8],
598
+ 1: [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21],
599
+ 2: [22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34],
600
+ 3: [35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47],
601
+ }
602
+ model.parallelize(device_map)
603
+ ```
604
+ """
605
+ DEPARALLELIZE_DOCSTRING = r"""
606
+ Moves the model to cpu from a model parallel state.
607
+
608
+ Example:
609
+
610
+ ```python
611
+ # On a 4 GPU machine with gpt2-large:
612
+ model = GPT2LMHeadModel.from_pretrained("gpt2-large")
613
+ device_map = {
614
+ 0: [0, 1, 2, 3, 4, 5, 6, 7],
615
+ 1: [8, 9, 10, 11, 12, 13, 14, 15],
616
+ 2: [16, 17, 18, 19, 20, 21, 22, 23],
617
+ 3: [24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35],
618
+ }
619
+ model.parallelize(device_map) # Splits the model across several devices
620
+ model.deparallelize() # Put the model back on cpu and cleans memory by calling torch.cuda.empty_cache()
621
+ ```
622
+ """
623
+
624
+
625
+ @add_start_docstrings(
626
+ "The bare GPT2 Model transformer outputting raw hidden-states without any specific head on top.",
627
+ GPT2_START_DOCSTRING,
628
+ )
629
+ class GPT2Model(GPT2PreTrainedModel):
630
+ def __init__(self, config, no_embedding=False, no_extra_embedding=False, no_layer_norm=False, n_layers_manual=None):
631
+ super().__init__(config)
632
+
633
+ if n_layers_manual:
634
+ self.config.num_hidden_layers = n_layers_manual
635
+ self.config.n_layer = n_layers_manual
636
+
637
+ self.embed_dim = config.hidden_size
638
+
639
+ if not no_embedding:
640
+ self.wte = nn.Embedding(config.vocab_size, self.embed_dim)
641
+
642
+ if not no_extra_embedding:
643
+ self.wpe = nn.Embedding(config.max_position_embeddings, self.embed_dim)
644
+
645
+ self.drop = nn.Dropout(config.embd_pdrop)
646
+ self.h = nn.ModuleList([GPT2Block(config, layer_idx=i) for i in range(config.num_hidden_layers)])
647
+
648
+ if not no_layer_norm:
649
+ self.ln_f = nn.LayerNorm(self.embed_dim, eps=config.layer_norm_epsilon)
650
+ self.no_extra_embedding = no_extra_embedding
651
+ self.no_layer_norm = no_layer_norm
652
+
653
+ # Model parallel
654
+ self.model_parallel = False
655
+ self.device_map = None
656
+ self.gradient_checkpointing = False
657
+
658
+ # Initialize weights and apply final processing
659
+ self.post_init()
660
+
661
+
662
+ def get_input_embeddings(self):
663
+ return self.wte
664
+
665
+ def set_input_embeddings(self, new_embeddings):
666
+ self.wte = new_embeddings
667
+
668
+ def _prune_heads(self, heads_to_prune):
669
+ """
670
+ Prunes heads of the model. heads_to_prune: dict of {layer_num: list of heads to prune in this layer}
671
+ """
672
+ for layer, heads in heads_to_prune.items():
673
+ self.h[layer].attn.prune_heads(heads)
674
+
675
+ @add_start_docstrings_to_model_forward(GPT2_INPUTS_DOCSTRING)
676
+ @add_code_sample_docstrings(
677
+ checkpoint=_CHECKPOINT_FOR_DOC,
678
+ output_type=BaseModelOutputWithPastAndCrossAttentions,
679
+ config_class=_CONFIG_FOR_DOC,
680
+ )
681
+ def forward(
682
+ self,
683
+ input_ids: Optional[torch.LongTensor] = None,
684
+ past_key_values: Optional[Tuple[Tuple[torch.Tensor]]] = None,
685
+ attention_mask: Optional[torch.FloatTensor] = None,
686
+ token_type_ids: Optional[torch.LongTensor] = None,
687
+ position_ids: Optional[torch.LongTensor] = None,
688
+ head_mask: Optional[torch.FloatTensor] = None,
689
+ inputs_embeds: Optional[torch.FloatTensor] = None,
690
+ encoder_hidden_states: Optional[torch.Tensor] = None,
691
+ encoder_attention_mask: Optional[torch.FloatTensor] = None,
692
+ use_cache: Optional[bool] = None,
693
+ output_attentions: Optional[bool] = None,
694
+ output_hidden_states: Optional[bool] = None,
695
+ return_dict: Optional[bool] = None,
696
+ ) -> Union[Tuple, BaseModelOutputWithPastAndCrossAttentions]:
697
+ output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
698
+ output_hidden_states = (
699
+ output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
700
+ )
701
+ use_cache = use_cache if use_cache is not None else self.config.use_cache
702
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
703
+
704
+ if input_ids is not None and inputs_embeds is not None:
705
+ raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
706
+ elif input_ids is not None:
707
+ input_shape = input_ids.size()
708
+ input_ids = input_ids.view(-1, input_shape[-1])
709
+ batch_size = input_ids.shape[0]
710
+ elif inputs_embeds is not None:
711
+ input_shape = inputs_embeds.size()[:-1]
712
+ batch_size = inputs_embeds.shape[0]
713
+ else:
714
+ raise ValueError("You have to specify either input_ids or inputs_embeds")
715
+
716
+ device = input_ids.device if input_ids is not None else inputs_embeds.device
717
+
718
+ if token_type_ids is not None:
719
+ token_type_ids = token_type_ids.view(-1, input_shape[-1])
720
+ if position_ids is not None:
721
+ position_ids = position_ids.view(-1, input_shape[-1])
722
+
723
+ if past_key_values is None:
724
+ past_length = 0
725
+ past_key_values = tuple([None] * len(self.h))
726
+ else:
727
+ past_length = past_key_values[0][0].size(-2)
728
+ if position_ids is None:
729
+ position_ids = torch.arange(past_length, input_shape[-1] + past_length, dtype=torch.long, device=device)
730
+ position_ids = position_ids.unsqueeze(0).view(-1, input_shape[-1])
731
+
732
+ # GPT2Attention mask.
733
+ if attention_mask is not None:
734
+ if batch_size <= 0:
735
+ raise ValueError("batch_size has to be defined and > 0")
736
+ attention_mask = attention_mask.view(batch_size, -1)
737
+ # We create a 3D attention mask from a 2D tensor mask.
738
+ # Sizes are [batch_size, 1, 1, to_seq_length]
739
+ # So we can broadcast to [batch_size, num_heads, from_seq_length, to_seq_length]
740
+ # this attention mask is more simple than the triangular masking of causal attention
741
+ # used in OpenAI GPT, we just need to prepare the broadcast dimension here.
742
+ attention_mask = attention_mask[:, None, None, :]
743
+
744
+ # Since attention_mask is 1.0 for positions we want to attend and 0.0 for
745
+ # masked positions, this operation will create a tensor which is 0.0 for
746
+ # positions we want to attend and the dtype's smallest value for masked positions.
747
+ # Since we are adding it to the raw scores before the softmax, this is
748
+ # effectively the same as removing these entirely.
749
+ attention_mask = attention_mask.to(dtype=self.dtype) # fp16 compatibility
750
+ attention_mask = (1.0 - attention_mask) * torch.finfo(self.dtype).min
751
+
752
+ # If a 2D or 3D attention mask is provided for the cross-attention
753
+ # we need to make broadcastable to [batch_size, num_heads, seq_length, seq_length]
754
+ if self.config.add_cross_attention and encoder_hidden_states is not None:
755
+ encoder_batch_size, encoder_sequence_length, _ = encoder_hidden_states.size()
756
+ encoder_hidden_shape = (encoder_batch_size, encoder_sequence_length)
757
+ if encoder_attention_mask is None:
758
+ encoder_attention_mask = torch.ones(encoder_hidden_shape, device=device)
759
+ encoder_attention_mask = self.invert_attention_mask(encoder_attention_mask)
760
+ else:
761
+ encoder_attention_mask = None
762
+
763
+ # Prepare head mask if needed
764
+ # 1.0 in head_mask indicate we keep the head
765
+ # attention_probs has shape bsz x n_heads x N x N
766
+ # head_mask has shape n_layer x batch x n_heads x N x N
767
+ head_mask = self.get_head_mask(head_mask, self.config.n_layer)
768
+
769
+ if inputs_embeds is None:
770
+ inputs_embeds = self.wte(input_ids)
771
+
772
+ if not self.no_extra_embedding:
773
+ position_embeds = self.wpe(position_ids)
774
+ hidden_states = inputs_embeds + position_embeds
775
+
776
+ if token_type_ids is not None:
777
+ token_type_embeds = self.wte(token_type_ids)
778
+ hidden_states = hidden_states + token_type_embeds
779
+ else:
780
+ hidden_states = inputs_embeds
781
+
782
+ hidden_states = self.drop(hidden_states)
783
+
784
+ output_shape = (-1,) + input_shape[1:] + (hidden_states.size(-1),)
785
+
786
+ if self.gradient_checkpointing and self.training:
787
+ if use_cache:
788
+ # logger.warning(
789
+ # "`use_cache=True` is incompatible with gradient checkpointing. Setting `use_cache=False`..."
790
+ # )
791
+ pass
792
+
793
+ presents = () if use_cache else None
794
+ all_self_attentions = () if output_attentions else None
795
+ all_cross_attentions = () if output_attentions and self.config.add_cross_attention else None
796
+ all_hidden_states = () if output_hidden_states else None
797
+ for i, (block, layer_past) in enumerate(zip(self.h, past_key_values)):
798
+ # Model parallel
799
+ if self.model_parallel:
800
+ torch.cuda.set_device(hidden_states.device)
801
+ # Ensure layer_past is on same device as hidden_states (might not be correct)
802
+ if layer_past is not None:
803
+ layer_past = tuple(past_state.to(hidden_states.device) for past_state in layer_past)
804
+ # Ensure that attention_mask is always on the same device as hidden_states
805
+ if attention_mask is not None:
806
+ attention_mask = attention_mask.to(hidden_states.device)
807
+ if isinstance(head_mask, torch.Tensor):
808
+ head_mask = head_mask.to(hidden_states.device)
809
+ if output_hidden_states:
810
+ all_hidden_states = all_hidden_states + (hidden_states,)
811
+
812
+ if self.gradient_checkpointing and self.training:
813
+
814
+ def create_custom_forward(module):
815
+ def custom_forward(*inputs):
816
+ # None for past_key_value
817
+ return module(*inputs, use_cache, output_attentions)
818
+
819
+ return custom_forward
820
+
821
+ outputs = torch.utils.checkpoint.checkpoint(
822
+ create_custom_forward(block),
823
+ hidden_states,
824
+ None,
825
+ attention_mask,
826
+ head_mask[i],
827
+ encoder_hidden_states,
828
+ encoder_attention_mask,
829
+ )
830
+ else:
831
+ outputs = block(
832
+ hidden_states,
833
+ layer_past=layer_past,
834
+ attention_mask=attention_mask,
835
+ head_mask=head_mask[i],
836
+ encoder_hidden_states=encoder_hidden_states,
837
+ encoder_attention_mask=encoder_attention_mask,
838
+ use_cache=use_cache,
839
+ output_attentions=output_attentions,
840
+ )
841
+
842
+ hidden_states = outputs[0]
843
+ if use_cache is True:
844
+ presents = presents + (outputs[1],)
845
+
846
+ if output_attentions:
847
+ all_self_attentions = all_self_attentions + (outputs[2 if use_cache else 1],)
848
+ if self.config.add_cross_attention:
849
+ all_cross_attentions = all_cross_attentions + (outputs[3 if use_cache else 2],)
850
+
851
+ # Model Parallel: If it's the last layer for that device, put things on the next device
852
+ if self.model_parallel:
853
+ for k, v in self.device_map.items():
854
+ if i == v[-1] and "cuda:" + str(k) != self.last_device:
855
+ hidden_states = hidden_states.to("cuda:" + str(k + 1))
856
+
857
+ if not self.no_layer_norm:
858
+ hidden_states = self.ln_f(hidden_states)
859
+
860
+ hidden_states = hidden_states.view(output_shape)
861
+ # Add last hidden state
862
+ if output_hidden_states:
863
+ all_hidden_states = all_hidden_states + (hidden_states,)
864
+
865
+ if not return_dict:
866
+ return tuple(
867
+ v
868
+ for v in [hidden_states, presents, all_hidden_states, all_self_attentions, all_cross_attentions]
869
+ if v is not None
870
+ )
871
+
872
+ return BaseModelOutputWithPastAndCrossAttentions(
873
+ last_hidden_state=hidden_states,
874
+ past_key_values=presents,
875
+ hidden_states=all_hidden_states,
876
+ attentions=all_self_attentions,
877
+ cross_attentions=all_cross_attentions,
878
+ )
879
+
880
+
881
+ @add_start_docstrings(
882
+ """
883
+ The GPT2 Model transformer with a language modeling head on top (linear layer with weights tied to the input
884
+ embeddings).
885
+ """,
886
+ GPT2_START_DOCSTRING,
887
+ )
888
+ class GPT2LMHeadModel(GPT2PreTrainedModel):
889
+ _tied_weights_keys = ["lm_head.weight"]
890
+
891
+ def __init__(self, config):
892
+ super().__init__(config)
893
+ self.transformer = GPT2Model(config)
894
+ self.lm_head = nn.Linear(config.n_embd, config.vocab_size, bias=False)
895
+
896
+ # Model parallel
897
+ self.model_parallel = False
898
+ self.device_map = None
899
+
900
+ # Initialize weights and apply final processing
901
+ self.post_init()
902
+
903
+ @add_start_docstrings(PARALLELIZE_DOCSTRING)
904
+ def parallelize(self, device_map=None):
905
+ warnings.warn(
906
+ "`GPT2LMHeadModel.parallelize` is deprecated and will be removed in v5 of Transformers, you should load"
907
+ " your model with `device_map='balanced'` in the call to `from_pretrained`. You can also provide your own"
908
+ " `device_map` but it needs to be a dictionary module_name to device, so for instance {'transformer.h.0':"
909
+ " 0, 'transformer.h.1': 1, ...}",
910
+ FutureWarning,
911
+ )
912
+ self.device_map = (
913
+ get_device_map(len(self.transformer.h), range(torch.cuda.device_count()))
914
+ if device_map is None
915
+ else device_map
916
+ )
917
+ assert_device_map(self.device_map, len(self.transformer.h))
918
+ self.transformer.parallelize(self.device_map)
919
+ self.lm_head = self.lm_head.to(self.transformer.first_device)
920
+ self.model_parallel = True
921
+
922
+ @add_start_docstrings(DEPARALLELIZE_DOCSTRING)
923
+ def deparallelize(self):
924
+ warnings.warn(
925
+ "Like `parallelize`, `deparallelize` is deprecated and will be removed in v5 of Transformers.",
926
+ FutureWarning,
927
+ )
928
+ self.transformer.deparallelize()
929
+ self.transformer = self.transformer.to("cpu")
930
+ self.lm_head = self.lm_head.to("cpu")
931
+ self.model_parallel = False
932
+ torch.cuda.empty_cache()
933
+
934
+ def get_output_embeddings(self):
935
+ return self.lm_head
936
+
937
+ def set_output_embeddings(self, new_embeddings):
938
+ self.lm_head = new_embeddings
939
+
940
+ def prepare_inputs_for_generation(self, input_ids, past_key_values=None, inputs_embeds=None, **kwargs):
941
+ token_type_ids = kwargs.get("token_type_ids", None)
942
+ # only last token for inputs_ids if past is defined in kwargs
943
+ if past_key_values:
944
+ input_ids = input_ids[:, -1].unsqueeze(-1)
945
+ if token_type_ids is not None:
946
+ token_type_ids = token_type_ids[:, -1].unsqueeze(-1)
947
+
948
+ attention_mask = kwargs.get("attention_mask", None)
949
+ position_ids = kwargs.get("position_ids", None)
950
+
951
+ if attention_mask is not None and position_ids is None:
952
+ # create position_ids on the fly for batch generation
953
+ position_ids = attention_mask.long().cumsum(-1) - 1
954
+ position_ids.masked_fill_(attention_mask == 0, 1)
955
+ if past_key_values:
956
+ position_ids = position_ids[:, -1].unsqueeze(-1)
957
+ else:
958
+ position_ids = None
959
+
960
+ # if `inputs_embeds` are passed, we only want to use them in the 1st generation step
961
+ if inputs_embeds is not None and past_key_values is None:
962
+ model_inputs = {"inputs_embeds": inputs_embeds}
963
+ else:
964
+ model_inputs = {"input_ids": input_ids}
965
+
966
+ model_inputs.update(
967
+ {
968
+ "past_key_values": past_key_values,
969
+ "use_cache": kwargs.get("use_cache"),
970
+ "position_ids": position_ids,
971
+ "attention_mask": attention_mask,
972
+ "token_type_ids": token_type_ids,
973
+ }
974
+ )
975
+ return model_inputs
976
+
977
+ @add_start_docstrings_to_model_forward(GPT2_INPUTS_DOCSTRING)
978
+ @add_code_sample_docstrings(
979
+ checkpoint=_CHECKPOINT_FOR_DOC,
980
+ output_type=CausalLMOutputWithCrossAttentions,
981
+ config_class=_CONFIG_FOR_DOC,
982
+ )
983
+ def forward(
984
+ self,
985
+ input_ids: Optional[torch.LongTensor] = None,
986
+ past_key_values: Optional[Tuple[Tuple[torch.Tensor]]] = None,
987
+ attention_mask: Optional[torch.FloatTensor] = None,
988
+ token_type_ids: Optional[torch.LongTensor] = None,
989
+ position_ids: Optional[torch.LongTensor] = None,
990
+ head_mask: Optional[torch.FloatTensor] = None,
991
+ inputs_embeds: Optional[torch.FloatTensor] = None,
992
+ encoder_hidden_states: Optional[torch.Tensor] = None,
993
+ encoder_attention_mask: Optional[torch.FloatTensor] = None,
994
+ labels: Optional[torch.LongTensor] = None,
995
+ use_cache: Optional[bool] = None,
996
+ output_attentions: Optional[bool] = None,
997
+ output_hidden_states: Optional[bool] = None,
998
+ return_dict: Optional[bool] = None,
999
+ ) -> Union[Tuple, CausalLMOutputWithCrossAttentions]:
1000
+ r"""
1001
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
1002
+ Labels for language modeling. Note that the labels **are shifted** inside the model, i.e. you can set
1003
+ `labels = input_ids` Indices are selected in `[-100, 0, ..., config.vocab_size]` All labels set to `-100`
1004
+ are ignored (masked), the loss is only computed for labels in `[0, ..., config.vocab_size]`
1005
+ """
1006
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
1007
+
1008
+ transformer_outputs = self.transformer(
1009
+ input_ids,
1010
+ past_key_values=past_key_values,
1011
+ attention_mask=attention_mask,
1012
+ token_type_ids=token_type_ids,
1013
+ position_ids=position_ids,
1014
+ head_mask=head_mask,
1015
+ inputs_embeds=inputs_embeds,
1016
+ encoder_hidden_states=encoder_hidden_states,
1017
+ encoder_attention_mask=encoder_attention_mask,
1018
+ use_cache=use_cache,
1019
+ output_attentions=output_attentions,
1020
+ output_hidden_states=output_hidden_states,
1021
+ return_dict=return_dict,
1022
+ )
1023
+ hidden_states = transformer_outputs[0]
1024
+
1025
+ # Set device for model parallelism
1026
+ if self.model_parallel:
1027
+ torch.cuda.set_device(self.transformer.first_device)
1028
+ hidden_states = hidden_states.to(self.lm_head.weight.device)
1029
+
1030
+ lm_logits = self.lm_head(hidden_states)
1031
+
1032
+ loss = None
1033
+ if labels is not None:
1034
+ # move labels to correct device to enable model parallelism
1035
+ labels = labels.to(lm_logits.device)
1036
+ # Shift so that tokens < n predict n
1037
+ shift_logits = lm_logits[..., :-1, :].contiguous()
1038
+ shift_labels = labels[..., 1:].contiguous()
1039
+ # Flatten the tokens
1040
+ loss_fct = CrossEntropyLoss()
1041
+ loss = loss_fct(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))
1042
+
1043
+ if not return_dict:
1044
+ output = (lm_logits,) + transformer_outputs[1:]
1045
+ return ((loss,) + output) if loss is not None else output
1046
+
1047
+ return CausalLMOutputWithCrossAttentions(
1048
+ loss=loss,
1049
+ logits=lm_logits,
1050
+ past_key_values=transformer_outputs.past_key_values,
1051
+ hidden_states=transformer_outputs.hidden_states,
1052
+ attentions=transformer_outputs.attentions,
1053
+ cross_attentions=transformer_outputs.cross_attentions,
1054
+ )
1055
+
1056
+ @staticmethod
1057
+ def _reorder_cache(
1058
+ past_key_values: Tuple[Tuple[torch.Tensor]], beam_idx: torch.Tensor
1059
+ ) -> Tuple[Tuple[torch.Tensor]]:
1060
+ """
1061
+ This function is used to re-order the `past_key_values` cache if [`~PreTrainedModel.beam_search`] or
1062
+ [`~PreTrainedModel.beam_sample`] is called. This is required to match `past_key_values` with the correct
1063
+ beam_idx at every generation step.
1064
+ """
1065
+ return tuple(
1066
+ tuple(past_state.index_select(0, beam_idx.to(past_state.device)) for past_state in layer_past)
1067
+ for layer_past in past_key_values
1068
+ )
1069
+
1070
+
1071
+ @add_start_docstrings(
1072
+ """
1073
+ The GPT2 Model transformer with a language modeling and a multiple-choice classification head on top e.g. for
1074
+ RocStories/SWAG tasks. The two heads are two linear layers. The language modeling head has its weights tied to the
1075
+ input embeddings, the classification head takes as input the input of a specified classification token index in the
1076
+ input sequence).
1077
+ """,
1078
+ GPT2_START_DOCSTRING,
1079
+ )
1080
+ class GPT2DoubleHeadsModel(GPT2PreTrainedModel):
1081
+ _tied_weights_keys = ["lm_head.weight"]
1082
+
1083
+ def __init__(self, config):
1084
+ super().__init__(config)
1085
+ config.num_labels = 1
1086
+ self.transformer = GPT2Model(config)
1087
+ self.lm_head = nn.Linear(config.n_embd, config.vocab_size, bias=False)
1088
+ self.multiple_choice_head = SequenceSummary(config)
1089
+
1090
+ # Model parallel
1091
+ self.model_parallel = False
1092
+ self.device_map = None
1093
+
1094
+ # Initialize weights and apply final processing
1095
+ self.post_init()
1096
+
1097
+ @add_start_docstrings(PARALLELIZE_DOCSTRING)
1098
+ def parallelize(self, device_map=None):
1099
+ warnings.warn(
1100
+ "`GPT2DoubleHeadsModel.parallelize` is deprecated and will be removed in v5 of Transformers, you should"
1101
+ " load your model with `device_map='balanced'` in the call to `from_pretrained`. You can also provide your"
1102
+ " own `device_map` but it needs to be a dictionary module_name to device, so for instance"
1103
+ " {'transformer.h.0': 0, 'transformer.h.1': 1, ...}",
1104
+ FutureWarning,
1105
+ )
1106
+ self.device_map = (
1107
+ get_device_map(len(self.transformer.h), range(torch.cuda.device_count()))
1108
+ if device_map is None
1109
+ else device_map
1110
+ )
1111
+ assert_device_map(self.device_map, len(self.transformer.h))
1112
+ self.transformer.parallelize(self.device_map)
1113
+ self.lm_head = self.lm_head.to(self.transformer.first_device)
1114
+ self.multiple_choice_head = self.multiple_choice_head.to(self.transformer.first_device)
1115
+ self.model_parallel = True
1116
+
1117
+ @add_start_docstrings(DEPARALLELIZE_DOCSTRING)
1118
+ def deparallelize(self):
1119
+ warnings.warn(
1120
+ "Like `parallelize`, `deparallelize` is deprecated and will be removed in v5 of Transformers.",
1121
+ FutureWarning,
1122
+ )
1123
+ self.transformer.deparallelize()
1124
+ self.transformer = self.transformer.to("cpu")
1125
+ self.lm_head = self.lm_head.to("cpu")
1126
+ self.multiple_choice_head = self.multiple_choice_head.to("cpu")
1127
+ self.model_parallel = False
1128
+ torch.cuda.empty_cache()
1129
+
1130
+ def get_output_embeddings(self):
1131
+ return self.lm_head
1132
+
1133
+ def set_output_embeddings(self, new_embeddings):
1134
+ self.lm_head = new_embeddings
1135
+
1136
+ def prepare_inputs_for_generation(self, input_ids, past_key_values=None, **kwargs):
1137
+ token_type_ids = kwargs.get("token_type_ids", None)
1138
+ # only last token for inputs_ids if past is defined in kwargs
1139
+ if past_key_values:
1140
+ input_ids = input_ids[:, -1].unsqueeze(-1)
1141
+ if token_type_ids is not None:
1142
+ token_type_ids = token_type_ids[:, -1].unsqueeze(-1)
1143
+
1144
+ attention_mask = kwargs.get("attention_mask", None)
1145
+ position_ids = kwargs.get("position_ids", None)
1146
+
1147
+ if attention_mask is not None and position_ids is None:
1148
+ # create position_ids on the fly for batch generation
1149
+ position_ids = attention_mask.long().cumsum(-1) - 1
1150
+ position_ids.masked_fill_(attention_mask == 0, 1)
1151
+ if past_key_values:
1152
+ position_ids = position_ids[:, -1].unsqueeze(-1)
1153
+ else:
1154
+ position_ids = None
1155
+
1156
+ return {
1157
+ "input_ids": input_ids,
1158
+ "past_key_values": past_key_values,
1159
+ "use_cache": kwargs.get("use_cache"),
1160
+ "position_ids": position_ids,
1161
+ "attention_mask": attention_mask,
1162
+ "token_type_ids": token_type_ids,
1163
+ }
1164
+
1165
+ @add_start_docstrings_to_model_forward(GPT2_INPUTS_DOCSTRING)
1166
+ @replace_return_docstrings(output_type=GPT2DoubleHeadsModelOutput, config_class=_CONFIG_FOR_DOC)
1167
+ def forward(
1168
+ self,
1169
+ input_ids: Optional[torch.LongTensor] = None,
1170
+ past_key_values: Optional[Tuple[Tuple[torch.Tensor]]] = None,
1171
+ attention_mask: Optional[torch.FloatTensor] = None,
1172
+ token_type_ids: Optional[torch.LongTensor] = None,
1173
+ position_ids: Optional[torch.LongTensor] = None,
1174
+ head_mask: Optional[torch.FloatTensor] = None,
1175
+ inputs_embeds: Optional[torch.FloatTensor] = None,
1176
+ mc_token_ids: Optional[torch.LongTensor] = None,
1177
+ labels: Optional[torch.LongTensor] = None,
1178
+ mc_labels: Optional[torch.LongTensor] = None,
1179
+ use_cache: Optional[bool] = None,
1180
+ output_attentions: Optional[bool] = None,
1181
+ output_hidden_states: Optional[bool] = None,
1182
+ return_dict: Optional[bool] = None,
1183
+ **kwargs,
1184
+ ) -> Union[Tuple, GPT2DoubleHeadsModelOutput]:
1185
+ r"""
1186
+ mc_token_ids (`torch.LongTensor` of shape `(batch_size, num_choices)`, *optional*, default to index of the last token of the input):
1187
+ Index of the classification token in each input sequence. Selected in the range `[0, input_ids.size(-1) -
1188
+ 1]`.
1189
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
1190
+ Labels for language modeling. Note that the labels **are shifted** inside the model, i.e. you can set
1191
+ `labels = input_ids`. Indices are selected in `[-100, 0, ..., config.vocab_size - 1]`. All labels set to
1192
+ `-100` are ignored (masked), the loss is only computed for labels in `[0, ..., config.vocab_size - 1]`
1193
+ mc_labels (`torch.LongTensor` of shape `(batch_size)`, *optional*):
1194
+ Labels for computing the multiple choice classification loss. Indices should be in `[0, ..., num_choices]`
1195
+ where *num_choices* is the size of the second dimension of the input tensors. (see *input_ids* above)
1196
+
1197
+ Return:
1198
+
1199
+ Example:
1200
+
1201
+ ```python
1202
+ >>> import torch
1203
+ >>> from transformers import AutoTokenizer, GPT2DoubleHeadsModel
1204
+
1205
+ >>> tokenizer = AutoTokenizer.from_pretrained("gpt2")
1206
+ >>> model = GPT2DoubleHeadsModel.from_pretrained("gpt2")
1207
+
1208
+ >>> # Add a [CLS] to the vocabulary (we should train it also!)
1209
+ >>> num_added_tokens = tokenizer.add_special_tokens({"cls_token": "[CLS]"})
1210
+ >>> # Update the model embeddings with the new vocabulary size
1211
+ >>> embedding_layer = model.resize_token_embeddings(len(tokenizer))
1212
+
1213
+ >>> choices = ["Hello, my dog is cute [CLS]", "Hello, my cat is cute [CLS]"]
1214
+ >>> encoded_choices = [tokenizer.encode(s) for s in choices]
1215
+ >>> cls_token_location = [tokens.index(tokenizer.cls_token_id) for tokens in encoded_choices]
1216
+
1217
+ >>> input_ids = torch.tensor(encoded_choices).unsqueeze(0) # Batch size: 1, number of choices: 2
1218
+ >>> mc_token_ids = torch.tensor([cls_token_location]) # Batch size: 1
1219
+
1220
+ >>> outputs = model(input_ids, mc_token_ids=mc_token_ids)
1221
+ >>> lm_logits = outputs.logits
1222
+ >>> mc_logits = outputs.mc_logits
1223
+ ```"""
1224
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
1225
+
1226
+ transformer_outputs = self.transformer(
1227
+ input_ids,
1228
+ past_key_values=past_key_values,
1229
+ attention_mask=attention_mask,
1230
+ token_type_ids=token_type_ids,
1231
+ position_ids=position_ids,
1232
+ head_mask=head_mask,
1233
+ inputs_embeds=inputs_embeds,
1234
+ use_cache=use_cache,
1235
+ output_attentions=output_attentions,
1236
+ output_hidden_states=output_hidden_states,
1237
+ return_dict=return_dict,
1238
+ )
1239
+
1240
+ hidden_states = transformer_outputs[0]
1241
+
1242
+ # Set device for model parallelism
1243
+ if self.model_parallel:
1244
+ torch.cuda.set_device(self.transformer.first_device)
1245
+ hidden_states = hidden_states.to(self.lm_head.weight.device)
1246
+
1247
+ lm_logits = self.lm_head(hidden_states)
1248
+ mc_logits = self.multiple_choice_head(hidden_states, mc_token_ids).squeeze(-1)
1249
+
1250
+ mc_loss = None
1251
+ if mc_labels is not None:
1252
+ loss_fct = CrossEntropyLoss()
1253
+ mc_loss = loss_fct(mc_logits.view(-1, mc_logits.size(-1)), mc_labels.view(-1))
1254
+ lm_loss = None
1255
+ if labels is not None:
1256
+ labels = labels.to(lm_logits.device)
1257
+ shift_logits = lm_logits[..., :-1, :].contiguous()
1258
+ shift_labels = labels[..., 1:].contiguous()
1259
+ loss_fct = CrossEntropyLoss()
1260
+ lm_loss = loss_fct(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))
1261
+
1262
+ if not return_dict:
1263
+ output = (lm_logits, mc_logits) + transformer_outputs[1:]
1264
+ if mc_loss is not None:
1265
+ output = (mc_loss,) + output
1266
+ return ((lm_loss,) + output) if lm_loss is not None else output
1267
+
1268
+ return GPT2DoubleHeadsModelOutput(
1269
+ loss=lm_loss,
1270
+ mc_loss=mc_loss,
1271
+ logits=lm_logits,
1272
+ mc_logits=mc_logits,
1273
+ past_key_values=transformer_outputs.past_key_values,
1274
+ hidden_states=transformer_outputs.hidden_states,
1275
+ attentions=transformer_outputs.attentions,
1276
+ )
1277
+
1278
+ @staticmethod
1279
+ def _reorder_cache(
1280
+ past_key_values: Tuple[Tuple[torch.Tensor]], beam_idx: torch.Tensor
1281
+ ) -> Tuple[Tuple[torch.Tensor]]:
1282
+ """
1283
+ This function is used to re-order the `past_key_values` cache if [`~PreTrainedModel.beam_search`] or
1284
+ [`~PreTrainedModel.beam_sample`] is called. This is required to match `past_key_values` with the correct
1285
+ beam_idx at every generation step.
1286
+ """
1287
+ return tuple(
1288
+ tuple(past_state.index_select(0, beam_idx.to(past_state.device)) for past_state in layer_past)
1289
+ for layer_past in past_key_values
1290
+ )
1291
+
1292
+
1293
+ @add_start_docstrings(
1294
+ """
1295
+ The GPT2 Model transformer with a sequence classification head on top (linear layer).
1296
+
1297
+ [`GPT2ForSequenceClassification`] uses the last token in order to do the classification, as other causal models
1298
+ (e.g. GPT-1) do.
1299
+
1300
+ Since it does classification on the last token, it requires to know the position of the last token. If a
1301
+ `pad_token_id` is defined in the configuration, it finds the last token that is not a padding token in each row. If
1302
+ no `pad_token_id` is defined, it simply takes the last value in each row of the batch. Since it cannot guess the
1303
+ padding tokens when `inputs_embeds` are passed instead of `input_ids`, it does the same (take the last value in
1304
+ each row of the batch).
1305
+ """,
1306
+ GPT2_START_DOCSTRING,
1307
+ )
1308
+ class GPT2ForSequenceClassification(GPT2PreTrainedModel):
1309
+ def __init__(self, config):
1310
+ super().__init__(config)
1311
+ self.num_labels = config.num_labels
1312
+ self.transformer = GPT2Model(config)
1313
+ self.score = nn.Linear(config.n_embd, self.num_labels, bias=False)
1314
+
1315
+ # Model parallel
1316
+ self.model_parallel = False
1317
+ self.device_map = None
1318
+
1319
+ # Initialize weights and apply final processing
1320
+ self.post_init()
1321
+
1322
+ @add_start_docstrings_to_model_forward(GPT2_INPUTS_DOCSTRING)
1323
+ @add_code_sample_docstrings(
1324
+ checkpoint="microsoft/DialogRPT-updown",
1325
+ output_type=SequenceClassifierOutputWithPast,
1326
+ config_class=_CONFIG_FOR_DOC,
1327
+ )
1328
+ def forward(
1329
+ self,
1330
+ input_ids: Optional[torch.LongTensor] = None,
1331
+ past_key_values: Optional[Tuple[Tuple[torch.Tensor]]] = None,
1332
+ attention_mask: Optional[torch.FloatTensor] = None,
1333
+ token_type_ids: Optional[torch.LongTensor] = None,
1334
+ position_ids: Optional[torch.LongTensor] = None,
1335
+ head_mask: Optional[torch.FloatTensor] = None,
1336
+ inputs_embeds: Optional[torch.FloatTensor] = None,
1337
+ labels: Optional[torch.LongTensor] = None,
1338
+ use_cache: Optional[bool] = None,
1339
+ output_attentions: Optional[bool] = None,
1340
+ output_hidden_states: Optional[bool] = None,
1341
+ return_dict: Optional[bool] = None,
1342
+ ) -> Union[Tuple, SequenceClassifierOutputWithPast]:
1343
+ r"""
1344
+ labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
1345
+ Labels for computing the sequence classification/regression loss. Indices should be in `[0, ...,
1346
+ config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If
1347
+ `config.num_labels > 1` a classification loss is computed (Cross-Entropy).
1348
+ """
1349
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
1350
+
1351
+ transformer_outputs = self.transformer(
1352
+ input_ids,
1353
+ past_key_values=past_key_values,
1354
+ attention_mask=attention_mask,
1355
+ token_type_ids=token_type_ids,
1356
+ position_ids=position_ids,
1357
+ head_mask=head_mask,
1358
+ inputs_embeds=inputs_embeds,
1359
+ use_cache=use_cache,
1360
+ output_attentions=output_attentions,
1361
+ output_hidden_states=output_hidden_states,
1362
+ return_dict=return_dict,
1363
+ )
1364
+ hidden_states = transformer_outputs[0]
1365
+ logits = self.score(hidden_states)
1366
+
1367
+ if input_ids is not None:
1368
+ batch_size, sequence_length = input_ids.shape[:2]
1369
+ else:
1370
+ batch_size, sequence_length = inputs_embeds.shape[:2]
1371
+
1372
+ assert (
1373
+ self.config.pad_token_id is not None or batch_size == 1
1374
+ ), "Cannot handle batch sizes > 1 if no padding token is defined."
1375
+ if self.config.pad_token_id is None:
1376
+ sequence_lengths = -1
1377
+ else:
1378
+ if input_ids is not None:
1379
+ sequence_lengths = (torch.eq(input_ids, self.config.pad_token_id).long().argmax(-1) - 1).to(
1380
+ logits.device
1381
+ )
1382
+ else:
1383
+ sequence_lengths = -1
1384
+ logger.warning(
1385
+ f"{self.__class__.__name__} will not detect padding tokens in `inputs_embeds`. Results may be "
1386
+ "unexpected if using padding tokens in conjunction with `inputs_embeds.`"
1387
+ )
1388
+
1389
+ pooled_logits = logits[torch.arange(batch_size, device=logits.device), sequence_lengths]
1390
+
1391
+ loss = None
1392
+ if labels is not None:
1393
+ if self.config.problem_type is None:
1394
+ if self.num_labels == 1:
1395
+ self.config.problem_type = "regression"
1396
+ elif self.num_labels > 1 and (labels.dtype == torch.long or labels.dtype == torch.int):
1397
+ self.config.problem_type = "single_label_classification"
1398
+ else:
1399
+ self.config.problem_type = "multi_label_classification"
1400
+
1401
+ if self.config.problem_type == "regression":
1402
+ loss_fct = MSELoss()
1403
+ if self.num_labels == 1:
1404
+ loss = loss_fct(pooled_logits.squeeze(), labels.squeeze())
1405
+ else:
1406
+ loss = loss_fct(pooled_logits, labels)
1407
+ elif self.config.problem_type == "single_label_classification":
1408
+ loss_fct = CrossEntropyLoss()
1409
+ loss = loss_fct(pooled_logits.view(-1, self.num_labels), labels.view(-1))
1410
+ elif self.config.problem_type == "multi_label_classification":
1411
+ loss_fct = BCEWithLogitsLoss()
1412
+ loss = loss_fct(pooled_logits, labels)
1413
+ if not return_dict:
1414
+ output = (pooled_logits,) + transformer_outputs[1:]
1415
+ return ((loss,) + output) if loss is not None else output
1416
+
1417
+ return SequenceClassifierOutputWithPast(
1418
+ loss=loss,
1419
+ logits=pooled_logits,
1420
+ past_key_values=transformer_outputs.past_key_values,
1421
+ hidden_states=transformer_outputs.hidden_states,
1422
+ attentions=transformer_outputs.attentions,
1423
+ )
1424
+
1425
+
1426
+ @add_start_docstrings(
1427
+ """
1428
+ GPT2 Model with a token classification head on top (a linear layer on top of the hidden-states output) e.g. for
1429
+ Named-Entity-Recognition (NER) tasks.
1430
+ """,
1431
+ GPT2_START_DOCSTRING,
1432
+ )
1433
+ class GPT2ForTokenClassification(GPT2PreTrainedModel):
1434
+ def __init__(self, config):
1435
+ super().__init__(config)
1436
+ self.num_labels = config.num_labels
1437
+
1438
+ self.transformer = GPT2Model(config)
1439
+ if hasattr(config, "classifier_dropout") and config.classifier_dropout is not None:
1440
+ classifier_dropout = config.classifier_dropout
1441
+ elif hasattr(config, "hidden_dropout") and config.hidden_dropout is not None:
1442
+ classifier_dropout = config.hidden_dropout
1443
+ else:
1444
+ classifier_dropout = 0.1
1445
+ self.dropout = nn.Dropout(classifier_dropout)
1446
+ self.classifier = nn.Linear(config.hidden_size, config.num_labels)
1447
+
1448
+ # Model parallel
1449
+ self.model_parallel = False
1450
+ self.device_map = None
1451
+
1452
+ # Initialize weights and apply final processing
1453
+ self.post_init()
1454
+
1455
+ @add_start_docstrings_to_model_forward(GPT2_INPUTS_DOCSTRING)
1456
+ # fmt: off
1457
+ @add_code_sample_docstrings(
1458
+ checkpoint="brad1141/gpt2-finetuned-comp2",
1459
+ output_type=TokenClassifierOutput,
1460
+ config_class=_CONFIG_FOR_DOC,
1461
+ expected_loss=0.25,
1462
+ expected_output=["Lead", "Lead", "Lead", "Position", "Lead", "Lead", "Lead", "Lead", "Lead", "Lead", "Lead", "Lead"],
1463
+ )
1464
+ # fmt: on
1465
+ def forward(
1466
+ self,
1467
+ input_ids: Optional[torch.LongTensor] = None,
1468
+ past_key_values: Optional[Tuple[Tuple[torch.Tensor]]] = None,
1469
+ attention_mask: Optional[torch.FloatTensor] = None,
1470
+ token_type_ids: Optional[torch.LongTensor] = None,
1471
+ position_ids: Optional[torch.LongTensor] = None,
1472
+ head_mask: Optional[torch.FloatTensor] = None,
1473
+ inputs_embeds: Optional[torch.FloatTensor] = None,
1474
+ labels: Optional[torch.LongTensor] = None,
1475
+ use_cache: Optional[bool] = None,
1476
+ output_attentions: Optional[bool] = None,
1477
+ output_hidden_states: Optional[bool] = None,
1478
+ return_dict: Optional[bool] = None,
1479
+ ) -> Union[Tuple, TokenClassifierOutput]:
1480
+ r"""
1481
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
1482
+ Labels for computing the sequence classification/regression loss. Indices should be in `[0, ...,
1483
+ config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If
1484
+ `config.num_labels > 1` a classification loss is computed (Cross-Entropy).
1485
+ """
1486
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
1487
+
1488
+ transformer_outputs = self.transformer(
1489
+ input_ids,
1490
+ past_key_values=past_key_values,
1491
+ attention_mask=attention_mask,
1492
+ token_type_ids=token_type_ids,
1493
+ position_ids=position_ids,
1494
+ head_mask=head_mask,
1495
+ inputs_embeds=inputs_embeds,
1496
+ use_cache=use_cache,
1497
+ output_attentions=output_attentions,
1498
+ output_hidden_states=output_hidden_states,
1499
+ return_dict=return_dict,
1500
+ )
1501
+
1502
+ hidden_states = transformer_outputs[0]
1503
+ hidden_states = self.dropout(hidden_states)
1504
+ logits = self.classifier(hidden_states)
1505
+
1506
+ loss = None
1507
+ if labels is not None:
1508
+ labels = labels.to(logits.device)
1509
+ loss_fct = CrossEntropyLoss()
1510
+ loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
1511
+
1512
+ if not return_dict:
1513
+ output = (logits,) + transformer_outputs[2:]
1514
+ return ((loss,) + output) if loss is not None else output
1515
+
1516
+ return TokenClassifierOutput(
1517
+ loss=loss,
1518
+ logits=logits,
1519
+ hidden_states=transformer_outputs.hidden_states,
1520
+ attentions=transformer_outputs.attentions,
1521
+ )
1522
+
1523
+
1524
+ @add_start_docstrings(
1525
+ """
1526
+ The GPT-2 Model transformer with a span classification head on top for extractive question-answering tasks like
1527
+ SQuAD (a linear layer on top of the hidden-states output to compute `span start logits` and `span end logits`).
1528
+ """,
1529
+ GPT2_START_DOCSTRING,
1530
+ )
1531
+ class GPT2ForQuestionAnswering(GPT2PreTrainedModel):
1532
+ def __init__(self, config):
1533
+ super().__init__(config)
1534
+ self.num_labels = config.num_labels
1535
+ self.transformer = GPT2Model(config)
1536
+ self.qa_outputs = nn.Linear(config.hidden_size, 2)
1537
+
1538
+ # Model parallel
1539
+ self.model_parallel = False
1540
+ self.device_map = None
1541
+ self.gradient_checkpointing = False
1542
+
1543
+ # Initialize weights and apply final processing
1544
+ self.post_init()
1545
+
1546
+ @add_start_docstrings_to_model_forward(GPT2_INPUTS_DOCSTRING.format("batch_size, sequence_length"))
1547
+ @add_code_sample_docstrings(
1548
+ checkpoint=_CHECKPOINT_FOR_DOC,
1549
+ output_type=QuestionAnsweringModelOutput,
1550
+ config_class=_CONFIG_FOR_DOC,
1551
+ real_checkpoint=_CHECKPOINT_FOR_DOC,
1552
+ )
1553
+ def forward(
1554
+ self,
1555
+ input_ids: Optional[torch.LongTensor] = None,
1556
+ attention_mask: Optional[torch.FloatTensor] = None,
1557
+ token_type_ids: Optional[torch.LongTensor] = None,
1558
+ position_ids: Optional[torch.LongTensor] = None,
1559
+ head_mask: Optional[torch.FloatTensor] = None,
1560
+ inputs_embeds: Optional[torch.FloatTensor] = None,
1561
+ start_positions: Optional[torch.LongTensor] = None,
1562
+ end_positions: Optional[torch.LongTensor] = None,
1563
+ output_attentions: Optional[bool] = None,
1564
+ output_hidden_states: Optional[bool] = None,
1565
+ return_dict: Optional[bool] = None,
1566
+ ) -> Union[Tuple, QuestionAnsweringModelOutput]:
1567
+ r"""
1568
+ start_positions (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
1569
+ Labels for position (index) of the start of the labelled span for computing the token classification loss.
1570
+ Positions are clamped to the length of the sequence (`sequence_length`). Position outside of the sequence
1571
+ are not taken into account for computing the loss.
1572
+ end_positions (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
1573
+ Labels for position (index) of the end of the labelled span for computing the token classification loss.
1574
+ Positions are clamped to the length of the sequence (`sequence_length`). Position outside of the sequence
1575
+ are not taken into account for computing the loss.
1576
+ """
1577
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
1578
+
1579
+ outputs = self.transformer(
1580
+ input_ids,
1581
+ attention_mask=attention_mask,
1582
+ token_type_ids=token_type_ids,
1583
+ position_ids=position_ids,
1584
+ head_mask=head_mask,
1585
+ inputs_embeds=inputs_embeds,
1586
+ output_attentions=output_attentions,
1587
+ output_hidden_states=output_hidden_states,
1588
+ return_dict=return_dict,
1589
+ )
1590
+
1591
+ sequence_output = outputs[0]
1592
+
1593
+ logits = self.qa_outputs(sequence_output)
1594
+ start_logits, end_logits = logits.split(1, dim=-1)
1595
+ start_logits = start_logits.squeeze(-1).contiguous()
1596
+ end_logits = end_logits.squeeze(-1).contiguous()
1597
+
1598
+ total_loss = None
1599
+ if start_positions is not None and end_positions is not None:
1600
+ # If we are on multi-GPU, split add a dimension
1601
+ if len(start_positions.size()) > 1:
1602
+ start_positions = start_positions.squeeze(-1).to(start_logits.device)
1603
+ if len(end_positions.size()) > 1:
1604
+ end_positions = end_positions.squeeze(-1).to(end_logits.device)
1605
+ # sometimes the start/end positions are outside our model inputs, we ignore these terms
1606
+ ignored_index = start_logits.size(1)
1607
+ start_positions = start_positions.clamp(0, ignored_index)
1608
+ end_positions = end_positions.clamp(0, ignored_index)
1609
+
1610
+ loss_fct = CrossEntropyLoss(ignore_index=ignored_index)
1611
+ start_loss = loss_fct(start_logits, start_positions)
1612
+ end_loss = loss_fct(end_logits, end_positions)
1613
+ total_loss = (start_loss + end_loss) / 2
1614
+
1615
+ if not return_dict:
1616
+ output = (start_logits, end_logits) + outputs[2:]
1617
+ return ((total_loss,) + output) if total_loss is not None else output
1618
+
1619
+ return QuestionAnsweringModelOutput(
1620
+ loss=total_loss,
1621
+ start_logits=start_logits,
1622
+ end_logits=end_logits,
1623
+ hidden_states=outputs.hidden_states,
1624
+ attentions=outputs.attentions,
1625
+ )
gpst/math_util.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import torch
3
+ import torch.nn.functional as F
4
+
5
+
6
+ def softmax(logits):
7
+ max = np.max(logits)
8
+ logits = logits - max
9
+ exp_x = np.exp(logits)
10
+ softmax_x = exp_x / np.sum(exp_x)
11
+ return softmax_x
12
+
13
+
14
+ def max_neg_value(dtype):
15
+ return -torch.finfo(dtype).max
16
+
17
+
18
+ def gumbel_softmax(logits, temperature=1, hard=True, train=False):
19
+ """
20
+ ST-gumple-softmax
21
+ input: [*, seq_len, seq_len]
22
+ return: flatten --> [*, seq_len, seq_len] an one-hot vector
23
+ """
24
+ if train:
25
+ return F.gumbel_softmax(logits, tau=temperature, hard=hard, dim=-1)
26
+ else:
27
+ y = F.softmax(logits, dim=-1)
28
+ if not hard:
29
+ return y
30
+
31
+ shape = y.size()
32
+ _, ind = y.max(dim=-1)
33
+ y_hard = torch.zeros_like(y).view(-1, shape[-1])
34
+ y_hard.scatter_(1, ind.view(-1, 1), 1)
35
+ y_hard = y_hard.view(*shape)
36
+ y_hard = (y_hard - y).detach() + y
37
+ return y_hard
gpst/r2d2_base.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from torch import nn
2
+ import torch
3
+
4
+
5
+ class R2D2Base(nn.Module):
6
+ def __init__(self, config, **kwargs):
7
+ super().__init__()
8
+ self.vocab_size = config.vocab_size
9
+ self.input_dim = config.hidden_size
10
+ self.hidden_dim = config.intermediate_size
11
+ self.window_size = config.window_size
12
+
13
+ self.tie_decoder = getattr(config, 'tie_decoder', True)
14
+ self.cls_token_id = config.cls_token_id
15
+ self.mask_token_id = config.mask_token_id
16
+ self.pad_token_id = config.pad_token_id
17
+ self.bos_token_id = config.bos_token_id
18
+ self.eos_token_id = config.eos_token_id
19
+ self.nsp_token_id = config.nsp_token_id
20
+ self.sum_token_id = config.sum_token_id
21
+
22
+ @property
23
+ def device(self):
24
+ return next(self.parameters()).device
25
+
26
+ @property
27
+ def eos_vec(self):
28
+ return self.embedding(torch.tensor([self.eos_token_id]).to(self.device)).squeeze(0)
29
+
30
+ @property
31
+ def bos_vec(self):
32
+ return self.embedding(torch.tensor([self.bos_token_id]).to(self.device)).squeeze(0)
33
+
34
+ def from_pretrain(self, model_path, strict=True):
35
+ state_dict = torch.load(model_path, map_location=lambda a, b: a)
36
+ transfered_state_dict = {}
37
+ for k, v in state_dict.items():
38
+ new_k = k.replace('module.', '')
39
+ transfered_state_dict[new_k] = v
40
+ self.load_state_dict(transfered_state_dict, strict=strict)
41
+ self._tie_weights()
gpst/r2d2_common.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections import namedtuple
2
+
3
+
4
+ class CacheSlots:
5
+ E_IJ = 0
6
+ LOG_P_IJ_SUM = 1
7
+ NT_SCORE = 2
8
+
9
+
10
+ LMLossParam = namedtuple(
11
+ 'LMLossParam',
12
+ [
13
+ 'model',
14
+ 'chart_tables',
15
+ 'tensor_cache',
16
+ 'input_ids',
17
+ 'flatten_input_ids',
18
+ 's_indices',
19
+ 'atom_spans',
20
+ 'seq_lens'
21
+ ]
22
+ )
23
+
24
+ NodeCombination = namedtuple(
25
+ 'NodeCombination',
26
+ [
27
+ 'node_ik',
28
+ 'node_kj',
29
+ 'left',
30
+ 'right'
31
+ ]
32
+ )
33
+
34
+ BOS_CACHE_ID = 0
35
+ EOS_CACHE_ID = 1
36
+ INF_LOG_P_ID = 2
37
+ SPECIAL_TOKEN_NUM = 3 # BOS, EOS
38
+
39
+ ROLE_LEFT = 1
40
+ ROLE_RIGHT = 2
41
+ ROLE_PARENT = 3
gpst/r2d2_insideoutside.py ADDED
@@ -0,0 +1,462 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright (c) 2024 Ant Group
3
+ # Author: Xiang Hu
4
+ from typing import List
5
+ import torch.nn as nn
6
+ from typing import Optional
7
+ from gpst.data_structure.py_backend import CPPChartTableManager
8
+ from gpst.fast_parser import TransformerParser
9
+ from gpst.tree_encoder import InsideEncoder, OutsideEncoder
10
+ import torch
11
+ from torch.utils.checkpoint import checkpoint
12
+ from gpst.data_structure.tensor_cache import TensorCache, CacheType
13
+ import torch.nn.functional as F
14
+ from datetime import datetime
15
+ from gpst.math_util import gumbel_softmax
16
+ from dataclasses import dataclass
17
+
18
+ SPECIAL_TOKEN_NUM = 3
19
+
20
+ class WeightedSumFunc(torch.autograd.Function):
21
+ a_ij_require_grad=True
22
+
23
+ @staticmethod
24
+ def forward(ctx, a_ij, e_ijk):
25
+ # a_ij (N, group_size) e_ijk (N, group_size, dim)
26
+ ctx.save_for_backward(a_ij, e_ijk)
27
+ output = torch.einsum('bi,bij->bj', a_ij, e_ijk)
28
+ return output
29
+
30
+ @staticmethod
31
+ def backward(ctx, grad_output):
32
+ # (N, dim)
33
+ a_ij, e_ijk = ctx.saved_tensors
34
+ if WeightedSumFunc.a_ij_require_grad:
35
+ d_a_ij = torch.einsum('bj,bij->bi', grad_output.float(), e_ijk)
36
+ else:
37
+ d_a_ij = None
38
+ d_e_ijk = torch.einsum('bi,bj->bij', a_ij, grad_output.float())
39
+ return d_a_ij, d_e_ijk
40
+
41
+ @dataclass
42
+ class InsideOutsideContext:
43
+ scores: Optional = None,
44
+ attention_mask: Optional = None,
45
+ split_masks: Optional = None,
46
+ split_points: Optional = None,
47
+ batch_size: Optional = None,
48
+ root_ids: Optional = None,
49
+ inside_cache: Optional = None,
50
+ outside_groups: Optional = None,
51
+ input_cache_ids: Optional = None
52
+
53
+ DEFAULT_HEIGHT_THRESHOLD=15
54
+
55
+ class R2D2Base(nn.Module):
56
+ def __init__(self, config, **kwargs):
57
+ super().__init__()
58
+ self.vocab_size = config.vocab_size
59
+ self.input_dim = config.hidden_size
60
+ self.hidden_dim = config.intermediate_size
61
+ self.window_size = config.window_size
62
+
63
+ self.tie_decoder = getattr(config, 'tie_decoder', True)
64
+ self.cls_token_id = config.cls_token_id
65
+ self.mask_token_id = config.mask_token_id
66
+ self.pad_token_id = config.pad_token_id
67
+ self.bos_token_id = config.bos_token_id
68
+ self.eos_token_id = config.eos_token_id
69
+ self.nsp_token_id = config.nsp_token_id
70
+ self.sum_token_id = config.sum_token_id
71
+
72
+ @property
73
+ def device(self):
74
+ return next(self.parameters()).device
75
+
76
+ @property
77
+ def eos_vec(self):
78
+ return self.embedding(torch.tensor([self.eos_token_id]).to(self.device)).squeeze(0)
79
+
80
+ @property
81
+ def bos_vec(self):
82
+ return self.embedding(torch.tensor([self.bos_token_id]).to(self.device)).squeeze(0)
83
+
84
+ def from_pretrain(self, model_path, strict=True):
85
+ state_dict = torch.load(model_path, map_location=lambda a, b: a)
86
+ transfered_state_dict = {}
87
+ for k, v in state_dict.items():
88
+ new_k = k.replace('module.', '')
89
+ transfered_state_dict[new_k] = v
90
+ self.load_state_dict(transfered_state_dict, strict=strict)
91
+ self._tie_weights()
92
+
93
+ class InsideOutsideModule(R2D2Base):
94
+ def __init__(self, config, **kwargs):
95
+ super().__init__(config)
96
+ self.parser_chunked = config.parser_chunked
97
+
98
+ self.parser = TransformerParser(config)
99
+
100
+ self.inside_enc = InsideEncoder(config)
101
+ self.outside_enc = OutsideEncoder(config)
102
+ self.outside_root_embedding = nn.Parameter(torch.rand(config.hidden_size))
103
+ self.norm = nn.InstanceNorm1d(config.hidden_size)
104
+
105
+ if config.ext_vocab_size > 0:
106
+ self.ext_embeds = nn.Embedding(config.ext_vocab_size + 1, self.input_dim, padding_idx=0)
107
+ # initialize with zero
108
+ self.ext_embeds.weight.data.fill_(0.0)
109
+
110
+ self.height_threshold = DEFAULT_HEIGHT_THRESHOLD
111
+ if hasattr(config, 'height_threshold'):
112
+ self.height_threshold = config.height_threshold
113
+ self.use_gumbel = False
114
+ if hasattr(config, 'use_gumbel'):
115
+ self.use_gumbel = config.use_gumbel
116
+ self.ldr_detach = False
117
+ if hasattr(config, 'ldr_detach'):
118
+ self.ldr_detach = config.ldr_detach
119
+
120
+ self.e_ij_id = -1
121
+ self.score_sum_id = -1
122
+ self.score_ijk = -1
123
+ self.height_ij = -1
124
+
125
+ self.reduce_id = config.reduce_token_id
126
+
127
+ def create_tensor_cache(self, seq_lens, total_cache_size=-1):
128
+ # e_ij, log_p_ij, log_p_sum_ij
129
+ tensor_cache = TensorCache(
130
+ self.window_size,
131
+ seq_lens,
132
+ cache_types=[
133
+ CacheType.NORMAL, CacheType.DETACH,
134
+ CacheType.NORMAL, CacheType.NORMAL
135
+ ],
136
+ dims=[self.input_dim, 1, 1, 1],
137
+ placeholder_num=SPECIAL_TOKEN_NUM,
138
+ device=self.device,
139
+ total_cache_size=total_cache_size)
140
+ self.e_ij_id = 0
141
+ self.score_sum_id = 1
142
+ self.score_ijk = 2
143
+ self.height_ij = 3
144
+ tensor_cache.fill(0, tensor_cache.capacity, [self.height_ij], [0])
145
+ return tensor_cache
146
+
147
+ def _flatten_inputs(self, input_ids, seq_lens, r2d2_embeddings):
148
+ # Initialize embeddings
149
+ block_size = input_ids.shape[-1]
150
+ indices_gather = []
151
+ for seq_i, seq_len in enumerate(seq_lens):
152
+ indices_gather.extend(
153
+ range(block_size * seq_i, block_size * seq_i + seq_len))
154
+
155
+ flatten_input_ids = input_ids.flatten()
156
+ indices_gather = torch.tensor(indices_gather, device=self.device)
157
+ flatten_input_ids = flatten_input_ids.gather(
158
+ dim=0, index=indices_gather)
159
+ flatten_r2d2_emb = r2d2_embeddings.view(-1, r2d2_embeddings.shape[-1]).gather(
160
+ dim=0, index=indices_gather.unsqueeze(1).repeat(1, r2d2_embeddings.shape[-1])
161
+ )
162
+
163
+ return flatten_input_ids, flatten_r2d2_emb
164
+
165
+ def prepare_composition(self, group_ids, log_p_ids, tensor_cache):
166
+ e_ij, h_ij = tensor_cache.gather(group_ids.flatten(), [self.e_ij_id, self.height_ij])
167
+ log_p_ij = tensor_cache.gather(log_p_ids.flatten(), [self.score_sum_id])[0]
168
+ e_ij = e_ij.view(*group_ids.shape, self.input_dim)
169
+ h_ij = h_ij.view(*group_ids.shape) # (batch_size, group_size, 2)
170
+ log_p_ij = log_p_ij.view(*group_ids.shape) # (batch_size, group_size, 2)
171
+
172
+ return e_ij, log_p_ij.sum(dim=-1), h_ij
173
+
174
+ def inside(self,
175
+ inside_cache,
176
+ span_embeds,
177
+ temperature,
178
+ inside_groups):
179
+ score_orders = []
180
+ # a_ij_orders = []
181
+
182
+ prepare_time = None
183
+ inside_time = None
184
+ weighted_time = None
185
+ arg_sort_time = None
186
+ for target_cache_ids, span_ids, cache_ids, detach_cache_ids in inside_groups:
187
+ # target_cache_ids: (?)
188
+ # cache_ids: (?, group_size, 2)
189
+ # detach_cache_ids: (?, group_size, 2)
190
+
191
+ # if candidate e_ij and log_p is not empty, apply composition function
192
+ e_ij, scores_ij_sum, h_ij = self.prepare_composition(
193
+ cache_ids, detach_cache_ids, inside_cache)
194
+ # # e_ij: (batch_size, group_size, 2, dim), c_ij: (batch_size, 2, dim)
195
+
196
+ if span_embeds is None:
197
+ scores_ijk, c_ijk = self.inside_enc(e_ij)
198
+ else:
199
+ scores_ijk, c_ijk = self.inside_enc(e_ij, span_embeds[span_ids, :])
200
+ # scores_ijk, c_ijk = checkpoint(self.inside_enc, e_ij, use_reentrant=False)
201
+
202
+ # expected output put c_ijk: (batch_size, group_size, dim)
203
+ # log_p_ijk: (batch_size, group_size)
204
+ # print(scores_ijk.shape)
205
+ # print(scores_ij_sum.shape)
206
+ scores_ijk_sum = scores_ijk # (batch_size, combination_size)
207
+
208
+ # assert not torch.any(torch.isinf(log_p_ij_step))
209
+ if not self.use_gumbel:
210
+ a_ij = F.softmax(scores_ijk_sum / temperature, dim=-1)
211
+ else:
212
+ a_ij = gumbel_softmax(scores_ijk_sum, temperature)
213
+
214
+ # (batch_size, combination_size)
215
+
216
+ # c_ij = torch.einsum("ij,ijk->ik", a_ij, c_ijk)
217
+ c_ij = WeightedSumFunc.apply(a_ij, c_ijk)
218
+ c_ij = self.norm(c_ij)
219
+
220
+ # c_ij_detach = torch.einsum("ij,ijk->ik", a_ij.detach(), c_ijk)
221
+ h_ij_next, _ = h_ij.max(dim=-1) # (batch_size, group_size)
222
+ h_ij_next = h_ij_next + 1
223
+ h_ij = torch.einsum("ij, ij->i", a_ij, h_ij_next) # (batch_size)
224
+
225
+ scores_ij_sum = torch.einsum("ij, ij->i", a_ij, scores_ijk_sum).unsqueeze(1)
226
+
227
+ inside_cache.scatter(target_cache_ids, [self.e_ij_id, self.score_sum_id, self.height_ij],
228
+ [c_ij, scores_ij_sum, h_ij.unsqueeze(1)])
229
+
230
+ # padding to group_size
231
+ score_orders.append(scores_ijk_sum.argsort(dim=1, descending=True).to('cpu', non_blocking=True))
232
+ # a_ij_orders.append(a_ij.argsort(dim=1, descending=True).to('cpu', non_blocking=True))
233
+
234
+ return score_orders #, a_ij_orders
235
+
236
+ def outside_embeddings(self, ctx):
237
+ root_embedding = self.outside_root_embedding.unsqueeze(0).repeat(ctx.batch_size, 1)
238
+ outside_cache = self.outside(ctx.batch_size, ctx.root_ids, root_embedding, \
239
+ ctx.inside_cache, ctx.outside_groups)
240
+ outside_repr = outside_cache.gather(ctx.input_cache_ids, [self.e_ij_id])[0]
241
+ return outside_repr
242
+
243
+ def parser_loss(self, ctx):
244
+ # split_masks: (batch_size, L - 1, L - 1)
245
+ # split points: (batch_size, L - 1)
246
+ scores = ctx.scores.clone()
247
+ split_masks = ctx.split_masks.clone()
248
+ split_points = ctx.split_points.clone()
249
+ L = scores.shape[1]
250
+ attention_mask = ctx.attention_mask.clone()
251
+
252
+ proxyminusinf = -1e9
253
+ assert len(attention_mask.shape) == 2
254
+ scores.masked_fill_(attention_mask[:, 1: L + 1] == 0, proxyminusinf)
255
+ scores = scores.unsqueeze(1).repeat(1, L, 1)
256
+ scores.masked_fill_(split_masks[:, :L, :L] == 0, proxyminusinf) # (batch_size, L - 1, L - 1)
257
+ #print("Split points: ", split_points.shape, "\n", split_points)
258
+ # test only feedback on root split
259
+ # log_p = F.log_softmax(scores.float(), dim=-1) # (batch_size, L - 1, L - 1)
260
+ #print("scores stats: ", scores.min().item(), scores.max().item(), scores.mean().item())
261
+ #print("split_points shape:", split_points.shape)
262
+ #print("split_points unique:", split_points.unique())
263
+ #print("split_points max:", split_points.max().item(), "vocab size:", scores.size(-1))
264
+
265
+ return F.cross_entropy(scores.clone().transpose(1, 2).float(), split_points.clone()[:, :L], ignore_index=-1)
266
+
267
+ def outside(self, batch_size, root_ids, root_embedding, inside_cache, outside_groups):
268
+ # initialize tensor cache for outside algorithm
269
+ out_cache_size = inside_cache.capacity - inside_cache.placeholder_num
270
+ outside_cache = TensorCache(0, None, [CacheType.NORMAL, CacheType.NORMAL, CacheType.NORMAL],
271
+ [self.input_dim, 1, 1], inside_cache.placeholder_num,
272
+ total_cache_size=out_cache_size,
273
+ device=inside_cache.device)
274
+ topdown_e_ij_slot = 0
275
+ topdown_score_slot = 1 # weighted sum for outside scores
276
+ topdown_score_ln_sum = 2 # store log (e^w1 + e^w2 + e^w3), w1, w2, w3 is the calculated outside scores
277
+
278
+ # (batch_size, dim), add root role embedding
279
+
280
+ zero_padding = torch.zeros(batch_size, 1, dtype=torch.float, device=self.device)
281
+ neg_padding = torch.zeros((outside_cache.capacity, 1), dtype=torch.float, device=self.device).fill_(-1e20)
282
+
283
+ # As there is no calcuated outside scores, initialize caches with a huge neg value
284
+ outside_cache.fill(0, outside_cache.capacity, [topdown_score_ln_sum], [neg_padding])
285
+ outside_cache.scatter(root_ids.long(), [topdown_e_ij_slot, topdown_score_slot, topdown_score_ln_sum],
286
+ [root_embedding, zero_padding, zero_padding])
287
+
288
+ # run outside according to inside groups
289
+ for target_cache_ids, cache_ids, detach_cache_ids in outside_groups:
290
+ parent_ids = target_cache_ids
291
+ child_ids = cache_ids # (N, comb_size, 2)
292
+
293
+ # assert child_ids[:, :, 0].unique().shape[0] == cache_ids.shape[0] * cache_ids.shape[1]
294
+ # assert child_ids[:, :, 1].unique().shape[0] == cache_ids.shape[0] * cache_ids.shape[1]
295
+
296
+ score_ids = detach_cache_ids
297
+
298
+ parent_ij, parent_ij_score = outside_cache.gather(parent_ids, [topdown_e_ij_slot, topdown_score_slot])
299
+
300
+ child_ids_shape = child_ids.shape # (batch_size, comb_size, 2)
301
+ child_ikj = inside_cache.gather(child_ids.flatten(), [self.e_ij_id])[0]
302
+ child_scores = inside_cache.gather(score_ids.flatten(), [self.score_sum_id])[0]
303
+ child_ikj = child_ikj.view(*child_ids.shape, -1)
304
+ child_scores = child_scores.view(*child_ids.shape) # (batch_size, comb_size, 2)
305
+
306
+ out_scores, out_ikj = self.outside_enc(parent_ij, child_ikj, parent_ij_score, child_scores)
307
+ # out_scores, out_ikj = checkpoint(self.outside_enc, parent_ij, child_ikj, parent_ij_score, child_scores, use_reentrant=False)
308
+ # span_norm = (1 + max_lens - span_lens).unsqueeze(1).unsqueeze(2)
309
+ # out_ikj: (batch_size, comb_size, 2, dim)
310
+
311
+ dim = out_ikj.shape[-1]
312
+
313
+ weighted_e_ij, weighted_scores, log_ksum_score = \
314
+ outside_cache.gather(child_ids[:, :, 0].flatten(),
315
+ [topdown_e_ij_slot, topdown_score_slot, topdown_score_ln_sum])
316
+ weighted_e_ij = weighted_e_ij.view(*child_ids_shape[:-1], dim) # (batch_size, comb_size, dim)
317
+ log_ksum_score = log_ksum_score.view(*child_ids_shape[:-1]) # (batch_size, comb_size)
318
+ weighted_scores = weighted_scores.view(*child_ids_shape[:-1])
319
+
320
+ # log_p_ijk_mean: (batch_size, comb_size)
321
+ left_k_sum_scores = torch.stack([log_ksum_score, out_scores[:, :, 0]], dim=2) # (batch_size, comb_size, 2)
322
+ left_k_weights = F.softmax(left_k_sum_scores, dim=2)
323
+ left_weighted_e_ij = left_k_weights[:, :, 0].unsqueeze(2) * weighted_e_ij + \
324
+ left_k_weights[:, :, 1].unsqueeze(2) * out_ikj[:, :, 0, :]
325
+ left_weighted_scores = left_k_weights[:, :, 0] * weighted_scores + \
326
+ left_k_weights[:, :, 1] * out_scores[:, :, 0]
327
+
328
+ # (batch_size, comb_size, dim)
329
+ left_k_sum_scores = left_k_sum_scores.logsumexp(dim=2, keepdim=True)
330
+
331
+ left_weighted_e_ij = left_weighted_e_ij.view(-1, dim)
332
+ left_weighted_scores = left_weighted_scores.view(-1, 1)
333
+ left_k_sum_scores = left_k_sum_scores.view(-1, 1)
334
+
335
+ outside_cache.scatter(child_ids[:, :, 0].flatten().long(),
336
+ [topdown_e_ij_slot, topdown_score_slot, topdown_score_ln_sum],
337
+ [left_weighted_e_ij, left_weighted_scores, left_k_sum_scores])
338
+
339
+ weighted_e_ij, weighted_scores, log_ksum_score = \
340
+ outside_cache.gather(child_ids[:, :, 1].flatten(),
341
+ [topdown_e_ij_slot, topdown_score_slot, topdown_score_ln_sum])
342
+ weighted_e_ij = weighted_e_ij.view(*child_ids_shape[:-1], dim) # (batch_size, comb_size, dim)
343
+ log_ksum_score = log_ksum_score.view(*child_ids_shape[:-1]) # (batch_size, comb_size)
344
+ weighted_scores = weighted_scores.view(*child_ids_shape[:-1])
345
+
346
+ right_k_sum_scores = torch.stack([log_ksum_score, out_scores[:, :, 1]], dim=2) # (batch_size, comb_size, 2)
347
+ right_k_weights = F.softmax(right_k_sum_scores, dim=2)
348
+ right_weighted_e_ij = right_k_weights[:, :, 0].unsqueeze(2) * weighted_e_ij + \
349
+ right_k_weights[:, :, 1].unsqueeze(2) * out_ikj[:, :, 1, :]
350
+ right_weighted_scores = right_k_weights[:, :, 0] * weighted_scores + \
351
+ right_k_weights[:, :, 1] * out_scores[:, :, 1]
352
+
353
+ # (batch_size, comb_size, dim)
354
+ right_k_sum_scores = right_k_sum_scores.logsumexp(dim=2, keepdim=True)
355
+
356
+ right_weighted_e_ij = right_weighted_e_ij.view(-1, dim)
357
+ right_weighted_scores = right_weighted_scores.view(-1, 1)
358
+ right_k_sum_scores = right_k_sum_scores.view(-1, 1)
359
+
360
+ outside_cache.scatter(child_ids[:, :, 1].flatten().long(),
361
+ [topdown_e_ij_slot, topdown_score_slot, topdown_score_ln_sum],
362
+ [right_weighted_e_ij, right_weighted_scores, right_k_sum_scores])
363
+
364
+ return outside_cache
365
+
366
+ def forward(self,
367
+ chunk_input_ids,
368
+ chunk_masks,
369
+ input_ids,
370
+ masks,
371
+ r2d2_embeddings, # corresponding to chunked_input_ids
372
+ group_ids,
373
+ max_input_len,
374
+ atom_spans:List[List[int]]=None,
375
+ eos_labels=None,
376
+ span_ids=None,
377
+ external_vocab_ids=None,
378
+ coeff=1.0,
379
+ temperature=1.0):
380
+
381
+ split_indices, split_scores = self.parser(chunk_input_ids, chunk_masks, atom_spans=atom_spans, noise_coeff=coeff)
382
+ split_indices = split_indices.to('cpu', non_blocking=True)
383
+
384
+ seq_lens = torch.sum(masks, dim=1, dtype=torch.int) # (batch_size)
385
+ seq_lens_np = seq_lens.to('cpu').data.numpy()
386
+
387
+ if len(chunk_masks.shape) == 2:
388
+ chunk_seq_lens_np = (chunk_masks != 0).sum(dim=1).cpu().data.numpy()
389
+ # chunk_seq_lens_np = chunk_masks.sum(dim=1).cpu().data.numpy()
390
+ # elif len(chunk_masks.shape) == 3:
391
+ # chunk_seq_lens_np = (chunk_masks.sum(dim=1) > 0).cpu().to(int).sum(dim=1).data.numpy()
392
+
393
+ batch_size = input_ids.shape[0]
394
+ input_ids_cpu = input_ids.to('cpu', non_blocking=True)
395
+
396
+ flatten_input_ids, flatten_r2d2_emb = self._flatten_inputs(chunk_input_ids, chunk_seq_lens_np, r2d2_embeddings)
397
+ ids_num = flatten_input_ids.shape[0]
398
+ input_cache_ids = torch.arange(SPECIAL_TOKEN_NUM,
399
+ SPECIAL_TOKEN_NUM + ids_num).to(self.device)
400
+
401
+ inside_cache = self.create_tensor_cache(seq_lens_np)
402
+ inside_cache.scatter(input_cache_ids, [self.e_ij_id], [flatten_r2d2_emb])
403
+
404
+ tables = CPPChartTableManager(seq_lens_np, self.window_size, split_indices.data.numpy(),
405
+ inside_cache.placeholder_num, inside_cache.detach_offset, group_ids=group_ids,
406
+ span_ids=span_ids)
407
+ target_cache_ids, span_ids, cache_ids, detach_cache_ids = \
408
+ tables.construct_inside_groups(self.device)
409
+ root_ids = tables.root_ids
410
+
411
+ span_embeds = None
412
+ if external_vocab_ids is not None:
413
+ span_embeds = self.ext_embeds(external_vocab_ids)
414
+
415
+ score_orders = self.inside(inside_cache, span_embeds, temperature,
416
+ zip(target_cache_ids, span_ids, cache_ids, detach_cache_ids))
417
+
418
+ span_masks, split_targets, ldr_cache_ids, position_ids, tgt_ids, token_indices, ext_ids = \
419
+ tables.prepare_generation(score_orders, score_orders, atom_spans, input_ids_cpu.data.numpy(),
420
+ group_ids, self.eos_token_id, self.reduce_id,
421
+ max_input_len, eos_labels=eos_labels)
422
+ # span_mask, split_targets, ldr_cache_ids, position_ids, tgt_ids
423
+
424
+ ldr_cache_ids = ldr_cache_ids.clone().to(self.device, non_blocking=True)
425
+ position_ids = position_ids.to(self.device, non_blocking=True)
426
+ tgt_ids = tgt_ids.to(self.device, non_blocking=True)
427
+ ext_ids = ext_ids.to(self.device, non_blocking=True)
428
+ token_indices = token_indices.to(self.device, non_blocking=True)
429
+
430
+ span_masks = span_masks.to(self.device, non_blocking=True)
431
+ split_targets = split_targets.to(self.device, non_blocking=True)
432
+
433
+ ldr_repr = inside_cache.gather(ldr_cache_ids.flatten(), [self.e_ij_id])[0]
434
+ ldr_repr = ldr_repr.view(*ldr_cache_ids.shape, -1) # (N, L, dim)
435
+
436
+ # l_height = (inside_cache.gather(root_ids, [self.height_ij])[0] / seq_lens).mean()
437
+ inside_height = inside_cache.gather(root_ids, [self.height_ij])[0]
438
+
439
+ inside_height = torch.where(inside_height > self.height_threshold, inside_height - self.height_threshold, 0)
440
+ height_norm = torch.where(seq_lens > self.height_threshold, seq_lens - self.height_threshold, 1)
441
+ l_height = (inside_height / height_norm).mean()
442
+
443
+ # fix clones
444
+ tci = [t.clone() for t in target_cache_ids]
445
+ ci = [t.clone() for t in cache_ids]
446
+ dci = [t.clone() for t in detach_cache_ids]
447
+ ctx = InsideOutsideContext(
448
+ scores=split_scores,
449
+ attention_mask=chunk_masks,
450
+ split_masks=span_masks.clone(),
451
+ split_points=split_targets.clone(),
452
+ batch_size=batch_size,
453
+ root_ids=root_ids,
454
+ inside_cache=inside_cache,
455
+ input_cache_ids=input_cache_ids,
456
+ outside_groups=list(zip(reversed(tci), reversed(ci), reversed(dci)))
457
+ )
458
+ if self.ldr_detach:
459
+ ldr_repr = ldr_repr.detach()
460
+
461
+ return ctx, flatten_input_ids, ldr_repr, position_ids.clone(), \
462
+ tgt_ids.clone(), token_indices.clone(), ext_ids, split_targets.clone(), l_height
gpst/setup.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from setuptools import setup
2
+ import os
3
+ import torch
4
+ import glob
5
+ from torch.utils.cpp_extension import BuildExtension, CUDAExtension, CppExtension
6
+
7
+
8
+ include_dirs = os.path.dirname(os.path.abspath(__file__))
9
+ source_file = glob.glob(os.path.join('./', 'cpp_extension', '*.cpp'))
10
+
11
+ if torch.cuda.is_available():
12
+ setup(
13
+ name='cppbackend',
14
+ ext_modules=[
15
+ CppExtension('cppbackend',
16
+ sources=source_file,
17
+ include_dirs=[include_dirs]
18
+ )
19
+ ],
20
+ cmdclass={'build_ext': BuildExtension})
gpst/topdown_parser.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from copy import deepcopy
2
+ from typing import List, Tuple
3
+ import torch.nn.functional as F
4
+ import torch.nn as nn
5
+ import torch
6
+ import numpy as np
7
+ from torch.nn.utils.rnn import pack_padded_sequence, pad_packed_sequence
8
+ from gpst.tree_encoder import _get_activation_fn
9
+
10
+
11
+ INF=1e7
12
+
13
+ class BasicParser(nn.Module):
14
+ def __init__(self):
15
+ super().__init__()
16
+
17
+ def _split_point_scores(self, input_ids, attn_mask):
18
+ pass
19
+
20
+ def _adjust_atom_span(self, scores, atom_spans, const=1):
21
+ # scores.masked_fill_(attention_mask[:, 1:scores.shape[1] + 1] == 0, float('-inf'))
22
+ points_mask = np.full(scores.shape, fill_value=0)
23
+ for batch_i, spans in enumerate(atom_spans):
24
+ if spans is not None:
25
+ for (i, j) in spans:
26
+ points_mask[batch_i][i: j] += 1
27
+ points_mask = torch.tensor(points_mask, device=scores.device)
28
+ assert const > 0
29
+ mask_scores = points_mask * (scores.max() - scores.min() + const)
30
+ return scores - mask_scores
31
+
32
+ # @torch.inference_mode
33
+ def parse(self, input_ids: torch.Tensor = None, attention_mask: torch.Tensor = None,
34
+ atom_spans: List[List[Tuple[int]]] = None, noise_coeff: float = 1.0):
35
+ """
36
+ params:
37
+ input_ids: torch.Tensor,
38
+ attention_mask:
39
+ atom_spans: List[List[Tuple[int]]], batch_size * span_lens * 2, each span contains start and end position
40
+ splits: List[List[int]], batch_size * split_num, list of split positions
41
+ """
42
+ org_scores = self._split_point_scores(input_ids, attention_mask)
43
+ # meaningful split points: seq_lens - 1
44
+
45
+ if self.training:
46
+ noise = -torch.empty_like(
47
+ org_scores,
48
+ memory_format=torch.legacy_contiguous_format,
49
+ requires_grad=False).exponential_().log() * max(0, noise_coeff)
50
+ scores = org_scores.detach() + noise
51
+ else:
52
+ scores = org_scores.detach()
53
+ if atom_spans is not None:
54
+ scores = self._adjust_atom_span(scores, atom_spans)
55
+
56
+ if attention_mask is not None:
57
+ if len(attention_mask.shape) == 3:
58
+ attention_mask = (attention_mask.sum(dim=1) > 0).to(int)
59
+ scores = scores.masked_fill_(attention_mask[:, 1:scores.shape[1] + 1] == 0, float('inf'))
60
+ # split according to scores
61
+ # for torch >= 1.9
62
+ _, s_indices = scores.sort(dim=-1, descending=False, stable=True)
63
+ return s_indices, org_scores
64
+
65
+ def forward(self, input_ids: torch.Tensor = None, attention_mask: torch.Tensor = None,
66
+ atom_spans: List[List[Tuple[int]]] = None, noise_coeff: float = 1.0):
67
+ return self.parse(input_ids, attention_mask=attention_mask, atom_spans=atom_spans,
68
+ noise_coeff=noise_coeff)
69
+
gpst/tree_encoder.py ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ from typing import List
3
+ import torch.nn as nn
4
+ import torch.nn.functional as F
5
+ import torch
6
+ from torch.nn import init
7
+ from copy import deepcopy
8
+ import numpy as np
9
+
10
+ ACTIVATION_POOL = ['relu', 'gelu']
11
+
12
+
13
+ def _get_activation_fn(activation):
14
+ if activation in ACTIVATION_POOL:
15
+ return getattr(F, activation)
16
+
17
+ raise RuntimeError("activation should be relu/gelu, not {}".format(activation))
18
+
19
+
20
+ class TreeEncoderLayer(nn.Module):
21
+ def __init__(self, d_model, nhead, dim_feedforward, dropout, max_role_count,
22
+ activation='gelu', batch_first=False, val_position=False):
23
+ super().__init__()
24
+ self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout, batch_first=batch_first)
25
+ self._val_position = val_position
26
+ self.linear1 = nn.Linear(d_model, dim_feedforward)
27
+ self.dropout = nn.Dropout(dropout)
28
+ self.linear2 = nn.Linear(dim_feedforward, d_model)
29
+
30
+ self.norm1 = nn.InstanceNorm1d(d_model)
31
+ self.norm2 = nn.InstanceNorm1d(d_model)
32
+ self.dropout1 = nn.Dropout(dropout)
33
+ self.dropout2 = nn.Dropout(dropout)
34
+ self.position_embedding = nn.Embedding(max_role_count, d_model)
35
+
36
+ self.activation = _get_activation_fn(activation)
37
+
38
+ def forward(self, src, src_mask=None, pos_ids=None):
39
+ """
40
+ :param src: concatenation of task embeddings and representation for left and right.
41
+ src shape: (task_embeddings + left + right, batch_size, dim)
42
+ :param src_mask:
43
+ :param pos_ids:
44
+ :return:
45
+ """
46
+ if len(pos_ids.shape) == 1:
47
+ sz = src.shape[1] # sz: batch_size
48
+ pos_ids = pos_ids.unsqueeze(1).expand(-1, sz) # (3, batch_size)
49
+ position_embedding = self.position_embedding(pos_ids)
50
+ src2 = self.self_attn(src + position_embedding, src + position_embedding, src,
51
+ attn_mask=src_mask)[0]
52
+ src = src + self.dropout1(src2)
53
+ src = self.norm1(src)
54
+ src2 = self.linear2(self.dropout(self.activation(self.linear1(src))))
55
+ src = src + self.dropout2(src2)
56
+ src = self.norm2(src)
57
+ return src
58
+
59
+ class InsideEncoder(nn.Module):
60
+ def __init__(self, config):
61
+ super().__init__()
62
+
63
+ self.const_size = config.const_size
64
+ self.left_linear = nn.Sequential(nn.Linear(config.hidden_size, config.hidden_size),
65
+ nn.GELU(),
66
+ nn.Linear(config.hidden_size, config.const_size))
67
+ self.right_linear = nn.Sequential(nn.Linear(config.hidden_size, config.hidden_size),
68
+ nn.GELU(),
69
+ nn.Linear(config.hidden_size, config.const_size))
70
+ # self.const_linear = nn.Sequential(GroupLinear(2, config.hidden_size, config.hidden_size),
71
+ # nn.GELU(),
72
+ # GroupLinear(2, config.hidden_size, config.hidden_size))
73
+
74
+ layer = TreeEncoderLayer(config.hidden_size,
75
+ config.num_attention_heads,
76
+ config.intermediate_size,
77
+ max_role_count=config.max_role_embeddings,
78
+ dropout=config.attention_probs_dropout_prob,
79
+ activation='gelu',
80
+ batch_first=True,
81
+ val_position=True)
82
+ self.norm = nn.InstanceNorm1d(config.hidden_size)
83
+ self.layers = nn.ModuleList([layer] + [deepcopy(layer) for _ in range(config.encoder_num_hidden_layers - 1)])
84
+ self._device = None
85
+ self._pos_ids = None
86
+
87
+
88
+ @property
89
+ def device(self):
90
+ if self._device is None:
91
+ self._device = next(self.parameters()).device
92
+ return self._device
93
+
94
+ @property
95
+ def pos_ids(self):
96
+ if self._pos_ids is None:
97
+ self._pos_ids = torch.arange(2).to(self.device)
98
+ return self._pos_ids
99
+
100
+ def forward(self, src, span_embeds=None):
101
+ """
102
+ :param src: [batch_size, comb_size, 2, dim]
103
+ :param span_embeds: [batch_size, dim]
104
+ :return:
105
+ """
106
+ dim = src.shape[-1]
107
+ org_shape = src.shape # (batch_size, comb_size, 2, dim)
108
+ output = src.view(-1, 2, dim)
109
+
110
+ # torch.cuda.synchronize()
111
+ # with torch.cuda.stream(self.s1):
112
+ left_const = self.left_linear(output[:, 0, :])
113
+ right_const = self.right_linear(output[:, 1, :])
114
+
115
+ for mod in self.layers:
116
+ output = mod(output, pos_ids=self.pos_ids.unsqueeze(0))
117
+
118
+ mat_scores = torch.einsum("bi,bi->b", left_const, right_const) / math.sqrt(self.const_size)
119
+ mat_scores = mat_scores.view(*org_shape[:-2]) # (batch_size, comb_size)
120
+ if span_embeds is not None:
121
+ output = output.sum(dim=1).view(*org_shape[:-2], dim) + span_embeds.unsqueeze(1)
122
+ else:
123
+ output = output.sum(dim=1).view(*org_shape[:-2], dim)
124
+
125
+ return mat_scores, self.norm(output)
126
+
127
+
128
+ class OutsideEncoder(nn.Module):
129
+ def __init__(self, config) -> None:
130
+ super().__init__()
131
+
132
+ self.parent_linear = nn.Sequential(nn.Linear(config.hidden_size, config.hidden_size),
133
+ nn.GELU(),
134
+ nn.Linear(config.hidden_size, config.const_size))
135
+ self.left_linear = nn.Sequential(nn.Linear(config.hidden_size, config.hidden_size),
136
+ nn.GELU(),
137
+ nn.Linear(config.hidden_size, config.const_size))
138
+ self.right_linear = nn.Sequential(nn.Linear(config.hidden_size, config.hidden_size),
139
+ nn.GELU(),
140
+ nn.Linear(config.hidden_size, config.const_size))
141
+ # self.const_linear = nn.Sequential(GroupLinear(3, config.hidden_size, config.hidden_size),
142
+ # nn.GELU(),
143
+ # GroupLinear(3, config.hidden_size, config.hidden_size))
144
+ self.const_size = config.const_size
145
+
146
+ layer = TreeEncoderLayer(config.hidden_size,
147
+ config.num_attention_heads,
148
+ config.intermediate_size,
149
+ max_role_count=config.max_role_embeddings,
150
+ dropout=config.attention_probs_dropout_prob,
151
+ activation='gelu',
152
+ batch_first=True,
153
+ val_position=True)
154
+ self.norm = nn.InstanceNorm1d(config.hidden_size)
155
+ self.layers = nn.ModuleList([layer] + [deepcopy(layer) for _ in range(config.decoder_num_hidden_layers - 1)])
156
+ self._device = None
157
+ self._dec_pos_ids = None
158
+
159
+ @property
160
+ def device(self):
161
+ if self._device is None:
162
+ self._device = next(self.parameters()).device
163
+ return self._device
164
+
165
+ @property
166
+ def dec_pos_ids(self):
167
+ if self._dec_pos_ids is None:
168
+ self._dec_pos_ids = torch.tensor([[0, 1], [0, 2]], device=self.device)
169
+ return self._dec_pos_ids
170
+
171
+ def forward(self, parent_ij, child_ikj, parent_scores=None, child_scores=None):
172
+ """
173
+ :param parent_ij: (batch_size, dim)
174
+ :param parent_scores: (batch_size, 1)
175
+ :param child_ikj: (batch_size, comb_size, 2, dim)
176
+ :param child_scores: (batch_size, comb_size, 2)
177
+ :return: (batch_size, 2), (batch_size, 2, dim)
178
+ """
179
+ # p_l = parent_ij @ self.W_outside_r # (batch_size, dim)
180
+ # out_score_ik = torch.einsum('bd, bcd->bc', p_l, child_ikj[:, :, 1, :]) # (batch_size, comb_size)
181
+ # out_score_ik = out_score_ik + parent_scores + child_scores[:, :, 1, 0] # (batch_size, comb_size)
182
+
183
+ # p_r = parent_ij @ self.W_outside_l # (batch_size, dim)
184
+ # out_score_kj = torch.einsum('bd, bcd->bc', p_r, child_ikj[:, :, 0, :]) # (batch_size, comb_size)
185
+ # out_score_kj = out_score_kj + parent_scores + child_scores[:, :, 0, 0] # (batch_size, comb_size)
186
+
187
+ batch_size = child_ikj.shape[0]
188
+ comb_size = child_ikj.shape[1]
189
+
190
+ comb_size = child_ikj.shape[1]
191
+ parent_ij_ext = parent_ij.unsqueeze(1).unsqueeze(2).repeat(1, comb_size, 2, 1) # (batch_size, comb_size, 2, dim)
192
+
193
+ inputs = torch.stack([parent_ij_ext, child_ikj.flip([2])], dim=3) # (batch_size, comb_size, 2, 2, dim)
194
+ inputs = inputs.view(batch_size * comb_size * 2, 2, -1)
195
+
196
+
197
+ outside_scores = None
198
+
199
+ if parent_scores is not None and child_scores is not None:
200
+ parent_const = self.parent_linear(inputs[:, 0, :])
201
+ right_child_const = self.right_linear(inputs[::2, 1, :])
202
+ left_child_const = self.left_linear(inputs[1::2, 1, :])
203
+
204
+
205
+ # self.dec_pos_ids: (2, 2)
206
+ pos_ids = self.dec_pos_ids.repeat(batch_size * comb_size, 1)
207
+ for mod in self.layers:
208
+ inputs = mod(inputs, pos_ids=pos_ids)
209
+
210
+ if parent_scores is not None and child_scores is not None:
211
+ parent_const_r = parent_const[::2, :]
212
+ parent_const_l = parent_const[1::2, :]
213
+ left_score = (parent_const_r * right_child_const).sum(dim=-1) / math.sqrt(self.const_size)
214
+ # right_score = torch.einsum('bi,bi->b', parent_const_l, left_child_const) / math.sqrt(self.const_size)
215
+ right_score = (parent_const_l * left_child_const).sum(dim=-1) / math.sqrt(self.const_size)
216
+ left_score = left_score.view(batch_size, comb_size)
217
+ right_score = right_score.view(batch_size, comb_size)
218
+ out_score_ik = left_score
219
+ out_score_kj = right_score
220
+ outside_scores = torch.stack([out_score_ik, out_score_kj], dim=2)
221
+ # inputs: (?, 2, dim)
222
+ out_e_ij = self.norm(inputs.sum(dim=1))
223
+
224
+ return outside_scores, \
225
+ out_e_ij.view(batch_size, comb_size, 2, -1) # (batch_size, comb_size, 2, dim)