-
Notifications
You must be signed in to change notification settings - Fork 34.1k
add ONNX support for BLOOM #17961
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add ONNX support for BLOOM #17961
Changes from 1 commit
2009710
c15f12a
fb1b76c
0f9199d
cf43ce2
a6fb1be
71ecf5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,13 @@ | |
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| """ Bloom configuration""" | ||
| from collections import OrderedDict | ||
| from typing import Any, List, Mapping, Optional | ||
|
|
||
| from transformers import PreTrainedTokenizer, TensorType, is_torch_available | ||
|
|
||
| from ...configuration_utils import PretrainedConfig | ||
| from ...onnx import OnnxConfigWithPast, PatchingSpec | ||
| from ...utils import logging | ||
|
|
||
|
|
||
|
|
@@ -153,3 +159,85 @@ def __init__( | |
| self.slow_but_exact = slow_but_exact | ||
|
|
||
| super().__init__(bos_token_id=bos_token_id, eos_token_id=eos_token_id, **kwargs) | ||
|
|
||
|
|
||
| # Copied from transformers.models.gpt2.configuration_gpt2.GPT2OnnxConfig | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! |
||
| class BloomOnnxConfig(OnnxConfigWithPast): | ||
| def __init__( | ||
| self, | ||
| config: PretrainedConfig, | ||
| task: str = "default", | ||
| patching_specs: List[PatchingSpec] = None, | ||
| use_past: bool = False, | ||
| ): | ||
| super().__init__(config, task=task, patching_specs=patching_specs, use_past=use_past) | ||
| if not getattr(self._config, "pad_token_id", None): | ||
| # TODO: how to do that better? | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hehe @michaelbenayoun we should fix this sometime :) |
||
| self._config.pad_token_id = 0 | ||
|
|
||
| @property | ||
| def inputs(self) -> Mapping[str, Mapping[int, str]]: | ||
| common_inputs = OrderedDict({"input_ids": {0: "batch", 1: "sequence"}}) | ||
| if self.use_past: | ||
| self.fill_with_past_key_values_(common_inputs, direction="inputs") | ||
| common_inputs["attention_mask"] = {0: "batch", 1: "past_sequence + sequence"} | ||
| else: | ||
| common_inputs["attention_mask"] = {0: "batch", 1: "sequence"} | ||
|
|
||
| return common_inputs | ||
|
|
||
| @property | ||
| def num_layers(self) -> int: | ||
| return self._config.n_layer | ||
|
|
||
| @property | ||
| def num_attention_heads(self) -> int: | ||
| return self._config.n_head | ||
|
|
||
| def generate_dummy_inputs( | ||
| self, | ||
| tokenizer: PreTrainedTokenizer, | ||
| batch_size: int = -1, | ||
| seq_length: int = -1, | ||
| is_pair: bool = False, | ||
| framework: Optional[TensorType] = None, | ||
| ) -> Mapping[str, Any]: | ||
| common_inputs = super(OnnxConfigWithPast, self).generate_dummy_inputs( | ||
| tokenizer, batch_size=batch_size, seq_length=seq_length, is_pair=is_pair, framework=framework | ||
| ) | ||
|
|
||
| # We need to order the input in the way they appears in the forward() | ||
| ordered_inputs = OrderedDict({"input_ids": common_inputs["input_ids"]}) | ||
|
|
||
| # Need to add the past_keys | ||
| if self.use_past: | ||
| if not is_torch_available(): | ||
| raise ValueError("Cannot generate dummy past_keys inputs without PyTorch installed.") | ||
| else: | ||
| import torch | ||
|
|
||
| batch, seqlen = common_inputs["input_ids"].shape | ||
| # Not using the same length for past_key_values | ||
| past_key_values_length = seqlen + 2 | ||
|
nmntz marked this conversation as resolved.
|
||
| past_shape = ( | ||
| batch, | ||
| self.num_attention_heads, | ||
| past_key_values_length, | ||
| self._config.hidden_size // self.num_attention_heads, | ||
| ) | ||
| ordered_inputs["past_key_values"] = [ | ||
| (torch.zeros(past_shape), torch.zeros(past_shape)) for _ in range(self.num_layers) | ||
| ] | ||
|
|
||
| ordered_inputs["attention_mask"] = common_inputs["attention_mask"] | ||
| if self.use_past: | ||
| mask_dtype = ordered_inputs["attention_mask"].dtype | ||
| ordered_inputs["attention_mask"] = torch.cat( | ||
| [ordered_inputs["attention_mask"], torch.ones(batch, past_key_values_length, dtype=mask_dtype)], dim=1 | ||
| ) | ||
|
|
||
| return ordered_inputs | ||
|
|
||
| @property | ||
| def default_onnx_opset(self) -> int: | ||
| return 13 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -78,17 +78,14 @@ def split_tensor_along_last_dim(tensor, num_partitions, contiguous_split_chunks= | |
|
|
||
|
|
||
| def attention_mask_func(attention_scores, attention_mask, causal_mask): | ||
| if attention_mask.dtype == torch.bool: | ||
| attention_mask_bool = ~attention_mask | ||
| else: | ||
| attention_mask_bool = (1 - attention_mask).bool() | ||
| attention_mask_bool = 1 - attention_mask.int() | ||
|
|
||
| query_length, key_length, n_heads = attention_scores.size(2), attention_scores.size(3), attention_scores.size(1) | ||
| padded_causal_mask = ( | ||
| attention_mask_bool[:, None, key_length - query_length : key_length, None] | ||
| + ~causal_mask[:, :, key_length - query_length : key_length, :key_length] | ||
| ).bool() | ||
| padded_causal_mask = padded_causal_mask + attention_mask_bool[:, None, None, :key_length].bool() | ||
| padded_causal_mask = attention_mask_bool[:, None, key_length - query_length : key_length, None] + ( | ||
| 1 - causal_mask[:, :, key_length - query_length : key_length, :key_length].int() | ||
| ) | ||
| padded_causal_mask = padded_causal_mask + attention_mask_bool[:, None, None, :key_length] | ||
| padded_causal_mask = padded_causal_mask.bool() | ||
| # Make use of floats | ||
| return ( | ||
| attention_scores.masked_fill_(padded_causal_mask.expand(-1, n_heads, -1, -1), -10000.0), | ||
|
|
@@ -296,8 +293,9 @@ def forward(self, input, mask, max_positions): | |
| mask = torch.ones(input.shape[0], max_positions, dtype=torch.bool, device=input.device) | ||
|
|
||
| mask = mask.to(input.device) | ||
| seq_ids = torch.arange(max_positions, device=input.device) | ||
| causal_mask = ( | ||
| torch.tril(torch.ones((max_positions, max_positions), dtype=torch.bool)) | ||
| (seq_ids[None, None, :] <= seq_ids[None, :, None]) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dont know if this is relevant but the original implementation outputs a tensor of rank 2, and your change outputs a tensor of rank 3. Should not be a big deal since we do reshape it afterwards but just wanted to point this out.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we keep it like that?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed :) Thank you for the notice 🤗 |
||
| .view(1, 1, max_positions, max_positions) | ||
| .to(input.device) | ||
| ) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -204,6 +204,7 @@ def test_values_override(self): | |
| } | ||
|
|
||
| PYTORCH_EXPORT_WITH_PAST_MODELS = { | ||
| ("bloom", "bigscience/bloom-350m"), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have you checked that the slow tests pass for this checkpoint? You can run:
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for reminding me. All tests are passing now 🙂 |
||
| ("gpt2", "gpt2"), | ||
| ("gpt-neo", "EleutherAI/gpt-neo-125M"), | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.