David Arps commited on
Commit ·
0bbc3d8
1
Parent(s): 68f7559
update model
Browse files- LICENSE +201 -0
- generative_r2d2_fast.py +5 -41
- gpst/Llama_flash_attn.py +284 -0
- gpst/backend_loader.py +42 -0
- gpst/config.py +10 -0
- gpst/cpp_extension/binding.cpp +29 -0
- gpst/cpp_extension/py_backend.cpp +1100 -0
- gpst/cpp_extension/py_backend.h +204 -0
- gpst/data_structure/py_backend.py +74 -0
- gpst/data_structure/tensor_cache.py +121 -0
- gpst/fast_parser.py +103 -0
- gpst/generative_r2d2_fast.py +299 -0
- gpst/gpt2_flash_attn.py +1625 -0
- gpst/math_util.py +37 -0
- gpst/r2d2_base.py +41 -0
- gpst/r2d2_common.py +41 -0
- gpst/r2d2_insideoutside.py +462 -0
- gpst/setup.py +20 -0
- gpst/topdown_parser.py +69 -0
- gpst/tree_encoder.py +225 -0
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
|
| 14 |
-
|
| 15 |
-
|
|
|
|
| 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,
|
| 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)
|