Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- third_party/transformers/src/transformers/models/apertus/__init__.py +31 -0
- third_party/transformers/src/transformers/models/apertus/configuration_apertus.py +99 -0
- third_party/transformers/src/transformers/models/apertus/modeling_apertus.py +505 -0
- third_party/transformers/src/transformers/models/apertus/modular_apertus.py +268 -0
- third_party/transformers/src/transformers/models/arcee/__init__.py +27 -0
- third_party/transformers/src/transformers/models/arcee/configuration_arcee.py +100 -0
- third_party/transformers/src/transformers/models/arcee/modeling_arcee.py +520 -0
- third_party/transformers/src/transformers/models/arcee/modular_arcee.py +117 -0
- third_party/transformers/src/transformers/models/aya_vision/__init__.py +28 -0
- third_party/transformers/src/transformers/models/aya_vision/configuration_aya_vision.py +80 -0
- third_party/transformers/src/transformers/models/aya_vision/modeling_aya_vision.py +446 -0
- third_party/transformers/src/transformers/models/aya_vision/modular_aya_vision.py +262 -0
- third_party/transformers/src/transformers/models/aya_vision/processing_aya_vision.py +208 -0
- third_party/transformers/src/transformers/models/blt/__init__.py +28 -0
- third_party/transformers/src/transformers/models/blt/configuration_blt.py +286 -0
- third_party/transformers/src/transformers/models/blt/convert_blt_weights_to_hf.py +487 -0
- third_party/transformers/src/transformers/models/blt/modeling_blt.py +1463 -0
- third_party/transformers/src/transformers/models/blt/modular_blt.py +1195 -0
- third_party/transformers/src/transformers/models/byt5/__init__.py +26 -0
- third_party/transformers/src/transformers/models/byt5/convert_byt5_original_tf_checkpoint_to_pytorch.py +167 -0
- third_party/transformers/src/transformers/models/byt5/tokenization_byt5.py +234 -0
- third_party/transformers/src/transformers/models/clip/__init__.py +31 -0
- third_party/transformers/src/transformers/models/clip/configuration_clip.py +248 -0
- third_party/transformers/src/transformers/models/clip/convert_clip_original_pytorch_to_hf.py +155 -0
- third_party/transformers/src/transformers/models/clip/image_processing_clip.py +45 -0
- third_party/transformers/src/transformers/models/clip/image_processing_pil_clip.py +45 -0
- third_party/transformers/src/transformers/models/clip/modeling_clip.py +1148 -0
- third_party/transformers/src/transformers/models/clip/processing_clip.py +28 -0
- third_party/transformers/src/transformers/models/clip/tokenization_clip.py +142 -0
- third_party/transformers/src/transformers/models/deberta_v2/__init__.py +28 -0
- third_party/transformers/src/transformers/models/deberta_v2/configuration_deberta_v2.py +94 -0
- third_party/transformers/src/transformers/models/deberta_v2/modeling_deberta_v2.py +1361 -0
- third_party/transformers/src/transformers/models/deberta_v2/tokenization_deberta_v2.py +169 -0
- third_party/transformers/src/transformers/models/depth_anything/__init__.py +27 -0
- third_party/transformers/src/transformers/models/depth_anything/configuration_depth_anything.py +99 -0
- third_party/transformers/src/transformers/models/depth_anything/convert_depth_anything_to_hf.py +370 -0
- third_party/transformers/src/transformers/models/depth_anything/convert_distill_any_depth_to_hf.py +249 -0
- third_party/transformers/src/transformers/models/depth_anything/modeling_depth_anything.py +416 -0
- third_party/transformers/src/transformers/models/dpr/__init__.py +29 -0
- third_party/transformers/src/transformers/models/dpr/configuration_dpr.py +63 -0
- third_party/transformers/src/transformers/models/dpr/convert_dpr_original_checkpoint_to_pytorch.py +145 -0
- third_party/transformers/src/transformers/models/dpr/modeling_dpr.py +576 -0
- third_party/transformers/src/transformers/models/dpr/tokenization_dpr.py +330 -0
- third_party/transformers/src/transformers/models/dpr/tokenization_dpr_fast.py +318 -0
- third_party/transformers/src/transformers/models/dpt/__init__.py +29 -0
- third_party/transformers/src/transformers/models/dpt/configuration_dpt.py +158 -0
- third_party/transformers/src/transformers/models/dpt/convert_dinov2_depth_to_hf.py +384 -0
- third_party/transformers/src/transformers/models/dpt/convert_dpt_beit_to_hf.py +306 -0
- third_party/transformers/src/transformers/models/dpt/convert_dpt_hybrid_to_pytorch.py +316 -0
- third_party/transformers/src/transformers/models/dpt/convert_dpt_swinv2_to_hf.py +322 -0
third_party/transformers/src/transformers/models/apertus/__init__.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 The HuggingFace Inc. team and the Swiss AI Initiative. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# This code is based on HuggingFace's LLaMA implementation in this library.
|
| 4 |
+
# It has been modified from its original forms to accommodate the architectural
|
| 5 |
+
# differences made by the Swiss AI Initiative that trained the model.
|
| 6 |
+
#
|
| 7 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 8 |
+
# you may not use this file except in compliance with the License.
|
| 9 |
+
# You may obtain a copy of the License at
|
| 10 |
+
#
|
| 11 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 12 |
+
#
|
| 13 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 14 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 15 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 16 |
+
# See the License for the specific language governing permissions and
|
| 17 |
+
# limitations under the License.
|
| 18 |
+
from typing import TYPE_CHECKING
|
| 19 |
+
|
| 20 |
+
from ...utils import _LazyModule
|
| 21 |
+
from ...utils.import_utils import define_import_structure
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
if TYPE_CHECKING:
|
| 25 |
+
from .configuration_apertus import *
|
| 26 |
+
from .modeling_apertus import *
|
| 27 |
+
else:
|
| 28 |
+
import sys
|
| 29 |
+
|
| 30 |
+
_file = globals()["__file__"]
|
| 31 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/apertus/configuration_apertus.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/apertus/modular_apertus.py.
|
| 3 |
+
# Do NOT edit this file manually as any edits will be overwritten by the generation of
|
| 4 |
+
# the file from the modular. If any change should be done, please apply the change to the
|
| 5 |
+
# modular_apertus.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2025 the HuggingFace Inc. team and the Swiss AI Initiative. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
#
|
| 10 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 11 |
+
# you may not use this file except in compliance with the License.
|
| 12 |
+
# You may obtain a copy of the License at
|
| 13 |
+
#
|
| 14 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 15 |
+
#
|
| 16 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 17 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 18 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 19 |
+
# See the License for the specific language governing permissions and
|
| 20 |
+
# limitations under the License.
|
| 21 |
+
from huggingface_hub.dataclasses import strict
|
| 22 |
+
|
| 23 |
+
from ...configuration_utils import PreTrainedConfig
|
| 24 |
+
from ...modeling_rope_utils import RopeParameters
|
| 25 |
+
from ...utils import auto_docstring
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
@auto_docstring(checkpoint="swiss-ai/Apertus-8B-Instruct-2509")
|
| 29 |
+
@strict
|
| 30 |
+
class ApertusConfig(PreTrainedConfig):
|
| 31 |
+
r"""
|
| 32 |
+
```python
|
| 33 |
+
>>> from transformers import ApertusModel, ApertusConfig
|
| 34 |
+
|
| 35 |
+
>>> # Initializing a Apertus-8B style configuration
|
| 36 |
+
>>> configuration = ApertusConfig()
|
| 37 |
+
|
| 38 |
+
>>> # Initializing a model from the Apertus-8B style configuration
|
| 39 |
+
>>> model = ApertusModel(configuration)
|
| 40 |
+
|
| 41 |
+
>>> # Accessing the model configuration
|
| 42 |
+
>>> configuration = model.config
|
| 43 |
+
```"""
|
| 44 |
+
|
| 45 |
+
model_type = "apertus"
|
| 46 |
+
keys_to_ignore_at_inference = ["past_key_values"]
|
| 47 |
+
default_theta = 12000000.0
|
| 48 |
+
base_model_tp_plan = {
|
| 49 |
+
"layers.*.self_attn.q_proj": "colwise",
|
| 50 |
+
"layers.*.self_attn.k_proj": "colwise",
|
| 51 |
+
"layers.*.self_attn.v_proj": "colwise",
|
| 52 |
+
"layers.*.self_attn.q_norm": "replicated_with_grad_allreduce",
|
| 53 |
+
"layers.*.self_attn.k_norm": "replicated_with_grad_allreduce",
|
| 54 |
+
"layers.*.self_attn.o_proj": "rowwise",
|
| 55 |
+
"layers.*.mlp.up_proj": "colwise",
|
| 56 |
+
"layers.*.mlp.down_proj": "rowwise",
|
| 57 |
+
}
|
| 58 |
+
base_model_pp_plan = {
|
| 59 |
+
"embed_tokens": (["input_ids"], ["inputs_embeds"]),
|
| 60 |
+
"layers": (["hidden_states", "attention_mask"], ["hidden_states"]),
|
| 61 |
+
"norm": (["hidden_states"], ["hidden_states"]),
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
vocab_size: int = 131072
|
| 65 |
+
hidden_size: int = 4096
|
| 66 |
+
intermediate_size: int = 14336
|
| 67 |
+
num_hidden_layers: int = 32
|
| 68 |
+
num_attention_heads: int = 32
|
| 69 |
+
num_key_value_heads: int | None = None
|
| 70 |
+
hidden_act: str = "xielu"
|
| 71 |
+
max_position_embeddings: int = 65536
|
| 72 |
+
initializer_range: float = 0.02
|
| 73 |
+
rms_norm_eps: float = 1e-5
|
| 74 |
+
use_cache: bool = True
|
| 75 |
+
pad_token_id: int | None = 3
|
| 76 |
+
bos_token_id: int | None = 1
|
| 77 |
+
eos_token_id: int | list[int] | None = 2
|
| 78 |
+
tie_word_embeddings: bool = False
|
| 79 |
+
rope_parameters: RopeParameters | dict | None = None
|
| 80 |
+
attention_bias: bool = False
|
| 81 |
+
attention_dropout: float | int = 0.0
|
| 82 |
+
|
| 83 |
+
def __post_init__(self, **kwargs):
|
| 84 |
+
if self.num_key_value_heads is None:
|
| 85 |
+
self.num_key_value_heads = self.num_attention_heads
|
| 86 |
+
|
| 87 |
+
if self.rope_parameters is None:
|
| 88 |
+
self.rope_parameters = {
|
| 89 |
+
"rope_type": "llama3",
|
| 90 |
+
"rope_theta": 12000000.0,
|
| 91 |
+
"factor": 8.0,
|
| 92 |
+
"original_max_position_embeddings": 8192,
|
| 93 |
+
"low_freq_factor": 1.0,
|
| 94 |
+
"high_freq_factor": 4.0,
|
| 95 |
+
}
|
| 96 |
+
super().__post_init__(**kwargs)
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
__all__ = ["ApertusConfig"]
|
third_party/transformers/src/transformers/models/apertus/modeling_apertus.py
ADDED
|
@@ -0,0 +1,505 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/apertus/modular_apertus.py.
|
| 3 |
+
# Do NOT edit this file manually as any edits will be overwritten by the generation of
|
| 4 |
+
# the file from the modular. If any change should be done, please apply the change to the
|
| 5 |
+
# modular_apertus.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2025 the HuggingFace Inc. team and the Swiss AI Initiative. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
#
|
| 10 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 11 |
+
# you may not use this file except in compliance with the License.
|
| 12 |
+
# You may obtain a copy of the License at
|
| 13 |
+
#
|
| 14 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 15 |
+
#
|
| 16 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 17 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 18 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 19 |
+
# See the License for the specific language governing permissions and
|
| 20 |
+
# limitations under the License.
|
| 21 |
+
from collections.abc import Callable
|
| 22 |
+
from typing import Optional
|
| 23 |
+
|
| 24 |
+
import torch
|
| 25 |
+
from torch import nn
|
| 26 |
+
|
| 27 |
+
from ...activations import ACT2CLS, ACT2FN
|
| 28 |
+
from ...cache_utils import Cache, DynamicCache
|
| 29 |
+
from ...generation import GenerationMixin
|
| 30 |
+
from ...integrations import use_kernel_forward_from_hub, use_kernel_func_from_hub, use_kernelized_func
|
| 31 |
+
from ...masking_utils import create_causal_mask
|
| 32 |
+
from ...modeling_layers import GenericForTokenClassification, GradientCheckpointingLayer
|
| 33 |
+
from ...modeling_outputs import BaseModelOutputWithPast, CausalLMOutputWithPast
|
| 34 |
+
from ...modeling_rope_utils import ROPE_INIT_FUNCTIONS, dynamic_rope_update
|
| 35 |
+
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
|
| 36 |
+
from ...processing_utils import Unpack
|
| 37 |
+
from ...utils import TransformersKwargs, auto_docstring, can_return_tuple
|
| 38 |
+
from ...utils.generic import maybe_autocast, merge_with_config_defaults
|
| 39 |
+
from ...utils.output_capturing import capture_outputs
|
| 40 |
+
from .configuration_apertus import ApertusConfig
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
class ApertusMLP(nn.Module):
|
| 44 |
+
def __init__(self, config):
|
| 45 |
+
super().__init__()
|
| 46 |
+
self.config = config
|
| 47 |
+
self.hidden_size = config.hidden_size
|
| 48 |
+
self.intermediate_size = config.intermediate_size
|
| 49 |
+
self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
| 50 |
+
self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
|
| 51 |
+
self.act_fn = ACT2FN[config.hidden_act]
|
| 52 |
+
if config.hidden_act == "xielu":
|
| 53 |
+
self.act_fn = ACT2CLS["xielu"](dtype=config.dtype)
|
| 54 |
+
|
| 55 |
+
def forward(self, x):
|
| 56 |
+
return self.down_proj(self.act_fn(self.up_proj(x)))
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
@use_kernel_forward_from_hub("RMSNorm")
|
| 60 |
+
class ApertusRMSNorm(nn.Module):
|
| 61 |
+
def __init__(self, hidden_size, eps: float = 1e-6) -> None:
|
| 62 |
+
"""
|
| 63 |
+
ApertusRMSNorm is equivalent to T5LayerNorm
|
| 64 |
+
"""
|
| 65 |
+
super().__init__()
|
| 66 |
+
self.weight = nn.Parameter(torch.ones(hidden_size))
|
| 67 |
+
self.variance_epsilon = eps
|
| 68 |
+
|
| 69 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 70 |
+
input_dtype = hidden_states.dtype
|
| 71 |
+
hidden_states = hidden_states.to(torch.float32)
|
| 72 |
+
variance = hidden_states.pow(2).mean(-1, keepdim=True)
|
| 73 |
+
hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
|
| 74 |
+
return self.weight * hidden_states.to(input_dtype)
|
| 75 |
+
|
| 76 |
+
def extra_repr(self):
|
| 77 |
+
return f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}"
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
class ApertusRotaryEmbedding(nn.Module):
|
| 81 |
+
inv_freq: torch.Tensor # fix linting for `register_buffer`
|
| 82 |
+
|
| 83 |
+
def __init__(self, config: ApertusConfig, device=None):
|
| 84 |
+
super().__init__()
|
| 85 |
+
self.max_seq_len_cached = config.max_position_embeddings
|
| 86 |
+
self.original_max_seq_len = config.max_position_embeddings
|
| 87 |
+
|
| 88 |
+
self.config = config
|
| 89 |
+
|
| 90 |
+
self.rope_type = self.config.rope_parameters["rope_type"]
|
| 91 |
+
rope_init_fn: Callable = self.compute_default_rope_parameters
|
| 92 |
+
if self.rope_type != "default":
|
| 93 |
+
rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
|
| 94 |
+
inv_freq, self.attention_scaling = rope_init_fn(self.config, device)
|
| 95 |
+
|
| 96 |
+
self.register_buffer("inv_freq", inv_freq, persistent=False)
|
| 97 |
+
self.register_buffer("original_inv_freq", inv_freq.clone(), persistent=False)
|
| 98 |
+
|
| 99 |
+
@staticmethod
|
| 100 |
+
def compute_default_rope_parameters(
|
| 101 |
+
config: ApertusConfig | None = None,
|
| 102 |
+
device: Optional["torch.device"] = None,
|
| 103 |
+
seq_len: int | None = None,
|
| 104 |
+
) -> tuple["torch.Tensor", float]:
|
| 105 |
+
"""
|
| 106 |
+
Computes the inverse frequencies according to the original RoPE implementation
|
| 107 |
+
Args:
|
| 108 |
+
config ([`~transformers.PreTrainedConfig`]):
|
| 109 |
+
The model configuration.
|
| 110 |
+
device (`torch.device`):
|
| 111 |
+
The device to use for initialization of the inverse frequencies.
|
| 112 |
+
seq_len (`int`, *optional*):
|
| 113 |
+
The current sequence length. Unused for this type of RoPE.
|
| 114 |
+
Returns:
|
| 115 |
+
Tuple of (`torch.Tensor`, `float`), containing the inverse frequencies for the RoPE embeddings and the
|
| 116 |
+
post-processing scaling factor applied to the computed cos/sin (unused in this type of RoPE).
|
| 117 |
+
"""
|
| 118 |
+
base = config.rope_parameters["rope_theta"]
|
| 119 |
+
dim = getattr(config, "head_dim", None) or config.hidden_size // config.num_attention_heads
|
| 120 |
+
|
| 121 |
+
attention_factor = 1.0 # Unused in this type of RoPE
|
| 122 |
+
|
| 123 |
+
# Compute the inverse frequencies
|
| 124 |
+
inv_freq = 1.0 / (
|
| 125 |
+
base ** (torch.arange(0, dim, 2, dtype=torch.int64).to(device=device, dtype=torch.float) / dim)
|
| 126 |
+
)
|
| 127 |
+
return inv_freq, attention_factor
|
| 128 |
+
|
| 129 |
+
@torch.no_grad()
|
| 130 |
+
@dynamic_rope_update # power user: used with advanced RoPE types (e.g. dynamic rope)
|
| 131 |
+
def forward(self, x, position_ids):
|
| 132 |
+
inv_freq_expanded = self.inv_freq[None, :, None].float().expand(position_ids.shape[0], -1, 1).to(x.device)
|
| 133 |
+
position_ids_expanded = position_ids[:, None, :].float()
|
| 134 |
+
|
| 135 |
+
device_type = x.device.type if isinstance(x.device.type, str) and x.device.type != "mps" else "cpu"
|
| 136 |
+
with maybe_autocast(device_type=device_type, enabled=False): # Force float32
|
| 137 |
+
freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(1, 2)
|
| 138 |
+
emb = torch.cat((freqs, freqs), dim=-1)
|
| 139 |
+
cos = emb.cos() * self.attention_scaling
|
| 140 |
+
sin = emb.sin() * self.attention_scaling
|
| 141 |
+
|
| 142 |
+
return cos.to(dtype=x.dtype), sin.to(dtype=x.dtype)
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
def rotate_half(x):
|
| 146 |
+
"""Rotates half the hidden dims of the input."""
|
| 147 |
+
x1 = x[..., : x.shape[-1] // 2]
|
| 148 |
+
x2 = x[..., x.shape[-1] // 2 :]
|
| 149 |
+
return torch.cat((-x2, x1), dim=-1)
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
@use_kernel_func_from_hub("rotary_pos_emb")
|
| 153 |
+
def apply_rotary_pos_emb(q, k, cos, sin, unsqueeze_dim=1):
|
| 154 |
+
"""Applies Rotary Position Embedding to the query and key tensors.
|
| 155 |
+
|
| 156 |
+
Args:
|
| 157 |
+
q (`torch.Tensor`): The query tensor.
|
| 158 |
+
k (`torch.Tensor`): The key tensor.
|
| 159 |
+
cos (`torch.Tensor`): The cosine part of the rotary embedding.
|
| 160 |
+
sin (`torch.Tensor`): The sine part of the rotary embedding.
|
| 161 |
+
unsqueeze_dim (`int`, *optional*, defaults to 1):
|
| 162 |
+
The 'unsqueeze_dim' argument specifies the dimension along which to unsqueeze cos[position_ids] and
|
| 163 |
+
sin[position_ids] so that they can be properly broadcasted to the dimensions of q and k. For example, note
|
| 164 |
+
that cos[position_ids] and sin[position_ids] have the shape [batch_size, seq_len, head_dim]. Then, if q and
|
| 165 |
+
k have the shape [batch_size, heads, seq_len, head_dim], then setting unsqueeze_dim=1 makes
|
| 166 |
+
cos[position_ids] and sin[position_ids] broadcastable to the shapes of q and k. Similarly, if q and k have
|
| 167 |
+
the shape [batch_size, seq_len, heads, head_dim], then set unsqueeze_dim=2.
|
| 168 |
+
Returns:
|
| 169 |
+
`tuple(torch.Tensor)` comprising of the query and key tensors rotated using the Rotary Position Embedding.
|
| 170 |
+
"""
|
| 171 |
+
cos = cos.unsqueeze(unsqueeze_dim)
|
| 172 |
+
sin = sin.unsqueeze(unsqueeze_dim)
|
| 173 |
+
q_embed = (q * cos) + (rotate_half(q) * sin)
|
| 174 |
+
k_embed = (k * cos) + (rotate_half(k) * sin)
|
| 175 |
+
return q_embed, k_embed
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
|
| 179 |
+
"""
|
| 180 |
+
This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
|
| 181 |
+
num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
|
| 182 |
+
"""
|
| 183 |
+
batch, num_key_value_heads, slen, head_dim = hidden_states.shape
|
| 184 |
+
if n_rep == 1:
|
| 185 |
+
return hidden_states
|
| 186 |
+
hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
|
| 187 |
+
return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
|
| 188 |
+
|
| 189 |
+
|
| 190 |
+
def eager_attention_forward(
|
| 191 |
+
module: nn.Module,
|
| 192 |
+
query: torch.Tensor,
|
| 193 |
+
key: torch.Tensor,
|
| 194 |
+
value: torch.Tensor,
|
| 195 |
+
attention_mask: torch.Tensor | None,
|
| 196 |
+
scaling: float,
|
| 197 |
+
dropout: float = 0.0,
|
| 198 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 199 |
+
):
|
| 200 |
+
key_states = repeat_kv(key, module.num_key_value_groups)
|
| 201 |
+
value_states = repeat_kv(value, module.num_key_value_groups)
|
| 202 |
+
|
| 203 |
+
attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
|
| 204 |
+
if attention_mask is not None:
|
| 205 |
+
attn_weights = attn_weights + attention_mask
|
| 206 |
+
|
| 207 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
|
| 208 |
+
attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
|
| 209 |
+
attn_output = torch.matmul(attn_weights, value_states)
|
| 210 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 211 |
+
|
| 212 |
+
return attn_output, attn_weights
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
@use_kernelized_func(apply_rotary_pos_emb)
|
| 216 |
+
class ApertusAttention(nn.Module):
|
| 217 |
+
"""Multi-headed attention from 'Attention Is All You Need' paper"""
|
| 218 |
+
|
| 219 |
+
def __init__(self, config: ApertusConfig, layer_idx: int | None = None):
|
| 220 |
+
super().__init__()
|
| 221 |
+
self.config = config
|
| 222 |
+
self.layer_idx = layer_idx
|
| 223 |
+
self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
|
| 224 |
+
self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
|
| 225 |
+
self.scaling = self.head_dim**-0.5
|
| 226 |
+
self.attention_dropout = config.attention_dropout
|
| 227 |
+
self.is_causal = True
|
| 228 |
+
|
| 229 |
+
self.q_proj = nn.Linear(
|
| 230 |
+
config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.attention_bias
|
| 231 |
+
)
|
| 232 |
+
self.k_proj = nn.Linear(
|
| 233 |
+
config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
|
| 234 |
+
)
|
| 235 |
+
self.v_proj = nn.Linear(
|
| 236 |
+
config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
|
| 237 |
+
)
|
| 238 |
+
self.o_proj = nn.Linear(
|
| 239 |
+
config.num_attention_heads * self.head_dim, config.hidden_size, bias=config.attention_bias
|
| 240 |
+
)
|
| 241 |
+
self.q_norm = ApertusRMSNorm(self.head_dim, config.rms_norm_eps)
|
| 242 |
+
self.k_norm = ApertusRMSNorm(self.head_dim, config.rms_norm_eps)
|
| 243 |
+
|
| 244 |
+
def forward(
|
| 245 |
+
self,
|
| 246 |
+
hidden_states: torch.Tensor,
|
| 247 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
| 248 |
+
attention_mask: torch.Tensor | None,
|
| 249 |
+
past_key_values: Cache | None = None,
|
| 250 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 251 |
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
| 252 |
+
input_shape = hidden_states.shape[:-1]
|
| 253 |
+
hidden_shape = (*input_shape, -1, self.head_dim)
|
| 254 |
+
|
| 255 |
+
query_states = self.q_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 256 |
+
key_states = self.k_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 257 |
+
value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 258 |
+
query_states = self.q_norm(query_states)
|
| 259 |
+
key_states = self.k_norm(key_states)
|
| 260 |
+
|
| 261 |
+
cos, sin = position_embeddings
|
| 262 |
+
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
|
| 263 |
+
|
| 264 |
+
if past_key_values is not None:
|
| 265 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
| 266 |
+
|
| 267 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 268 |
+
self.config._attn_implementation, eager_attention_forward
|
| 269 |
+
)
|
| 270 |
+
|
| 271 |
+
attn_output, attn_weights = attention_interface(
|
| 272 |
+
self,
|
| 273 |
+
query_states,
|
| 274 |
+
key_states,
|
| 275 |
+
value_states,
|
| 276 |
+
attention_mask,
|
| 277 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 278 |
+
scaling=self.scaling,
|
| 279 |
+
**kwargs,
|
| 280 |
+
)
|
| 281 |
+
|
| 282 |
+
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
| 283 |
+
attn_output = self.o_proj(attn_output)
|
| 284 |
+
return attn_output, attn_weights
|
| 285 |
+
|
| 286 |
+
|
| 287 |
+
class ApertusDecoderLayer(GradientCheckpointingLayer):
|
| 288 |
+
def __init__(self, config: ApertusConfig, layer_idx: int):
|
| 289 |
+
super().__init__()
|
| 290 |
+
self.hidden_size = config.hidden_size
|
| 291 |
+
|
| 292 |
+
self.self_attn = ApertusAttention(config=config, layer_idx=layer_idx)
|
| 293 |
+
|
| 294 |
+
self.mlp = ApertusMLP(config)
|
| 295 |
+
self.attention_layernorm = ApertusRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 296 |
+
self.feedforward_layernorm = ApertusRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 297 |
+
|
| 298 |
+
def forward(
|
| 299 |
+
self,
|
| 300 |
+
hidden_states: torch.Tensor,
|
| 301 |
+
attention_mask: torch.Tensor | None = None,
|
| 302 |
+
position_ids: torch.LongTensor | None = None,
|
| 303 |
+
past_key_values: Cache | None = None,
|
| 304 |
+
use_cache: bool | None = False,
|
| 305 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
|
| 306 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 307 |
+
) -> torch.Tensor:
|
| 308 |
+
residual = hidden_states
|
| 309 |
+
hidden_states = self.attention_layernorm(hidden_states)
|
| 310 |
+
hidden_states, _ = self.self_attn(
|
| 311 |
+
hidden_states=hidden_states,
|
| 312 |
+
attention_mask=attention_mask,
|
| 313 |
+
position_ids=position_ids,
|
| 314 |
+
past_key_values=past_key_values,
|
| 315 |
+
use_cache=use_cache,
|
| 316 |
+
position_embeddings=position_embeddings,
|
| 317 |
+
**kwargs,
|
| 318 |
+
)
|
| 319 |
+
hidden_states = residual + hidden_states
|
| 320 |
+
|
| 321 |
+
# Fully Connected
|
| 322 |
+
residual = hidden_states
|
| 323 |
+
hidden_states = self.feedforward_layernorm(hidden_states)
|
| 324 |
+
hidden_states = self.mlp(hidden_states)
|
| 325 |
+
hidden_states = residual + hidden_states
|
| 326 |
+
return hidden_states
|
| 327 |
+
|
| 328 |
+
|
| 329 |
+
@auto_docstring
|
| 330 |
+
class ApertusPreTrainedModel(PreTrainedModel):
|
| 331 |
+
config: ApertusConfig
|
| 332 |
+
base_model_prefix = "model"
|
| 333 |
+
supports_gradient_checkpointing = True
|
| 334 |
+
_no_split_modules = ["ApertusDecoderLayer"]
|
| 335 |
+
_skip_keys_device_placement = ["past_key_values"]
|
| 336 |
+
_supports_flash_attn = True
|
| 337 |
+
_supports_sdpa = True
|
| 338 |
+
_supports_flex_attn = True
|
| 339 |
+
|
| 340 |
+
_can_compile_fullgraph = True
|
| 341 |
+
_supports_attention_backend = True
|
| 342 |
+
_can_record_outputs = {
|
| 343 |
+
"hidden_states": ApertusDecoderLayer,
|
| 344 |
+
"attentions": ApertusAttention,
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
@auto_docstring
|
| 349 |
+
class ApertusModel(ApertusPreTrainedModel):
|
| 350 |
+
def __init__(self, config: ApertusConfig):
|
| 351 |
+
super().__init__(config)
|
| 352 |
+
self.padding_idx = config.pad_token_id
|
| 353 |
+
self.vocab_size = config.vocab_size
|
| 354 |
+
|
| 355 |
+
self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
|
| 356 |
+
self.layers = nn.ModuleList(
|
| 357 |
+
[ApertusDecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
|
| 358 |
+
)
|
| 359 |
+
self.norm = ApertusRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 360 |
+
self.rotary_emb = ApertusRotaryEmbedding(config=config)
|
| 361 |
+
self.gradient_checkpointing = False
|
| 362 |
+
|
| 363 |
+
# Initialize weights and apply final processing
|
| 364 |
+
self.post_init()
|
| 365 |
+
|
| 366 |
+
@merge_with_config_defaults
|
| 367 |
+
@capture_outputs
|
| 368 |
+
@auto_docstring
|
| 369 |
+
def forward(
|
| 370 |
+
self,
|
| 371 |
+
input_ids: torch.LongTensor | None = None,
|
| 372 |
+
attention_mask: torch.Tensor | None = None,
|
| 373 |
+
position_ids: torch.LongTensor | None = None,
|
| 374 |
+
past_key_values: Cache | None = None,
|
| 375 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 376 |
+
use_cache: bool | None = None,
|
| 377 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 378 |
+
) -> BaseModelOutputWithPast:
|
| 379 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 380 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 381 |
+
|
| 382 |
+
if inputs_embeds is None:
|
| 383 |
+
inputs_embeds: torch.Tensor = self.embed_tokens(input_ids)
|
| 384 |
+
|
| 385 |
+
if use_cache and past_key_values is None:
|
| 386 |
+
past_key_values = DynamicCache(config=self.config)
|
| 387 |
+
|
| 388 |
+
if position_ids is None:
|
| 389 |
+
past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
|
| 390 |
+
position_ids = torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device) + past_seen_tokens
|
| 391 |
+
position_ids = position_ids.unsqueeze(0)
|
| 392 |
+
|
| 393 |
+
causal_mask = create_causal_mask(
|
| 394 |
+
config=self.config,
|
| 395 |
+
inputs_embeds=inputs_embeds,
|
| 396 |
+
attention_mask=attention_mask,
|
| 397 |
+
past_key_values=past_key_values,
|
| 398 |
+
position_ids=position_ids,
|
| 399 |
+
)
|
| 400 |
+
|
| 401 |
+
hidden_states = inputs_embeds
|
| 402 |
+
position_embeddings = self.rotary_emb(hidden_states, position_ids=position_ids)
|
| 403 |
+
|
| 404 |
+
for decoder_layer in self.layers[: self.config.num_hidden_layers]:
|
| 405 |
+
hidden_states = decoder_layer(
|
| 406 |
+
hidden_states,
|
| 407 |
+
attention_mask=causal_mask,
|
| 408 |
+
position_embeddings=position_embeddings,
|
| 409 |
+
position_ids=position_ids,
|
| 410 |
+
past_key_values=past_key_values,
|
| 411 |
+
use_cache=use_cache,
|
| 412 |
+
**kwargs,
|
| 413 |
+
)
|
| 414 |
+
|
| 415 |
+
hidden_states = self.norm(hidden_states)
|
| 416 |
+
return BaseModelOutputWithPast(
|
| 417 |
+
last_hidden_state=hidden_states,
|
| 418 |
+
past_key_values=past_key_values,
|
| 419 |
+
)
|
| 420 |
+
|
| 421 |
+
|
| 422 |
+
@auto_docstring
|
| 423 |
+
class ApertusForCausalLM(ApertusPreTrainedModel, GenerationMixin):
|
| 424 |
+
_tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
|
| 425 |
+
_tp_plan = {"lm_head": "colwise_gather_output"}
|
| 426 |
+
_pp_plan = {"lm_head": (["hidden_states"], ["logits"])}
|
| 427 |
+
|
| 428 |
+
def __init__(self, config):
|
| 429 |
+
super().__init__(config)
|
| 430 |
+
self.model = ApertusModel(config)
|
| 431 |
+
self.vocab_size = config.vocab_size
|
| 432 |
+
self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
|
| 433 |
+
|
| 434 |
+
# Initialize weights and apply final processing
|
| 435 |
+
self.post_init()
|
| 436 |
+
|
| 437 |
+
@can_return_tuple
|
| 438 |
+
@auto_docstring
|
| 439 |
+
def forward(
|
| 440 |
+
self,
|
| 441 |
+
input_ids: torch.LongTensor | None = None,
|
| 442 |
+
attention_mask: torch.Tensor | None = None,
|
| 443 |
+
position_ids: torch.LongTensor | None = None,
|
| 444 |
+
past_key_values: Cache | None = None,
|
| 445 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 446 |
+
labels: torch.LongTensor | None = None,
|
| 447 |
+
use_cache: bool | None = None,
|
| 448 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 449 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 450 |
+
) -> CausalLMOutputWithPast:
|
| 451 |
+
r"""
|
| 452 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 453 |
+
Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
|
| 454 |
+
config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
|
| 455 |
+
(masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
|
| 456 |
+
|
| 457 |
+
Example:
|
| 458 |
+
|
| 459 |
+
```python
|
| 460 |
+
>>> from transformers import AutoTokenizer, ApertusForCausalLM
|
| 461 |
+
|
| 462 |
+
>>> model = ApertusForCausalLM.from_pretrained("swiss-ai/Apertus-8B-Instruct-2509")
|
| 463 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("swiss-ai/Apertus-8B-Instruct-2509")
|
| 464 |
+
|
| 465 |
+
>>> prompt = "Hey, are you conscious? Can you talk to me?"
|
| 466 |
+
>>> inputs = tokenizer(prompt, return_tensors="pt")
|
| 467 |
+
|
| 468 |
+
>>> # Generate
|
| 469 |
+
>>> generate_ids = model.generate(inputs.input_ids, max_length=30)
|
| 470 |
+
>>> tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
|
| 471 |
+
"Hey, are you conscious? Can you talk to me?\nI'm not conscious, but I can talk to you."
|
| 472 |
+
```"""
|
| 473 |
+
outputs: BaseModelOutputWithPast = self.model(
|
| 474 |
+
input_ids=input_ids,
|
| 475 |
+
attention_mask=attention_mask,
|
| 476 |
+
position_ids=position_ids,
|
| 477 |
+
past_key_values=past_key_values,
|
| 478 |
+
inputs_embeds=inputs_embeds,
|
| 479 |
+
use_cache=use_cache,
|
| 480 |
+
**kwargs,
|
| 481 |
+
)
|
| 482 |
+
|
| 483 |
+
hidden_states = outputs.last_hidden_state
|
| 484 |
+
# Only compute necessary logits, and do not upcast them to float if we are not computing the loss
|
| 485 |
+
slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
|
| 486 |
+
logits = self.lm_head(hidden_states[:, slice_indices, :])
|
| 487 |
+
|
| 488 |
+
loss = None
|
| 489 |
+
if labels is not None:
|
| 490 |
+
loss = self.loss_function(logits=logits, labels=labels, vocab_size=self.config.vocab_size, **kwargs)
|
| 491 |
+
|
| 492 |
+
return CausalLMOutputWithPast(
|
| 493 |
+
loss=loss,
|
| 494 |
+
logits=logits,
|
| 495 |
+
past_key_values=outputs.past_key_values,
|
| 496 |
+
hidden_states=outputs.hidden_states,
|
| 497 |
+
attentions=outputs.attentions,
|
| 498 |
+
)
|
| 499 |
+
|
| 500 |
+
|
| 501 |
+
class ApertusForTokenClassification(GenericForTokenClassification, ApertusPreTrainedModel):
|
| 502 |
+
pass
|
| 503 |
+
|
| 504 |
+
|
| 505 |
+
__all__ = ["ApertusModel", "ApertusForCausalLM", "ApertusForTokenClassification", "ApertusPreTrainedModel"]
|
third_party/transformers/src/transformers/models/apertus/modular_apertus.py
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 the HuggingFace Inc. team and the Swiss AI Initiative. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
#
|
| 4 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 5 |
+
# you may not use this file except in compliance with the License.
|
| 6 |
+
# You may obtain a copy of the License at
|
| 7 |
+
#
|
| 8 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 9 |
+
#
|
| 10 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 11 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 12 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 13 |
+
# See the License for the specific language governing permissions and
|
| 14 |
+
# limitations under the License.
|
| 15 |
+
from collections.abc import Callable
|
| 16 |
+
|
| 17 |
+
import torch
|
| 18 |
+
from huggingface_hub.dataclasses import strict
|
| 19 |
+
from torch import nn
|
| 20 |
+
|
| 21 |
+
from ...activations import ACT2CLS
|
| 22 |
+
from ...cache_utils import Cache
|
| 23 |
+
from ...configuration_utils import PreTrainedConfig
|
| 24 |
+
from ...modeling_rope_utils import RopeParameters
|
| 25 |
+
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS
|
| 26 |
+
from ...processing_utils import Unpack
|
| 27 |
+
from ...utils import TransformersKwargs, auto_docstring, logging
|
| 28 |
+
from ..llama.modeling_llama import (
|
| 29 |
+
LlamaAttention,
|
| 30 |
+
LlamaDecoderLayer,
|
| 31 |
+
LlamaForCausalLM,
|
| 32 |
+
LlamaForTokenClassification,
|
| 33 |
+
LlamaModel,
|
| 34 |
+
LlamaPreTrainedModel,
|
| 35 |
+
LlamaRMSNorm,
|
| 36 |
+
LlamaRotaryEmbedding,
|
| 37 |
+
apply_rotary_pos_emb,
|
| 38 |
+
eager_attention_forward,
|
| 39 |
+
)
|
| 40 |
+
from ..nemotron.modeling_nemotron import NemotronMLP
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
logger = logging.get_logger(__name__)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
@auto_docstring(checkpoint="swiss-ai/Apertus-8B-Instruct-2509")
|
| 47 |
+
@strict
|
| 48 |
+
class ApertusConfig(PreTrainedConfig):
|
| 49 |
+
r"""
|
| 50 |
+
```python
|
| 51 |
+
>>> from transformers import ApertusModel, ApertusConfig
|
| 52 |
+
|
| 53 |
+
>>> # Initializing a Apertus-8B style configuration
|
| 54 |
+
>>> configuration = ApertusConfig()
|
| 55 |
+
|
| 56 |
+
>>> # Initializing a model from the Apertus-8B style configuration
|
| 57 |
+
>>> model = ApertusModel(configuration)
|
| 58 |
+
|
| 59 |
+
>>> # Accessing the model configuration
|
| 60 |
+
>>> configuration = model.config
|
| 61 |
+
```"""
|
| 62 |
+
|
| 63 |
+
model_type = "apertus"
|
| 64 |
+
keys_to_ignore_at_inference = ["past_key_values"]
|
| 65 |
+
default_theta = 12000000.0
|
| 66 |
+
base_model_tp_plan = {
|
| 67 |
+
"layers.*.self_attn.q_proj": "colwise",
|
| 68 |
+
"layers.*.self_attn.k_proj": "colwise",
|
| 69 |
+
"layers.*.self_attn.v_proj": "colwise",
|
| 70 |
+
"layers.*.self_attn.q_norm": "replicated_with_grad_allreduce",
|
| 71 |
+
"layers.*.self_attn.k_norm": "replicated_with_grad_allreduce",
|
| 72 |
+
"layers.*.self_attn.o_proj": "rowwise",
|
| 73 |
+
"layers.*.mlp.up_proj": "colwise",
|
| 74 |
+
"layers.*.mlp.down_proj": "rowwise",
|
| 75 |
+
}
|
| 76 |
+
base_model_pp_plan = {
|
| 77 |
+
"embed_tokens": (["input_ids"], ["inputs_embeds"]),
|
| 78 |
+
"layers": (["hidden_states", "attention_mask"], ["hidden_states"]),
|
| 79 |
+
"norm": (["hidden_states"], ["hidden_states"]),
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
vocab_size: int = 131072
|
| 83 |
+
hidden_size: int = 4096
|
| 84 |
+
intermediate_size: int = 14336
|
| 85 |
+
num_hidden_layers: int = 32
|
| 86 |
+
num_attention_heads: int = 32
|
| 87 |
+
num_key_value_heads: int | None = None
|
| 88 |
+
hidden_act: str = "xielu"
|
| 89 |
+
max_position_embeddings: int = 65536
|
| 90 |
+
initializer_range: float = 0.02
|
| 91 |
+
rms_norm_eps: float = 1e-5
|
| 92 |
+
use_cache: bool = True
|
| 93 |
+
pad_token_id: int | None = 3
|
| 94 |
+
bos_token_id: int | None = 1
|
| 95 |
+
eos_token_id: int | list[int] | None = 2
|
| 96 |
+
tie_word_embeddings: bool = False
|
| 97 |
+
rope_parameters: RopeParameters | dict | None = None
|
| 98 |
+
attention_bias: bool = False
|
| 99 |
+
attention_dropout: float | int = 0.0
|
| 100 |
+
|
| 101 |
+
def __post_init__(self, **kwargs):
|
| 102 |
+
if self.num_key_value_heads is None:
|
| 103 |
+
self.num_key_value_heads = self.num_attention_heads
|
| 104 |
+
|
| 105 |
+
if self.rope_parameters is None:
|
| 106 |
+
self.rope_parameters = {
|
| 107 |
+
"rope_type": "llama3",
|
| 108 |
+
"rope_theta": 12000000.0,
|
| 109 |
+
"factor": 8.0,
|
| 110 |
+
"original_max_position_embeddings": 8192,
|
| 111 |
+
"low_freq_factor": 1.0,
|
| 112 |
+
"high_freq_factor": 4.0,
|
| 113 |
+
}
|
| 114 |
+
super().__post_init__(**kwargs)
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
class ApertusMLP(NemotronMLP):
|
| 118 |
+
def __init__(self, config):
|
| 119 |
+
super().__init__(config)
|
| 120 |
+
self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
| 121 |
+
self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
|
| 122 |
+
if config.hidden_act == "xielu":
|
| 123 |
+
self.act_fn = ACT2CLS["xielu"](dtype=config.dtype)
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
class ApertusRMSNorm(LlamaRMSNorm):
|
| 127 |
+
pass
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
class ApertusRotaryEmbedding(LlamaRotaryEmbedding):
|
| 131 |
+
pass
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
class ApertusAttention(LlamaAttention):
|
| 135 |
+
def __init__(self, config: ApertusConfig, layer_idx: int | None = None):
|
| 136 |
+
super().__init__(config, layer_idx)
|
| 137 |
+
self.q_norm = ApertusRMSNorm(self.head_dim, config.rms_norm_eps)
|
| 138 |
+
self.k_norm = ApertusRMSNorm(self.head_dim, config.rms_norm_eps)
|
| 139 |
+
|
| 140 |
+
def forward(
|
| 141 |
+
self,
|
| 142 |
+
hidden_states: torch.Tensor,
|
| 143 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
| 144 |
+
attention_mask: torch.Tensor | None,
|
| 145 |
+
past_key_values: Cache | None = None,
|
| 146 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 147 |
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
| 148 |
+
input_shape = hidden_states.shape[:-1]
|
| 149 |
+
hidden_shape = (*input_shape, -1, self.head_dim)
|
| 150 |
+
|
| 151 |
+
query_states = self.q_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 152 |
+
key_states = self.k_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 153 |
+
value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 154 |
+
query_states = self.q_norm(query_states)
|
| 155 |
+
key_states = self.k_norm(key_states)
|
| 156 |
+
|
| 157 |
+
cos, sin = position_embeddings
|
| 158 |
+
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
|
| 159 |
+
|
| 160 |
+
if past_key_values is not None:
|
| 161 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
| 162 |
+
|
| 163 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 164 |
+
self.config._attn_implementation, eager_attention_forward
|
| 165 |
+
)
|
| 166 |
+
|
| 167 |
+
attn_output, attn_weights = attention_interface(
|
| 168 |
+
self,
|
| 169 |
+
query_states,
|
| 170 |
+
key_states,
|
| 171 |
+
value_states,
|
| 172 |
+
attention_mask,
|
| 173 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 174 |
+
scaling=self.scaling,
|
| 175 |
+
**kwargs,
|
| 176 |
+
)
|
| 177 |
+
|
| 178 |
+
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
| 179 |
+
attn_output = self.o_proj(attn_output)
|
| 180 |
+
return attn_output, attn_weights
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
class ApertusDecoderLayer(LlamaDecoderLayer):
|
| 184 |
+
def __init__(self, config: ApertusConfig, layer_idx: int):
|
| 185 |
+
super().__init__(config, layer_idx)
|
| 186 |
+
self.attention_layernorm = ApertusRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 187 |
+
self.feedforward_layernorm = ApertusRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 188 |
+
|
| 189 |
+
del self.input_layernorm
|
| 190 |
+
del self.post_attention_layernorm
|
| 191 |
+
|
| 192 |
+
def forward(
|
| 193 |
+
self,
|
| 194 |
+
hidden_states: torch.Tensor,
|
| 195 |
+
attention_mask: torch.Tensor | None = None,
|
| 196 |
+
position_ids: torch.LongTensor | None = None,
|
| 197 |
+
past_key_values: Cache | None = None,
|
| 198 |
+
use_cache: bool | None = False,
|
| 199 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
|
| 200 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 201 |
+
) -> torch.Tensor:
|
| 202 |
+
residual = hidden_states
|
| 203 |
+
hidden_states = self.attention_layernorm(hidden_states)
|
| 204 |
+
hidden_states, _ = self.self_attn(
|
| 205 |
+
hidden_states=hidden_states,
|
| 206 |
+
attention_mask=attention_mask,
|
| 207 |
+
position_ids=position_ids,
|
| 208 |
+
past_key_values=past_key_values,
|
| 209 |
+
use_cache=use_cache,
|
| 210 |
+
position_embeddings=position_embeddings,
|
| 211 |
+
**kwargs,
|
| 212 |
+
)
|
| 213 |
+
hidden_states = residual + hidden_states
|
| 214 |
+
|
| 215 |
+
# Fully Connected
|
| 216 |
+
residual = hidden_states
|
| 217 |
+
hidden_states = self.feedforward_layernorm(hidden_states)
|
| 218 |
+
hidden_states = self.mlp(hidden_states)
|
| 219 |
+
hidden_states = residual + hidden_states
|
| 220 |
+
return hidden_states
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
class ApertusPreTrainedModel(LlamaPreTrainedModel):
|
| 224 |
+
pass
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
class ApertusModel(LlamaModel):
|
| 228 |
+
pass
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
class ApertusForCausalLM(LlamaForCausalLM):
|
| 232 |
+
def forward(self, **super_kwargs):
|
| 233 |
+
r"""
|
| 234 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 235 |
+
Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
|
| 236 |
+
config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
|
| 237 |
+
(masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
|
| 238 |
+
|
| 239 |
+
Example:
|
| 240 |
+
|
| 241 |
+
```python
|
| 242 |
+
>>> from transformers import AutoTokenizer, ApertusForCausalLM
|
| 243 |
+
|
| 244 |
+
>>> model = ApertusForCausalLM.from_pretrained("swiss-ai/Apertus-8B-Instruct-2509")
|
| 245 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("swiss-ai/Apertus-8B-Instruct-2509")
|
| 246 |
+
|
| 247 |
+
>>> prompt = "Hey, are you conscious? Can you talk to me?"
|
| 248 |
+
>>> inputs = tokenizer(prompt, return_tensors="pt")
|
| 249 |
+
|
| 250 |
+
>>> # Generate
|
| 251 |
+
>>> generate_ids = model.generate(inputs.input_ids, max_length=30)
|
| 252 |
+
>>> tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
|
| 253 |
+
"Hey, are you conscious? Can you talk to me?\nI'm not conscious, but I can talk to you."
|
| 254 |
+
```"""
|
| 255 |
+
return super().forward(**super_kwargs)
|
| 256 |
+
|
| 257 |
+
|
| 258 |
+
class ApertusForTokenClassification(LlamaForTokenClassification):
|
| 259 |
+
pass
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
__all__ = [
|
| 263 |
+
"ApertusConfig",
|
| 264 |
+
"ApertusModel",
|
| 265 |
+
"ApertusForCausalLM",
|
| 266 |
+
"ApertusForTokenClassification",
|
| 267 |
+
"ApertusPreTrainedModel",
|
| 268 |
+
]
|
third_party/transformers/src/transformers/models/arcee/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 Arcee AI and the HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .configuration_arcee import *
|
| 22 |
+
from .modeling_arcee import *
|
| 23 |
+
else:
|
| 24 |
+
import sys
|
| 25 |
+
|
| 26 |
+
_file = globals()["__file__"]
|
| 27 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/arcee/configuration_arcee.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/arcee/modular_arcee.py.
|
| 3 |
+
# Do NOT edit this file manually as any edits will be overwritten by the generation of
|
| 4 |
+
# the file from the modular. If any change should be done, please apply the change to the
|
| 5 |
+
# modular_arcee.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2025 Arcee AI and the HuggingFace Inc. team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
|
| 21 |
+
from huggingface_hub.dataclasses import strict
|
| 22 |
+
|
| 23 |
+
from transformers.utils import auto_docstring
|
| 24 |
+
|
| 25 |
+
from ...configuration_utils import PreTrainedConfig
|
| 26 |
+
from ...modeling_rope_utils import RopeParameters
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
@auto_docstring(checkpoint="arcee-ai/AFM-4.5B")
|
| 30 |
+
@strict
|
| 31 |
+
class ArceeConfig(PreTrainedConfig):
|
| 32 |
+
r"""
|
| 33 |
+
```python
|
| 34 |
+
>>> from transformers import ArceeModel, ArceeConfig
|
| 35 |
+
|
| 36 |
+
>>> # Initializing an Arcee AFM-4.5B-Base style configuration
|
| 37 |
+
>>> configuration = ArceeConfig()
|
| 38 |
+
|
| 39 |
+
>>> # Initializing a model from the AFM-4.5B-Base style configuration
|
| 40 |
+
>>> model = ArceeModel(configuration)
|
| 41 |
+
|
| 42 |
+
>>> # Accessing the model configuration
|
| 43 |
+
>>> configuration = model.config
|
| 44 |
+
```"""
|
| 45 |
+
|
| 46 |
+
model_type = "arcee"
|
| 47 |
+
keys_to_ignore_at_inference = ["past_key_values"]
|
| 48 |
+
base_model_tp_plan = {
|
| 49 |
+
"layers.*.self_attn.q_proj": "colwise",
|
| 50 |
+
"layers.*.self_attn.k_proj": "colwise",
|
| 51 |
+
"layers.*.self_attn.v_proj": "colwise",
|
| 52 |
+
"layers.*.self_attn.o_proj": "rowwise",
|
| 53 |
+
"layers.*.mlp.up_proj": "colwise",
|
| 54 |
+
"layers.*.mlp.down_proj": "rowwise",
|
| 55 |
+
}
|
| 56 |
+
base_model_pp_plan = {
|
| 57 |
+
"embed_tokens": (["input_ids"], ["inputs_embeds"]),
|
| 58 |
+
"layers": (["hidden_states", "attention_mask"], ["hidden_states"]),
|
| 59 |
+
"norm": (["hidden_states"], ["hidden_states"]),
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
vocab_size: int = 32000
|
| 63 |
+
hidden_size: int = 2560
|
| 64 |
+
intermediate_size: int = 18432
|
| 65 |
+
num_hidden_layers: int = 32
|
| 66 |
+
num_attention_heads: int = 32
|
| 67 |
+
num_key_value_heads: int | None = None
|
| 68 |
+
hidden_act: str = "relu2"
|
| 69 |
+
max_position_embeddings: int = 4096
|
| 70 |
+
initializer_range: float = 0.02
|
| 71 |
+
rms_norm_eps: float = 1e-5
|
| 72 |
+
use_cache: bool = True
|
| 73 |
+
pad_token_id: int | None = None
|
| 74 |
+
bos_token_id: int | None = 128000
|
| 75 |
+
eos_token_id: int | list[int] | None = 128001
|
| 76 |
+
tie_word_embeddings: bool = False
|
| 77 |
+
rope_parameters: RopeParameters | dict | None = None
|
| 78 |
+
attention_bias: bool = False
|
| 79 |
+
attention_dropout: float | int = 0.0
|
| 80 |
+
mlp_bias: bool = False
|
| 81 |
+
head_dim: int | None = None
|
| 82 |
+
|
| 83 |
+
def __post_init__(self, **kwargs):
|
| 84 |
+
if self.head_dim is None:
|
| 85 |
+
self.head_dim = self.hidden_size // self.num_attention_heads
|
| 86 |
+
if self.num_key_value_heads is None:
|
| 87 |
+
self.num_key_value_heads = self.num_attention_heads
|
| 88 |
+
|
| 89 |
+
super().__post_init__(**kwargs)
|
| 90 |
+
|
| 91 |
+
def validate_architecture(self):
|
| 92 |
+
"""Part of `@strict`-powered validation. Validates the architecture of the config."""
|
| 93 |
+
if self.hidden_size % self.num_attention_heads != 0:
|
| 94 |
+
raise ValueError(
|
| 95 |
+
f"The hidden size ({self.hidden_size}) is not a multiple of the number of attention "
|
| 96 |
+
f"heads ({self.num_attention_heads})."
|
| 97 |
+
)
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
__all__ = ["ArceeConfig"]
|
third_party/transformers/src/transformers/models/arcee/modeling_arcee.py
ADDED
|
@@ -0,0 +1,520 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/arcee/modular_arcee.py.
|
| 3 |
+
# Do NOT edit this file manually as any edits will be overwritten by the generation of
|
| 4 |
+
# the file from the modular. If any change should be done, please apply the change to the
|
| 5 |
+
# modular_arcee.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2025 Arcee AI and the HuggingFace Inc. team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
|
| 21 |
+
from collections.abc import Callable
|
| 22 |
+
from typing import Optional
|
| 23 |
+
|
| 24 |
+
import torch
|
| 25 |
+
from torch import nn
|
| 26 |
+
|
| 27 |
+
from transformers.utils import auto_docstring
|
| 28 |
+
|
| 29 |
+
from ...activations import ACT2FN
|
| 30 |
+
from ...cache_utils import Cache, DynamicCache
|
| 31 |
+
from ...generation import GenerationMixin
|
| 32 |
+
from ...integrations import use_kernel_forward_from_hub, use_kernel_func_from_hub, use_kernelized_func
|
| 33 |
+
from ...masking_utils import create_causal_mask
|
| 34 |
+
from ...modeling_layers import (
|
| 35 |
+
GenericForQuestionAnswering,
|
| 36 |
+
GenericForSequenceClassification,
|
| 37 |
+
GenericForTokenClassification,
|
| 38 |
+
GradientCheckpointingLayer,
|
| 39 |
+
)
|
| 40 |
+
from ...modeling_outputs import BaseModelOutputWithPast, CausalLMOutputWithPast
|
| 41 |
+
from ...modeling_rope_utils import ROPE_INIT_FUNCTIONS, dynamic_rope_update
|
| 42 |
+
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
|
| 43 |
+
from ...processing_utils import Unpack
|
| 44 |
+
from ...utils import TransformersKwargs, can_return_tuple
|
| 45 |
+
from ...utils.generic import maybe_autocast, merge_with_config_defaults
|
| 46 |
+
from ...utils.output_capturing import capture_outputs
|
| 47 |
+
from .configuration_arcee import ArceeConfig
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
class ArceeMLP(nn.Module):
|
| 51 |
+
def __init__(self, config):
|
| 52 |
+
super().__init__()
|
| 53 |
+
self.config = config
|
| 54 |
+
self.hidden_size = config.hidden_size
|
| 55 |
+
self.intermediate_size = config.intermediate_size
|
| 56 |
+
self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=config.mlp_bias)
|
| 57 |
+
self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=config.mlp_bias)
|
| 58 |
+
self.act_fn = ACT2FN[config.hidden_act]
|
| 59 |
+
|
| 60 |
+
def forward(self, x):
|
| 61 |
+
return self.down_proj(self.act_fn(self.up_proj(x)))
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
@use_kernel_forward_from_hub("RMSNorm")
|
| 65 |
+
class ArceeRMSNorm(nn.Module):
|
| 66 |
+
def __init__(self, hidden_size, eps: float = 1e-6) -> None:
|
| 67 |
+
"""
|
| 68 |
+
ArceeRMSNorm is equivalent to T5LayerNorm
|
| 69 |
+
"""
|
| 70 |
+
super().__init__()
|
| 71 |
+
self.weight = nn.Parameter(torch.ones(hidden_size))
|
| 72 |
+
self.variance_epsilon = eps
|
| 73 |
+
|
| 74 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 75 |
+
input_dtype = hidden_states.dtype
|
| 76 |
+
hidden_states = hidden_states.to(torch.float32)
|
| 77 |
+
variance = hidden_states.pow(2).mean(-1, keepdim=True)
|
| 78 |
+
hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
|
| 79 |
+
return self.weight * hidden_states.to(input_dtype)
|
| 80 |
+
|
| 81 |
+
def extra_repr(self):
|
| 82 |
+
return f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}"
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
class ArceeRotaryEmbedding(nn.Module):
|
| 86 |
+
inv_freq: torch.Tensor # fix linting for `register_buffer`
|
| 87 |
+
|
| 88 |
+
def __init__(self, config: ArceeConfig, device=None):
|
| 89 |
+
super().__init__()
|
| 90 |
+
self.max_seq_len_cached = config.max_position_embeddings
|
| 91 |
+
self.original_max_seq_len = config.max_position_embeddings
|
| 92 |
+
|
| 93 |
+
self.config = config
|
| 94 |
+
|
| 95 |
+
self.rope_type = self.config.rope_parameters["rope_type"]
|
| 96 |
+
rope_init_fn: Callable = self.compute_default_rope_parameters
|
| 97 |
+
if self.rope_type != "default":
|
| 98 |
+
rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
|
| 99 |
+
inv_freq, self.attention_scaling = rope_init_fn(self.config, device)
|
| 100 |
+
|
| 101 |
+
self.register_buffer("inv_freq", inv_freq, persistent=False)
|
| 102 |
+
self.register_buffer("original_inv_freq", inv_freq.clone(), persistent=False)
|
| 103 |
+
|
| 104 |
+
@staticmethod
|
| 105 |
+
def compute_default_rope_parameters(
|
| 106 |
+
config: ArceeConfig | None = None,
|
| 107 |
+
device: Optional["torch.device"] = None,
|
| 108 |
+
seq_len: int | None = None,
|
| 109 |
+
) -> tuple["torch.Tensor", float]:
|
| 110 |
+
"""
|
| 111 |
+
Computes the inverse frequencies according to the original RoPE implementation
|
| 112 |
+
Args:
|
| 113 |
+
config ([`~transformers.PreTrainedConfig`]):
|
| 114 |
+
The model configuration.
|
| 115 |
+
device (`torch.device`):
|
| 116 |
+
The device to use for initialization of the inverse frequencies.
|
| 117 |
+
seq_len (`int`, *optional*):
|
| 118 |
+
The current sequence length. Unused for this type of RoPE.
|
| 119 |
+
Returns:
|
| 120 |
+
Tuple of (`torch.Tensor`, `float`), containing the inverse frequencies for the RoPE embeddings and the
|
| 121 |
+
post-processing scaling factor applied to the computed cos/sin (unused in this type of RoPE).
|
| 122 |
+
"""
|
| 123 |
+
base = config.rope_parameters["rope_theta"]
|
| 124 |
+
dim = getattr(config, "head_dim", None) or config.hidden_size // config.num_attention_heads
|
| 125 |
+
|
| 126 |
+
attention_factor = 1.0 # Unused in this type of RoPE
|
| 127 |
+
|
| 128 |
+
# Compute the inverse frequencies
|
| 129 |
+
inv_freq = 1.0 / (
|
| 130 |
+
base ** (torch.arange(0, dim, 2, dtype=torch.int64).to(device=device, dtype=torch.float) / dim)
|
| 131 |
+
)
|
| 132 |
+
return inv_freq, attention_factor
|
| 133 |
+
|
| 134 |
+
@torch.no_grad()
|
| 135 |
+
@dynamic_rope_update # power user: used with advanced RoPE types (e.g. dynamic rope)
|
| 136 |
+
def forward(self, x, position_ids):
|
| 137 |
+
inv_freq_expanded = self.inv_freq[None, :, None].float().expand(position_ids.shape[0], -1, 1).to(x.device)
|
| 138 |
+
position_ids_expanded = position_ids[:, None, :].float()
|
| 139 |
+
|
| 140 |
+
device_type = x.device.type if isinstance(x.device.type, str) and x.device.type != "mps" else "cpu"
|
| 141 |
+
with maybe_autocast(device_type=device_type, enabled=False): # Force float32
|
| 142 |
+
freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(1, 2)
|
| 143 |
+
emb = torch.cat((freqs, freqs), dim=-1)
|
| 144 |
+
cos = emb.cos() * self.attention_scaling
|
| 145 |
+
sin = emb.sin() * self.attention_scaling
|
| 146 |
+
|
| 147 |
+
return cos.to(dtype=x.dtype), sin.to(dtype=x.dtype)
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def rotate_half(x):
|
| 151 |
+
"""Rotates half the hidden dims of the input."""
|
| 152 |
+
x1 = x[..., : x.shape[-1] // 2]
|
| 153 |
+
x2 = x[..., x.shape[-1] // 2 :]
|
| 154 |
+
return torch.cat((-x2, x1), dim=-1)
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
@use_kernel_func_from_hub("rotary_pos_emb")
|
| 158 |
+
def apply_rotary_pos_emb(q, k, cos, sin, unsqueeze_dim=1):
|
| 159 |
+
"""Applies Rotary Position Embedding to the query and key tensors.
|
| 160 |
+
|
| 161 |
+
Args:
|
| 162 |
+
q (`torch.Tensor`): The query tensor.
|
| 163 |
+
k (`torch.Tensor`): The key tensor.
|
| 164 |
+
cos (`torch.Tensor`): The cosine part of the rotary embedding.
|
| 165 |
+
sin (`torch.Tensor`): The sine part of the rotary embedding.
|
| 166 |
+
unsqueeze_dim (`int`, *optional*, defaults to 1):
|
| 167 |
+
The 'unsqueeze_dim' argument specifies the dimension along which to unsqueeze cos[position_ids] and
|
| 168 |
+
sin[position_ids] so that they can be properly broadcasted to the dimensions of q and k. For example, note
|
| 169 |
+
that cos[position_ids] and sin[position_ids] have the shape [batch_size, seq_len, head_dim]. Then, if q and
|
| 170 |
+
k have the shape [batch_size, heads, seq_len, head_dim], then setting unsqueeze_dim=1 makes
|
| 171 |
+
cos[position_ids] and sin[position_ids] broadcastable to the shapes of q and k. Similarly, if q and k have
|
| 172 |
+
the shape [batch_size, seq_len, heads, head_dim], then set unsqueeze_dim=2.
|
| 173 |
+
Returns:
|
| 174 |
+
`tuple(torch.Tensor)` comprising of the query and key tensors rotated using the Rotary Position Embedding.
|
| 175 |
+
"""
|
| 176 |
+
cos = cos.unsqueeze(unsqueeze_dim)
|
| 177 |
+
sin = sin.unsqueeze(unsqueeze_dim)
|
| 178 |
+
q_embed = (q * cos) + (rotate_half(q) * sin)
|
| 179 |
+
k_embed = (k * cos) + (rotate_half(k) * sin)
|
| 180 |
+
return q_embed, k_embed
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
|
| 184 |
+
"""
|
| 185 |
+
This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
|
| 186 |
+
num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
|
| 187 |
+
"""
|
| 188 |
+
batch, num_key_value_heads, slen, head_dim = hidden_states.shape
|
| 189 |
+
if n_rep == 1:
|
| 190 |
+
return hidden_states
|
| 191 |
+
hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
|
| 192 |
+
return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
def eager_attention_forward(
|
| 196 |
+
module: nn.Module,
|
| 197 |
+
query: torch.Tensor,
|
| 198 |
+
key: torch.Tensor,
|
| 199 |
+
value: torch.Tensor,
|
| 200 |
+
attention_mask: torch.Tensor | None,
|
| 201 |
+
scaling: float,
|
| 202 |
+
dropout: float = 0.0,
|
| 203 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 204 |
+
):
|
| 205 |
+
key_states = repeat_kv(key, module.num_key_value_groups)
|
| 206 |
+
value_states = repeat_kv(value, module.num_key_value_groups)
|
| 207 |
+
|
| 208 |
+
attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
|
| 209 |
+
if attention_mask is not None:
|
| 210 |
+
attn_weights = attn_weights + attention_mask
|
| 211 |
+
|
| 212 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
|
| 213 |
+
attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
|
| 214 |
+
attn_output = torch.matmul(attn_weights, value_states)
|
| 215 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 216 |
+
|
| 217 |
+
return attn_output, attn_weights
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
@use_kernelized_func(apply_rotary_pos_emb)
|
| 221 |
+
class ArceeAttention(nn.Module):
|
| 222 |
+
"""Multi-headed attention from 'Attention Is All You Need' paper"""
|
| 223 |
+
|
| 224 |
+
def __init__(self, config: ArceeConfig, layer_idx: int):
|
| 225 |
+
super().__init__()
|
| 226 |
+
self.config = config
|
| 227 |
+
self.layer_idx = layer_idx
|
| 228 |
+
self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
|
| 229 |
+
self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
|
| 230 |
+
self.scaling = self.head_dim**-0.5
|
| 231 |
+
self.attention_dropout = config.attention_dropout
|
| 232 |
+
self.is_causal = True
|
| 233 |
+
|
| 234 |
+
self.q_proj = nn.Linear(
|
| 235 |
+
config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.attention_bias
|
| 236 |
+
)
|
| 237 |
+
self.k_proj = nn.Linear(
|
| 238 |
+
config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
|
| 239 |
+
)
|
| 240 |
+
self.v_proj = nn.Linear(
|
| 241 |
+
config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
|
| 242 |
+
)
|
| 243 |
+
self.o_proj = nn.Linear(
|
| 244 |
+
config.num_attention_heads * self.head_dim, config.hidden_size, bias=config.attention_bias
|
| 245 |
+
)
|
| 246 |
+
|
| 247 |
+
def forward(
|
| 248 |
+
self,
|
| 249 |
+
hidden_states: torch.Tensor,
|
| 250 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
|
| 251 |
+
attention_mask: torch.Tensor | None = None,
|
| 252 |
+
past_key_values: Cache | None = None,
|
| 253 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 254 |
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
| 255 |
+
input_shape = hidden_states.shape[:-1]
|
| 256 |
+
hidden_shape = (*input_shape, -1, self.head_dim)
|
| 257 |
+
|
| 258 |
+
query_states = self.q_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 259 |
+
key_states = self.k_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 260 |
+
value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
| 261 |
+
|
| 262 |
+
cos, sin = position_embeddings
|
| 263 |
+
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
|
| 264 |
+
|
| 265 |
+
if past_key_values is not None:
|
| 266 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
| 267 |
+
|
| 268 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 269 |
+
self.config._attn_implementation, eager_attention_forward
|
| 270 |
+
)
|
| 271 |
+
|
| 272 |
+
attn_output, attn_weights = attention_interface(
|
| 273 |
+
self,
|
| 274 |
+
query_states,
|
| 275 |
+
key_states,
|
| 276 |
+
value_states,
|
| 277 |
+
attention_mask,
|
| 278 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 279 |
+
scaling=self.scaling,
|
| 280 |
+
**kwargs,
|
| 281 |
+
)
|
| 282 |
+
|
| 283 |
+
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
| 284 |
+
attn_output = self.o_proj(attn_output)
|
| 285 |
+
return attn_output, attn_weights
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
class ArceeDecoderLayer(GradientCheckpointingLayer):
|
| 289 |
+
def __init__(self, config: ArceeConfig, layer_idx: int):
|
| 290 |
+
super().__init__()
|
| 291 |
+
self.hidden_size = config.hidden_size
|
| 292 |
+
|
| 293 |
+
self.self_attn = ArceeAttention(config=config, layer_idx=layer_idx)
|
| 294 |
+
|
| 295 |
+
self.mlp = ArceeMLP(config)
|
| 296 |
+
self.input_layernorm = ArceeRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 297 |
+
self.post_attention_layernorm = ArceeRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 298 |
+
|
| 299 |
+
def forward(
|
| 300 |
+
self,
|
| 301 |
+
hidden_states: torch.Tensor,
|
| 302 |
+
attention_mask: torch.Tensor | None = None,
|
| 303 |
+
position_ids: torch.LongTensor | None = None,
|
| 304 |
+
past_key_values: Cache | None = None,
|
| 305 |
+
use_cache: bool | None = False,
|
| 306 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
|
| 307 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 308 |
+
) -> torch.Tensor:
|
| 309 |
+
residual = hidden_states
|
| 310 |
+
hidden_states = self.input_layernorm(hidden_states)
|
| 311 |
+
# Self Attention
|
| 312 |
+
hidden_states, _ = self.self_attn(
|
| 313 |
+
hidden_states=hidden_states,
|
| 314 |
+
attention_mask=attention_mask,
|
| 315 |
+
position_ids=position_ids,
|
| 316 |
+
past_key_values=past_key_values,
|
| 317 |
+
use_cache=use_cache,
|
| 318 |
+
position_embeddings=position_embeddings,
|
| 319 |
+
**kwargs,
|
| 320 |
+
)
|
| 321 |
+
hidden_states = residual + hidden_states
|
| 322 |
+
|
| 323 |
+
# Fully Connected
|
| 324 |
+
residual = hidden_states
|
| 325 |
+
hidden_states = self.post_attention_layernorm(hidden_states)
|
| 326 |
+
hidden_states = self.mlp(hidden_states)
|
| 327 |
+
hidden_states = residual + hidden_states
|
| 328 |
+
return hidden_states
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
@auto_docstring
|
| 332 |
+
class ArceePreTrainedModel(PreTrainedModel):
|
| 333 |
+
config: ArceeConfig
|
| 334 |
+
base_model_prefix = "model"
|
| 335 |
+
supports_gradient_checkpointing = True
|
| 336 |
+
_no_split_modules = ["ArceeDecoderLayer"]
|
| 337 |
+
_skip_keys_device_placement = ["past_key_values"]
|
| 338 |
+
_supports_flash_attn = True
|
| 339 |
+
_supports_sdpa = True
|
| 340 |
+
_supports_flex_attn = True
|
| 341 |
+
|
| 342 |
+
_can_compile_fullgraph = True
|
| 343 |
+
_supports_attention_backend = True
|
| 344 |
+
_can_record_outputs = {
|
| 345 |
+
"hidden_states": ArceeDecoderLayer,
|
| 346 |
+
"attentions": ArceeAttention,
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
|
| 350 |
+
@auto_docstring
|
| 351 |
+
class ArceeModel(ArceePreTrainedModel):
|
| 352 |
+
def __init__(self, config: ArceeConfig):
|
| 353 |
+
super().__init__(config)
|
| 354 |
+
self.padding_idx = config.pad_token_id
|
| 355 |
+
self.vocab_size = config.vocab_size
|
| 356 |
+
|
| 357 |
+
self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
|
| 358 |
+
self.layers = nn.ModuleList(
|
| 359 |
+
[ArceeDecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
|
| 360 |
+
)
|
| 361 |
+
self.norm = ArceeRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 362 |
+
self.rotary_emb = ArceeRotaryEmbedding(config=config)
|
| 363 |
+
self.gradient_checkpointing = False
|
| 364 |
+
|
| 365 |
+
# Initialize weights and apply final processing
|
| 366 |
+
self.post_init()
|
| 367 |
+
|
| 368 |
+
@merge_with_config_defaults
|
| 369 |
+
@capture_outputs
|
| 370 |
+
@auto_docstring
|
| 371 |
+
def forward(
|
| 372 |
+
self,
|
| 373 |
+
input_ids: torch.LongTensor | None = None,
|
| 374 |
+
attention_mask: torch.Tensor | None = None,
|
| 375 |
+
position_ids: torch.LongTensor | None = None,
|
| 376 |
+
past_key_values: Cache | None = None,
|
| 377 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 378 |
+
use_cache: bool | None = None,
|
| 379 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 380 |
+
) -> BaseModelOutputWithPast:
|
| 381 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 382 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 383 |
+
|
| 384 |
+
if inputs_embeds is None:
|
| 385 |
+
inputs_embeds: torch.Tensor = self.embed_tokens(input_ids)
|
| 386 |
+
|
| 387 |
+
if use_cache and past_key_values is None:
|
| 388 |
+
past_key_values = DynamicCache(config=self.config)
|
| 389 |
+
|
| 390 |
+
if position_ids is None:
|
| 391 |
+
past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
|
| 392 |
+
position_ids = torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device) + past_seen_tokens
|
| 393 |
+
position_ids = position_ids.unsqueeze(0)
|
| 394 |
+
|
| 395 |
+
causal_mask = create_causal_mask(
|
| 396 |
+
config=self.config,
|
| 397 |
+
inputs_embeds=inputs_embeds,
|
| 398 |
+
attention_mask=attention_mask,
|
| 399 |
+
past_key_values=past_key_values,
|
| 400 |
+
position_ids=position_ids,
|
| 401 |
+
)
|
| 402 |
+
|
| 403 |
+
hidden_states = inputs_embeds
|
| 404 |
+
position_embeddings = self.rotary_emb(hidden_states, position_ids=position_ids)
|
| 405 |
+
|
| 406 |
+
for decoder_layer in self.layers[: self.config.num_hidden_layers]:
|
| 407 |
+
hidden_states = decoder_layer(
|
| 408 |
+
hidden_states,
|
| 409 |
+
attention_mask=causal_mask,
|
| 410 |
+
position_embeddings=position_embeddings,
|
| 411 |
+
position_ids=position_ids,
|
| 412 |
+
past_key_values=past_key_values,
|
| 413 |
+
use_cache=use_cache,
|
| 414 |
+
**kwargs,
|
| 415 |
+
)
|
| 416 |
+
|
| 417 |
+
hidden_states = self.norm(hidden_states)
|
| 418 |
+
return BaseModelOutputWithPast(
|
| 419 |
+
last_hidden_state=hidden_states,
|
| 420 |
+
past_key_values=past_key_values,
|
| 421 |
+
)
|
| 422 |
+
|
| 423 |
+
|
| 424 |
+
@auto_docstring(checkpoint="arcee-ai/AFM-4.5B")
|
| 425 |
+
class ArceeForCausalLM(ArceePreTrainedModel, GenerationMixin):
|
| 426 |
+
_tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
|
| 427 |
+
_tp_plan = {"lm_head": "colwise_gather_output"}
|
| 428 |
+
_pp_plan = {"lm_head": (["hidden_states"], ["logits"])}
|
| 429 |
+
|
| 430 |
+
def __init__(self, config):
|
| 431 |
+
super().__init__(config)
|
| 432 |
+
self.model = ArceeModel(config)
|
| 433 |
+
self.vocab_size = config.vocab_size
|
| 434 |
+
self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
|
| 435 |
+
|
| 436 |
+
# Initialize weights and apply final processing
|
| 437 |
+
self.post_init()
|
| 438 |
+
|
| 439 |
+
@can_return_tuple
|
| 440 |
+
@auto_docstring
|
| 441 |
+
def forward(
|
| 442 |
+
self,
|
| 443 |
+
input_ids: torch.LongTensor | None = None,
|
| 444 |
+
attention_mask: torch.Tensor | None = None,
|
| 445 |
+
position_ids: torch.LongTensor | None = None,
|
| 446 |
+
past_key_values: Cache | None = None,
|
| 447 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 448 |
+
labels: torch.LongTensor | None = None,
|
| 449 |
+
use_cache: bool | None = None,
|
| 450 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 451 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 452 |
+
) -> CausalLMOutputWithPast:
|
| 453 |
+
r"""
|
| 454 |
+
Example:
|
| 455 |
+
|
| 456 |
+
```python
|
| 457 |
+
>>> from transformers import AutoTokenizer, ArceeForCausalLM
|
| 458 |
+
|
| 459 |
+
>>> model = ArceeForCausalLM.from_pretrained("meta-arcee/Arcee-2-7b-hf")
|
| 460 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("meta-arcee/Arcee-2-7b-hf")
|
| 461 |
+
|
| 462 |
+
>>> prompt = "Hey, are you conscious? Can you talk to me?"
|
| 463 |
+
>>> inputs = tokenizer(prompt, return_tensors="pt")
|
| 464 |
+
|
| 465 |
+
>>> # Generate
|
| 466 |
+
>>> generate_ids = model.generate(inputs.input_ids, max_length=30)
|
| 467 |
+
>>> tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
|
| 468 |
+
"Hey, are you conscious? Can you talk to me?\nI'm not conscious, but I can talk to you."
|
| 469 |
+
```"""
|
| 470 |
+
outputs: BaseModelOutputWithPast = self.model(
|
| 471 |
+
input_ids=input_ids,
|
| 472 |
+
attention_mask=attention_mask,
|
| 473 |
+
position_ids=position_ids,
|
| 474 |
+
past_key_values=past_key_values,
|
| 475 |
+
inputs_embeds=inputs_embeds,
|
| 476 |
+
use_cache=use_cache,
|
| 477 |
+
**kwargs,
|
| 478 |
+
)
|
| 479 |
+
|
| 480 |
+
hidden_states = outputs.last_hidden_state
|
| 481 |
+
# Only compute necessary logits, and do not upcast them to float if we are not computing the loss
|
| 482 |
+
slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
|
| 483 |
+
logits = self.lm_head(hidden_states[:, slice_indices, :])
|
| 484 |
+
|
| 485 |
+
loss = None
|
| 486 |
+
if labels is not None:
|
| 487 |
+
loss = self.loss_function(logits=logits, labels=labels, vocab_size=self.config.vocab_size, **kwargs)
|
| 488 |
+
|
| 489 |
+
return CausalLMOutputWithPast(
|
| 490 |
+
loss=loss,
|
| 491 |
+
logits=logits,
|
| 492 |
+
past_key_values=outputs.past_key_values,
|
| 493 |
+
hidden_states=outputs.hidden_states,
|
| 494 |
+
attentions=outputs.attentions,
|
| 495 |
+
)
|
| 496 |
+
|
| 497 |
+
|
| 498 |
+
@auto_docstring(checkpoint="arcee-ai/AFM-4.5B")
|
| 499 |
+
class ArceeForSequenceClassification(GenericForSequenceClassification, ArceePreTrainedModel):
|
| 500 |
+
pass
|
| 501 |
+
|
| 502 |
+
|
| 503 |
+
@auto_docstring(checkpoint="arcee-ai/AFM-4.5B")
|
| 504 |
+
class ArceeForQuestionAnswering(GenericForQuestionAnswering, ArceePreTrainedModel):
|
| 505 |
+
base_model_prefix = "transformer" # For BC, where `transformer` was used instead of `model`
|
| 506 |
+
|
| 507 |
+
|
| 508 |
+
@auto_docstring(checkpoint="arcee-ai/AFM-4.5B")
|
| 509 |
+
class ArceeForTokenClassification(GenericForTokenClassification, ArceePreTrainedModel):
|
| 510 |
+
pass
|
| 511 |
+
|
| 512 |
+
|
| 513 |
+
__all__ = [
|
| 514 |
+
"ArceeForCausalLM",
|
| 515 |
+
"ArceeForQuestionAnswering",
|
| 516 |
+
"ArceeForSequenceClassification",
|
| 517 |
+
"ArceeForTokenClassification",
|
| 518 |
+
"ArceeModel",
|
| 519 |
+
"ArceePreTrainedModel",
|
| 520 |
+
]
|
third_party/transformers/src/transformers/models/arcee/modular_arcee.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 Arcee AI and the HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""PyTorch Arcee model."""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from transformers.utils import auto_docstring, logging
|
| 19 |
+
|
| 20 |
+
from ...modeling_rope_utils import RopeParameters
|
| 21 |
+
from ..llama.configuration_llama import LlamaConfig
|
| 22 |
+
from ..llama.modeling_llama import (
|
| 23 |
+
LlamaForCausalLM,
|
| 24 |
+
LlamaForQuestionAnswering,
|
| 25 |
+
LlamaForSequenceClassification,
|
| 26 |
+
LlamaForTokenClassification,
|
| 27 |
+
)
|
| 28 |
+
from ..nemotron.modeling_nemotron import NemotronMLP
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
logger = logging.get_logger(__name__)
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
@auto_docstring(checkpoint="arcee-ai/AFM-4.5B")
|
| 35 |
+
@strict
|
| 36 |
+
class ArceeConfig(LlamaConfig):
|
| 37 |
+
r"""
|
| 38 |
+
```python
|
| 39 |
+
>>> from transformers import ArceeModel, ArceeConfig
|
| 40 |
+
|
| 41 |
+
>>> # Initializing an Arcee AFM-4.5B-Base style configuration
|
| 42 |
+
>>> configuration = ArceeConfig()
|
| 43 |
+
|
| 44 |
+
>>> # Initializing a model from the AFM-4.5B-Base style configuration
|
| 45 |
+
>>> model = ArceeModel(configuration)
|
| 46 |
+
|
| 47 |
+
>>> # Accessing the model configuration
|
| 48 |
+
>>> configuration = model.config
|
| 49 |
+
```"""
|
| 50 |
+
|
| 51 |
+
model_type = "arcee"
|
| 52 |
+
base_model_tp_plan = {
|
| 53 |
+
"layers.*.self_attn.q_proj": "colwise",
|
| 54 |
+
"layers.*.self_attn.k_proj": "colwise",
|
| 55 |
+
"layers.*.self_attn.v_proj": "colwise",
|
| 56 |
+
"layers.*.self_attn.o_proj": "rowwise",
|
| 57 |
+
"layers.*.mlp.up_proj": "colwise",
|
| 58 |
+
"layers.*.mlp.down_proj": "rowwise",
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
vocab_size: int = 32000
|
| 62 |
+
hidden_size: int = 2560
|
| 63 |
+
intermediate_size: int = 18432
|
| 64 |
+
num_hidden_layers: int = 32
|
| 65 |
+
num_attention_heads: int = 32
|
| 66 |
+
num_key_value_heads: int | None = None
|
| 67 |
+
hidden_act: str = "relu2"
|
| 68 |
+
max_position_embeddings: int = 4096
|
| 69 |
+
initializer_range: float = 0.02
|
| 70 |
+
rms_norm_eps: float = 1e-5
|
| 71 |
+
use_cache: bool = True
|
| 72 |
+
pad_token_id: int | None = None
|
| 73 |
+
bos_token_id: int | None = 128000
|
| 74 |
+
eos_token_id: int | list[int] | None = 128001
|
| 75 |
+
tie_word_embeddings: bool = False
|
| 76 |
+
rope_parameters: RopeParameters | dict | None = None
|
| 77 |
+
attention_bias: bool = False
|
| 78 |
+
attention_dropout: float | int = 0.0
|
| 79 |
+
mlp_bias: bool = False
|
| 80 |
+
head_dim: int | None = None
|
| 81 |
+
|
| 82 |
+
pretraining_tp = AttributeError()
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
class ArceeMLP(NemotronMLP):
|
| 86 |
+
pass
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
@auto_docstring(checkpoint="arcee-ai/AFM-4.5B")
|
| 90 |
+
class ArceeForCausalLM(LlamaForCausalLM):
|
| 91 |
+
pass
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
@auto_docstring(checkpoint="arcee-ai/AFM-4.5B")
|
| 95 |
+
class ArceeForSequenceClassification(LlamaForSequenceClassification):
|
| 96 |
+
pass
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
@auto_docstring(checkpoint="arcee-ai/AFM-4.5B")
|
| 100 |
+
class ArceeForQuestionAnswering(LlamaForQuestionAnswering):
|
| 101 |
+
pass
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
@auto_docstring(checkpoint="arcee-ai/AFM-4.5B")
|
| 105 |
+
class ArceeForTokenClassification(LlamaForTokenClassification):
|
| 106 |
+
pass
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
__all__ = [
|
| 110 |
+
"ArceeConfig",
|
| 111 |
+
"ArceeForCausalLM",
|
| 112 |
+
"ArceeForQuestionAnswering",
|
| 113 |
+
"ArceeForSequenceClassification",
|
| 114 |
+
"ArceeForTokenClassification",
|
| 115 |
+
"ArceeModel", # noqa: F822
|
| 116 |
+
"ArceePreTrainedModel", # noqa: F822
|
| 117 |
+
]
|
third_party/transformers/src/transformers/models/aya_vision/__init__.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .configuration_aya_vision import *
|
| 22 |
+
from .modeling_aya_vision import *
|
| 23 |
+
from .processing_aya_vision import *
|
| 24 |
+
else:
|
| 25 |
+
import sys
|
| 26 |
+
|
| 27 |
+
_file = globals()["__file__"]
|
| 28 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/aya_vision/configuration_aya_vision.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 Cohere team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""AyaVision model configuration"""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from ...configuration_utils import PreTrainedConfig
|
| 19 |
+
from ...utils import auto_docstring
|
| 20 |
+
from ..auto import CONFIG_MAPPING, AutoConfig
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
@auto_docstring(checkpoint="CohereForAI/aya-vision-8b")
|
| 24 |
+
@strict
|
| 25 |
+
class AyaVisionConfig(PreTrainedConfig):
|
| 26 |
+
r"""
|
| 27 |
+
downsample_factor (`int`, *optional*, defaults to 2):
|
| 28 |
+
The downsample factor to apply to the vision features.
|
| 29 |
+
adapter_layer_norm_eps (`float`, *optional*, defaults to 1e-06):
|
| 30 |
+
The epsilon value used for layer normalization in the adapter.
|
| 31 |
+
"""
|
| 32 |
+
|
| 33 |
+
model_type = "aya_vision"
|
| 34 |
+
attribute_map = {
|
| 35 |
+
"image_token_id": "image_token_index",
|
| 36 |
+
}
|
| 37 |
+
sub_configs = {"text_config": AutoConfig, "vision_config": AutoConfig}
|
| 38 |
+
|
| 39 |
+
vision_config: dict | PreTrainedConfig | None = None
|
| 40 |
+
text_config: dict | PreTrainedConfig | None = None
|
| 41 |
+
vision_feature_select_strategy: str = "full"
|
| 42 |
+
vision_feature_layer: int | list[int] = -1
|
| 43 |
+
downsample_factor: int = 2
|
| 44 |
+
adapter_layer_norm_eps: float = 1e-6
|
| 45 |
+
image_token_index: int = 255036
|
| 46 |
+
tie_word_embeddings: bool = True
|
| 47 |
+
|
| 48 |
+
def __post_init__(self, **kwargs):
|
| 49 |
+
if isinstance(self.vision_config, dict):
|
| 50 |
+
self.vision_config["model_type"] = self.vision_config.get("model_type", "siglip_vision_model")
|
| 51 |
+
self.vision_config = CONFIG_MAPPING[self.vision_config["model_type"]](**self.vision_config)
|
| 52 |
+
elif self.vision_config is None:
|
| 53 |
+
self.vision_config = CONFIG_MAPPING["siglip_vision_model"](
|
| 54 |
+
hidden_size=1152,
|
| 55 |
+
intermediate_size=4304,
|
| 56 |
+
patch_size=14,
|
| 57 |
+
image_size=384,
|
| 58 |
+
num_hidden_layers=26,
|
| 59 |
+
num_attention_heads=14,
|
| 60 |
+
vision_use_head=False,
|
| 61 |
+
)
|
| 62 |
+
|
| 63 |
+
if isinstance(self.text_config, dict):
|
| 64 |
+
self.text_config["model_type"] = self.text_config.get("model_type", "cohere2")
|
| 65 |
+
self.text_config = CONFIG_MAPPING[self.text_config["model_type"]](**self.text_config)
|
| 66 |
+
elif self.text_config is None:
|
| 67 |
+
self.text_config = CONFIG_MAPPING["cohere2"]()
|
| 68 |
+
|
| 69 |
+
super().__post_init__(**kwargs)
|
| 70 |
+
|
| 71 |
+
def validate_architecture(self):
|
| 72 |
+
"""Part of `@strict`-powered validation. Validates the architecture of the config."""
|
| 73 |
+
if self.vision_feature_select_strategy not in ["default", "full"]:
|
| 74 |
+
raise ValueError(
|
| 75 |
+
"vision_feature_select_strategy should be one of 'default', 'full'."
|
| 76 |
+
f"Got: {self.vision_feature_select_strategy}"
|
| 77 |
+
)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
__all__ = ["AyaVisionConfig"]
|
third_party/transformers/src/transformers/models/aya_vision/modeling_aya_vision.py
ADDED
|
@@ -0,0 +1,446 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/aya_vision/modular_aya_vision.py.
|
| 3 |
+
# Do NOT edit this file manually as any edits will be overwritten by the generation of
|
| 4 |
+
# the file from the modular. If any change should be done, please apply the change to the
|
| 5 |
+
# modular_aya_vision.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2025 the Cohere Inc. team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
|
| 21 |
+
from dataclasses import dataclass
|
| 22 |
+
|
| 23 |
+
import torch
|
| 24 |
+
from torch import nn
|
| 25 |
+
|
| 26 |
+
from ...activations import ACT2FN
|
| 27 |
+
from ...cache_utils import Cache
|
| 28 |
+
from ...generation import GenerationMixin
|
| 29 |
+
from ...modeling_outputs import BaseModelOutputWithPast, BaseModelOutputWithPooling, ModelOutput
|
| 30 |
+
from ...modeling_utils import PreTrainedModel
|
| 31 |
+
from ...processing_utils import Unpack
|
| 32 |
+
from ...utils import TransformersKwargs, auto_docstring, torch_compilable_check
|
| 33 |
+
from ...utils.generic import can_return_tuple, merge_with_config_defaults
|
| 34 |
+
from ..auto import AutoModel
|
| 35 |
+
from .configuration_aya_vision import AyaVisionConfig
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class AyaVisionMultiModalProjector(nn.Module):
|
| 39 |
+
def __init__(self, config: AyaVisionConfig):
|
| 40 |
+
super().__init__()
|
| 41 |
+
self.config = config
|
| 42 |
+
self.downsample_factor = config.downsample_factor
|
| 43 |
+
self.alignment_intermediate_size = getattr(
|
| 44 |
+
config, "alignment_intermediate_size", config.text_config.hidden_size
|
| 45 |
+
)
|
| 46 |
+
self.layernorm = nn.LayerNorm(
|
| 47 |
+
config.vision_config.hidden_size * (config.downsample_factor**2), eps=config.adapter_layer_norm_eps
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
self.linear_1 = nn.Linear(
|
| 51 |
+
config.vision_config.hidden_size * (config.downsample_factor**2),
|
| 52 |
+
self.alignment_intermediate_size,
|
| 53 |
+
bias=True,
|
| 54 |
+
)
|
| 55 |
+
|
| 56 |
+
self.act = ACT2FN["silu"] # SwiGLU uses SiLU activation
|
| 57 |
+
# For SwiGLU, project down to half size since we split intermediate dim
|
| 58 |
+
self.linear_2 = nn.Linear(self.alignment_intermediate_size // 2, config.text_config.hidden_size, bias=True)
|
| 59 |
+
|
| 60 |
+
def forward(self, image_features):
|
| 61 |
+
image_features = self.pixel_shuffle(image_features)
|
| 62 |
+
image_features = self.layernorm(image_features)
|
| 63 |
+
hidden_states = self.linear_1(image_features)
|
| 64 |
+
|
| 65 |
+
# Split along last dimension and apply SwiGLU
|
| 66 |
+
x, gate = hidden_states.chunk(2, dim=-1)
|
| 67 |
+
hidden_states = self.act(gate) * x
|
| 68 |
+
|
| 69 |
+
hidden_states = self.linear_2(hidden_states)
|
| 70 |
+
return hidden_states
|
| 71 |
+
|
| 72 |
+
def pixel_shuffle(self, image_features): # B, S, D
|
| 73 |
+
batch_size, seq_length, feature_dim = image_features.shape
|
| 74 |
+
height = width = int(seq_length**0.5)
|
| 75 |
+
image_features = image_features.reshape(image_features.shape[0], width, height, -1)
|
| 76 |
+
channels = image_features.shape[-1]
|
| 77 |
+
image_features = image_features.reshape(
|
| 78 |
+
batch_size, width, int(height / self.downsample_factor), int(channels * self.downsample_factor)
|
| 79 |
+
)
|
| 80 |
+
image_features = image_features.permute(0, 2, 1, 3)
|
| 81 |
+
image_features = image_features.reshape(
|
| 82 |
+
batch_size, int(height / self.downsample_factor), int(width / self.downsample_factor), -1
|
| 83 |
+
)
|
| 84 |
+
image_features = image_features.permute(0, 2, 1, 3)
|
| 85 |
+
return image_features
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
@auto_docstring
|
| 89 |
+
class AyaVisionPreTrainedModel(PreTrainedModel):
|
| 90 |
+
config: AyaVisionConfig
|
| 91 |
+
base_model_prefix = "model"
|
| 92 |
+
input_modalities = ("image", "text")
|
| 93 |
+
supports_gradient_checkpointing = True
|
| 94 |
+
_skip_keys_device_placement = "past_key_values"
|
| 95 |
+
|
| 96 |
+
_supports_flash_attn = True
|
| 97 |
+
_supports_sdpa = True
|
| 98 |
+
_can_compile_fullgraph = False
|
| 99 |
+
_supports_flex_attn = True
|
| 100 |
+
_supports_attention_backend = True
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
@dataclass
|
| 104 |
+
@auto_docstring(
|
| 105 |
+
custom_intro="""
|
| 106 |
+
Base class for AyaVision causal language model (or autoregressive) outputs.
|
| 107 |
+
"""
|
| 108 |
+
)
|
| 109 |
+
class AyaVisionCausalLMOutputWithPast(ModelOutput):
|
| 110 |
+
r"""
|
| 111 |
+
loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `labels` is provided):
|
| 112 |
+
Language modeling loss (for next-token prediction).
|
| 113 |
+
logits (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.vocab_size)`):
|
| 114 |
+
Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).
|
| 115 |
+
past_key_values (`Cache`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
|
| 116 |
+
It is a [`~cache_utils.Cache`] instance. For more details, see our [kv cache guide](https://huggingface.co/docs/transformers/en/kv_cache).
|
| 117 |
+
|
| 118 |
+
Contains pre-computed hidden-states (key and values in the self-attention blocks) that can be used (see
|
| 119 |
+
`past_key_values` input) to speed up sequential decoding.
|
| 120 |
+
image_hidden_states (`torch.FloatTensor`, *optional*):
|
| 121 |
+
A `torch.FloatTensor` of size `(batch_size, num_images, sequence_length, hidden_size)`.
|
| 122 |
+
image_hidden_states of the model produced by the vision encoder and after projecting the last hidden state.
|
| 123 |
+
"""
|
| 124 |
+
|
| 125 |
+
loss: torch.FloatTensor | None = None
|
| 126 |
+
logits: torch.FloatTensor | None = None
|
| 127 |
+
past_key_values: Cache | None = None
|
| 128 |
+
hidden_states: tuple[torch.FloatTensor] | None = None
|
| 129 |
+
attentions: tuple[torch.FloatTensor] | None = None
|
| 130 |
+
image_hidden_states: torch.FloatTensor | None = None
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
@dataclass
|
| 134 |
+
@auto_docstring(
|
| 135 |
+
custom_intro="""
|
| 136 |
+
Base class for AyaVision outputs, with hidden states and attentions.
|
| 137 |
+
"""
|
| 138 |
+
)
|
| 139 |
+
class AyaVisionModelOutputWithPast(BaseModelOutputWithPast):
|
| 140 |
+
r"""
|
| 141 |
+
past_key_values (`Cache`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
|
| 142 |
+
It is a [`~cache_utils.Cache`] instance. For more details, see our [kv cache guide](https://huggingface.co/docs/transformers/en/kv_cache).
|
| 143 |
+
|
| 144 |
+
Contains pre-computed hidden-states (key and values in the self-attention blocks) that can be used (see
|
| 145 |
+
`past_key_values` input) to speed up sequential decoding.
|
| 146 |
+
image_hidden_states (`torch.FloatTensor`, *optional*):
|
| 147 |
+
A `torch.FloatTensor` of size `(batch_size, num_images, sequence_length, hidden_size)`.
|
| 148 |
+
image_hidden_states of the model produced by the vision encoder and after projecting the last hidden state.
|
| 149 |
+
"""
|
| 150 |
+
|
| 151 |
+
image_hidden_states: torch.FloatTensor | None = None
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
@auto_docstring(
|
| 155 |
+
custom_intro="""
|
| 156 |
+
The AyaVision model which consists of a vision backbone and a language model, without a language modeling head.
|
| 157 |
+
"""
|
| 158 |
+
)
|
| 159 |
+
class AyaVisionModel(AyaVisionPreTrainedModel):
|
| 160 |
+
def __init__(self, config: AyaVisionConfig):
|
| 161 |
+
super().__init__(config)
|
| 162 |
+
self.vision_tower = AutoModel.from_config(config.vision_config)
|
| 163 |
+
|
| 164 |
+
self.multi_modal_projector = AyaVisionMultiModalProjector(config)
|
| 165 |
+
self.language_model = AutoModel.from_config(config.text_config)
|
| 166 |
+
self.post_init()
|
| 167 |
+
|
| 168 |
+
def get_input_embeddings(self):
|
| 169 |
+
return self.language_model.get_input_embeddings()
|
| 170 |
+
|
| 171 |
+
def set_input_embeddings(self, value):
|
| 172 |
+
self.language_model.set_input_embeddings(value)
|
| 173 |
+
|
| 174 |
+
@merge_with_config_defaults
|
| 175 |
+
@can_return_tuple
|
| 176 |
+
@auto_docstring(
|
| 177 |
+
custom_intro="Obtains image last hidden states from the vision tower and apply multimodal projection."
|
| 178 |
+
)
|
| 179 |
+
def get_image_features(
|
| 180 |
+
self,
|
| 181 |
+
pixel_values: torch.FloatTensor,
|
| 182 |
+
vision_feature_layer: int | list[int] | list[int] | None = None,
|
| 183 |
+
vision_feature_select_strategy: str | None = None,
|
| 184 |
+
output_hidden_states: bool | None = None,
|
| 185 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 186 |
+
) -> tuple | BaseModelOutputWithPooling:
|
| 187 |
+
kwargs = {k: v for k, v in kwargs.items() if v is not None}
|
| 188 |
+
# this is not memory efficient at all (output_hidden_states=True) will save all the hidden states.
|
| 189 |
+
image_outputs = self.vision_tower(
|
| 190 |
+
pixel_values,
|
| 191 |
+
output_hidden_states=True, # Ignore arg on purpose
|
| 192 |
+
return_dict=True,
|
| 193 |
+
**kwargs,
|
| 194 |
+
)
|
| 195 |
+
|
| 196 |
+
# If we have one vision feature layer, return the corresponding hidden states,
|
| 197 |
+
# otherwise, select the hidden states of each feature layer and concatenate them
|
| 198 |
+
if isinstance(vision_feature_layer, int):
|
| 199 |
+
selected_image_feature = image_outputs.hidden_states[vision_feature_layer]
|
| 200 |
+
if vision_feature_select_strategy == "default":
|
| 201 |
+
selected_image_feature = selected_image_feature[:, 1:]
|
| 202 |
+
else:
|
| 203 |
+
hs_pool = [image_outputs.hidden_states[layer_idx] for layer_idx in vision_feature_layer]
|
| 204 |
+
# For default; crop CLS from each hidden state in the hidden state pool
|
| 205 |
+
if vision_feature_select_strategy == "default":
|
| 206 |
+
hs_pool = [hs[:, 1:] for hs in hs_pool]
|
| 207 |
+
selected_image_feature = torch.cat(hs_pool, dim=-1)
|
| 208 |
+
|
| 209 |
+
image_outputs.pooler_output = self.multi_modal_projector(selected_image_feature)
|
| 210 |
+
|
| 211 |
+
return image_outputs
|
| 212 |
+
|
| 213 |
+
def get_placeholder_mask(
|
| 214 |
+
self, input_ids: torch.LongTensor, inputs_embeds: torch.FloatTensor, image_features: torch.FloatTensor
|
| 215 |
+
):
|
| 216 |
+
"""
|
| 217 |
+
Obtains multimodal placeholder mask from `input_ids` or `inputs_embeds`, and checks that the placeholder token count is
|
| 218 |
+
equal to the length of multimodal features. If the lengths are different, an error is raised.
|
| 219 |
+
"""
|
| 220 |
+
if input_ids is None:
|
| 221 |
+
special_image_mask = inputs_embeds == self.get_input_embeddings()(
|
| 222 |
+
torch.tensor(self.config.image_token_id, dtype=torch.long, device=inputs_embeds.device)
|
| 223 |
+
)
|
| 224 |
+
special_image_mask = special_image_mask.all(-1)
|
| 225 |
+
else:
|
| 226 |
+
special_image_mask = input_ids == self.config.image_token_id
|
| 227 |
+
|
| 228 |
+
n_image_tokens = special_image_mask.sum()
|
| 229 |
+
n_image_features = image_features.shape[0] * image_features.shape[1]
|
| 230 |
+
special_image_mask = special_image_mask.unsqueeze(-1).expand_as(inputs_embeds).to(inputs_embeds.device)
|
| 231 |
+
torch_compilable_check(
|
| 232 |
+
inputs_embeds[special_image_mask].numel() == image_features.numel(),
|
| 233 |
+
f"Image features and image tokens do not match, tokens: {n_image_tokens}, features: {n_image_features}",
|
| 234 |
+
)
|
| 235 |
+
return special_image_mask
|
| 236 |
+
|
| 237 |
+
@can_return_tuple
|
| 238 |
+
@auto_docstring
|
| 239 |
+
def forward(
|
| 240 |
+
self,
|
| 241 |
+
input_ids: torch.LongTensor | None = None,
|
| 242 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 243 |
+
attention_mask: torch.Tensor | None = None,
|
| 244 |
+
position_ids: torch.LongTensor | None = None,
|
| 245 |
+
past_key_values: Cache | None = None,
|
| 246 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 247 |
+
vision_feature_layer: int | list[int] | list[int] | None = None,
|
| 248 |
+
vision_feature_select_strategy: str | None = None,
|
| 249 |
+
use_cache: bool | None = None,
|
| 250 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 251 |
+
) -> tuple | AyaVisionModelOutputWithPast:
|
| 252 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 253 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 254 |
+
|
| 255 |
+
if inputs_embeds is None:
|
| 256 |
+
inputs_embeds = self.get_input_embeddings()(input_ids)
|
| 257 |
+
|
| 258 |
+
if pixel_values is not None:
|
| 259 |
+
image_features = self.get_image_features(
|
| 260 |
+
pixel_values=pixel_values,
|
| 261 |
+
vision_feature_layer=vision_feature_layer,
|
| 262 |
+
vision_feature_select_strategy=vision_feature_select_strategy,
|
| 263 |
+
return_dict=True,
|
| 264 |
+
).pooler_output
|
| 265 |
+
image_features = image_features.to(inputs_embeds.device, inputs_embeds.dtype)
|
| 266 |
+
special_image_mask = self.get_placeholder_mask(
|
| 267 |
+
input_ids, inputs_embeds=inputs_embeds, image_features=image_features
|
| 268 |
+
)
|
| 269 |
+
inputs_embeds = inputs_embeds.masked_scatter(special_image_mask, image_features)
|
| 270 |
+
|
| 271 |
+
outputs = self.language_model(
|
| 272 |
+
attention_mask=attention_mask,
|
| 273 |
+
position_ids=position_ids,
|
| 274 |
+
past_key_values=past_key_values,
|
| 275 |
+
inputs_embeds=inputs_embeds,
|
| 276 |
+
use_cache=use_cache,
|
| 277 |
+
**kwargs,
|
| 278 |
+
)
|
| 279 |
+
|
| 280 |
+
return AyaVisionModelOutputWithPast(
|
| 281 |
+
last_hidden_state=outputs.last_hidden_state,
|
| 282 |
+
past_key_values=outputs.past_key_values,
|
| 283 |
+
hidden_states=outputs.hidden_states,
|
| 284 |
+
attentions=outputs.attentions,
|
| 285 |
+
image_hidden_states=image_features if pixel_values is not None else None,
|
| 286 |
+
)
|
| 287 |
+
|
| 288 |
+
|
| 289 |
+
@auto_docstring(
|
| 290 |
+
custom_intro="""
|
| 291 |
+
The AYA_VISION model which consists of a vision backbone and a language model.
|
| 292 |
+
"""
|
| 293 |
+
)
|
| 294 |
+
class AyaVisionForConditionalGeneration(AyaVisionPreTrainedModel, GenerationMixin):
|
| 295 |
+
_tied_weights_keys = {"lm_head.weight": "model.language_model.embed_tokens.weight"}
|
| 296 |
+
|
| 297 |
+
def __init__(self, config: AyaVisionConfig):
|
| 298 |
+
super().__init__(config)
|
| 299 |
+
self.model = AyaVisionModel(config)
|
| 300 |
+
self.lm_head = nn.Linear(config.text_config.hidden_size, config.text_config.vocab_size, bias=False)
|
| 301 |
+
self.post_init()
|
| 302 |
+
|
| 303 |
+
def get_input_embeddings(self):
|
| 304 |
+
return self.model.get_input_embeddings()
|
| 305 |
+
|
| 306 |
+
def set_input_embeddings(self, value):
|
| 307 |
+
self.model.set_input_embeddings(value)
|
| 308 |
+
|
| 309 |
+
def get_output_embeddings(self) -> nn.Module:
|
| 310 |
+
return self.lm_head
|
| 311 |
+
|
| 312 |
+
@auto_docstring
|
| 313 |
+
def get_image_features(
|
| 314 |
+
self,
|
| 315 |
+
pixel_values: torch.FloatTensor,
|
| 316 |
+
vision_feature_layer: int | list[int] | list[int] | None = None,
|
| 317 |
+
vision_feature_select_strategy: str | None = None,
|
| 318 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 319 |
+
) -> tuple | BaseModelOutputWithPooling:
|
| 320 |
+
return self.model.get_image_features(
|
| 321 |
+
pixel_values=pixel_values,
|
| 322 |
+
vision_feature_layer=vision_feature_layer,
|
| 323 |
+
vision_feature_select_strategy=vision_feature_select_strategy,
|
| 324 |
+
**kwargs,
|
| 325 |
+
)
|
| 326 |
+
|
| 327 |
+
@can_return_tuple
|
| 328 |
+
@auto_docstring
|
| 329 |
+
def forward(
|
| 330 |
+
self,
|
| 331 |
+
input_ids: torch.LongTensor | None = None,
|
| 332 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 333 |
+
attention_mask: torch.Tensor | None = None,
|
| 334 |
+
position_ids: torch.LongTensor | None = None,
|
| 335 |
+
past_key_values: Cache | None = None,
|
| 336 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 337 |
+
vision_feature_layer: int | list[int] | list[int] | None = None,
|
| 338 |
+
vision_feature_select_strategy: str | None = None,
|
| 339 |
+
labels: torch.LongTensor | None = None,
|
| 340 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 341 |
+
image_sizes: torch.Tensor | None = None,
|
| 342 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 343 |
+
) -> tuple | AyaVisionCausalLMOutputWithPast:
|
| 344 |
+
r"""
|
| 345 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 346 |
+
Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
|
| 347 |
+
config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
|
| 348 |
+
(masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
|
| 349 |
+
|
| 350 |
+
Example:
|
| 351 |
+
|
| 352 |
+
```python
|
| 353 |
+
>>> from transformers import AutoProcessor, AyaVisionForConditionalGeneration
|
| 354 |
+
>>> import torch
|
| 355 |
+
|
| 356 |
+
>>> torch_device = "cuda:0"
|
| 357 |
+
>>> processor = AutoProcessor.from_pretrained("CohereForAI/aya-vision-8b", use_fast=True)
|
| 358 |
+
>>> model = AyaVisionForConditionalGeneration.from_pretrained("CohereForAI/aya-vision-8b", device_map=torch_device)
|
| 359 |
+
|
| 360 |
+
>>> messages = [
|
| 361 |
+
... {
|
| 362 |
+
... "role": "user",
|
| 363 |
+
... "content": [
|
| 364 |
+
... {
|
| 365 |
+
... "type": "image",
|
| 366 |
+
... "url": "https://pbs.twimg.com/media/Fx7YvfQWYAIp6rZ?format=jpg&name=medium",
|
| 367 |
+
... },
|
| 368 |
+
... {"type": "text", "text": "चित्र में लिखा पाठ क्या कहता है?"},
|
| 369 |
+
... ],
|
| 370 |
+
... }
|
| 371 |
+
... ]
|
| 372 |
+
|
| 373 |
+
>>> inputs = processor.apply_chat_template(
|
| 374 |
+
... messages, padding=True, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", device=torch_device
|
| 375 |
+
... ).to(model.device)
|
| 376 |
+
|
| 377 |
+
>>> gen_tokens = model.generate(**inputs, max_new_tokens=300, do_sample=True, temperature=0.3)
|
| 378 |
+
>>> processor.tokenizer.decode(gen_tokens[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
|
| 379 |
+
```"""
|
| 380 |
+
outputs = self.model(
|
| 381 |
+
input_ids=input_ids,
|
| 382 |
+
pixel_values=pixel_values,
|
| 383 |
+
attention_mask=attention_mask,
|
| 384 |
+
position_ids=position_ids,
|
| 385 |
+
past_key_values=past_key_values,
|
| 386 |
+
inputs_embeds=inputs_embeds,
|
| 387 |
+
vision_feature_layer=vision_feature_layer,
|
| 388 |
+
vision_feature_select_strategy=vision_feature_select_strategy,
|
| 389 |
+
image_sizes=image_sizes,
|
| 390 |
+
**kwargs,
|
| 391 |
+
)
|
| 392 |
+
|
| 393 |
+
hidden_states = outputs[0]
|
| 394 |
+
# Only compute necessary logits, and do not upcast them to float if we are not computing the loss
|
| 395 |
+
slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
|
| 396 |
+
logits = self.lm_head(hidden_states[:, slice_indices, :])
|
| 397 |
+
|
| 398 |
+
loss = None
|
| 399 |
+
if labels is not None:
|
| 400 |
+
loss = self.loss_function(
|
| 401 |
+
logits=logits, labels=labels, vocab_size=self.config.text_config.vocab_size, **kwargs
|
| 402 |
+
)
|
| 403 |
+
|
| 404 |
+
return AyaVisionCausalLMOutputWithPast(
|
| 405 |
+
loss=loss,
|
| 406 |
+
logits=logits,
|
| 407 |
+
past_key_values=outputs.past_key_values,
|
| 408 |
+
hidden_states=outputs.hidden_states,
|
| 409 |
+
attentions=outputs.attentions,
|
| 410 |
+
image_hidden_states=outputs.image_hidden_states,
|
| 411 |
+
)
|
| 412 |
+
|
| 413 |
+
def prepare_inputs_for_generation(
|
| 414 |
+
self,
|
| 415 |
+
input_ids,
|
| 416 |
+
past_key_values=None,
|
| 417 |
+
inputs_embeds=None,
|
| 418 |
+
pixel_values=None,
|
| 419 |
+
attention_mask=None,
|
| 420 |
+
logits_to_keep=None,
|
| 421 |
+
is_first_iteration=False,
|
| 422 |
+
**kwargs,
|
| 423 |
+
):
|
| 424 |
+
# Overwritten -- in specific circumstances we don't want to forward image inputs to the model
|
| 425 |
+
|
| 426 |
+
model_inputs = super().prepare_inputs_for_generation(
|
| 427 |
+
input_ids,
|
| 428 |
+
past_key_values=past_key_values,
|
| 429 |
+
inputs_embeds=inputs_embeds,
|
| 430 |
+
attention_mask=attention_mask,
|
| 431 |
+
logits_to_keep=logits_to_keep,
|
| 432 |
+
is_first_iteration=is_first_iteration,
|
| 433 |
+
**kwargs,
|
| 434 |
+
)
|
| 435 |
+
|
| 436 |
+
if is_first_iteration or not kwargs.get("use_cache", True):
|
| 437 |
+
# Pixel values are used only in the first iteration if available
|
| 438 |
+
# In subsequent iterations, they are already merged with text and cached
|
| 439 |
+
# NOTE: first iteration doesn't have to be prefill, it can be the first
|
| 440 |
+
# iteration with a question and cached system prompt (continue generate from cache)
|
| 441 |
+
model_inputs["pixel_values"] = pixel_values
|
| 442 |
+
|
| 443 |
+
return model_inputs
|
| 444 |
+
|
| 445 |
+
|
| 446 |
+
__all__ = ["AyaVisionForConditionalGeneration", "AyaVisionPreTrainedModel", "AyaVisionModel"]
|
third_party/transformers/src/transformers/models/aya_vision/modular_aya_vision.py
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 the Cohere Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""PyTorch AyaVision model."""
|
| 15 |
+
|
| 16 |
+
import torch
|
| 17 |
+
from torch import nn
|
| 18 |
+
|
| 19 |
+
from transformers.models.llava.modeling_llava import (
|
| 20 |
+
LlavaCausalLMOutputWithPast,
|
| 21 |
+
LlavaForConditionalGeneration,
|
| 22 |
+
LlavaModel,
|
| 23 |
+
LlavaModelOutputWithPast,
|
| 24 |
+
LlavaPreTrainedModel,
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
from ...activations import ACT2FN
|
| 28 |
+
from ...cache_utils import Cache
|
| 29 |
+
from ...modeling_outputs import BaseModelOutputWithPooling
|
| 30 |
+
from ...processing_utils import Unpack
|
| 31 |
+
from ...utils import TransformersKwargs, auto_docstring, logging
|
| 32 |
+
from ...utils.generic import can_return_tuple, merge_with_config_defaults
|
| 33 |
+
from .configuration_aya_vision import AyaVisionConfig
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
logger = logging.get_logger(__name__)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
class AyaVisionMultiModalProjector(nn.Module):
|
| 40 |
+
def __init__(self, config: AyaVisionConfig):
|
| 41 |
+
super().__init__()
|
| 42 |
+
self.config = config
|
| 43 |
+
self.downsample_factor = config.downsample_factor
|
| 44 |
+
self.alignment_intermediate_size = getattr(
|
| 45 |
+
config, "alignment_intermediate_size", config.text_config.hidden_size
|
| 46 |
+
)
|
| 47 |
+
self.layernorm = nn.LayerNorm(
|
| 48 |
+
config.vision_config.hidden_size * (config.downsample_factor**2), eps=config.adapter_layer_norm_eps
|
| 49 |
+
)
|
| 50 |
+
|
| 51 |
+
self.linear_1 = nn.Linear(
|
| 52 |
+
config.vision_config.hidden_size * (config.downsample_factor**2),
|
| 53 |
+
self.alignment_intermediate_size,
|
| 54 |
+
bias=True,
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
self.act = ACT2FN["silu"] # SwiGLU uses SiLU activation
|
| 58 |
+
# For SwiGLU, project down to half size since we split intermediate dim
|
| 59 |
+
self.linear_2 = nn.Linear(self.alignment_intermediate_size // 2, config.text_config.hidden_size, bias=True)
|
| 60 |
+
|
| 61 |
+
def forward(self, image_features):
|
| 62 |
+
image_features = self.pixel_shuffle(image_features)
|
| 63 |
+
image_features = self.layernorm(image_features)
|
| 64 |
+
hidden_states = self.linear_1(image_features)
|
| 65 |
+
|
| 66 |
+
# Split along last dimension and apply SwiGLU
|
| 67 |
+
x, gate = hidden_states.chunk(2, dim=-1)
|
| 68 |
+
hidden_states = self.act(gate) * x
|
| 69 |
+
|
| 70 |
+
hidden_states = self.linear_2(hidden_states)
|
| 71 |
+
return hidden_states
|
| 72 |
+
|
| 73 |
+
def pixel_shuffle(self, image_features): # B, S, D
|
| 74 |
+
batch_size, seq_length, feature_dim = image_features.shape
|
| 75 |
+
height = width = int(seq_length**0.5)
|
| 76 |
+
image_features = image_features.reshape(image_features.shape[0], width, height, -1)
|
| 77 |
+
channels = image_features.shape[-1]
|
| 78 |
+
image_features = image_features.reshape(
|
| 79 |
+
batch_size, width, int(height / self.downsample_factor), int(channels * self.downsample_factor)
|
| 80 |
+
)
|
| 81 |
+
image_features = image_features.permute(0, 2, 1, 3)
|
| 82 |
+
image_features = image_features.reshape(
|
| 83 |
+
batch_size, int(height / self.downsample_factor), int(width / self.downsample_factor), -1
|
| 84 |
+
)
|
| 85 |
+
image_features = image_features.permute(0, 2, 1, 3)
|
| 86 |
+
return image_features
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
class AyaVisionPreTrainedModel(LlavaPreTrainedModel):
|
| 90 |
+
_can_compile_fullgraph = False
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
class AyaVisionCausalLMOutputWithPast(LlavaCausalLMOutputWithPast):
|
| 94 |
+
pass
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
class AyaVisionModelOutputWithPast(LlavaModelOutputWithPast):
|
| 98 |
+
pass
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
class AyaVisionModel(LlavaModel):
|
| 102 |
+
# Unlike LLaVA, the model doesn't have to deal with Pixtral-style image states
|
| 103 |
+
@merge_with_config_defaults
|
| 104 |
+
@can_return_tuple
|
| 105 |
+
@auto_docstring(
|
| 106 |
+
custom_intro="Obtains image last hidden states from the vision tower and apply multimodal projection."
|
| 107 |
+
)
|
| 108 |
+
def get_image_features(
|
| 109 |
+
self,
|
| 110 |
+
pixel_values: torch.FloatTensor,
|
| 111 |
+
vision_feature_layer: int | list[int] | list[int] | None = None,
|
| 112 |
+
vision_feature_select_strategy: str | None = None,
|
| 113 |
+
output_hidden_states: bool | None = None,
|
| 114 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 115 |
+
) -> tuple | BaseModelOutputWithPooling:
|
| 116 |
+
kwargs = {k: v for k, v in kwargs.items() if v is not None}
|
| 117 |
+
# this is not memory efficient at all (output_hidden_states=True) will save all the hidden states.
|
| 118 |
+
image_outputs = self.vision_tower(
|
| 119 |
+
pixel_values,
|
| 120 |
+
output_hidden_states=True, # Ignore arg on purpose
|
| 121 |
+
return_dict=True,
|
| 122 |
+
**kwargs,
|
| 123 |
+
)
|
| 124 |
+
|
| 125 |
+
# If we have one vision feature layer, return the corresponding hidden states,
|
| 126 |
+
# otherwise, select the hidden states of each feature layer and concatenate them
|
| 127 |
+
if isinstance(vision_feature_layer, int):
|
| 128 |
+
selected_image_feature = image_outputs.hidden_states[vision_feature_layer]
|
| 129 |
+
if vision_feature_select_strategy == "default":
|
| 130 |
+
selected_image_feature = selected_image_feature[:, 1:]
|
| 131 |
+
else:
|
| 132 |
+
hs_pool = [image_outputs.hidden_states[layer_idx] for layer_idx in vision_feature_layer]
|
| 133 |
+
# For default; crop CLS from each hidden state in the hidden state pool
|
| 134 |
+
if vision_feature_select_strategy == "default":
|
| 135 |
+
hs_pool = [hs[:, 1:] for hs in hs_pool]
|
| 136 |
+
selected_image_feature = torch.cat(hs_pool, dim=-1)
|
| 137 |
+
|
| 138 |
+
image_outputs.pooler_output = self.multi_modal_projector(selected_image_feature)
|
| 139 |
+
|
| 140 |
+
return image_outputs
|
| 141 |
+
|
| 142 |
+
@can_return_tuple
|
| 143 |
+
@auto_docstring
|
| 144 |
+
def forward(
|
| 145 |
+
self,
|
| 146 |
+
input_ids: torch.LongTensor | None = None,
|
| 147 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 148 |
+
attention_mask: torch.Tensor | None = None,
|
| 149 |
+
position_ids: torch.LongTensor | None = None,
|
| 150 |
+
past_key_values: Cache | None = None,
|
| 151 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 152 |
+
vision_feature_layer: int | list[int] | list[int] | None = None,
|
| 153 |
+
vision_feature_select_strategy: str | None = None,
|
| 154 |
+
use_cache: bool | None = None,
|
| 155 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 156 |
+
) -> tuple | AyaVisionModelOutputWithPast:
|
| 157 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 158 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 159 |
+
|
| 160 |
+
if inputs_embeds is None:
|
| 161 |
+
inputs_embeds = self.get_input_embeddings()(input_ids)
|
| 162 |
+
|
| 163 |
+
if pixel_values is not None:
|
| 164 |
+
image_features = self.get_image_features(
|
| 165 |
+
pixel_values=pixel_values,
|
| 166 |
+
vision_feature_layer=vision_feature_layer,
|
| 167 |
+
vision_feature_select_strategy=vision_feature_select_strategy,
|
| 168 |
+
return_dict=True,
|
| 169 |
+
).pooler_output
|
| 170 |
+
image_features = image_features.to(inputs_embeds.device, inputs_embeds.dtype)
|
| 171 |
+
special_image_mask = self.get_placeholder_mask(
|
| 172 |
+
input_ids, inputs_embeds=inputs_embeds, image_features=image_features
|
| 173 |
+
)
|
| 174 |
+
inputs_embeds = inputs_embeds.masked_scatter(special_image_mask, image_features)
|
| 175 |
+
|
| 176 |
+
outputs = self.language_model(
|
| 177 |
+
attention_mask=attention_mask,
|
| 178 |
+
position_ids=position_ids,
|
| 179 |
+
past_key_values=past_key_values,
|
| 180 |
+
inputs_embeds=inputs_embeds,
|
| 181 |
+
use_cache=use_cache,
|
| 182 |
+
**kwargs,
|
| 183 |
+
)
|
| 184 |
+
|
| 185 |
+
return AyaVisionModelOutputWithPast(
|
| 186 |
+
last_hidden_state=outputs.last_hidden_state,
|
| 187 |
+
past_key_values=outputs.past_key_values,
|
| 188 |
+
hidden_states=outputs.hidden_states,
|
| 189 |
+
attentions=outputs.attentions,
|
| 190 |
+
image_hidden_states=image_features if pixel_values is not None else None,
|
| 191 |
+
)
|
| 192 |
+
|
| 193 |
+
|
| 194 |
+
class AyaVisionForConditionalGeneration(LlavaForConditionalGeneration):
|
| 195 |
+
def forward(
|
| 196 |
+
self,
|
| 197 |
+
input_ids: torch.LongTensor | None = None,
|
| 198 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 199 |
+
attention_mask: torch.Tensor | None = None,
|
| 200 |
+
position_ids: torch.LongTensor | None = None,
|
| 201 |
+
past_key_values: Cache | None = None,
|
| 202 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 203 |
+
vision_feature_layer: int | list[int] | list[int] | None = None,
|
| 204 |
+
vision_feature_select_strategy: str | None = None,
|
| 205 |
+
labels: torch.LongTensor | None = None,
|
| 206 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 207 |
+
image_sizes: torch.Tensor | None = None,
|
| 208 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 209 |
+
) -> tuple | AyaVisionCausalLMOutputWithPast:
|
| 210 |
+
r"""
|
| 211 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 212 |
+
Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
|
| 213 |
+
config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
|
| 214 |
+
(masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
|
| 215 |
+
|
| 216 |
+
Example:
|
| 217 |
+
|
| 218 |
+
```python
|
| 219 |
+
>>> from transformers import AutoProcessor, AyaVisionForConditionalGeneration
|
| 220 |
+
>>> import torch
|
| 221 |
+
|
| 222 |
+
>>> torch_device = "cuda:0"
|
| 223 |
+
>>> processor = AutoProcessor.from_pretrained("CohereForAI/aya-vision-8b", use_fast=True)
|
| 224 |
+
>>> model = AyaVisionForConditionalGeneration.from_pretrained("CohereForAI/aya-vision-8b", device_map=torch_device)
|
| 225 |
+
|
| 226 |
+
>>> messages = [
|
| 227 |
+
... {
|
| 228 |
+
... "role": "user",
|
| 229 |
+
... "content": [
|
| 230 |
+
... {
|
| 231 |
+
... "type": "image",
|
| 232 |
+
... "url": "https://pbs.twimg.com/media/Fx7YvfQWYAIp6rZ?format=jpg&name=medium",
|
| 233 |
+
... },
|
| 234 |
+
... {"type": "text", "text": "चित्र में लिखा पाठ क्या कहता है?"},
|
| 235 |
+
... ],
|
| 236 |
+
... }
|
| 237 |
+
... ]
|
| 238 |
+
|
| 239 |
+
>>> inputs = processor.apply_chat_template(
|
| 240 |
+
... messages, padding=True, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", device=torch_device
|
| 241 |
+
... ).to(model.device)
|
| 242 |
+
|
| 243 |
+
>>> gen_tokens = model.generate(**inputs, max_new_tokens=300, do_sample=True, temperature=0.3)
|
| 244 |
+
>>> processor.tokenizer.decode(gen_tokens[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
|
| 245 |
+
```"""
|
| 246 |
+
super().forward(
|
| 247 |
+
input_ids=input_ids,
|
| 248 |
+
pixel_values=pixel_values,
|
| 249 |
+
attention_mask=attention_mask,
|
| 250 |
+
position_ids=position_ids,
|
| 251 |
+
past_key_values=past_key_values,
|
| 252 |
+
inputs_embeds=inputs_embeds,
|
| 253 |
+
vision_feature_layer=vision_feature_layer,
|
| 254 |
+
vision_feature_select_strategy=vision_feature_select_strategy,
|
| 255 |
+
labels=labels,
|
| 256 |
+
logits_to_keep=logits_to_keep,
|
| 257 |
+
image_sizes=image_sizes,
|
| 258 |
+
**kwargs,
|
| 259 |
+
)
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
__all__ = ["AyaVisionForConditionalGeneration", "AyaVisionPreTrainedModel", "AyaVisionModel"]
|
third_party/transformers/src/transformers/models/aya_vision/processing_aya_vision.py
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
from ...image_processing_utils import BatchFeature
|
| 17 |
+
from ...image_utils import ImageInput, make_flat_list_of_images
|
| 18 |
+
from ...processing_utils import MultiModalData, ProcessingKwargs, ProcessorMixin, Unpack
|
| 19 |
+
from ...tokenization_utils_base import PreTokenizedInput, TextInput
|
| 20 |
+
from ...utils import auto_docstring
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
class AyaVisionProcessorKwargs(ProcessingKwargs, total=False):
|
| 24 |
+
_defaults = {
|
| 25 |
+
"text_kwargs": {
|
| 26 |
+
"padding_side": "left",
|
| 27 |
+
"padding": True,
|
| 28 |
+
"return_mm_token_type_ids": False,
|
| 29 |
+
},
|
| 30 |
+
"images_kwargs": {
|
| 31 |
+
"crop_to_patches": True,
|
| 32 |
+
},
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
@auto_docstring
|
| 37 |
+
class AyaVisionProcessor(ProcessorMixin):
|
| 38 |
+
def __init__(
|
| 39 |
+
self,
|
| 40 |
+
image_processor=None,
|
| 41 |
+
tokenizer=None,
|
| 42 |
+
patch_size: int = 28,
|
| 43 |
+
img_size: int = 364,
|
| 44 |
+
image_token="<image>", # set the default and let users change if they have peculiar special tokens in rare cases
|
| 45 |
+
downsample_factor: int = 1,
|
| 46 |
+
start_of_img_token="<|START_OF_IMG|>",
|
| 47 |
+
end_of_img_token="<|END_OF_IMG|>",
|
| 48 |
+
img_patch_token="<|IMG_PATCH|>",
|
| 49 |
+
img_line_break_token="<|IMG_LINE_BREAK|>",
|
| 50 |
+
tile_token="TILE",
|
| 51 |
+
tile_global_token="TILE_GLOBAL",
|
| 52 |
+
chat_template=None,
|
| 53 |
+
**kwargs,
|
| 54 |
+
):
|
| 55 |
+
r"""
|
| 56 |
+
patch_size (`int`, *optional*, defaults to 28):
|
| 57 |
+
The size of image patches for tokenization.
|
| 58 |
+
img_size (`int`, *optional*, defaults to 364):
|
| 59 |
+
The size of the image to be tokenized. This should correspond to the size given to the image processor.
|
| 60 |
+
image_token (`str`, *optional*, defaults to `"<image>"`):
|
| 61 |
+
The token to be used to represent an image in the text.
|
| 62 |
+
downsample_factor (`int`, *optional*, defaults to 1):
|
| 63 |
+
The factor by which to scale the patch size.
|
| 64 |
+
start_of_img_token (`str`, *optional*, defaults to `"<|START_OF_IMG|>"`):
|
| 65 |
+
The token to be used to represent the start of an image in the text.
|
| 66 |
+
end_of_img_token (`str`, *optional*, defaults to `"<|END_OF_IMG|>"`):
|
| 67 |
+
The token to be used to represent the end of an image in the text.
|
| 68 |
+
img_patch_token (`str`, *optional*, defaults to `"<|IMG_PATCH|>"`):
|
| 69 |
+
The token to be used to represent an image patch in the text.
|
| 70 |
+
img_line_break_token (`str`, *optional*, defaults to `"<|IMG_LINE_BREAK|>"`):
|
| 71 |
+
The token to be used to represent a line break in the text.
|
| 72 |
+
tile_token (`str`, *optional*, defaults to `"TILE"`):
|
| 73 |
+
The token to be used to represent an image patch in the text.
|
| 74 |
+
tile_global_token (`str`, *optional*, defaults to `"TILE_GLOBAL"`):
|
| 75 |
+
The token to be used to represent the cover image in the text.
|
| 76 |
+
"""
|
| 77 |
+
super().__init__(image_processor, tokenizer, chat_template=chat_template)
|
| 78 |
+
|
| 79 |
+
self.image_token = image_token
|
| 80 |
+
self.patch_size = patch_size * downsample_factor
|
| 81 |
+
self.img_size = img_size
|
| 82 |
+
|
| 83 |
+
self.start_of_img_token = start_of_img_token
|
| 84 |
+
self.end_of_img_token = end_of_img_token
|
| 85 |
+
self.img_patch_token = img_patch_token
|
| 86 |
+
self.img_line_break_token = img_line_break_token
|
| 87 |
+
self.tile_token = tile_token
|
| 88 |
+
self.tile_global_token = tile_global_token
|
| 89 |
+
self.image_token_id = tokenizer.convert_tokens_to_ids(self.img_patch_token)
|
| 90 |
+
self.image_ids = tokenizer.convert_tokens_to_ids(
|
| 91 |
+
[img_patch_token, tile_token, tile_global_token, start_of_img_token, end_of_img_token]
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
def _prompt_split_image(self, num_patches):
|
| 95 |
+
"""
|
| 96 |
+
Create a structured string representation of image tokens
|
| 97 |
+
|
| 98 |
+
Args:
|
| 99 |
+
num_patches: Number of patches in the image
|
| 100 |
+
|
| 101 |
+
Returns:
|
| 102 |
+
String with appropriate image tokens
|
| 103 |
+
"""
|
| 104 |
+
|
| 105 |
+
img_patches_per_tile = (self.img_size // self.patch_size) ** 2
|
| 106 |
+
img_string = f"{self.start_of_img_token}"
|
| 107 |
+
if num_patches > 1:
|
| 108 |
+
for idx in range(1, num_patches):
|
| 109 |
+
img_string += f"{self.tile_token}_{idx}" + f"{self.img_patch_token}" * img_patches_per_tile
|
| 110 |
+
|
| 111 |
+
img_string += f"{self.tile_global_token}" + f"{self.img_patch_token}" * img_patches_per_tile
|
| 112 |
+
img_string += f"{self.end_of_img_token}"
|
| 113 |
+
return img_string
|
| 114 |
+
|
| 115 |
+
@auto_docstring
|
| 116 |
+
def __call__(
|
| 117 |
+
self,
|
| 118 |
+
images: ImageInput | None = None,
|
| 119 |
+
text: TextInput | PreTokenizedInput | list[TextInput] | list[PreTokenizedInput] | None = None,
|
| 120 |
+
**kwargs: Unpack[AyaVisionProcessorKwargs],
|
| 121 |
+
) -> BatchFeature:
|
| 122 |
+
r"""
|
| 123 |
+
Returns:
|
| 124 |
+
[`BatchFeature`]: A [`BatchFeature`] with the following fields:
|
| 125 |
+
|
| 126 |
+
- **input_ids** -- List of token ids to be fed to a model. Returned when `text` is not `None`.
|
| 127 |
+
- **attention_mask** -- List of indices specifying which tokens should be attended to by the model (when
|
| 128 |
+
`return_attention_mask=True` or if *"attention_mask"* is in `self.model_input_names` and if `text` is not
|
| 129 |
+
`None`).
|
| 130 |
+
- **pixel_values** -- Pixel values to be fed to a model. Returned when `images` is not `None`.
|
| 131 |
+
"""
|
| 132 |
+
if text is None:
|
| 133 |
+
raise ValueError("You have to specify text.")
|
| 134 |
+
|
| 135 |
+
output_kwargs = self._merge_kwargs(
|
| 136 |
+
AyaVisionProcessorKwargs,
|
| 137 |
+
tokenizer_init_kwargs=self.tokenizer.init_kwargs,
|
| 138 |
+
**kwargs,
|
| 139 |
+
)
|
| 140 |
+
|
| 141 |
+
if not isinstance(text, (list, tuple)):
|
| 142 |
+
text = [text]
|
| 143 |
+
|
| 144 |
+
# Process images
|
| 145 |
+
image_inputs = {}
|
| 146 |
+
if images is not None:
|
| 147 |
+
images = self.image_processor.fetch_images(images)
|
| 148 |
+
images = make_flat_list_of_images(images)
|
| 149 |
+
image_inputs = self.image_processor(images=images, **output_kwargs["images_kwargs"])
|
| 150 |
+
num_patches = image_inputs.pop("num_patches")
|
| 151 |
+
image_index = 0
|
| 152 |
+
processed_text = []
|
| 153 |
+
for prompt in text:
|
| 154 |
+
new_prompt = prompt
|
| 155 |
+
while "<image>" in new_prompt:
|
| 156 |
+
# Replace the image placeholder with structured image tokens
|
| 157 |
+
image_tokens = self._prompt_split_image(num_patches[image_index])
|
| 158 |
+
new_prompt = new_prompt.replace("<image>", image_tokens, 1)
|
| 159 |
+
image_index += 1
|
| 160 |
+
processed_text.append(new_prompt)
|
| 161 |
+
|
| 162 |
+
if image_index != len(images):
|
| 163 |
+
raise ValueError("Number of image placeholders in the prompt does not match the number of images.")
|
| 164 |
+
|
| 165 |
+
text = processed_text
|
| 166 |
+
|
| 167 |
+
return_tensors = output_kwargs["text_kwargs"].pop("return_tensors", None)
|
| 168 |
+
return_mm_token_type_ids = output_kwargs["text_kwargs"].pop("return_mm_token_type_ids", False)
|
| 169 |
+
text_inputs = self.tokenizer(text, **output_kwargs["text_kwargs"], return_tensors=None)
|
| 170 |
+
|
| 171 |
+
if return_mm_token_type_ids:
|
| 172 |
+
text_inputs["mm_token_type_ids"] = self.create_mm_token_type_ids(text_inputs["input_ids"])
|
| 173 |
+
return BatchFeature(data={**text_inputs, **image_inputs}, tensor_type=return_tensors)
|
| 174 |
+
|
| 175 |
+
def _get_num_multimodal_tokens(self, image_sizes=None, **kwargs):
|
| 176 |
+
"""
|
| 177 |
+
Computes the number of placeholder tokens needed for multimodal inputs with the given sizes.
|
| 178 |
+
|
| 179 |
+
Args:
|
| 180 |
+
image_sizes (`list[list[int]]`, *optional*):
|
| 181 |
+
The input sizes formatted as (height, width) per each image.
|
| 182 |
+
|
| 183 |
+
Returns:
|
| 184 |
+
`MultiModalData`: A `MultiModalData` object holding number of tokens per each of the provided
|
| 185 |
+
input modalities, along with other useful data.
|
| 186 |
+
"""
|
| 187 |
+
|
| 188 |
+
vision_data = {}
|
| 189 |
+
if image_sizes is not None:
|
| 190 |
+
images_kwargs = AyaVisionProcessorKwargs._defaults.get("images_kwargs", {})
|
| 191 |
+
images_kwargs.update(kwargs)
|
| 192 |
+
|
| 193 |
+
num_image_patches = [
|
| 194 |
+
self.image_processor.get_number_of_image_patches(*image_size, images_kwargs)
|
| 195 |
+
for image_size in image_sizes
|
| 196 |
+
]
|
| 197 |
+
|
| 198 |
+
token_per_patch = (self.img_size // self.patch_size) ** 2
|
| 199 |
+
num_image_tokens = [
|
| 200 |
+
token_per_patch + 3 + sum(token_per_patch + 1 for _ in range(1, num_patches))
|
| 201 |
+
for num_patches in num_image_patches
|
| 202 |
+
] # Add +3 and +1 for BOI/EOI and image tile tokens
|
| 203 |
+
vision_data.update({"num_image_tokens": num_image_tokens, "num_image_patches": num_image_patches})
|
| 204 |
+
|
| 205 |
+
return MultiModalData(**vision_data)
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
__all__ = ["AyaVisionProcessor"]
|
third_party/transformers/src/transformers/models/blt/__init__.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .configuration_blt import *
|
| 22 |
+
from .modeling_blt import *
|
| 23 |
+
from .tokenization_blt import *
|
| 24 |
+
else:
|
| 25 |
+
import sys
|
| 26 |
+
|
| 27 |
+
_file = globals()["__file__"]
|
| 28 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/blt/configuration_blt.py
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Blt model configuration"""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from ...configuration_utils import PreTrainedConfig
|
| 19 |
+
from ...modeling_rope_utils import RopeParameters
|
| 20 |
+
from ...utils import auto_docstring, logging
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
logger = logging.get_logger(__name__)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
@auto_docstring(checkpoint="itazap/blt-1b-hf")
|
| 27 |
+
@strict
|
| 28 |
+
class BltLocalEncoderConfig(PreTrainedConfig):
|
| 29 |
+
r"""
|
| 30 |
+
cross_attn_all_layers (`bool`, *optional*, defaults to `True`):
|
| 31 |
+
Whether all attention layers have cross attention.
|
| 32 |
+
cross_attn_k (`int`, *optional*, defaults to 2):
|
| 33 |
+
Number of cross-attention heads used in the model.
|
| 34 |
+
hidden_size_global (`int`, *int*, defaults to 2048):
|
| 35 |
+
Hidden size of the global transformer layer.
|
| 36 |
+
"""
|
| 37 |
+
|
| 38 |
+
model_type = "blt_local_encoder"
|
| 39 |
+
default_theta = 500000.0
|
| 40 |
+
|
| 41 |
+
vocab_size: int = 260
|
| 42 |
+
cross_attn_all_layers: bool | None = False
|
| 43 |
+
cross_attn_k: int | None = 2
|
| 44 |
+
hidden_size_global: int | None = 2048
|
| 45 |
+
hidden_size: int = 1024
|
| 46 |
+
num_attention_heads: int = 16
|
| 47 |
+
num_key_value_heads: int | None = None
|
| 48 |
+
num_hidden_layers: int = 1
|
| 49 |
+
rms_norm_eps: float = 1e-5
|
| 50 |
+
dropout: float | int | None = 0.0
|
| 51 |
+
max_position_embeddings: int = 24576
|
| 52 |
+
rope_parameters: RopeParameters | dict | None = None
|
| 53 |
+
hidden_act: str = "silu"
|
| 54 |
+
intermediate_size: int | None = None
|
| 55 |
+
initializer_range: float = 0.02
|
| 56 |
+
|
| 57 |
+
def __post_init__(self, **kwargs):
|
| 58 |
+
self.num_key_value_heads = self.num_key_value_heads or self.num_attention_heads
|
| 59 |
+
self.intermediate_size = self.intermediate_size or int(8 * self.hidden_size / 3)
|
| 60 |
+
self.tie_word_embeddings = False
|
| 61 |
+
super().__post_init__(**kwargs)
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
@auto_docstring(checkpoint="itazap/blt-1b-hf")
|
| 65 |
+
@strict
|
| 66 |
+
class BltLocalDecoderConfig(PreTrainedConfig):
|
| 67 |
+
r"""
|
| 68 |
+
cross_attn_all_layers (`bool`, *optional*, defaults to `True`):
|
| 69 |
+
Whether all attention layers have cross attention.
|
| 70 |
+
cross_attn_k (`int`, *optional*, defaults to 2):
|
| 71 |
+
Number of cross-attention heads used in the model.
|
| 72 |
+
hidden_size_global (`int`, *int*, defaults to 2048):
|
| 73 |
+
Hidden size of the global transformer layer.
|
| 74 |
+
"""
|
| 75 |
+
|
| 76 |
+
model_type = "blt_local_decoder"
|
| 77 |
+
default_theta = 500000.0
|
| 78 |
+
|
| 79 |
+
vocab_size: int = 260
|
| 80 |
+
cross_attn_all_layers: bool | None = True
|
| 81 |
+
cross_attn_k: int | None = 2
|
| 82 |
+
hidden_size_global: int | None = 2048
|
| 83 |
+
hidden_size: int = 1024
|
| 84 |
+
num_attention_heads: int = 16
|
| 85 |
+
num_key_value_heads: int | None = None
|
| 86 |
+
num_hidden_layers: int = 9
|
| 87 |
+
rms_norm_eps: float = 1e-5
|
| 88 |
+
dropout: float | int | None = 0.0
|
| 89 |
+
max_position_embeddings: int = 24576
|
| 90 |
+
rope_parameters: RopeParameters | dict | None = None
|
| 91 |
+
hidden_act: str = "silu"
|
| 92 |
+
intermediate_size: int = 2816
|
| 93 |
+
initializer_range: float = 0.02
|
| 94 |
+
pad_token_id: int | None = None
|
| 95 |
+
bos_token_id: int | None = None
|
| 96 |
+
eos_token_id: int | list[int] | None = None
|
| 97 |
+
tie_word_embeddings: bool = False
|
| 98 |
+
|
| 99 |
+
def __post_init__(self, **kwargs):
|
| 100 |
+
self.num_key_value_heads = self.num_key_value_heads or self.num_attention_heads
|
| 101 |
+
self.head_dim = self.hidden_size // self.num_attention_heads
|
| 102 |
+
self.intermediate_size = self.intermediate_size or int(8 * self.hidden_size / 3)
|
| 103 |
+
self.tie_word_embeddings = False # Force-set to False for BC
|
| 104 |
+
super().__post_init__(**kwargs)
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
@auto_docstring(checkpoint="itazap/blt-1b-hf")
|
| 108 |
+
@strict
|
| 109 |
+
class BltGlobalTransformerConfig(PreTrainedConfig):
|
| 110 |
+
model_type = "blt_global_transformer"
|
| 111 |
+
default_theta = 500000.0
|
| 112 |
+
|
| 113 |
+
hidden_size: int = 2048
|
| 114 |
+
num_attention_heads: int = 16
|
| 115 |
+
num_key_value_heads: int | None = None
|
| 116 |
+
num_hidden_layers: int = 25
|
| 117 |
+
rms_norm_eps: float = 1e-5
|
| 118 |
+
dropout: float | int | None = 0.0
|
| 119 |
+
max_position_embeddings: int = 4096
|
| 120 |
+
rope_parameters: RopeParameters | dict | None = None
|
| 121 |
+
hidden_act: str = "silu"
|
| 122 |
+
intermediate_size: int = 5632
|
| 123 |
+
initializer_range: float = 0.02
|
| 124 |
+
tie_word_embeddings: bool = False
|
| 125 |
+
|
| 126 |
+
def __post_init__(self, **kwargs):
|
| 127 |
+
self.num_key_value_heads = self.num_key_value_heads or self.num_attention_heads
|
| 128 |
+
self.head_dim = self.hidden_size // self.num_attention_heads
|
| 129 |
+
self.intermediate_size = self.intermediate_size or int(8 * self.hidden_size / 3)
|
| 130 |
+
self.tie_word_embeddings = False
|
| 131 |
+
|
| 132 |
+
super().__post_init__(**kwargs)
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
@auto_docstring(checkpoint="itazap/blt-1b-hf")
|
| 136 |
+
@strict
|
| 137 |
+
class BltPatcherConfig(PreTrainedConfig):
|
| 138 |
+
model_type = "blt_patcher"
|
| 139 |
+
|
| 140 |
+
vocab_size: int = 260
|
| 141 |
+
hidden_size: int = 768
|
| 142 |
+
num_hidden_layers: int = 14
|
| 143 |
+
num_attention_heads: int = 12
|
| 144 |
+
num_key_value_heads: int | None = None
|
| 145 |
+
max_position_embeddings: int = 8192
|
| 146 |
+
rms_norm_eps: float = 1e-5
|
| 147 |
+
dropout: float | int | None = 0.0
|
| 148 |
+
intermediate_size: int = 2048
|
| 149 |
+
rope_parameters: RopeParameters | dict | None = None
|
| 150 |
+
initializer_range: float = 0.02
|
| 151 |
+
tie_word_embeddings: bool = False
|
| 152 |
+
|
| 153 |
+
def __post_init__(self, **kwargs):
|
| 154 |
+
self.num_key_value_heads = self.num_key_value_heads or self.num_attention_heads
|
| 155 |
+
self.head_dim = self.hidden_size // self.num_attention_heads
|
| 156 |
+
self.intermediate_size = self.intermediate_size or int(8 * self.hidden_size / 3)
|
| 157 |
+
self.tie_word_embeddings = False
|
| 158 |
+
self.hidden_act = "silu" # Blt uses silu activation
|
| 159 |
+
|
| 160 |
+
super().__post_init__(**kwargs)
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
@auto_docstring(checkpoint="itazap/blt-1b-hf")
|
| 164 |
+
@strict
|
| 165 |
+
class BltConfig(PreTrainedConfig):
|
| 166 |
+
r"""
|
| 167 |
+
patch_in_forward (`bool`, *optional*, defaults to `True`):
|
| 168 |
+
Whether to perform patching during the forward pass.
|
| 169 |
+
patch_size (`int`, *optional*, defaults to 4):
|
| 170 |
+
Size of the patches used in the patching mechanism.
|
| 171 |
+
patching_mode (`str`, *optional*, defaults to `"entropy"`):
|
| 172 |
+
The mode used for patching, such as entropy-based patching.
|
| 173 |
+
patching_threshold (`float`, *optional*, defaults to 1.34):
|
| 174 |
+
Threshold value used for determining when to apply patches.
|
| 175 |
+
patching_batch_size (`int`, *optional*, defaults to 1):
|
| 176 |
+
Batch size used during the patching process.
|
| 177 |
+
max_patch_length (`int`, *optional*):
|
| 178 |
+
Maximum length of patches that can be generated.
|
| 179 |
+
cross_attn_k (`int`, *optional*, defaults to 2):
|
| 180 |
+
Number of cross-attention heads used in the model.
|
| 181 |
+
encoder_hash_byte_group_size (`list`, *optional*):
|
| 182 |
+
List of byte group sizes used in the encoder hash function.
|
| 183 |
+
encoder_hash_byte_group_vocab (`int`, *optional*, defaults to 500002):
|
| 184 |
+
Vocabulary size for the encoder hash byte groups.
|
| 185 |
+
encoder_hash_byte_group_nb_functions (`int`, *optional*, defaults to 1):
|
| 186 |
+
Number of hash functions used in the encoder byte grouping.
|
| 187 |
+
patcher_config (`BltPatcherConfig`, *optional*):
|
| 188 |
+
Configuration for the patcher component of the model.
|
| 189 |
+
global_config (`BltGlobalTransformerConfig`, *optional*):
|
| 190 |
+
Configuration for the global transformer component of the model.
|
| 191 |
+
|
| 192 |
+
Example:
|
| 193 |
+
```python
|
| 194 |
+
>>> from transformers import BltModel, BltConfig
|
| 195 |
+
|
| 196 |
+
>>> # Initializing a Blt configuration
|
| 197 |
+
>>> configuration = BltConfig()
|
| 198 |
+
|
| 199 |
+
>>> # Initializing a model from the configuration
|
| 200 |
+
>>> model = BltModel(configuration)
|
| 201 |
+
|
| 202 |
+
>>> # Accessing the model configuration
|
| 203 |
+
>>> configuration = model.config
|
| 204 |
+
```"""
|
| 205 |
+
|
| 206 |
+
model_type = "blt"
|
| 207 |
+
keys_to_ignore_at_inference = ["past_key_values"]
|
| 208 |
+
default_theta = 500000.0
|
| 209 |
+
sub_configs = {
|
| 210 |
+
"patcher_config": BltPatcherConfig,
|
| 211 |
+
"encoder_config": BltLocalEncoderConfig,
|
| 212 |
+
"decoder_config": BltLocalDecoderConfig,
|
| 213 |
+
"global_config": BltGlobalTransformerConfig,
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
vocab_size: int = 260
|
| 217 |
+
max_position_embeddings: int = 4096
|
| 218 |
+
patch_in_forward: bool | None = True
|
| 219 |
+
patch_size: int | None = 4
|
| 220 |
+
patching_mode: str | None = "entropy"
|
| 221 |
+
patching_threshold: float | None = 1.335442066192627
|
| 222 |
+
patching_batch_size: int | None = 1
|
| 223 |
+
max_patch_length: int | None = None
|
| 224 |
+
cross_attn_k: int | None = 2
|
| 225 |
+
encoder_hash_byte_group_size: list[int] | None = None
|
| 226 |
+
encoder_hash_byte_group_vocab: int | None = 500002
|
| 227 |
+
encoder_hash_byte_group_nb_functions: int | None = 1
|
| 228 |
+
patcher_config: dict | PreTrainedConfig | None = None
|
| 229 |
+
encoder_config: dict | PreTrainedConfig | None = None
|
| 230 |
+
decoder_config: dict | PreTrainedConfig | None = None
|
| 231 |
+
global_config: dict | PreTrainedConfig | None = None
|
| 232 |
+
tie_word_embeddings: bool = False
|
| 233 |
+
pad_token_id: int | None = None
|
| 234 |
+
bos_token_id: int | None = None
|
| 235 |
+
eos_token_id: int | list[int] | None = None
|
| 236 |
+
initializer_range: float = 0.02
|
| 237 |
+
rope_parameters: RopeParameters | dict | None = None
|
| 238 |
+
|
| 239 |
+
def __post_init__(self, **kwargs):
|
| 240 |
+
self.encoder_hash_byte_group_size = self.encoder_hash_byte_group_size or [3, 4, 5, 6, 7, 8]
|
| 241 |
+
|
| 242 |
+
# Initialize component configurations
|
| 243 |
+
if self.patcher_config is None:
|
| 244 |
+
self.patcher_config = BltPatcherConfig(initializer_range=self.initializer_range)
|
| 245 |
+
logger.info("patcher_config is None, using default Blt patcher config")
|
| 246 |
+
elif isinstance(self.patcher_config, dict):
|
| 247 |
+
self.patcher_config.setdefault("initializer_range", self.initializer_range)
|
| 248 |
+
self.patcher_config = BltPatcherConfig(**self.patcher_config)
|
| 249 |
+
|
| 250 |
+
if self.encoder_config is None:
|
| 251 |
+
self.encoder_config = BltLocalEncoderConfig(initializer_range=self.initializer_range)
|
| 252 |
+
logger.info("encoder_config is None, using default Blt encoder config")
|
| 253 |
+
elif isinstance(self.encoder_config, dict):
|
| 254 |
+
self.encoder_config.setdefault("initializer_range", self.initializer_range)
|
| 255 |
+
self.encoder_config = BltLocalEncoderConfig(**self.encoder_config)
|
| 256 |
+
|
| 257 |
+
if self.decoder_config is None:
|
| 258 |
+
self.decoder_config = BltLocalDecoderConfig(initializer_range=self.initializer_range)
|
| 259 |
+
logger.info("decoder_config is None, using default Blt decoder config")
|
| 260 |
+
elif isinstance(self.decoder_config, dict):
|
| 261 |
+
self.decoder_config.setdefault("initializer_range", self.initializer_range)
|
| 262 |
+
self.decoder_config = BltLocalDecoderConfig(**self.decoder_config)
|
| 263 |
+
|
| 264 |
+
if self.global_config is None:
|
| 265 |
+
self.global_config = BltGlobalTransformerConfig(initializer_range=self.initializer_range)
|
| 266 |
+
logger.info("global_config is None, using default Blt global config")
|
| 267 |
+
elif isinstance(self.global_config, dict):
|
| 268 |
+
self.global_config.setdefault("initializer_range", self.initializer_range)
|
| 269 |
+
self.global_config = BltGlobalTransformerConfig(**self.global_config)
|
| 270 |
+
|
| 271 |
+
# Determine if token embedding projection is needed based on dimension mismatch (7b)
|
| 272 |
+
encoder_cross_output_size = self.encoder_config.hidden_size * self.cross_attn_k
|
| 273 |
+
self.global_config.encoder_cross_output_size = (
|
| 274 |
+
encoder_cross_output_size if encoder_cross_output_size != self.global_config.hidden_size else None
|
| 275 |
+
)
|
| 276 |
+
|
| 277 |
+
super().__post_init__(**kwargs)
|
| 278 |
+
|
| 279 |
+
|
| 280 |
+
__all__ = [
|
| 281 |
+
"BltConfig",
|
| 282 |
+
"BltPatcherConfig",
|
| 283 |
+
"BltLocalEncoderConfig",
|
| 284 |
+
"BltLocalDecoderConfig",
|
| 285 |
+
"BltGlobalTransformerConfig",
|
| 286 |
+
]
|
third_party/transformers/src/transformers/models/blt/convert_blt_weights_to_hf.py
ADDED
|
@@ -0,0 +1,487 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import json
|
| 3 |
+
import logging
|
| 4 |
+
import os
|
| 5 |
+
from typing import Any
|
| 6 |
+
|
| 7 |
+
import torch
|
| 8 |
+
from huggingface_hub import hf_hub_download, upload_folder
|
| 9 |
+
from safetensors.torch import load_file, save_file
|
| 10 |
+
from tokenizers import Tokenizer, decoders, pre_tokenizers, processors
|
| 11 |
+
from tokenizers.models import BPE
|
| 12 |
+
|
| 13 |
+
from transformers import PreTrainedTokenizerFast
|
| 14 |
+
from transformers.convert_slow_tokenizer import bytes_to_unicode
|
| 15 |
+
from transformers.utils import logging as transformers_logging
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
logger = transformers_logging.get_logger(__name__)
|
| 19 |
+
transformers_logging.set_verbosity_info()
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def merge_configurations(config_path: str, entropy_params_path: str) -> dict[str, Any]:
|
| 23 |
+
logger.info("Merging configurations")
|
| 24 |
+
|
| 25 |
+
with open(config_path, "r") as f:
|
| 26 |
+
main_config = json.load(f)
|
| 27 |
+
|
| 28 |
+
with open(entropy_params_path, "r") as f:
|
| 29 |
+
entropy_data = json.load(f)
|
| 30 |
+
|
| 31 |
+
entropy_model_params = entropy_data.get("entropy_model", {})
|
| 32 |
+
patcher_args = entropy_data.get("data", {}).get("patcher_args", {})
|
| 33 |
+
|
| 34 |
+
unified_config = main_config.copy()["args"]
|
| 35 |
+
|
| 36 |
+
for key in ["vocab_size", "dim", "n_layers", "n_heads", "max_seqlen"]:
|
| 37 |
+
if key in unified_config and not isinstance(unified_config[key], int):
|
| 38 |
+
unified_config[key] = int(unified_config[key])
|
| 39 |
+
|
| 40 |
+
patch_size = patcher_args.get("patch_size", 8)
|
| 41 |
+
if isinstance(patch_size, float):
|
| 42 |
+
patch_size = int(patch_size)
|
| 43 |
+
|
| 44 |
+
# Create patcher config
|
| 45 |
+
patcher_hidden_size = int(entropy_model_params.get("dim", 512))
|
| 46 |
+
patcher_multiple_of = int(entropy_model_params.get("multiple_of", 256))
|
| 47 |
+
patcher_intermediate_size = patcher_multiple_of * (
|
| 48 |
+
(int(8 * patcher_hidden_size / 3) + patcher_multiple_of - 1) // patcher_multiple_of
|
| 49 |
+
)
|
| 50 |
+
|
| 51 |
+
patcher_config = {
|
| 52 |
+
"vocab_size": int(entropy_model_params.get("vocab_size", 256)),
|
| 53 |
+
"hidden_size": patcher_hidden_size,
|
| 54 |
+
"num_hidden_layers": int(entropy_model_params.get("n_layers", 8)),
|
| 55 |
+
"num_attention_heads": int(entropy_model_params.get("n_heads", 8)),
|
| 56 |
+
"num_key_value_heads": int(entropy_model_params.get("n_kv_heads"))
|
| 57 |
+
if entropy_model_params.get("n_kv_heads") is not None
|
| 58 |
+
else None,
|
| 59 |
+
"max_position_embeddings": int(entropy_model_params.get("max_seqlen", 1024)),
|
| 60 |
+
"norm_eps": entropy_model_params.get("norm_eps", 1e-5),
|
| 61 |
+
"dropout": entropy_model_params.get("dropout", 0.0),
|
| 62 |
+
"rope_theta": entropy_model_params.get("rope_theta", 10000.0),
|
| 63 |
+
"attn_impl": entropy_model_params.get("attn_impl", "sdpa"),
|
| 64 |
+
"attn_bias_type": entropy_model_params.get("attn_bias_type", "causal"),
|
| 65 |
+
"intermediate_size": patcher_intermediate_size,
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
# Create encoder config
|
| 69 |
+
encoder_hidden_size = unified_config.get("dim_local_encoder", 1024)
|
| 70 |
+
encoder_multiple_of = unified_config.get("multiple_of", 256)
|
| 71 |
+
encoder_intermediate_size = encoder_multiple_of * (
|
| 72 |
+
(int(8 * encoder_hidden_size / 3) + encoder_multiple_of - 1) // encoder_multiple_of
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
encoder_config = {
|
| 76 |
+
"vocab_size": unified_config.get("vocab_size", 256),
|
| 77 |
+
"cross_attn_all_layers": unified_config.get("cross_attn_all_layers_encoder", False),
|
| 78 |
+
"cross_attn_k": unified_config.get("cross_attn_k", 2),
|
| 79 |
+
"hidden_size_global": unified_config.get("dim_global", 2048),
|
| 80 |
+
"pm_size": unified_config.get("pm_size", 0),
|
| 81 |
+
"hidden_size": encoder_hidden_size,
|
| 82 |
+
"num_attention_heads": unified_config.get("n_heads_local_encoder", 16),
|
| 83 |
+
"num_key_value_heads": unified_config.get("n_kv_heads"),
|
| 84 |
+
"num_hidden_layers": unified_config.get("n_layers_local_encoder", 1),
|
| 85 |
+
"norm_eps": unified_config.get("norm_eps", 1e-5),
|
| 86 |
+
"dropout": unified_config.get("dropout", 0.0),
|
| 87 |
+
"max_position_embeddings": unified_config.get("max_encoder_seq_length")
|
| 88 |
+
or unified_config.get("max_seqlen", 1024),
|
| 89 |
+
"rope_theta": unified_config.get("rope_theta", 10000.0),
|
| 90 |
+
"rope_parameters": {"rope_type": "default"},
|
| 91 |
+
"hidden_act": unified_config.get("hidden_act", "silu"),
|
| 92 |
+
"_attn_implementation": unified_config.get("_attn_implementation", "sdpa"),
|
| 93 |
+
"intermediate_size": encoder_intermediate_size,
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
# Create decoder config
|
| 97 |
+
decoder_hidden_size = unified_config.get("dim_local_decoder", 1024)
|
| 98 |
+
decoder_multiple_of = unified_config.get("multiple_of", 256)
|
| 99 |
+
decoder_intermediate_size = decoder_multiple_of * (
|
| 100 |
+
(int(8 * decoder_hidden_size / 3) + decoder_multiple_of - 1) // decoder_multiple_of
|
| 101 |
+
)
|
| 102 |
+
|
| 103 |
+
decoder_config = {
|
| 104 |
+
"vocab_size": unified_config.get("vocab_size", 256),
|
| 105 |
+
"cross_attn_all_layers": unified_config.get("cross_attn_all_layers_decoder", False),
|
| 106 |
+
"cross_attn_k": unified_config.get("cross_attn_k", 2),
|
| 107 |
+
"hidden_size_global": unified_config.get("dim_global", 2048),
|
| 108 |
+
"hidden_size": decoder_hidden_size,
|
| 109 |
+
"num_attention_heads": unified_config.get("n_heads_local_decoder", 16),
|
| 110 |
+
"num_key_value_heads": unified_config.get("n_kv_heads"),
|
| 111 |
+
"num_hidden_layers": unified_config.get("n_layers_local_decoder", 9),
|
| 112 |
+
"norm_eps": unified_config.get("norm_eps", 1e-5),
|
| 113 |
+
"dropout": unified_config.get("dropout", 0.0),
|
| 114 |
+
"max_position_embeddings": unified_config.get("max_encoder_seq_length")
|
| 115 |
+
or unified_config.get("max_seqlen", 1024),
|
| 116 |
+
"rope_theta": unified_config.get("rope_theta", 10000.0),
|
| 117 |
+
"rope_parameters": {"rope_type": "default"},
|
| 118 |
+
"hidden_act": unified_config.get("hidden_act", "silu"),
|
| 119 |
+
"_attn_implementation": unified_config.get("_attn_implementation", "sdpa"),
|
| 120 |
+
"intermediate_size": decoder_intermediate_size,
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
# Create global transformer config
|
| 124 |
+
global_hidden_size = unified_config.get("dim_global", 2048)
|
| 125 |
+
global_multiple_of = unified_config.get("multiple_of", 256)
|
| 126 |
+
global_intermediate_size = global_multiple_of * (
|
| 127 |
+
(int(8 * global_hidden_size / 3) + global_multiple_of - 1) // global_multiple_of
|
| 128 |
+
)
|
| 129 |
+
|
| 130 |
+
global_config = {
|
| 131 |
+
"hidden_size": global_hidden_size,
|
| 132 |
+
"num_attention_heads": unified_config.get("n_heads_global", 16),
|
| 133 |
+
"num_key_value_heads": unified_config.get("n_kv_heads_global"),
|
| 134 |
+
"num_hidden_layers": unified_config.get("n_layers_global", 25),
|
| 135 |
+
"norm_eps": unified_config.get("norm_eps", 1e-5),
|
| 136 |
+
"dropout": unified_config.get("dropout", 0.0),
|
| 137 |
+
"max_position_embeddings": unified_config.get("max_seqlen", 1024),
|
| 138 |
+
"rope_theta": unified_config.get("rope_theta", 10000.0),
|
| 139 |
+
"rope_parameters": {"rope_type": "default"},
|
| 140 |
+
"hidden_act": unified_config.get("hidden_act", "silu"),
|
| 141 |
+
"_attn_implementation": unified_config.get("_attn_implementation", "sdpa"),
|
| 142 |
+
"intermediate_size": global_intermediate_size,
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
# Create main config with sub-configs
|
| 146 |
+
main_config_dict = {
|
| 147 |
+
"model_type": "blt",
|
| 148 |
+
"vocab_size": unified_config.get("vocab_size", 256),
|
| 149 |
+
"max_position_embeddings": unified_config.get("max_seqlen", 1024),
|
| 150 |
+
"patch_in_forward": True,
|
| 151 |
+
"realtime_patching": True,
|
| 152 |
+
"patching_mode": "entropy",
|
| 153 |
+
"patch_size": patch_size,
|
| 154 |
+
"patching_threshold": patcher_args.get("threshold", 0.5),
|
| 155 |
+
"patching_threshold_add": patcher_args.get("threshold_add", 0.0),
|
| 156 |
+
"max_patch_length": patcher_args.get("max_patch_length"),
|
| 157 |
+
"patching_batch_size": patcher_args.get("patching_batch_size", 1),
|
| 158 |
+
"patching_device": patcher_args.get("patching_device", "cuda"),
|
| 159 |
+
"monotonicity": patcher_args.get("monotonicity", False),
|
| 160 |
+
"cross_attn_k": unified_config.get("cross_attn_k", 2),
|
| 161 |
+
"encoder_hash_byte_group_size": unified_config.get("encoder_hash_byte_group_size"),
|
| 162 |
+
"encoder_hash_byte_group_vocab": unified_config.get("encoder_hash_byte_group_vocab", 30000),
|
| 163 |
+
"encoder_hash_byte_group_nb_functions": unified_config.get("encoder_hash_byte_group_nb_functions", 3),
|
| 164 |
+
"pm_size": unified_config.get("pm_size", 0),
|
| 165 |
+
"patcher_config": patcher_config,
|
| 166 |
+
"encoder_config": encoder_config,
|
| 167 |
+
"decoder_config": decoder_config,
|
| 168 |
+
"global_config": global_config,
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
main_config_dict["tie_word_embeddings"] = False
|
| 172 |
+
|
| 173 |
+
logger.info(f"Merged configuration with {len(main_config_dict)} parameters")
|
| 174 |
+
return main_config_dict
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
def apply_weight_mapping(state_dict: dict[str, torch.Tensor]) -> dict[str, torch.Tensor]:
|
| 178 |
+
component_mappings = {
|
| 179 |
+
".attention.": ".self_attn.",
|
| 180 |
+
".feed_forward.": ".mlp.",
|
| 181 |
+
".attention_norm.": ".input_layernorm.",
|
| 182 |
+
".ffn_norm.": ".post_attention_layernorm.",
|
| 183 |
+
".tok_embeddings.": ".embed_tokens.",
|
| 184 |
+
".cross_attn_norm_q.": ".q_norm.",
|
| 185 |
+
".cross_attn_norm_kv.": ".k_norm.",
|
| 186 |
+
".w1.": ".gate_proj.",
|
| 187 |
+
".w2.": ".down_proj.",
|
| 188 |
+
".w3.": ".up_proj.",
|
| 189 |
+
".wq.": ".q_proj.",
|
| 190 |
+
".wk.": ".k_proj.",
|
| 191 |
+
".wv.": ".v_proj.",
|
| 192 |
+
".wo.": ".o_proj.",
|
| 193 |
+
".output.": ".lm_head.",
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
new_state_dict = {}
|
| 197 |
+
|
| 198 |
+
for old_key, tensor in state_dict.items():
|
| 199 |
+
new_key = old_key
|
| 200 |
+
|
| 201 |
+
for old_pattern, new_pattern in component_mappings.items():
|
| 202 |
+
if old_pattern in new_key:
|
| 203 |
+
new_key = new_key.replace(old_pattern, new_pattern)
|
| 204 |
+
|
| 205 |
+
new_state_dict[new_key] = tensor
|
| 206 |
+
|
| 207 |
+
return new_state_dict
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
def convert_hash_embeddings_to_fused(
|
| 211 |
+
unified_weights: dict[str, torch.Tensor], config: dict[str, Any]
|
| 212 |
+
) -> dict[str, torch.Tensor]:
|
| 213 |
+
"""Convert ModuleList hash embeddings to nn.embedding format"""
|
| 214 |
+
original_keys_format = [
|
| 215 |
+
key
|
| 216 |
+
for key in unified_weights.keys()
|
| 217 |
+
if "encoder_hash_tok_embedding." in key and ".weight" in key and key.split(".")[-2].isdigit()
|
| 218 |
+
]
|
| 219 |
+
|
| 220 |
+
num_embeddings = config.get("encoder_hash_byte_group_nb_functions", 1) * len(
|
| 221 |
+
config.get("encoder_hash_byte_group_size", [3, 4, 5, 6, 7, 8])
|
| 222 |
+
)
|
| 223 |
+
vocab_size = config.get("encoder_hash_byte_group_vocab", 500002)
|
| 224 |
+
hidden_size = config.get("encoder_config", {}).get("hidden_size", 1024)
|
| 225 |
+
|
| 226 |
+
fused_weight = torch.zeros(vocab_size * num_embeddings, hidden_size)
|
| 227 |
+
|
| 228 |
+
sorted_keys = sorted(original_keys_format, key=lambda k: int(k.split(".")[-2]))
|
| 229 |
+
|
| 230 |
+
for i, old_key in enumerate(sorted_keys):
|
| 231 |
+
start_idx = i * vocab_size
|
| 232 |
+
end_idx = (i + 1) * vocab_size
|
| 233 |
+
fused_weight[start_idx:end_idx] = unified_weights[old_key]
|
| 234 |
+
logger.info(f"Copied {old_key} to indices {start_idx}:{end_idx}")
|
| 235 |
+
del unified_weights[old_key]
|
| 236 |
+
|
| 237 |
+
fused_key = "model.encoder_hash_tok_embedding.weight"
|
| 238 |
+
unified_weights[fused_key] = fused_weight
|
| 239 |
+
|
| 240 |
+
return unified_weights
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
def merge_weights(weights_path: str, entropy_weights_path: str) -> dict[str, torch.Tensor]:
|
| 244 |
+
main_weights = load_file(weights_path)
|
| 245 |
+
|
| 246 |
+
entropy_weights = torch.load(entropy_weights_path, map_location="cpu", weights_only=True)
|
| 247 |
+
|
| 248 |
+
if "model" in entropy_weights:
|
| 249 |
+
entropy_weights = entropy_weights["model"]
|
| 250 |
+
elif "state_dict" in entropy_weights:
|
| 251 |
+
entropy_weights = entropy_weights["state_dict"]
|
| 252 |
+
|
| 253 |
+
unified_weights = main_weights.copy()
|
| 254 |
+
|
| 255 |
+
for key, tensor in entropy_weights.items():
|
| 256 |
+
patcher_key = f"patcher.{key}"
|
| 257 |
+
unified_weights[patcher_key] = tensor
|
| 258 |
+
|
| 259 |
+
unified_weights = apply_weight_mapping(unified_weights)
|
| 260 |
+
|
| 261 |
+
decoder_lm_head_key = "local_decoder.lm_head.weight"
|
| 262 |
+
top_lm_head_key = "lm_head.weight"
|
| 263 |
+
unified_weights[top_lm_head_key] = unified_weights[decoder_lm_head_key]
|
| 264 |
+
del unified_weights[decoder_lm_head_key]
|
| 265 |
+
|
| 266 |
+
prefixed_weights = {}
|
| 267 |
+
for key, tensor in unified_weights.items():
|
| 268 |
+
if key == top_lm_head_key:
|
| 269 |
+
prefixed_weights[key] = tensor
|
| 270 |
+
elif not key.startswith("model."):
|
| 271 |
+
prefixed_weights[f"model.{key}"] = tensor
|
| 272 |
+
else:
|
| 273 |
+
prefixed_weights[key] = tensor
|
| 274 |
+
|
| 275 |
+
unified_weights = prefixed_weights
|
| 276 |
+
|
| 277 |
+
return unified_weights
|
| 278 |
+
|
| 279 |
+
|
| 280 |
+
def create_tokenizer_config(output_dir: str, config: dict[str, Any]):
|
| 281 |
+
tokenizer_config = {
|
| 282 |
+
"tokenizer_class": "PreTrainedTokenizerFast",
|
| 283 |
+
"vocab_size": config.get("vocab_size", 256),
|
| 284 |
+
"model_max_length": config.get("max_seqlen", 1024),
|
| 285 |
+
"model_input_names": ["input_ids", "attention_mask"],
|
| 286 |
+
"add_bos_token": True,
|
| 287 |
+
"add_eos_token": True,
|
| 288 |
+
"bos_token": "<s>",
|
| 289 |
+
"eos_token": "</s>",
|
| 290 |
+
"pad_token": "<pad>",
|
| 291 |
+
"unk_token": "<unk>",
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
tokenizer_path = os.path.join(output_dir, "tokenizer_config.json")
|
| 295 |
+
with open(tokenizer_path, "w") as f:
|
| 296 |
+
json.dump(tokenizer_config, f, indent=2)
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
def create_tokenizer_json(output_dir: str, config: dict[str, Any]):
|
| 300 |
+
byte_encoder = bytes_to_unicode()
|
| 301 |
+
|
| 302 |
+
vocab: dict[str, int] = {}
|
| 303 |
+
vocab["<boe>"] = 0
|
| 304 |
+
vocab["<s>"] = 1
|
| 305 |
+
vocab["</s>"] = 2
|
| 306 |
+
vocab["<pad>"] = 3
|
| 307 |
+
|
| 308 |
+
offset = 4
|
| 309 |
+
for byte_val, unicode_char in byte_encoder.items():
|
| 310 |
+
vocab[unicode_char] = byte_val + offset
|
| 311 |
+
|
| 312 |
+
backend = Tokenizer(
|
| 313 |
+
BPE(vocab=vocab, merges=[], continuing_subword_prefix="", end_of_word_suffix="", fuse_unk=False)
|
| 314 |
+
)
|
| 315 |
+
backend.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False)
|
| 316 |
+
backend.decoder = decoders.ByteLevel()
|
| 317 |
+
|
| 318 |
+
bos = config.get("bos_token", "<s>")
|
| 319 |
+
backend.post_processor = processors.TemplateProcessing(
|
| 320 |
+
single=f"{bos}:0 $A:0",
|
| 321 |
+
pair=f"{bos}:0 $A:0 $B:1",
|
| 322 |
+
special_tokens=[(bos, 1)],
|
| 323 |
+
)
|
| 324 |
+
|
| 325 |
+
tokenizer = PreTrainedTokenizerFast(
|
| 326 |
+
tokenizer_object=backend,
|
| 327 |
+
bos_token=config.get("bos_token", "<s>"),
|
| 328 |
+
eos_token=config.get("eos_token", "</s>"),
|
| 329 |
+
pad_token=config.get("pad_token", "<pad>"),
|
| 330 |
+
unk_token=config.get("unk_token", "<unk>"),
|
| 331 |
+
)
|
| 332 |
+
|
| 333 |
+
tokenizer.add_bos_token = bool(config.get("add_bos_token", True))
|
| 334 |
+
tokenizer.add_eos_token = bool(config.get("add_eos_token", True))
|
| 335 |
+
|
| 336 |
+
tokenizer.save_pretrained(output_dir)
|
| 337 |
+
logger.info(f"Saved tokenizer.json to {os.path.join(output_dir, 'tokenizer.json')}")
|
| 338 |
+
|
| 339 |
+
|
| 340 |
+
def push_to_hub(
|
| 341 |
+
local_dir: str,
|
| 342 |
+
repo_id: str,
|
| 343 |
+
commit_message: str = "Upload converted Blt model",
|
| 344 |
+
private: bool = False,
|
| 345 |
+
token: str | None = None,
|
| 346 |
+
) -> None:
|
| 347 |
+
try:
|
| 348 |
+
upload_folder(
|
| 349 |
+
folder_path=local_dir,
|
| 350 |
+
repo_id=repo_id,
|
| 351 |
+
commit_message=commit_message,
|
| 352 |
+
repo_type="model",
|
| 353 |
+
token=token,
|
| 354 |
+
)
|
| 355 |
+
logger.info(f"Successfully pushed model to {repo_id}")
|
| 356 |
+
|
| 357 |
+
except Exception as e:
|
| 358 |
+
logger.error(f"Failed to push model to Hub: {e}")
|
| 359 |
+
raise
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
def convert_hf_blt_to_unified(
|
| 363 |
+
model_id: str,
|
| 364 |
+
output_dir: str,
|
| 365 |
+
config_name: str = "config.json",
|
| 366 |
+
weights_name: str = "model.bin",
|
| 367 |
+
cache_dir: str | None = None,
|
| 368 |
+
push_to_hub_repo: str | None = None,
|
| 369 |
+
hub_private: bool = False,
|
| 370 |
+
hub_token: str | None = None,
|
| 371 |
+
) -> None:
|
| 372 |
+
# Download model files
|
| 373 |
+
config_path = hf_hub_download(repo_id=model_id, filename="config.json", cache_dir=cache_dir)
|
| 374 |
+
weights_path = hf_hub_download(repo_id=model_id, filename="model.safetensors", cache_dir=cache_dir)
|
| 375 |
+
entropy_params_path = hf_hub_download(repo_id=model_id, filename="entropy_model/params.json", cache_dir=cache_dir)
|
| 376 |
+
entropy_weights_path = hf_hub_download(
|
| 377 |
+
repo_id=model_id, filename="entropy_model/consolidated.pth", cache_dir=cache_dir
|
| 378 |
+
)
|
| 379 |
+
|
| 380 |
+
unified_config = merge_configurations(config_path, entropy_params_path)
|
| 381 |
+
unified_weights = merge_weights(weights_path, entropy_weights_path)
|
| 382 |
+
|
| 383 |
+
unified_weights = convert_hash_embeddings_to_fused(unified_weights, unified_config)
|
| 384 |
+
|
| 385 |
+
os.makedirs(output_dir, exist_ok=True)
|
| 386 |
+
|
| 387 |
+
config_path = os.path.join(output_dir, config_name)
|
| 388 |
+
with open(config_path, "w") as f:
|
| 389 |
+
json.dump(unified_config, f, indent=2)
|
| 390 |
+
|
| 391 |
+
if weights_name.endswith(".bin"):
|
| 392 |
+
weights_name = weights_name.replace(".bin", ".safetensors")
|
| 393 |
+
|
| 394 |
+
weights_path = os.path.join(output_dir, weights_name)
|
| 395 |
+
save_file(unified_weights, weights_path)
|
| 396 |
+
|
| 397 |
+
create_tokenizer_json(output_dir=output_dir, config=unified_config)
|
| 398 |
+
|
| 399 |
+
create_tokenizer_config(output_dir, unified_config)
|
| 400 |
+
|
| 401 |
+
logger.info(f"Conversion completed, model saved to: {output_dir}")
|
| 402 |
+
|
| 403 |
+
if push_to_hub_repo:
|
| 404 |
+
push_to_hub(
|
| 405 |
+
local_dir=output_dir,
|
| 406 |
+
repo_id=push_to_hub_repo,
|
| 407 |
+
commit_message="Upload Blt model converted",
|
| 408 |
+
private=hub_private,
|
| 409 |
+
token=hub_token,
|
| 410 |
+
)
|
| 411 |
+
|
| 412 |
+
|
| 413 |
+
def main():
|
| 414 |
+
parser = argparse.ArgumentParser(
|
| 415 |
+
description="Convert Blt models from HuggingFace Hub format to unified format",
|
| 416 |
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
| 417 |
+
)
|
| 418 |
+
|
| 419 |
+
parser.add_argument(
|
| 420 |
+
"--model_id",
|
| 421 |
+
type=str,
|
| 422 |
+
default="facebook/blt-7b",
|
| 423 |
+
)
|
| 424 |
+
parser.add_argument(
|
| 425 |
+
"--output_dir",
|
| 426 |
+
type=str,
|
| 427 |
+
default="./blt_converted",
|
| 428 |
+
)
|
| 429 |
+
parser.add_argument(
|
| 430 |
+
"--config_name",
|
| 431 |
+
type=str,
|
| 432 |
+
default="config.json",
|
| 433 |
+
)
|
| 434 |
+
parser.add_argument(
|
| 435 |
+
"--weights_name",
|
| 436 |
+
type=str,
|
| 437 |
+
default="model.bin",
|
| 438 |
+
)
|
| 439 |
+
parser.add_argument(
|
| 440 |
+
"--cache_dir",
|
| 441 |
+
type=str,
|
| 442 |
+
default=None,
|
| 443 |
+
)
|
| 444 |
+
parser.add_argument(
|
| 445 |
+
"--debug",
|
| 446 |
+
action="store_true",
|
| 447 |
+
default=True,
|
| 448 |
+
)
|
| 449 |
+
parser.add_argument(
|
| 450 |
+
"--push_to_hub",
|
| 451 |
+
type=str,
|
| 452 |
+
default=None,
|
| 453 |
+
)
|
| 454 |
+
parser.add_argument(
|
| 455 |
+
"--hub_private",
|
| 456 |
+
action="store_true",
|
| 457 |
+
default=False,
|
| 458 |
+
)
|
| 459 |
+
parser.add_argument(
|
| 460 |
+
"--hub_token",
|
| 461 |
+
type=str,
|
| 462 |
+
default="hf_token",
|
| 463 |
+
)
|
| 464 |
+
|
| 465 |
+
args = parser.parse_args()
|
| 466 |
+
|
| 467 |
+
transformers_logging.set_verbosity_debug()
|
| 468 |
+
logging.basicConfig(level=logging.DEBUG)
|
| 469 |
+
|
| 470 |
+
try:
|
| 471 |
+
convert_hf_blt_to_unified(
|
| 472 |
+
model_id=args.model_id,
|
| 473 |
+
output_dir=args.output_dir,
|
| 474 |
+
config_name=args.config_name,
|
| 475 |
+
weights_name=args.weights_name,
|
| 476 |
+
cache_dir=args.cache_dir,
|
| 477 |
+
push_to_hub_repo=False, # args.push_to_hub,
|
| 478 |
+
hub_private=args.hub_private,
|
| 479 |
+
hub_token=args.hub_token,
|
| 480 |
+
)
|
| 481 |
+
except Exception as e:
|
| 482 |
+
logger.error(f"Conversion failed: {e}")
|
| 483 |
+
raise
|
| 484 |
+
|
| 485 |
+
|
| 486 |
+
if __name__ == "__main__":
|
| 487 |
+
main()
|
third_party/transformers/src/transformers/models/blt/modeling_blt.py
ADDED
|
@@ -0,0 +1,1463 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 2 |
+
# This file was automatically generated from src/transformers/models/blt/modular_blt.py.
|
| 3 |
+
# Do NOT edit this file manually as any edits will be overwritten by the generation of
|
| 4 |
+
# the file from the modular. If any change should be done, please apply the change to the
|
| 5 |
+
# modular_blt.py file directly. One of our CI enforces this.
|
| 6 |
+
# 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
| 7 |
+
# Copyright 2025 HuggingFace Inc. team. All rights reserved.
|
| 8 |
+
#
|
| 9 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
# you may not use this file except in compliance with the License.
|
| 11 |
+
# You may obtain a copy of the License at
|
| 12 |
+
#
|
| 13 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 14 |
+
#
|
| 15 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 16 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 17 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 18 |
+
# See the License for the specific language governing permissions and
|
| 19 |
+
# limitations under the License.
|
| 20 |
+
|
| 21 |
+
from collections.abc import Callable
|
| 22 |
+
from typing import Optional
|
| 23 |
+
|
| 24 |
+
import torch
|
| 25 |
+
import torch.distributions
|
| 26 |
+
import torch.nn as nn
|
| 27 |
+
import torch.nn.functional as F
|
| 28 |
+
|
| 29 |
+
from ... import initialization as init
|
| 30 |
+
from ...activations import ACT2FN
|
| 31 |
+
from ...cache_utils import Cache, DynamicCache, EncoderDecoderCache
|
| 32 |
+
from ...generation import GenerationMixin
|
| 33 |
+
from ...masking_utils import create_causal_mask
|
| 34 |
+
from ...modeling_flash_attention_utils import FlashAttentionKwargs
|
| 35 |
+
from ...modeling_layers import GradientCheckpointingLayer
|
| 36 |
+
from ...modeling_outputs import BaseModelOutputWithPast, CausalLMOutputWithPast
|
| 37 |
+
from ...modeling_rope_utils import ROPE_INIT_FUNCTIONS, dynamic_rope_update
|
| 38 |
+
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
|
| 39 |
+
from ...processing_utils import Unpack
|
| 40 |
+
from ...utils import TransformersKwargs, auto_docstring, can_return_tuple
|
| 41 |
+
from ...utils.deprecation import deprecate_kwarg
|
| 42 |
+
from ...utils.generic import maybe_autocast, merge_with_config_defaults
|
| 43 |
+
from ...utils.output_capturing import OutputRecorder, capture_outputs
|
| 44 |
+
from .configuration_blt import (
|
| 45 |
+
BltConfig,
|
| 46 |
+
BltGlobalTransformerConfig,
|
| 47 |
+
BltLocalDecoderConfig,
|
| 48 |
+
BltLocalEncoderConfig,
|
| 49 |
+
BltPatcherConfig,
|
| 50 |
+
)
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
class BltMLP(nn.Module):
|
| 54 |
+
def __init__(self, config):
|
| 55 |
+
super().__init__()
|
| 56 |
+
self.config = config
|
| 57 |
+
self.hidden_size = config.hidden_size
|
| 58 |
+
self.intermediate_size = config.intermediate_size
|
| 59 |
+
self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
| 60 |
+
self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
| 61 |
+
self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
|
| 62 |
+
# Ignore copy
|
| 63 |
+
self.act_fn = ACT2FN[config.hidden_act]
|
| 64 |
+
|
| 65 |
+
def forward(self, x):
|
| 66 |
+
down_proj = self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
|
| 67 |
+
return down_proj
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
class BltRMSNorm(nn.Module):
|
| 71 |
+
def __init__(self, hidden_size, eps: float = 1e-6) -> None:
|
| 72 |
+
"""
|
| 73 |
+
BltRMSNorm is equivalent to T5LayerNorm
|
| 74 |
+
"""
|
| 75 |
+
super().__init__()
|
| 76 |
+
self.weight = nn.Parameter(torch.ones(hidden_size))
|
| 77 |
+
self.variance_epsilon = eps
|
| 78 |
+
|
| 79 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 80 |
+
input_dtype = hidden_states.dtype
|
| 81 |
+
hidden_states = hidden_states.to(torch.float32)
|
| 82 |
+
variance = hidden_states.pow(2).mean(-1, keepdim=True)
|
| 83 |
+
hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
|
| 84 |
+
return self.weight * hidden_states.to(input_dtype)
|
| 85 |
+
|
| 86 |
+
def extra_repr(self):
|
| 87 |
+
return f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}"
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
class BltRotaryEmbedding(nn.Module):
|
| 91 |
+
inv_freq: torch.Tensor # fix linting for `register_buffer`
|
| 92 |
+
|
| 93 |
+
def __init__(self, config: BltConfig, device=None):
|
| 94 |
+
super().__init__()
|
| 95 |
+
self.max_seq_len_cached = config.max_position_embeddings
|
| 96 |
+
self.original_max_seq_len = config.max_position_embeddings
|
| 97 |
+
|
| 98 |
+
self.config = config
|
| 99 |
+
|
| 100 |
+
self.rope_type = self.config.rope_parameters["rope_type"]
|
| 101 |
+
rope_init_fn: Callable = self.compute_default_rope_parameters
|
| 102 |
+
if self.rope_type != "default":
|
| 103 |
+
rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
|
| 104 |
+
inv_freq, self.attention_scaling = rope_init_fn(self.config, device)
|
| 105 |
+
|
| 106 |
+
self.register_buffer("inv_freq", inv_freq, persistent=False)
|
| 107 |
+
self.register_buffer("original_inv_freq", inv_freq.clone(), persistent=False)
|
| 108 |
+
|
| 109 |
+
@staticmethod
|
| 110 |
+
def compute_default_rope_parameters(
|
| 111 |
+
config: BltConfig | None = None,
|
| 112 |
+
device: Optional["torch.device"] = None,
|
| 113 |
+
seq_len: int | None = None,
|
| 114 |
+
) -> tuple["torch.Tensor", float]:
|
| 115 |
+
"""
|
| 116 |
+
Computes the inverse frequencies according to the original RoPE implementation
|
| 117 |
+
Args:
|
| 118 |
+
config ([`~transformers.PreTrainedConfig`]):
|
| 119 |
+
The model configuration.
|
| 120 |
+
device (`torch.device`):
|
| 121 |
+
The device to use for initialization of the inverse frequencies.
|
| 122 |
+
seq_len (`int`, *optional*):
|
| 123 |
+
The current sequence length. Unused for this type of RoPE.
|
| 124 |
+
Returns:
|
| 125 |
+
Tuple of (`torch.Tensor`, `float`), containing the inverse frequencies for the RoPE embeddings and the
|
| 126 |
+
post-processing scaling factor applied to the computed cos/sin (unused in this type of RoPE).
|
| 127 |
+
"""
|
| 128 |
+
base = config.rope_parameters["rope_theta"]
|
| 129 |
+
dim = getattr(config, "head_dim", None) or config.hidden_size // config.num_attention_heads
|
| 130 |
+
|
| 131 |
+
attention_factor = 1.0 # Unused in this type of RoPE
|
| 132 |
+
|
| 133 |
+
# Compute the inverse frequencies
|
| 134 |
+
inv_freq = 1.0 / (
|
| 135 |
+
base ** (torch.arange(0, dim, 2, dtype=torch.int64).to(device=device, dtype=torch.float) / dim)
|
| 136 |
+
)
|
| 137 |
+
return inv_freq, attention_factor
|
| 138 |
+
|
| 139 |
+
@torch.no_grad()
|
| 140 |
+
@dynamic_rope_update # power user: used with advanced RoPE types (e.g. dynamic rope)
|
| 141 |
+
def forward(self, x, position_ids):
|
| 142 |
+
inv_freq_expanded = self.inv_freq[None, :, None].float().expand(position_ids.shape[0], -1, 1)
|
| 143 |
+
position_ids_expanded = position_ids[:, None, :].float()
|
| 144 |
+
|
| 145 |
+
device_type = x.device.type if isinstance(x.device.type, str) and x.device.type != "mps" else "cpu"
|
| 146 |
+
with maybe_autocast(device_type=device_type, enabled=False): # Force float32
|
| 147 |
+
freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(1, 2)
|
| 148 |
+
emb = torch.repeat_interleave(freqs, 2, dim=-1) # diff from Llama: we interleave() instead of cat()
|
| 149 |
+
cos = emb.cos() * self.attention_scaling
|
| 150 |
+
sin = emb.sin() * self.attention_scaling
|
| 151 |
+
|
| 152 |
+
return cos.to(dtype=x.dtype), sin.to(dtype=x.dtype)
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
# Modified from transformers.models.llama.modeling_llama.LlamaDecoderLayer
|
| 156 |
+
class BltTransformerLayer(GradientCheckpointingLayer):
|
| 157 |
+
def __init__(self, config, layer_idx: int):
|
| 158 |
+
super().__init__()
|
| 159 |
+
self.hidden_size = config.hidden_size
|
| 160 |
+
|
| 161 |
+
self.self_attn = BltSelfAttention(config=config, layer_idx=layer_idx)
|
| 162 |
+
self.mlp = BltMLP(config)
|
| 163 |
+
self.input_layernorm = BltRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 164 |
+
self.post_attention_layernorm = BltRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 165 |
+
|
| 166 |
+
self.layer_idx = layer_idx
|
| 167 |
+
|
| 168 |
+
def forward(
|
| 169 |
+
self,
|
| 170 |
+
hidden_states: torch.Tensor,
|
| 171 |
+
cross_attention_states: torch.Tensor | None = None,
|
| 172 |
+
cross_attention_mask: torch.Tensor | None = None,
|
| 173 |
+
attention_mask: torch.Tensor | None = None,
|
| 174 |
+
full_text_row_masked_out_mask: tuple[torch.Tensor, torch.Tensor] | None = None,
|
| 175 |
+
position_ids: torch.LongTensor | None = None,
|
| 176 |
+
past_key_values: Cache | None = None,
|
| 177 |
+
use_cache: bool | None = False,
|
| 178 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
|
| 179 |
+
**kwargs: Unpack[FlashAttentionKwargs],
|
| 180 |
+
) -> tuple[torch.FloatTensor, tuple[torch.FloatTensor, torch.FloatTensor] | None]:
|
| 181 |
+
"""
|
| 182 |
+
Args:
|
| 183 |
+
hidden_states (`torch.FloatTensor`): input to the layer of shape `(batch, seq_len, embed_dim)`
|
| 184 |
+
attention_mask (`torch.FloatTensor`, *optional*):
|
| 185 |
+
attention mask of size `(batch_size, sequence_length)` if flash attention is used or `(batch_size, 1,
|
| 186 |
+
query_sequence_length, key_sequence_length)` if default attention is used.
|
| 187 |
+
|
| 188 |
+
use_cache (`bool`, *optional*):
|
| 189 |
+
If set to `True`, `past_key_values` key value states are returned and can be used to speed up decoding
|
| 190 |
+
(see `past_key_values`).
|
| 191 |
+
past_key_values (`Cache`, *optional*): cached past key and value projection states
|
| 192 |
+
position_embeddings (`tuple[torch.FloatTensor, torch.FloatTensor]`, *optional*):
|
| 193 |
+
Tuple containing the cosine and sine positional embeddings of shape `(batch_size, seq_len, head_dim)`,
|
| 194 |
+
with `head_dim` being the embedding dimension of each attention head.
|
| 195 |
+
kwargs (`dict`, *optional*):
|
| 196 |
+
Arbitrary kwargs to be ignored, used for FSDP and other methods that injects code
|
| 197 |
+
into the model
|
| 198 |
+
"""
|
| 199 |
+
residual = hidden_states
|
| 200 |
+
|
| 201 |
+
hidden_states = self.input_layernorm(hidden_states)
|
| 202 |
+
|
| 203 |
+
# Self Attention
|
| 204 |
+
hidden_states, self_attn_weights = self.self_attn(
|
| 205 |
+
hidden_states=hidden_states,
|
| 206 |
+
attention_mask=attention_mask,
|
| 207 |
+
position_ids=position_ids,
|
| 208 |
+
past_key_values=past_key_values,
|
| 209 |
+
use_cache=use_cache,
|
| 210 |
+
position_embeddings=position_embeddings,
|
| 211 |
+
**kwargs,
|
| 212 |
+
)
|
| 213 |
+
hidden_states = residual + hidden_states
|
| 214 |
+
|
| 215 |
+
# Fully Connected
|
| 216 |
+
residual = hidden_states
|
| 217 |
+
hidden_states = self.post_attention_layernorm(hidden_states)
|
| 218 |
+
hidden_states = self.mlp(hidden_states)
|
| 219 |
+
hidden_states = residual + hidden_states
|
| 220 |
+
|
| 221 |
+
return hidden_states
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
|
| 225 |
+
"""
|
| 226 |
+
This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
|
| 227 |
+
num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
|
| 228 |
+
"""
|
| 229 |
+
batch, num_key_value_heads, slen, head_dim = hidden_states.shape
|
| 230 |
+
if n_rep == 1:
|
| 231 |
+
return hidden_states
|
| 232 |
+
hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
|
| 233 |
+
return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
def eager_attention_forward(
|
| 237 |
+
module: nn.Module,
|
| 238 |
+
query: torch.Tensor,
|
| 239 |
+
key: torch.Tensor,
|
| 240 |
+
value: torch.Tensor,
|
| 241 |
+
attention_mask: torch.Tensor | None,
|
| 242 |
+
scaling: float,
|
| 243 |
+
dropout: float = 0.0,
|
| 244 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 245 |
+
):
|
| 246 |
+
key_states = repeat_kv(key, module.num_key_value_groups)
|
| 247 |
+
value_states = repeat_kv(value, module.num_key_value_groups)
|
| 248 |
+
|
| 249 |
+
attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
|
| 250 |
+
if attention_mask is not None:
|
| 251 |
+
attn_weights = attn_weights + attention_mask
|
| 252 |
+
|
| 253 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
|
| 254 |
+
attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
|
| 255 |
+
attn_output = torch.matmul(attn_weights, value_states)
|
| 256 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 257 |
+
|
| 258 |
+
return attn_output, attn_weights
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
def rotate_half(x):
|
| 262 |
+
# Split and rotate. Note that this function is different from e.g. Llama.
|
| 263 |
+
x1 = x[..., ::2]
|
| 264 |
+
x2 = x[..., 1::2]
|
| 265 |
+
rot_x = torch.stack([-x2, x1], dim=-1).flatten(-2)
|
| 266 |
+
return rot_x
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
def apply_rotary_pos_emb(q, k, cos, sin, unsqueeze_dim=1):
|
| 270 |
+
"""Applies Rotary Position Embedding to the query and key tensors.
|
| 271 |
+
|
| 272 |
+
Args:
|
| 273 |
+
q (`torch.Tensor`): The query tensor.
|
| 274 |
+
k (`torch.Tensor`): The key tensor.
|
| 275 |
+
cos (`torch.Tensor`): The cosine part of the rotary embedding.
|
| 276 |
+
sin (`torch.Tensor`): The sine part of the rotary embedding.
|
| 277 |
+
unsqueeze_dim (`int`, *optional*, defaults to 1):
|
| 278 |
+
The 'unsqueeze_dim' argument specifies the dimension along which to unsqueeze cos[position_ids] and
|
| 279 |
+
sin[position_ids] so that they can be properly broadcasted to the dimensions of q and k. For example, note
|
| 280 |
+
that cos[position_ids] and sin[position_ids] have the shape [batch_size, seq_len, head_dim]. Then, if q and
|
| 281 |
+
k have the shape [batch_size, heads, seq_len, head_dim], then setting unsqueeze_dim=1 makes
|
| 282 |
+
cos[position_ids] and sin[position_ids] broadcastable to the shapes of q and k. Similarly, if q and k have
|
| 283 |
+
the shape [batch_size, seq_len, heads, head_dim], then set unsqueeze_dim=2.
|
| 284 |
+
Returns:
|
| 285 |
+
`tuple(torch.Tensor)` comprising of the query and key tensors rotated using the Rotary Position Embedding.
|
| 286 |
+
"""
|
| 287 |
+
cos = cos.unsqueeze(unsqueeze_dim)
|
| 288 |
+
sin = sin.unsqueeze(unsqueeze_dim)
|
| 289 |
+
q_embed = (q * cos) + (rotate_half(q) * sin)
|
| 290 |
+
k_embed = (k * cos) + (rotate_half(k) * sin)
|
| 291 |
+
return q_embed, k_embed
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
class BltSelfAttention(nn.Module):
|
| 295 |
+
def __init__(self, config: BltConfig, layer_idx: int):
|
| 296 |
+
super().__init__()
|
| 297 |
+
self.config = config
|
| 298 |
+
self.num_heads = config.num_attention_heads
|
| 299 |
+
self.dropout = config.dropout
|
| 300 |
+
self.hidden_size = config.hidden_size
|
| 301 |
+
self.num_key_value_heads = config.num_key_value_heads
|
| 302 |
+
self.head_dim = config.hidden_size // self.num_heads
|
| 303 |
+
self.num_key_value_groups = self.num_heads // self.num_key_value_heads
|
| 304 |
+
self.scaling = self.head_dim**-0.5
|
| 305 |
+
|
| 306 |
+
self.layer_idx = layer_idx
|
| 307 |
+
self.is_causal = True
|
| 308 |
+
|
| 309 |
+
self.q_proj = nn.Linear(self.hidden_size, self.num_heads * self.head_dim, bias=False)
|
| 310 |
+
self.k_proj = nn.Linear(self.hidden_size, self.num_key_value_heads * self.head_dim, bias=False)
|
| 311 |
+
self.v_proj = nn.Linear(self.hidden_size, self.num_key_value_heads * self.head_dim, bias=False)
|
| 312 |
+
self.o_proj = nn.Linear(self.num_heads * self.head_dim, self.hidden_size, bias=False)
|
| 313 |
+
|
| 314 |
+
def forward(
|
| 315 |
+
self,
|
| 316 |
+
hidden_states: torch.Tensor,
|
| 317 |
+
attention_mask: torch.Tensor,
|
| 318 |
+
position_embeddings: torch.Tensor,
|
| 319 |
+
past_key_values=None,
|
| 320 |
+
**kwargs,
|
| 321 |
+
):
|
| 322 |
+
bsz, q_len, _ = hidden_states.size()
|
| 323 |
+
|
| 324 |
+
query_states = self.q_proj(hidden_states)
|
| 325 |
+
key_states = self.k_proj(hidden_states)
|
| 326 |
+
value_states = self.v_proj(hidden_states)
|
| 327 |
+
|
| 328 |
+
query_states = query_states.view(bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
|
| 329 |
+
key_states = key_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 330 |
+
value_states = value_states.view(bsz, q_len, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 331 |
+
|
| 332 |
+
cos, sin = position_embeddings
|
| 333 |
+
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
|
| 334 |
+
|
| 335 |
+
if past_key_values is not None:
|
| 336 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
| 337 |
+
|
| 338 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 339 |
+
self.config._attn_implementation, eager_attention_forward
|
| 340 |
+
)
|
| 341 |
+
|
| 342 |
+
attn_output, attn_weights = attention_interface(
|
| 343 |
+
self,
|
| 344 |
+
query_states,
|
| 345 |
+
key_states,
|
| 346 |
+
value_states,
|
| 347 |
+
attention_mask,
|
| 348 |
+
dropout=0.0 if not self.training else self.dropout,
|
| 349 |
+
scaling=self.scaling,
|
| 350 |
+
**kwargs,
|
| 351 |
+
)
|
| 352 |
+
|
| 353 |
+
attn_output = attn_output.reshape(bsz, q_len, -1).contiguous()
|
| 354 |
+
attn_output = self.o_proj(attn_output)
|
| 355 |
+
|
| 356 |
+
return attn_output, attn_weights
|
| 357 |
+
|
| 358 |
+
|
| 359 |
+
class BltCrossAttention(nn.Module):
|
| 360 |
+
"""Cross-attention module for Blt, following transformers style"""
|
| 361 |
+
|
| 362 |
+
def __init__(self, config: BltConfig, layer_idx: int, hidden_size: int | None = None):
|
| 363 |
+
super().__init__()
|
| 364 |
+
self.config = config
|
| 365 |
+
self.num_heads = self.config.num_attention_heads
|
| 366 |
+
self.num_key_value_heads = self.config.num_key_value_heads
|
| 367 |
+
self.dropout = config.dropout
|
| 368 |
+
self.hidden_size = config.hidden_size
|
| 369 |
+
self.head_dim = config.hidden_size // self.num_heads
|
| 370 |
+
self.layer_idx = layer_idx
|
| 371 |
+
self.num_key_value_groups = self.num_heads // self.num_key_value_heads
|
| 372 |
+
self.scaling = self.head_dim**-0.5
|
| 373 |
+
|
| 374 |
+
self.q_proj = nn.Linear(self.hidden_size, self.num_heads * self.head_dim, bias=False)
|
| 375 |
+
self.k_proj = nn.Linear(self.hidden_size, self.num_key_value_heads * self.head_dim, bias=False)
|
| 376 |
+
self.v_proj = nn.Linear(self.hidden_size, self.num_key_value_heads * self.head_dim, bias=False)
|
| 377 |
+
self.o_proj = nn.Linear(self.num_heads * self.head_dim, self.hidden_size, bias=False)
|
| 378 |
+
self.q_norm = BltRMSNorm(self.hidden_size, eps=config.rms_norm_eps)
|
| 379 |
+
self.k_norm = BltRMSNorm(self.hidden_size, eps=config.rms_norm_eps)
|
| 380 |
+
self.is_causal = False
|
| 381 |
+
|
| 382 |
+
def forward(
|
| 383 |
+
self,
|
| 384 |
+
hidden_states: torch.Tensor,
|
| 385 |
+
cross_attention_states: torch.Tensor | None = None,
|
| 386 |
+
attention_mask: torch.Tensor | None = None,
|
| 387 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 388 |
+
) -> tuple[torch.Tensor, torch.Tensor | None, tuple[torch.Tensor] | None]:
|
| 389 |
+
"""Input shape: Batch x Time x Channel"""
|
| 390 |
+
bsz, q_len, _ = hidden_states.size()
|
| 391 |
+
query_states = self.q_norm(hidden_states)
|
| 392 |
+
query_states = self.q_proj(query_states)
|
| 393 |
+
query_states = query_states.view(bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
|
| 394 |
+
|
| 395 |
+
cross_attention_states = self.k_norm(cross_attention_states)
|
| 396 |
+
key_states = self.k_proj(cross_attention_states)
|
| 397 |
+
value_states = self.v_proj(cross_attention_states)
|
| 398 |
+
key_states = key_states.view(bsz, -1, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 399 |
+
value_states = value_states.view(bsz, -1, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 400 |
+
|
| 401 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 402 |
+
self.config._attn_implementation, eager_attention_forward
|
| 403 |
+
)
|
| 404 |
+
|
| 405 |
+
attn_output, attn_weights = attention_interface(
|
| 406 |
+
self,
|
| 407 |
+
query_states,
|
| 408 |
+
key_states,
|
| 409 |
+
value_states,
|
| 410 |
+
attention_mask,
|
| 411 |
+
dropout=0.0 if not self.training else self.dropout,
|
| 412 |
+
scaling=self.scaling,
|
| 413 |
+
**kwargs,
|
| 414 |
+
)
|
| 415 |
+
attn_output = attn_output.reshape(bsz, q_len, -1).contiguous()
|
| 416 |
+
attn_output = self.o_proj(attn_output)
|
| 417 |
+
attn_output = attn_output + hidden_states
|
| 418 |
+
return attn_output, attn_weights
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
@auto_docstring
|
| 422 |
+
class BltPreTrainedModel(PreTrainedModel):
|
| 423 |
+
config: BltConfig
|
| 424 |
+
base_model_prefix = "model"
|
| 425 |
+
input_modalities = ("image", "text")
|
| 426 |
+
supports_gradient_checkpointing = True
|
| 427 |
+
_no_split_modules = ["BltTransformerLayer"]
|
| 428 |
+
_can_compile_fullgraph = False # static cache cannot have different shapes for each layer
|
| 429 |
+
_supports_sdpa = True
|
| 430 |
+
_supports_flash_attn = False
|
| 431 |
+
_supports_flex_attn = False
|
| 432 |
+
_supports_attention_backend = False
|
| 433 |
+
_can_record_outputs = {
|
| 434 |
+
"hidden_states": OutputRecorder(BltTransformerLayer, index=0),
|
| 435 |
+
"attentions": OutputRecorder(BltSelfAttention, index=1),
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
@torch.no_grad()
|
| 439 |
+
def _init_weights(self, module):
|
| 440 |
+
"""
|
| 441 |
+
Initialize BLT weights following the original ByteLatentTransformer:
|
| 442 |
+
|
| 443 |
+
- Most weights are drawn from a truncated normal.
|
| 444 |
+
- Scale is ~ 1 / sqrt(model_dim) (or 1 / sqrt(hidden_dim) for FFN outputs).
|
| 445 |
+
- Norm layers are set to weight = 1, bias = 0.
|
| 446 |
+
"""
|
| 447 |
+
class_name = module.__class__.__name__
|
| 448 |
+
|
| 449 |
+
# Norms: RMSNorm / LayerNorm
|
| 450 |
+
if isinstance(module, (BltRMSNorm, nn.LayerNorm)) or "RMSNorm" in class_name or "LayerNorm" in class_name:
|
| 451 |
+
if getattr(module, "weight", None) is not None:
|
| 452 |
+
init.ones_(module.weight)
|
| 453 |
+
if getattr(module, "bias", None) is not None:
|
| 454 |
+
init.zeros_(module.bias)
|
| 455 |
+
return
|
| 456 |
+
|
| 457 |
+
# Embeddings (encoder / patcher / hash embeddings)
|
| 458 |
+
if isinstance(module, nn.Embedding):
|
| 459 |
+
hidden_size = getattr(self.config, "hidden_size", None)
|
| 460 |
+
if hidden_size is None and hasattr(self.config, "encoder_config"):
|
| 461 |
+
hidden_size = getattr(self.config.encoder_config, "hidden_size", None)
|
| 462 |
+
if hidden_size is None:
|
| 463 |
+
hidden_size = module.embedding_dim
|
| 464 |
+
|
| 465 |
+
std = hidden_size**-0.5
|
| 466 |
+
init.trunc_normal_(
|
| 467 |
+
module.weight,
|
| 468 |
+
mean=0.0,
|
| 469 |
+
std=std,
|
| 470 |
+
a=-3 * std,
|
| 471 |
+
b=3 * std,
|
| 472 |
+
)
|
| 473 |
+
if module.padding_idx is not None:
|
| 474 |
+
init.zeros_(module.weight[module.padding_idx])
|
| 475 |
+
return
|
| 476 |
+
|
| 477 |
+
# Self-attention / cross-attention projections
|
| 478 |
+
if isinstance(module, (BltSelfAttention, BltCrossAttention)) or class_name in (
|
| 479 |
+
"MllamaTextSelfAttention",
|
| 480 |
+
"MllamaTextCrossAttention",
|
| 481 |
+
):
|
| 482 |
+
dim = getattr(self.config, "hidden_size", None)
|
| 483 |
+
if dim is None and hasattr(module, "hidden_size"):
|
| 484 |
+
dim = module.hidden_size
|
| 485 |
+
if dim is None:
|
| 486 |
+
for name in ("q_proj", "k_proj", "v_proj", "o_proj", "dense"):
|
| 487 |
+
proj = getattr(module, name, None)
|
| 488 |
+
if proj is not None and hasattr(proj, "weight"):
|
| 489 |
+
dim = proj.weight.shape[-1]
|
| 490 |
+
break
|
| 491 |
+
if dim is None:
|
| 492 |
+
return
|
| 493 |
+
|
| 494 |
+
std = dim**-0.5
|
| 495 |
+
|
| 496 |
+
# Input projections (q, k, v)
|
| 497 |
+
for proj_name in ("q_proj", "k_proj", "v_proj"):
|
| 498 |
+
proj = getattr(module, proj_name, None)
|
| 499 |
+
if proj is not None and hasattr(proj, "weight"):
|
| 500 |
+
init.trunc_normal_(
|
| 501 |
+
proj.weight,
|
| 502 |
+
mean=0.0,
|
| 503 |
+
std=std,
|
| 504 |
+
a=-3 * std,
|
| 505 |
+
b=3 * std,
|
| 506 |
+
)
|
| 507 |
+
if getattr(proj, "bias", None) is not None:
|
| 508 |
+
init.zeros_(proj.bias)
|
| 509 |
+
|
| 510 |
+
# Output projection: o_proj or dense
|
| 511 |
+
o_proj = getattr(module, "o_proj", getattr(module, "dense", None))
|
| 512 |
+
if o_proj is not None and hasattr(o_proj, "weight"):
|
| 513 |
+
init.trunc_normal_(
|
| 514 |
+
o_proj.weight,
|
| 515 |
+
mean=0.0,
|
| 516 |
+
std=std,
|
| 517 |
+
a=-3 * std,
|
| 518 |
+
b=3 * std,
|
| 519 |
+
)
|
| 520 |
+
if getattr(o_proj, "bias", None) is not None:
|
| 521 |
+
init.zeros_(o_proj.bias)
|
| 522 |
+
return
|
| 523 |
+
|
| 524 |
+
# MLP / FFN blocks
|
| 525 |
+
if isinstance(module, BltMLP) or class_name == "MllamaTextMLP":
|
| 526 |
+
hidden_size = getattr(self.config, "hidden_size", None)
|
| 527 |
+
if hidden_size is None and hasattr(self.config, "decoder_config"):
|
| 528 |
+
hidden_size = getattr(self.config.decoder_config, "hidden_size", None)
|
| 529 |
+
if hidden_size is None and hasattr(self.config, "encoder_config"):
|
| 530 |
+
hidden_size = getattr(self.config.encoder_config, "hidden_size", None)
|
| 531 |
+
|
| 532 |
+
# Input-side std
|
| 533 |
+
in_std = None
|
| 534 |
+
if hidden_size is not None:
|
| 535 |
+
in_std = hidden_size**-0.5
|
| 536 |
+
|
| 537 |
+
gate_proj = getattr(module, "gate_proj", getattr(module, "fc1", None))
|
| 538 |
+
up_proj = getattr(module, "up_proj", None)
|
| 539 |
+
down_proj = getattr(module, "down_proj", getattr(module, "fc2", None))
|
| 540 |
+
|
| 541 |
+
# gate / input projections
|
| 542 |
+
for proj in (gate_proj, up_proj):
|
| 543 |
+
if proj is not None and hasattr(proj, "weight"):
|
| 544 |
+
std = in_std or (proj.weight.shape[1] ** -0.5)
|
| 545 |
+
init.trunc_normal_(
|
| 546 |
+
proj.weight,
|
| 547 |
+
mean=0.0,
|
| 548 |
+
std=std,
|
| 549 |
+
a=-3 * std,
|
| 550 |
+
b=3 * std,
|
| 551 |
+
)
|
| 552 |
+
if getattr(proj, "bias", None) is not None:
|
| 553 |
+
init.zeros_(proj.bias)
|
| 554 |
+
|
| 555 |
+
# output/ down projections
|
| 556 |
+
if down_proj is not None and hasattr(down_proj, "weight"):
|
| 557 |
+
hidden_dim = down_proj.weight.shape[1]
|
| 558 |
+
out_std = hidden_dim**-0.5
|
| 559 |
+
init.trunc_normal_(
|
| 560 |
+
down_proj.weight,
|
| 561 |
+
mean=0.0,
|
| 562 |
+
std=out_std,
|
| 563 |
+
a=-3 * out_std,
|
| 564 |
+
b=3 * out_std,
|
| 565 |
+
)
|
| 566 |
+
if getattr(down_proj, "bias", None) is not None:
|
| 567 |
+
init.zeros_(down_proj.bias)
|
| 568 |
+
return
|
| 569 |
+
|
| 570 |
+
# Generic Linear layers (projections, lm_head, etc.)
|
| 571 |
+
if isinstance(module, nn.Linear):
|
| 572 |
+
fan_in = module.in_features
|
| 573 |
+
std = fan_in**-0.5
|
| 574 |
+
init.trunc_normal_(
|
| 575 |
+
module.weight,
|
| 576 |
+
mean=0.0,
|
| 577 |
+
std=std,
|
| 578 |
+
a=-3 * std,
|
| 579 |
+
b=3 * std,
|
| 580 |
+
)
|
| 581 |
+
if module.bias is not None:
|
| 582 |
+
init.zeros_(module.bias)
|
| 583 |
+
return
|
| 584 |
+
|
| 585 |
+
if isinstance(module, BltRotaryEmbedding):
|
| 586 |
+
rope_fn = (
|
| 587 |
+
ROPE_INIT_FUNCTIONS[module.rope_type]
|
| 588 |
+
if module.rope_type != "default"
|
| 589 |
+
else module.compute_default_rope_parameters
|
| 590 |
+
)
|
| 591 |
+
buffer_value, _ = rope_fn(module.config)
|
| 592 |
+
init.copy_(module.inv_freq, buffer_value)
|
| 593 |
+
init.copy_(module.original_inv_freq, buffer_value)
|
| 594 |
+
|
| 595 |
+
|
| 596 |
+
class BltLocalEncoder(BltPreTrainedModel):
|
| 597 |
+
config: BltLocalEncoderConfig
|
| 598 |
+
_can_record_outputs = {
|
| 599 |
+
"encoder_attentions": OutputRecorder(BltSelfAttention, index=1, layer_name="local_encoder"),
|
| 600 |
+
}
|
| 601 |
+
|
| 602 |
+
def __init__(self, config: BltLocalEncoderConfig):
|
| 603 |
+
super().__init__(config)
|
| 604 |
+
self.gradient_checkpointing = False
|
| 605 |
+
self.config = config
|
| 606 |
+
self.layers = nn.ModuleList(
|
| 607 |
+
[BltTransformerLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
|
| 608 |
+
)
|
| 609 |
+
self.rotary_emb = BltRotaryEmbedding(config=config)
|
| 610 |
+
self.patch_embedding_projection = nn.Linear(
|
| 611 |
+
in_features=config.hidden_size,
|
| 612 |
+
out_features=config.hidden_size * config.cross_attn_k,
|
| 613 |
+
bias=False,
|
| 614 |
+
)
|
| 615 |
+
self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size)
|
| 616 |
+
self.cross_attn_layers = nn.ModuleList()
|
| 617 |
+
layers_to_add = config.num_hidden_layers if config.cross_attn_all_layers else 1
|
| 618 |
+
for layer_idx in range(layers_to_add):
|
| 619 |
+
self.cross_attn_layers.append(
|
| 620 |
+
BltCrossAttention(config=config, layer_idx=layer_idx, hidden_size=config.hidden_size)
|
| 621 |
+
)
|
| 622 |
+
|
| 623 |
+
self.post_init()
|
| 624 |
+
|
| 625 |
+
def forward(
|
| 626 |
+
self,
|
| 627 |
+
input_ids: torch.LongTensor | None = None,
|
| 628 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 629 |
+
patch_embeds: torch.Tensor | None = None,
|
| 630 |
+
attention_mask: torch.Tensor | None = None,
|
| 631 |
+
position_ids: torch.LongTensor | None = None,
|
| 632 |
+
past_key_values: Cache | None = None,
|
| 633 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 634 |
+
num_patches: int | None = None,
|
| 635 |
+
patch_ids: torch.Tensor | None = None,
|
| 636 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 637 |
+
):
|
| 638 |
+
if inputs_embeds is None:
|
| 639 |
+
inputs_embeds = self.embed_tokens(input_ids)
|
| 640 |
+
|
| 641 |
+
batch_size = inputs_embeds.shape[0]
|
| 642 |
+
hidden_states = F.dropout(inputs_embeds, p=self.config.dropout, training=self.training)
|
| 643 |
+
|
| 644 |
+
if position_ids is None:
|
| 645 |
+
position_ids = (
|
| 646 |
+
torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device).unsqueeze(0).expand(batch_size, -1)
|
| 647 |
+
)
|
| 648 |
+
|
| 649 |
+
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
| 650 |
+
hidden_states = F.dropout(hidden_states, p=self.config.dropout, training=self.training)
|
| 651 |
+
|
| 652 |
+
for idx, layer in enumerate(self.layers):
|
| 653 |
+
hidden_states = layer(
|
| 654 |
+
hidden_states,
|
| 655 |
+
position_embeddings=position_embeddings,
|
| 656 |
+
attention_mask=attention_mask,
|
| 657 |
+
past_key_values=past_key_values,
|
| 658 |
+
**kwargs,
|
| 659 |
+
)
|
| 660 |
+
if idx == len(self.layers) - 1 or self.config.cross_attn_all_layers:
|
| 661 |
+
patch_embeds = self.patch_reduce(hidden_states, num_patches, patch_ids)
|
| 662 |
+
patch_embeds = self.patch_embedding_projection(patch_embeds)
|
| 663 |
+
patch_embeds = patch_embeds.reshape(
|
| 664 |
+
batch_size, patch_embeds.shape[1] * self.config.cross_attn_k, self.config.hidden_size
|
| 665 |
+
)
|
| 666 |
+
layer_idx = idx if self.config.cross_attn_all_layers else 0
|
| 667 |
+
cross_attention_output, _ = self.cross_attn_layers[layer_idx](
|
| 668 |
+
hidden_states=patch_embeds,
|
| 669 |
+
cross_attention_states=hidden_states,
|
| 670 |
+
attention_mask=encoder_attention_mask,
|
| 671 |
+
**kwargs,
|
| 672 |
+
)
|
| 673 |
+
patch_embeds = patch_embeds + cross_attention_output
|
| 674 |
+
encoder_cross_states = patch_embeds
|
| 675 |
+
return hidden_states, encoder_cross_states
|
| 676 |
+
|
| 677 |
+
def patch_reduce(self, hidden_states, max_num_patches, patch_ids):
|
| 678 |
+
"""
|
| 679 |
+
Reduce variable length patches to single embedding per patch
|
| 680 |
+
Note: this works with variable number of patches for different sequences in the batch
|
| 681 |
+
It handles variable length patches by assuming that patch_lengths will be 0 for any
|
| 682 |
+
extra patches on the *right*. Since there can be a variable number of patches
|
| 683 |
+
this function also return the number of patches for each sequence in the batch.
|
| 684 |
+
Any embeddings on the right that are not allocated to a patch
|
| 685 |
+
(i.e. if the sum(patch_lengths[i]) < seq_len for any i)
|
| 686 |
+
will be sent to a dummy patch, which is trimmed before returning.
|
| 687 |
+
"""
|
| 688 |
+
batch_size = hidden_states.shape[0]
|
| 689 |
+
embedding_dim = hidden_states.shape[-1]
|
| 690 |
+
|
| 691 |
+
patch_ids = patch_ids.unsqueeze(-1).expand(-1, -1, hidden_states.shape[-1])
|
| 692 |
+
|
| 693 |
+
reduced_embeddings = torch.zeros(
|
| 694 |
+
(batch_size, max_num_patches, embedding_dim), dtype=hidden_states.dtype, device=hidden_states.device
|
| 695 |
+
)
|
| 696 |
+
|
| 697 |
+
reduced_embeddings = reduced_embeddings.scatter_reduce(
|
| 698 |
+
src=hidden_states,
|
| 699 |
+
dim=1,
|
| 700 |
+
index=patch_ids,
|
| 701 |
+
reduce="amax",
|
| 702 |
+
include_self=False,
|
| 703 |
+
)
|
| 704 |
+
reduced_embeddings = reduced_embeddings[:, :max_num_patches, :]
|
| 705 |
+
|
| 706 |
+
return reduced_embeddings
|
| 707 |
+
|
| 708 |
+
|
| 709 |
+
class BltLocalDecoder(BltPreTrainedModel):
|
| 710 |
+
config: BltLocalDecoderConfig
|
| 711 |
+
|
| 712 |
+
def __init__(self, config: BltLocalDecoderConfig):
|
| 713 |
+
super().__init__(config)
|
| 714 |
+
self.gradient_checkpointing = False
|
| 715 |
+
self.config = config
|
| 716 |
+
self.cross_attn_decoder = True
|
| 717 |
+
self.layers = nn.ModuleList(
|
| 718 |
+
[BltTransformerLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
|
| 719 |
+
)
|
| 720 |
+
self.rotary_emb = BltRotaryEmbedding(config=config)
|
| 721 |
+
self.patch_embedding_projection = nn.Linear(
|
| 722 |
+
in_features=config.hidden_size_global,
|
| 723 |
+
out_features=config.hidden_size * config.cross_attn_k,
|
| 724 |
+
bias=False,
|
| 725 |
+
)
|
| 726 |
+
self.norm = BltRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 727 |
+
self.cross_attn_layers = nn.ModuleList()
|
| 728 |
+
layers_to_add = config.num_hidden_layers if config.cross_attn_all_layers else 1
|
| 729 |
+
for layer_idx in range(layers_to_add):
|
| 730 |
+
self.cross_attn_layers.append(
|
| 731 |
+
BltCrossAttention(config=config, layer_idx=layer_idx, hidden_size=config.hidden_size)
|
| 732 |
+
)
|
| 733 |
+
|
| 734 |
+
self.post_init()
|
| 735 |
+
|
| 736 |
+
def forward(
|
| 737 |
+
self,
|
| 738 |
+
input_ids: torch.LongTensor | None = None,
|
| 739 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 740 |
+
patch_embeds: torch.Tensor | None = None,
|
| 741 |
+
attention_mask: torch.Tensor | None = None,
|
| 742 |
+
position_ids: torch.LongTensor | None = None,
|
| 743 |
+
past_key_values: Cache | None = None,
|
| 744 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 745 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 746 |
+
):
|
| 747 |
+
batch_size = inputs_embeds.shape[0]
|
| 748 |
+
hidden_states = inputs_embeds
|
| 749 |
+
patch_embeds = self.patch_embedding_projection(patch_embeds)
|
| 750 |
+
patch_embeds = patch_embeds.reshape(
|
| 751 |
+
batch_size, patch_embeds.shape[1] * self.config.cross_attn_k, self.config.hidden_size
|
| 752 |
+
)
|
| 753 |
+
|
| 754 |
+
if patch_embeds is not None and not self.cross_attn_decoder:
|
| 755 |
+
hidden_states = hidden_states + patch_embeds
|
| 756 |
+
|
| 757 |
+
if position_ids is None:
|
| 758 |
+
position_ids = (
|
| 759 |
+
torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device).unsqueeze(0).expand(batch_size, -1)
|
| 760 |
+
)
|
| 761 |
+
|
| 762 |
+
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
| 763 |
+
hidden_states = F.dropout(hidden_states, p=self.config.dropout, training=self.training)
|
| 764 |
+
|
| 765 |
+
for i, layer in enumerate(self.layers):
|
| 766 |
+
if i == 0 or self.config.cross_attn_all_layers:
|
| 767 |
+
cross_attention_output, _ = self.cross_attn_layers[i](
|
| 768 |
+
hidden_states=hidden_states,
|
| 769 |
+
cross_attention_states=patch_embeds,
|
| 770 |
+
attention_mask=encoder_attention_mask,
|
| 771 |
+
**kwargs,
|
| 772 |
+
)
|
| 773 |
+
hidden_states = hidden_states + cross_attention_output
|
| 774 |
+
hidden_states = layer(
|
| 775 |
+
hidden_states,
|
| 776 |
+
position_embeddings=position_embeddings,
|
| 777 |
+
attention_mask=attention_mask,
|
| 778 |
+
past_key_values=past_key_values,
|
| 779 |
+
**kwargs,
|
| 780 |
+
)
|
| 781 |
+
logits = self.norm(hidden_states)
|
| 782 |
+
return logits
|
| 783 |
+
|
| 784 |
+
|
| 785 |
+
class BltGlobalTransformer(BltPreTrainedModel):
|
| 786 |
+
config: BltGlobalTransformerConfig
|
| 787 |
+
_can_record_outputs = {
|
| 788 |
+
"global_attentions": OutputRecorder(BltSelfAttention, index=1, layer_name="global_transformer"),
|
| 789 |
+
}
|
| 790 |
+
|
| 791 |
+
def __init__(self, config: BltGlobalTransformerConfig):
|
| 792 |
+
super().__init__(config)
|
| 793 |
+
self.config = config
|
| 794 |
+
self.layers = nn.ModuleList()
|
| 795 |
+
for layer_idx in range(config.num_hidden_layers):
|
| 796 |
+
self.layers.append(BltTransformerLayer(config, layer_idx))
|
| 797 |
+
self.rotary_emb = BltRotaryEmbedding(config=config)
|
| 798 |
+
|
| 799 |
+
# Create token embedding projection (use nn.Identity() when no projection needed)
|
| 800 |
+
if getattr(config, "encoder_cross_output_size", None) is not None:
|
| 801 |
+
self.token_embedding_projection = nn.Linear(
|
| 802 |
+
config.encoder_cross_output_size, config.hidden_size, bias=False
|
| 803 |
+
)
|
| 804 |
+
else:
|
| 805 |
+
self.token_embedding_projection = nn.Identity()
|
| 806 |
+
|
| 807 |
+
self.post_init()
|
| 808 |
+
|
| 809 |
+
@deprecate_kwarg("input_embeds", version="5.6.0", new_name="inputs_embeds")
|
| 810 |
+
def forward(
|
| 811 |
+
self,
|
| 812 |
+
inputs_embeds: torch.Tensor,
|
| 813 |
+
attention_mask: torch.Tensor | None = None,
|
| 814 |
+
position_ids: torch.LongTensor | None = None,
|
| 815 |
+
past_key_values: Cache | None = None,
|
| 816 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 817 |
+
):
|
| 818 |
+
batch_size, seq_len, _ = inputs_embeds.shape
|
| 819 |
+
hidden_states = self.token_embedding_projection(inputs_embeds)
|
| 820 |
+
hidden_states = F.dropout(hidden_states, p=self.config.dropout, training=self.training)
|
| 821 |
+
if position_ids is None:
|
| 822 |
+
position_ids = (
|
| 823 |
+
torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device).unsqueeze(0).expand(batch_size, -1)
|
| 824 |
+
)
|
| 825 |
+
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
| 826 |
+
for i, layer in enumerate(self.layers):
|
| 827 |
+
hidden_states = layer(
|
| 828 |
+
hidden_states,
|
| 829 |
+
position_embeddings=position_embeddings,
|
| 830 |
+
attention_mask=attention_mask,
|
| 831 |
+
past_key_values=past_key_values,
|
| 832 |
+
**kwargs,
|
| 833 |
+
)
|
| 834 |
+
return hidden_states
|
| 835 |
+
|
| 836 |
+
|
| 837 |
+
def process_patch_lengths(patch_lengths: torch.Tensor, max_patch_length: int | None) -> torch.Tensor:
|
| 838 |
+
"""
|
| 839 |
+
Splits patch lengths into smaller segments if they exceed `max_patch_length`.
|
| 840 |
+
Pads the result to uniform length across the batch.
|
| 841 |
+
|
| 842 |
+
Args:
|
| 843 |
+
patch_lengths (torch.Tensor): [batch_size, num_patches] tensor of patch lengths.
|
| 844 |
+
max_patch_length (int, optional): Maximum allowed length per patch.
|
| 845 |
+
|
| 846 |
+
Returns:
|
| 847 |
+
torch.Tensor: [batch_size, max_len] tensor of split and padded patch lengths.
|
| 848 |
+
"""
|
| 849 |
+
if max_patch_length is None:
|
| 850 |
+
return patch_lengths
|
| 851 |
+
|
| 852 |
+
batch_size = patch_lengths.size(0)
|
| 853 |
+
processed = []
|
| 854 |
+
|
| 855 |
+
for seq in patch_lengths:
|
| 856 |
+
splits = []
|
| 857 |
+
for length in seq[seq > 0]:
|
| 858 |
+
length = length.item()
|
| 859 |
+
full_chunks, remainder = divmod(length, max_patch_length)
|
| 860 |
+
splits.extend([max_patch_length] * full_chunks)
|
| 861 |
+
if remainder:
|
| 862 |
+
splits.append(remainder)
|
| 863 |
+
processed.append(splits)
|
| 864 |
+
|
| 865 |
+
# Find max length to pad to
|
| 866 |
+
max_len = max(len(splits) for splits in processed)
|
| 867 |
+
padded = torch.zeros((batch_size, max_len), dtype=patch_lengths.dtype, device=patch_lengths.device)
|
| 868 |
+
|
| 869 |
+
for i, splits in enumerate(processed):
|
| 870 |
+
if splits:
|
| 871 |
+
padded[i, : len(splits)] = torch.tensor(splits, dtype=patch_lengths.dtype, device=patch_lengths.device)
|
| 872 |
+
|
| 873 |
+
# Trim zero columns
|
| 874 |
+
if (padded != 0).any(dim=0).sum() < padded.shape[1]:
|
| 875 |
+
last_nonzero = (padded != 0).any(dim=0).nonzero().max().item() + 1
|
| 876 |
+
padded = padded[:, :last_nonzero]
|
| 877 |
+
|
| 878 |
+
return padded
|
| 879 |
+
|
| 880 |
+
|
| 881 |
+
class BltPatcher(BltPreTrainedModel):
|
| 882 |
+
config: BltPatcherConfig
|
| 883 |
+
|
| 884 |
+
def __init__(self, config: BltPatcherConfig):
|
| 885 |
+
super().__init__(config)
|
| 886 |
+
self.rotary_emb = BltRotaryEmbedding(config=self.config)
|
| 887 |
+
self.layers = nn.ModuleList()
|
| 888 |
+
for layer_idx in range(self.config.num_hidden_layers):
|
| 889 |
+
self.layers.append(BltTransformerLayer(self.config, layer_idx))
|
| 890 |
+
self.embed_tokens = nn.Embedding(self.config.vocab_size, self.config.hidden_size)
|
| 891 |
+
self.norm = BltRMSNorm(self.config.hidden_size, eps=self.config.rms_norm_eps)
|
| 892 |
+
self.lm_head = nn.Linear(
|
| 893 |
+
self.config.hidden_size,
|
| 894 |
+
self.config.vocab_size,
|
| 895 |
+
bias=False,
|
| 896 |
+
)
|
| 897 |
+
|
| 898 |
+
self.post_init()
|
| 899 |
+
|
| 900 |
+
def forward(
|
| 901 |
+
self,
|
| 902 |
+
input_ids: torch.LongTensor | None = None,
|
| 903 |
+
attention_mask: torch.Tensor | None = None,
|
| 904 |
+
position_ids: torch.LongTensor | None = None,
|
| 905 |
+
past_key_values: Cache | None = None,
|
| 906 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 907 |
+
use_cache: bool | None = None,
|
| 908 |
+
patch_size: int | None = None,
|
| 909 |
+
threshold: float | None = None,
|
| 910 |
+
max_patch_length: int | None = None,
|
| 911 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 912 |
+
):
|
| 913 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 914 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 915 |
+
|
| 916 |
+
if inputs_embeds is None:
|
| 917 |
+
inputs_embeds = self.embed_tokens(input_ids)
|
| 918 |
+
|
| 919 |
+
if use_cache and past_key_values is None:
|
| 920 |
+
past_key_values = DynamicCache(config=self.config)
|
| 921 |
+
|
| 922 |
+
if position_ids is None:
|
| 923 |
+
past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
|
| 924 |
+
position_ids = torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device) + past_seen_tokens
|
| 925 |
+
position_ids = position_ids.unsqueeze(0)
|
| 926 |
+
|
| 927 |
+
causal_mask = create_causal_mask(
|
| 928 |
+
config=self.config,
|
| 929 |
+
inputs_embeds=inputs_embeds,
|
| 930 |
+
attention_mask=attention_mask,
|
| 931 |
+
past_key_values=past_key_values,
|
| 932 |
+
position_ids=position_ids,
|
| 933 |
+
)
|
| 934 |
+
|
| 935 |
+
hidden_states = inputs_embeds
|
| 936 |
+
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
| 937 |
+
|
| 938 |
+
for layer in self.layers:
|
| 939 |
+
hidden_states = layer(hidden_states, position_embeddings=position_embeddings, attention_mask=causal_mask)
|
| 940 |
+
|
| 941 |
+
logits = self.lm_head(self.norm(hidden_states))
|
| 942 |
+
prediction_entropies = torch.distributions.Categorical(logits=logits).entropy()
|
| 943 |
+
|
| 944 |
+
batch_size, sequence_length = inputs_embeds.shape[:2]
|
| 945 |
+
if patch_size is not None:
|
| 946 |
+
patch_lengths = self.patch_lengths_from_entropies(
|
| 947 |
+
entropies=prediction_entropies,
|
| 948 |
+
sequence_length=sequence_length,
|
| 949 |
+
patch_size=patch_size,
|
| 950 |
+
threshold=threshold,
|
| 951 |
+
)
|
| 952 |
+
else:
|
| 953 |
+
patch_lengths = torch.ones(
|
| 954 |
+
(batch_size, sequence_length), dtype=inputs_embeds.dtype, device=inputs_embeds.device
|
| 955 |
+
)
|
| 956 |
+
patch_lengths = process_patch_lengths(patch_lengths, max_patch_length)
|
| 957 |
+
return prediction_entropies, patch_lengths, logits
|
| 958 |
+
|
| 959 |
+
@staticmethod
|
| 960 |
+
def patch_lengths_from_entropies(
|
| 961 |
+
entropies,
|
| 962 |
+
sequence_length,
|
| 963 |
+
patch_size=None,
|
| 964 |
+
threshold=None,
|
| 965 |
+
):
|
| 966 |
+
"""
|
| 967 |
+
Computes patch lengths from token entropies.
|
| 968 |
+
|
| 969 |
+
Depending on whether a threshold is provided, the function uses either:
|
| 970 |
+
- Thresholding the entropy values (when `threshold` is set).
|
| 971 |
+
"""
|
| 972 |
+
|
| 973 |
+
batch_size = entropies.shape[0]
|
| 974 |
+
|
| 975 |
+
# Always include token 0 and 1 as starting tokens
|
| 976 |
+
init_tokens = (
|
| 977 |
+
torch.tensor([0, 1], dtype=torch.long, device=entropies.device).unsqueeze(0).repeat(batch_size, 1)
|
| 978 |
+
)
|
| 979 |
+
offset = init_tokens.shape[1]
|
| 980 |
+
|
| 981 |
+
# Ignore first token entropy (BOS)
|
| 982 |
+
entropies = entropies[:, 1:]
|
| 983 |
+
|
| 984 |
+
# Threshold the entropy values to define patch start points
|
| 985 |
+
patch_mask = entropies > threshold
|
| 986 |
+
|
| 987 |
+
seq_len = patch_mask.shape[1]
|
| 988 |
+
|
| 989 |
+
# Create patch IDs (token indices), and add a sentinel to ensure alignment
|
| 990 |
+
token_indices = torch.arange(seq_len, device=entropies.device).unsqueeze(0).expand(batch_size, -1)
|
| 991 |
+
sentinel = torch.full_like(token_indices, seq_len)
|
| 992 |
+
padded_indices = torch.cat([token_indices, sentinel], dim=1)
|
| 993 |
+
|
| 994 |
+
# Pad mask with inverse to align sentinel correctly
|
| 995 |
+
padded_mask = torch.cat([patch_mask, ~patch_mask], dim=1)
|
| 996 |
+
|
| 997 |
+
# Select indices where mask is True
|
| 998 |
+
patch_starts = padded_indices[padded_mask].reshape(batch_size, seq_len)
|
| 999 |
+
max_valid_patches = patch_mask.sum(dim=1).max()
|
| 1000 |
+
patch_starts = patch_starts[:, :max_valid_patches]
|
| 1001 |
+
|
| 1002 |
+
# Offset patch starts to account for the two initial tokens
|
| 1003 |
+
patch_start_ids = torch.cat((init_tokens, patch_starts + offset), dim=1)
|
| 1004 |
+
|
| 1005 |
+
# Compute patch end positions by shifting start positions
|
| 1006 |
+
last_token = torch.full_like(patch_start_ids[:, :1], sequence_length - 1)
|
| 1007 |
+
patch_ends = torch.cat((patch_start_ids[:, 1:] - 1, last_token), dim=1)
|
| 1008 |
+
|
| 1009 |
+
patch_lengths = patch_ends - patch_start_ids + 1
|
| 1010 |
+
|
| 1011 |
+
return patch_lengths
|
| 1012 |
+
|
| 1013 |
+
|
| 1014 |
+
def rolling_polynomial_hash(token_tensor, prime: int = 1000000007):
|
| 1015 |
+
"""
|
| 1016 |
+
A polynomial rolling hash algorithm that converts sequences
|
| 1017 |
+
of tokens into hash values. The hash is computed as:
|
| 1018 |
+
hash = (token_0 * prime^0 + token_1 * prime^1 + ... + token_n * prime^n)
|
| 1019 |
+
|
| 1020 |
+
The rolling hash allows the model to efficiently
|
| 1021 |
+
identify and encode recurring byte-level patterns in the input text.
|
| 1022 |
+
|
| 1023 |
+
Args:
|
| 1024 |
+
token_tensor (torch.Tensor): [batch_size, seq_len, group_size] containing token IDs to hash
|
| 1025 |
+
prime (int): Prime number used as the base for the polynomial hash.
|
| 1026 |
+
|
| 1027 |
+
Returns:
|
| 1028 |
+
torch.Tensor: Hash values of shape [batch_size, seq_len] where each value
|
| 1029 |
+
represents the hash of the corresponding token group
|
| 1030 |
+
|
| 1031 |
+
Example:
|
| 1032 |
+
>>> tokens = torch.tensor([[1, 2, 3], [4, 5, 6]])
|
| 1033 |
+
>>> hashes = rolling_polynomial_hash(tokens, prime=31)
|
| 1034 |
+
>>> # hash[0] = 1*31^0 + 2*31^1 + 3*31^2
|
| 1035 |
+
>>> # hash[1] = 4*31^0 + 5*31^1 + 6*31^2
|
| 1036 |
+
"""
|
| 1037 |
+
prime_tensor = torch.tensor(prime, dtype=torch.int64, device=token_tensor.device)
|
| 1038 |
+
powers = torch.arange(token_tensor.shape[-1], device=token_tensor.device)
|
| 1039 |
+
prime_powers = prime_tensor**powers
|
| 1040 |
+
return torch.sum(token_tensor * prime_powers, dim=-1)
|
| 1041 |
+
|
| 1042 |
+
|
| 1043 |
+
def byte_group_hash_function(
|
| 1044 |
+
token_ids: torch.Tensor, group_size: int = 2, prime: int = 1000000007, max_hash: int = 30000
|
| 1045 |
+
):
|
| 1046 |
+
"""Hash token groups and map to range [0, max_hash]."""
|
| 1047 |
+
with torch.no_grad():
|
| 1048 |
+
batch_size, seq_len = token_ids.shape
|
| 1049 |
+
# Add padding for sliding window
|
| 1050 |
+
padding = torch.zeros(batch_size, group_size - 1, dtype=torch.int64, device=token_ids.device)
|
| 1051 |
+
padded_tokens = torch.cat([padding, token_ids], dim=1)
|
| 1052 |
+
|
| 1053 |
+
# Create sliding windows and compute hashes
|
| 1054 |
+
windows = padded_tokens.unfold(1, group_size, 1)
|
| 1055 |
+
hashes = rolling_polynomial_hash(windows, prime)
|
| 1056 |
+
hash_values = hashes % max_hash
|
| 1057 |
+
|
| 1058 |
+
return hash_values
|
| 1059 |
+
|
| 1060 |
+
|
| 1061 |
+
def compute_hash_embeddings(
|
| 1062 |
+
local_encoder_tokens: torch.Tensor,
|
| 1063 |
+
local_encoder,
|
| 1064 |
+
encoder_hash_tok_embedding: nn.Embedding,
|
| 1065 |
+
encoder_hash_byte_group_nb_functions: int,
|
| 1066 |
+
encoder_hash_byte_group_size: list,
|
| 1067 |
+
encoder_hash_byte_group_vocab: int,
|
| 1068 |
+
) -> torch.Tensor:
|
| 1069 |
+
"""Compute token embeddings enhanced with hash-based embeddings."""
|
| 1070 |
+
# Available primes for hash functions
|
| 1071 |
+
primes = [
|
| 1072 |
+
1000000007,
|
| 1073 |
+
5915587277,
|
| 1074 |
+
1500450271,
|
| 1075 |
+
3267000013,
|
| 1076 |
+
5754853343,
|
| 1077 |
+
4093082899,
|
| 1078 |
+
9576890767,
|
| 1079 |
+
3628273133,
|
| 1080 |
+
2860486313,
|
| 1081 |
+
5463458053,
|
| 1082 |
+
3367900313,
|
| 1083 |
+
]
|
| 1084 |
+
|
| 1085 |
+
embeddings = local_encoder.embed_tokens(local_encoder_tokens)
|
| 1086 |
+
embedding_idx = 0
|
| 1087 |
+
for func_nb in range(encoder_hash_byte_group_nb_functions):
|
| 1088 |
+
prime = primes[func_nb % len(primes)] # Cycle through primes if more functions than primes
|
| 1089 |
+
for group_size in encoder_hash_byte_group_size:
|
| 1090 |
+
hash_ids = byte_group_hash_function(local_encoder_tokens, group_size, prime, encoder_hash_byte_group_vocab)
|
| 1091 |
+
# Apply offset to get the correct slice of the fused embedding
|
| 1092 |
+
offset_hash_ids = hash_ids + embedding_idx * encoder_hash_byte_group_vocab
|
| 1093 |
+
embeddings += encoder_hash_tok_embedding(offset_hash_ids).to(embeddings.device)
|
| 1094 |
+
embedding_idx += 1
|
| 1095 |
+
|
| 1096 |
+
return embeddings
|
| 1097 |
+
|
| 1098 |
+
|
| 1099 |
+
def _prepare_patch_cross_attention_mask(
|
| 1100 |
+
patch_ids: torch.Tensor,
|
| 1101 |
+
num_patches: int,
|
| 1102 |
+
sequence_length: int,
|
| 1103 |
+
patches_as_queries: bool = False,
|
| 1104 |
+
cross_attn_k: int = 1,
|
| 1105 |
+
dtype: torch.dtype = torch.float32,
|
| 1106 |
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
| 1107 |
+
"""
|
| 1108 |
+
Prepare cross-attention mask for patch-based attention, following mllama's robust approach.
|
| 1109 |
+
|
| 1110 |
+
This function creates masks that control which patches can attend to which other patches,
|
| 1111 |
+
with support for query/key role swapping and cross-attention multipliers.
|
| 1112 |
+
|
| 1113 |
+
Args:
|
| 1114 |
+
patch_ids (torch.Tensor): Tensor of shape [batch_size, seq_len] containing patch ids.
|
| 1115 |
+
num_patches (int): Total number of patches.
|
| 1116 |
+
sequence_length (int): Length of the sequence.
|
| 1117 |
+
patches_as_queries (bool): If True, patches are used as queries, otherwise as keys.
|
| 1118 |
+
cross_attn_k (int): Cross-attention multiplier for repeating patches.
|
| 1119 |
+
dtype (torch.dtype): Data type for the output mask.
|
| 1120 |
+
|
| 1121 |
+
Returns:
|
| 1122 |
+
Tuple[torch.Tensor, torch.Tensor]:
|
| 1123 |
+
- cross_attention_mask: 4D tensor [batch_size, 1, q_len, kv_len]
|
| 1124 |
+
"""
|
| 1125 |
+
batch_size, seq_len = patch_ids.shape
|
| 1126 |
+
device = patch_ids.device
|
| 1127 |
+
|
| 1128 |
+
# Determine query and key lengths based on configuration
|
| 1129 |
+
if patches_as_queries:
|
| 1130 |
+
q_len = num_patches * cross_attn_k
|
| 1131 |
+
kv_len = sequence_length
|
| 1132 |
+
# Create patch-to-sequence mapping
|
| 1133 |
+
q_patch_ids = (
|
| 1134 |
+
torch.arange(num_patches, device=device)
|
| 1135 |
+
.unsqueeze(0)
|
| 1136 |
+
.unsqueeze(-1)
|
| 1137 |
+
.expand(batch_size, num_patches, seq_len)
|
| 1138 |
+
)
|
| 1139 |
+
kv_patch_ids = patch_ids.unsqueeze(1).expand(batch_size, num_patches, seq_len)
|
| 1140 |
+
else:
|
| 1141 |
+
q_len = sequence_length
|
| 1142 |
+
kv_len = num_patches * cross_attn_k
|
| 1143 |
+
# Create sequence-to-patch mapping
|
| 1144 |
+
q_patch_ids = patch_ids.unsqueeze(-1).expand(batch_size, seq_len, num_patches)
|
| 1145 |
+
kv_patch_ids = (
|
| 1146 |
+
torch.arange(num_patches, device=device).unsqueeze(0).unsqueeze(0).expand(batch_size, seq_len, num_patches)
|
| 1147 |
+
)
|
| 1148 |
+
|
| 1149 |
+
# Create base attention mask - boolean mask where True means "should attend"
|
| 1150 |
+
# Exact patch matching
|
| 1151 |
+
cross_attention_mask = q_patch_ids == kv_patch_ids
|
| 1152 |
+
|
| 1153 |
+
# Handle cross_attn_k multiplier by repeating along appropriate dimension
|
| 1154 |
+
repeat_dim = 1 if patches_as_queries else -1
|
| 1155 |
+
cross_attention_mask = cross_attention_mask.repeat_interleave(cross_attn_k, dim=repeat_dim)
|
| 1156 |
+
|
| 1157 |
+
# Validate dimensions
|
| 1158 |
+
expected_shape = (batch_size, q_len, kv_len)
|
| 1159 |
+
if cross_attention_mask.shape != expected_shape:
|
| 1160 |
+
raise ValueError(
|
| 1161 |
+
f"Cross attention mask shape {cross_attention_mask.shape} doesn't match expected {expected_shape}"
|
| 1162 |
+
)
|
| 1163 |
+
|
| 1164 |
+
# Reshape so it can be used by attn module - add head dimension
|
| 1165 |
+
cross_attention_mask = cross_attention_mask.unsqueeze(1) # [batch_size, 1, q_len, kv_len]
|
| 1166 |
+
|
| 1167 |
+
# Invert the mask (following mllama pattern exactly)
|
| 1168 |
+
# True -> 0.0 (attend), False -> 1.0 (will become -inf)
|
| 1169 |
+
inverted_cross_attn_mask = 1.0 - cross_attention_mask.to(dtype)
|
| 1170 |
+
cross_attention_mask = inverted_cross_attn_mask.masked_fill(
|
| 1171 |
+
inverted_cross_attn_mask.to(torch.bool), torch.finfo(dtype).min
|
| 1172 |
+
)
|
| 1173 |
+
|
| 1174 |
+
return cross_attention_mask
|
| 1175 |
+
|
| 1176 |
+
|
| 1177 |
+
class BltModel(BltPreTrainedModel):
|
| 1178 |
+
def __init__(self, config: BltConfig):
|
| 1179 |
+
super().__init__(config)
|
| 1180 |
+
self.gradient_checkpointing = False
|
| 1181 |
+
|
| 1182 |
+
self.config = config
|
| 1183 |
+
self.local_encoder = BltLocalEncoder(config.encoder_config)
|
| 1184 |
+
self.global_transformer = BltGlobalTransformer(config.global_config)
|
| 1185 |
+
self.local_decoder = BltLocalDecoder(config.decoder_config)
|
| 1186 |
+
num_embeddings = config.encoder_hash_byte_group_nb_functions * len(config.encoder_hash_byte_group_size)
|
| 1187 |
+
total_vocab_size = config.encoder_hash_byte_group_vocab * num_embeddings
|
| 1188 |
+
self.encoder_hash_tok_embedding = nn.Embedding(total_vocab_size, config.encoder_config.hidden_size)
|
| 1189 |
+
if self.config.patch_in_forward:
|
| 1190 |
+
self.patcher = BltPatcher(config.patcher_config)
|
| 1191 |
+
self.patcher.eval()
|
| 1192 |
+
for param in self.patcher.parameters():
|
| 1193 |
+
param.requires_grad = False
|
| 1194 |
+
else:
|
| 1195 |
+
self.patcher = None
|
| 1196 |
+
self.post_init()
|
| 1197 |
+
|
| 1198 |
+
@merge_with_config_defaults
|
| 1199 |
+
@capture_outputs
|
| 1200 |
+
def forward(
|
| 1201 |
+
self,
|
| 1202 |
+
input_ids: torch.LongTensor | None = None,
|
| 1203 |
+
patch_lengths: torch.Tensor | None = None,
|
| 1204 |
+
attention_mask: torch.Tensor | None = None,
|
| 1205 |
+
position_ids: torch.LongTensor | None = None,
|
| 1206 |
+
past_key_values: Cache | None = None,
|
| 1207 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 1208 |
+
use_cache: bool | None = None,
|
| 1209 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1210 |
+
) -> tuple | BaseModelOutputWithPast:
|
| 1211 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 1212 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 1213 |
+
|
| 1214 |
+
if use_cache:
|
| 1215 |
+
if past_key_values is None:
|
| 1216 |
+
past_key_values = EncoderDecoderCache(
|
| 1217 |
+
DynamicCache(config=self.config), DynamicCache(config=self.config)
|
| 1218 |
+
)
|
| 1219 |
+
elif not isinstance(past_key_values, EncoderDecoderCache):
|
| 1220 |
+
# BLT uses an encoder-decoder cache even though it is not en encoder-decoder model. Create a cross-cache
|
| 1221 |
+
# if not yet created by the user
|
| 1222 |
+
past_key_values = EncoderDecoderCache(past_key_values, DynamicCache(config=self.config))
|
| 1223 |
+
|
| 1224 |
+
# Extract input embeddings as early as possible
|
| 1225 |
+
if inputs_embeds is not None:
|
| 1226 |
+
encoder_embeds = inputs_embeds
|
| 1227 |
+
batch_size, sequence_length, _ = inputs_embeds.shape
|
| 1228 |
+
else:
|
| 1229 |
+
batch_size, sequence_length = input_ids.shape
|
| 1230 |
+
encoder_embeds = compute_hash_embeddings(
|
| 1231 |
+
input_ids,
|
| 1232 |
+
self.local_encoder,
|
| 1233 |
+
self.encoder_hash_tok_embedding,
|
| 1234 |
+
self.config.encoder_hash_byte_group_nb_functions,
|
| 1235 |
+
self.config.encoder_hash_byte_group_size,
|
| 1236 |
+
self.config.encoder_hash_byte_group_vocab,
|
| 1237 |
+
)
|
| 1238 |
+
|
| 1239 |
+
if patch_lengths is None:
|
| 1240 |
+
if self.config.patching_mode == "entropy" and self.patcher is not None:
|
| 1241 |
+
if input_ids is None:
|
| 1242 |
+
raise ValueError("input_ids is required for entropy-based patching")
|
| 1243 |
+
_, patch_lengths, _ = self.patcher(
|
| 1244 |
+
input_ids,
|
| 1245 |
+
patch_size=self.config.patch_size,
|
| 1246 |
+
threshold=self.config.patching_threshold,
|
| 1247 |
+
max_patch_length=self.config.max_patch_length,
|
| 1248 |
+
patching_batch_size=self.config.patching_batch_size,
|
| 1249 |
+
device=input_ids.device,
|
| 1250 |
+
)
|
| 1251 |
+
else:
|
| 1252 |
+
device = input_ids.device if input_ids is not None else inputs_embeds.device
|
| 1253 |
+
dtype = input_ids.dtype if input_ids is not None else inputs_embeds.dtype
|
| 1254 |
+
patch_lengths = process_patch_lengths(
|
| 1255 |
+
torch.ones((batch_size, sequence_length + 1), dtype=dtype, device=device),
|
| 1256 |
+
self.config.max_patch_length,
|
| 1257 |
+
)
|
| 1258 |
+
patch_ids = self._patch_ids_from_lengths(patch_lengths, sequence_length)
|
| 1259 |
+
|
| 1260 |
+
if position_ids is None:
|
| 1261 |
+
past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
|
| 1262 |
+
position_ids = torch.arange(encoder_embeds.shape[1], device=encoder_embeds.device) + past_seen_tokens
|
| 1263 |
+
position_ids = position_ids.unsqueeze(0)
|
| 1264 |
+
|
| 1265 |
+
causal_mask = create_causal_mask(
|
| 1266 |
+
config=self.config,
|
| 1267 |
+
inputs_embeds=encoder_embeds,
|
| 1268 |
+
attention_mask=attention_mask,
|
| 1269 |
+
past_key_values=past_key_values.self_attention_cache if past_key_values is not None else None,
|
| 1270 |
+
position_ids=position_ids,
|
| 1271 |
+
)
|
| 1272 |
+
|
| 1273 |
+
cross_attn_mask_enc = _prepare_patch_cross_attention_mask(
|
| 1274 |
+
patch_ids=patch_ids,
|
| 1275 |
+
num_patches=patch_lengths.shape[1],
|
| 1276 |
+
sequence_length=sequence_length,
|
| 1277 |
+
patches_as_queries=True,
|
| 1278 |
+
cross_attn_k=self.config.cross_attn_k,
|
| 1279 |
+
dtype=encoder_embeds.dtype,
|
| 1280 |
+
)
|
| 1281 |
+
encoder_hidden_states, encoder_cross_states = self.local_encoder(
|
| 1282 |
+
input_ids=input_ids,
|
| 1283 |
+
inputs_embeds=encoder_embeds,
|
| 1284 |
+
attention_mask=causal_mask,
|
| 1285 |
+
position_ids=position_ids,
|
| 1286 |
+
encoder_attention_mask=cross_attn_mask_enc,
|
| 1287 |
+
num_patches=patch_lengths.shape[1],
|
| 1288 |
+
patch_ids=patch_ids,
|
| 1289 |
+
past_key_values=past_key_values.self_attention_cache if past_key_values is not None else None,
|
| 1290 |
+
**kwargs,
|
| 1291 |
+
)
|
| 1292 |
+
encoder_cross_states = encoder_cross_states.view(batch_size, patch_lengths.shape[1], -1)
|
| 1293 |
+
global_position_ids = torch.arange(0, encoder_cross_states.shape[1], device=encoder_cross_states.device)
|
| 1294 |
+
global_position_ids = global_position_ids.unsqueeze(0)
|
| 1295 |
+
global_causal_mask = create_causal_mask(
|
| 1296 |
+
config=self.config,
|
| 1297 |
+
inputs_embeds=encoder_cross_states,
|
| 1298 |
+
attention_mask=None,
|
| 1299 |
+
past_key_values=None,
|
| 1300 |
+
position_ids=None,
|
| 1301 |
+
)
|
| 1302 |
+
|
| 1303 |
+
global_hidden_states = self.global_transformer(
|
| 1304 |
+
inputs_embeds=encoder_cross_states,
|
| 1305 |
+
attention_mask=global_causal_mask,
|
| 1306 |
+
position_ids=global_position_ids,
|
| 1307 |
+
**kwargs,
|
| 1308 |
+
)
|
| 1309 |
+
decoder_patch_ids = self._patch_ids_from_lengths(patch_lengths[:, 1:], sequence_length)
|
| 1310 |
+
cross_attn_mask_dec = _prepare_patch_cross_attention_mask(
|
| 1311 |
+
patch_ids=decoder_patch_ids,
|
| 1312 |
+
num_patches=patch_lengths.shape[1],
|
| 1313 |
+
sequence_length=sequence_length,
|
| 1314 |
+
patches_as_queries=False,
|
| 1315 |
+
cross_attn_k=self.config.cross_attn_k,
|
| 1316 |
+
dtype=encoder_embeds.dtype,
|
| 1317 |
+
)
|
| 1318 |
+
output = self.local_decoder(
|
| 1319 |
+
input_ids=input_ids,
|
| 1320 |
+
inputs_embeds=encoder_hidden_states,
|
| 1321 |
+
patch_embeds=global_hidden_states,
|
| 1322 |
+
attention_mask=causal_mask,
|
| 1323 |
+
position_ids=position_ids,
|
| 1324 |
+
past_key_values=past_key_values.cross_attention_cache if past_key_values is not None else None,
|
| 1325 |
+
encoder_attention_mask=cross_attn_mask_dec,
|
| 1326 |
+
**kwargs,
|
| 1327 |
+
)
|
| 1328 |
+
return BaseModelOutputWithPast(
|
| 1329 |
+
last_hidden_state=output,
|
| 1330 |
+
past_key_values=past_key_values,
|
| 1331 |
+
)
|
| 1332 |
+
|
| 1333 |
+
def get_input_embeddings(self):
|
| 1334 |
+
return self.local_encoder.embed_tokens
|
| 1335 |
+
|
| 1336 |
+
def set_input_embeddings(self, value):
|
| 1337 |
+
self.local_encoder.embed_tokens = value
|
| 1338 |
+
|
| 1339 |
+
def _patch_ids_from_lengths(self, patch_lengths: torch.Tensor, seq_len: int) -> torch.Tensor:
|
| 1340 |
+
batch_size = patch_lengths.shape[0]
|
| 1341 |
+
patch_starts = torch.cat(
|
| 1342 |
+
[
|
| 1343 |
+
torch.zeros(batch_size, 1, dtype=patch_lengths.dtype, device=patch_lengths.device),
|
| 1344 |
+
patch_lengths.cumsum(dim=-1)[:, :-1],
|
| 1345 |
+
],
|
| 1346 |
+
dim=-1,
|
| 1347 |
+
)
|
| 1348 |
+
token_positions = torch.arange(seq_len, device=patch_lengths.device)
|
| 1349 |
+
return (patch_starts.unsqueeze(1) <= token_positions.unsqueeze(0).unsqueeze(-1)).sum(dim=-1) - 1
|
| 1350 |
+
|
| 1351 |
+
|
| 1352 |
+
@auto_docstring(
|
| 1353 |
+
custom_intro="""
|
| 1354 |
+
The Blt Text Model with a language modeling head on top.
|
| 1355 |
+
"""
|
| 1356 |
+
)
|
| 1357 |
+
class BltForCausalLM(BltPreTrainedModel, GenerationMixin):
|
| 1358 |
+
config: BltConfig
|
| 1359 |
+
_can_compile_fullgraph = False
|
| 1360 |
+
base_model_prefix = "model"
|
| 1361 |
+
_tied_weights_keys = {"model.local_encoder.embed_tokens.weight": "lm_head.weight"}
|
| 1362 |
+
|
| 1363 |
+
def __init__(self, config: BltConfig):
|
| 1364 |
+
super().__init__(config)
|
| 1365 |
+
self.text_config = config.get_text_config()
|
| 1366 |
+
self.vocab_size = config.vocab_size
|
| 1367 |
+
self.model = BltModel(config)
|
| 1368 |
+
self.lm_head = nn.Linear(config.decoder_config.hidden_size, config.vocab_size, bias=False)
|
| 1369 |
+
|
| 1370 |
+
self.post_init()
|
| 1371 |
+
|
| 1372 |
+
@can_return_tuple
|
| 1373 |
+
@auto_docstring
|
| 1374 |
+
def forward(
|
| 1375 |
+
self,
|
| 1376 |
+
input_ids: torch.LongTensor | None = None,
|
| 1377 |
+
attention_mask: torch.Tensor | None = None,
|
| 1378 |
+
position_ids: torch.LongTensor | None = None,
|
| 1379 |
+
cross_attention_states: torch.LongTensor | None = None, # Keep for compatibility
|
| 1380 |
+
cross_attention_mask: torch.LongTensor | None = None,
|
| 1381 |
+
full_text_row_masked_out_mask: tuple[torch.Tensor, torch.Tensor] | None = None,
|
| 1382 |
+
past_key_values: Cache | None = None,
|
| 1383 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 1384 |
+
labels: torch.LongTensor | None = None,
|
| 1385 |
+
use_cache: bool | None = None,
|
| 1386 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 1387 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1388 |
+
) -> tuple | CausalLMOutputWithPast:
|
| 1389 |
+
r"""
|
| 1390 |
+
cross_attention_states (`torch.FloatTensor`, *optional*):
|
| 1391 |
+
Output of the vision model, used for cross-attention. This tensor contains the processed image features that
|
| 1392 |
+
the language model will attend to.
|
| 1393 |
+
cross_attention_mask (`torch.Tensor` of shape `(batch_size, seq_length, max_num_images, max_num_tiles)`, *optional*):
|
| 1394 |
+
Cross-attention mask to control the interaction between text tokens and image tiles.
|
| 1395 |
+
This 4D tensor defines which image tiles each text token should attend to.
|
| 1396 |
+
|
| 1397 |
+
For each text token (in seq_length):
|
| 1398 |
+
- 1 indicates the token **should attend** to the corresponding image tile
|
| 1399 |
+
- 0 indicates the token **should not attend** to the corresponding image tile
|
| 1400 |
+
full_text_row_masked_out_mask (`tuple[torch.Tensor, torch.Tensor]`, *optional*):
|
| 1401 |
+
A tuple containing two tensors that mask out rows in the cross-attention mechanism:
|
| 1402 |
+
- The first tensor has shape `(batch_size, 1, seq_length, 1)` and contains values of 0 or 1.
|
| 1403 |
+
A value of 0 indicates that the corresponding text token's entire row in the cross-attention
|
| 1404 |
+
matrix should be masked out (all image tokens ignored).
|
| 1405 |
+
- The second tensor has the same shape and is used internally to apply the masking during
|
| 1406 |
+
the forward pass of cross-attention layers.
|
| 1407 |
+
This mask is derived from the cross_attention_mask and is used to handle cases where a text token
|
| 1408 |
+
should not attend to any image token.
|
| 1409 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 1410 |
+
Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
|
| 1411 |
+
config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
|
| 1412 |
+
(masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
|
| 1413 |
+
|
| 1414 |
+
Example:
|
| 1415 |
+
|
| 1416 |
+
```python
|
| 1417 |
+
>>> from transformers import AutoTokenizer, BltForCausalLM
|
| 1418 |
+
|
| 1419 |
+
>>> model = BltForCausalLM.from_pretrained("itazap/blt-1b-hf")
|
| 1420 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("itazap/blt-1b-hf")
|
| 1421 |
+
|
| 1422 |
+
>>> prompt = "If I had to write a haiku, it would be:"
|
| 1423 |
+
>>> inputs = tokenizer(prompt, return_tensors="pt")
|
| 1424 |
+
|
| 1425 |
+
>>> # Generate
|
| 1426 |
+
>>> generate_ids = model.generate(inputs.input_ids, max_length=40, do_sample=True, temperature=0.6)
|
| 1427 |
+
>>> result = tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
|
| 1428 |
+
>>> print(result)
|
| 1429 |
+
If I had to write a haiku, it would be: "Snowflakes gently fall" - simple, yet peaceful.
|
| 1430 |
+
I love the idea of snowflakes gently falling, each one
|
| 1431 |
+
```
|
| 1432 |
+
"""
|
| 1433 |
+
# Call parent forward but exclude cross_attention_states from model call
|
| 1434 |
+
outputs = self.model(
|
| 1435 |
+
input_ids=input_ids,
|
| 1436 |
+
attention_mask=attention_mask,
|
| 1437 |
+
position_ids=position_ids,
|
| 1438 |
+
cross_attention_mask=cross_attention_mask,
|
| 1439 |
+
full_text_row_masked_out_mask=full_text_row_masked_out_mask,
|
| 1440 |
+
past_key_values=past_key_values,
|
| 1441 |
+
inputs_embeds=inputs_embeds,
|
| 1442 |
+
use_cache=use_cache,
|
| 1443 |
+
**kwargs,
|
| 1444 |
+
)
|
| 1445 |
+
|
| 1446 |
+
hidden_states = outputs.last_hidden_state
|
| 1447 |
+
slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
|
| 1448 |
+
logits = self.lm_head(hidden_states[:, slice_indices, :]).float()
|
| 1449 |
+
|
| 1450 |
+
loss = None
|
| 1451 |
+
if labels is not None:
|
| 1452 |
+
loss = self.loss_function(logits, labels, self.vocab_size, **kwargs)
|
| 1453 |
+
|
| 1454 |
+
return CausalLMOutputWithPast(
|
| 1455 |
+
loss=loss,
|
| 1456 |
+
logits=logits,
|
| 1457 |
+
past_key_values=outputs.past_key_values,
|
| 1458 |
+
hidden_states=outputs.hidden_states,
|
| 1459 |
+
attentions=outputs.attentions,
|
| 1460 |
+
)
|
| 1461 |
+
|
| 1462 |
+
|
| 1463 |
+
__all__ = ["BltPreTrainedModel", "BltModel", "BltPatcher", "BltForCausalLM"]
|
third_party/transformers/src/transformers/models/blt/modular_blt.py
ADDED
|
@@ -0,0 +1,1195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Blt modular model, inheriting from Mllama where appropriate."""
|
| 15 |
+
|
| 16 |
+
from collections.abc import Callable
|
| 17 |
+
|
| 18 |
+
import torch
|
| 19 |
+
import torch.distributions
|
| 20 |
+
import torch.nn as nn
|
| 21 |
+
import torch.nn.functional as F
|
| 22 |
+
|
| 23 |
+
from ... import initialization as init
|
| 24 |
+
from ...cache_utils import Cache, DynamicCache, EncoderDecoderCache
|
| 25 |
+
from ...generation import GenerationMixin
|
| 26 |
+
from ...masking_utils import create_causal_mask
|
| 27 |
+
from ...modeling_outputs import BaseModelOutputWithPast, CausalLMOutputWithPast
|
| 28 |
+
from ...modeling_rope_utils import ROPE_INIT_FUNCTIONS, dynamic_rope_update
|
| 29 |
+
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS
|
| 30 |
+
from ...processing_utils import Unpack
|
| 31 |
+
from ...utils import TransformersKwargs, auto_docstring, can_return_tuple, logging
|
| 32 |
+
from ...utils.deprecation import deprecate_kwarg
|
| 33 |
+
from ...utils.generic import maybe_autocast, merge_with_config_defaults
|
| 34 |
+
from ...utils.output_capturing import OutputRecorder, capture_outputs
|
| 35 |
+
from ..cohere2.modeling_cohere2 import rotate_half # noqa: F401
|
| 36 |
+
from ..llama.modeling_llama import LlamaRotaryEmbedding
|
| 37 |
+
from ..mllama.modeling_mllama import (
|
| 38 |
+
MllamaPreTrainedModel,
|
| 39 |
+
MllamaSelfAttentionDecoderLayer,
|
| 40 |
+
MllamaTextCrossAttention,
|
| 41 |
+
MllamaTextMLP,
|
| 42 |
+
MllamaTextRMSNorm,
|
| 43 |
+
MllamaTextSelfAttention,
|
| 44 |
+
eager_attention_forward,
|
| 45 |
+
)
|
| 46 |
+
from .configuration_blt import (
|
| 47 |
+
BltConfig,
|
| 48 |
+
BltGlobalTransformerConfig,
|
| 49 |
+
BltLocalDecoderConfig,
|
| 50 |
+
BltLocalEncoderConfig,
|
| 51 |
+
BltPatcherConfig,
|
| 52 |
+
)
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
logger = logging.get_logger(__name__)
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def rolling_polynomial_hash(token_tensor, prime: int = 1000000007):
|
| 59 |
+
"""
|
| 60 |
+
A polynomial rolling hash algorithm that converts sequences
|
| 61 |
+
of tokens into hash values. The hash is computed as:
|
| 62 |
+
hash = (token_0 * prime^0 + token_1 * prime^1 + ... + token_n * prime^n)
|
| 63 |
+
|
| 64 |
+
The rolling hash allows the model to efficiently
|
| 65 |
+
identify and encode recurring byte-level patterns in the input text.
|
| 66 |
+
|
| 67 |
+
Args:
|
| 68 |
+
token_tensor (torch.Tensor): [batch_size, seq_len, group_size] containing token IDs to hash
|
| 69 |
+
prime (int): Prime number used as the base for the polynomial hash.
|
| 70 |
+
|
| 71 |
+
Returns:
|
| 72 |
+
torch.Tensor: Hash values of shape [batch_size, seq_len] where each value
|
| 73 |
+
represents the hash of the corresponding token group
|
| 74 |
+
|
| 75 |
+
Example:
|
| 76 |
+
>>> tokens = torch.tensor([[1, 2, 3], [4, 5, 6]])
|
| 77 |
+
>>> hashes = rolling_polynomial_hash(tokens, prime=31)
|
| 78 |
+
>>> # hash[0] = 1*31^0 + 2*31^1 + 3*31^2
|
| 79 |
+
>>> # hash[1] = 4*31^0 + 5*31^1 + 6*31^2
|
| 80 |
+
"""
|
| 81 |
+
prime_tensor = torch.tensor(prime, dtype=torch.int64, device=token_tensor.device)
|
| 82 |
+
powers = torch.arange(token_tensor.shape[-1], device=token_tensor.device)
|
| 83 |
+
prime_powers = prime_tensor**powers
|
| 84 |
+
return torch.sum(token_tensor * prime_powers, dim=-1)
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def byte_group_hash_function(
|
| 88 |
+
token_ids: torch.Tensor, group_size: int = 2, prime: int = 1000000007, max_hash: int = 30000
|
| 89 |
+
):
|
| 90 |
+
"""Hash token groups and map to range [0, max_hash]."""
|
| 91 |
+
with torch.no_grad():
|
| 92 |
+
batch_size, seq_len = token_ids.shape
|
| 93 |
+
# Add padding for sliding window
|
| 94 |
+
padding = torch.zeros(batch_size, group_size - 1, dtype=torch.int64, device=token_ids.device)
|
| 95 |
+
padded_tokens = torch.cat([padding, token_ids], dim=1)
|
| 96 |
+
|
| 97 |
+
# Create sliding windows and compute hashes
|
| 98 |
+
windows = padded_tokens.unfold(1, group_size, 1)
|
| 99 |
+
hashes = rolling_polynomial_hash(windows, prime)
|
| 100 |
+
hash_values = hashes % max_hash
|
| 101 |
+
|
| 102 |
+
return hash_values
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def compute_hash_embeddings(
|
| 106 |
+
local_encoder_tokens: torch.Tensor,
|
| 107 |
+
local_encoder,
|
| 108 |
+
encoder_hash_tok_embedding: nn.Embedding,
|
| 109 |
+
encoder_hash_byte_group_nb_functions: int,
|
| 110 |
+
encoder_hash_byte_group_size: list,
|
| 111 |
+
encoder_hash_byte_group_vocab: int,
|
| 112 |
+
) -> torch.Tensor:
|
| 113 |
+
"""Compute token embeddings enhanced with hash-based embeddings."""
|
| 114 |
+
# Available primes for hash functions
|
| 115 |
+
primes = [
|
| 116 |
+
1000000007,
|
| 117 |
+
5915587277,
|
| 118 |
+
1500450271,
|
| 119 |
+
3267000013,
|
| 120 |
+
5754853343,
|
| 121 |
+
4093082899,
|
| 122 |
+
9576890767,
|
| 123 |
+
3628273133,
|
| 124 |
+
2860486313,
|
| 125 |
+
5463458053,
|
| 126 |
+
3367900313,
|
| 127 |
+
]
|
| 128 |
+
|
| 129 |
+
embeddings = local_encoder.embed_tokens(local_encoder_tokens)
|
| 130 |
+
embedding_idx = 0
|
| 131 |
+
for func_nb in range(encoder_hash_byte_group_nb_functions):
|
| 132 |
+
prime = primes[func_nb % len(primes)] # Cycle through primes if more functions than primes
|
| 133 |
+
for group_size in encoder_hash_byte_group_size:
|
| 134 |
+
hash_ids = byte_group_hash_function(local_encoder_tokens, group_size, prime, encoder_hash_byte_group_vocab)
|
| 135 |
+
# Apply offset to get the correct slice of the fused embedding
|
| 136 |
+
offset_hash_ids = hash_ids + embedding_idx * encoder_hash_byte_group_vocab
|
| 137 |
+
embeddings += encoder_hash_tok_embedding(offset_hash_ids).to(embeddings.device)
|
| 138 |
+
embedding_idx += 1
|
| 139 |
+
|
| 140 |
+
return embeddings
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
def _prepare_patch_cross_attention_mask(
|
| 144 |
+
patch_ids: torch.Tensor,
|
| 145 |
+
num_patches: int,
|
| 146 |
+
sequence_length: int,
|
| 147 |
+
patches_as_queries: bool = False,
|
| 148 |
+
cross_attn_k: int = 1,
|
| 149 |
+
dtype: torch.dtype = torch.float32,
|
| 150 |
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
| 151 |
+
"""
|
| 152 |
+
Prepare cross-attention mask for patch-based attention, following mllama's robust approach.
|
| 153 |
+
|
| 154 |
+
This function creates masks that control which patches can attend to which other patches,
|
| 155 |
+
with support for query/key role swapping and cross-attention multipliers.
|
| 156 |
+
|
| 157 |
+
Args:
|
| 158 |
+
patch_ids (torch.Tensor): Tensor of shape [batch_size, seq_len] containing patch ids.
|
| 159 |
+
num_patches (int): Total number of patches.
|
| 160 |
+
sequence_length (int): Length of the sequence.
|
| 161 |
+
patches_as_queries (bool): If True, patches are used as queries, otherwise as keys.
|
| 162 |
+
cross_attn_k (int): Cross-attention multiplier for repeating patches.
|
| 163 |
+
dtype (torch.dtype): Data type for the output mask.
|
| 164 |
+
|
| 165 |
+
Returns:
|
| 166 |
+
Tuple[torch.Tensor, torch.Tensor]:
|
| 167 |
+
- cross_attention_mask: 4D tensor [batch_size, 1, q_len, kv_len]
|
| 168 |
+
"""
|
| 169 |
+
batch_size, seq_len = patch_ids.shape
|
| 170 |
+
device = patch_ids.device
|
| 171 |
+
|
| 172 |
+
# Determine query and key lengths based on configuration
|
| 173 |
+
if patches_as_queries:
|
| 174 |
+
q_len = num_patches * cross_attn_k
|
| 175 |
+
kv_len = sequence_length
|
| 176 |
+
# Create patch-to-sequence mapping
|
| 177 |
+
q_patch_ids = (
|
| 178 |
+
torch.arange(num_patches, device=device)
|
| 179 |
+
.unsqueeze(0)
|
| 180 |
+
.unsqueeze(-1)
|
| 181 |
+
.expand(batch_size, num_patches, seq_len)
|
| 182 |
+
)
|
| 183 |
+
kv_patch_ids = patch_ids.unsqueeze(1).expand(batch_size, num_patches, seq_len)
|
| 184 |
+
else:
|
| 185 |
+
q_len = sequence_length
|
| 186 |
+
kv_len = num_patches * cross_attn_k
|
| 187 |
+
# Create sequence-to-patch mapping
|
| 188 |
+
q_patch_ids = patch_ids.unsqueeze(-1).expand(batch_size, seq_len, num_patches)
|
| 189 |
+
kv_patch_ids = (
|
| 190 |
+
torch.arange(num_patches, device=device).unsqueeze(0).unsqueeze(0).expand(batch_size, seq_len, num_patches)
|
| 191 |
+
)
|
| 192 |
+
|
| 193 |
+
# Create base attention mask - boolean mask where True means "should attend"
|
| 194 |
+
# Exact patch matching
|
| 195 |
+
cross_attention_mask = q_patch_ids == kv_patch_ids
|
| 196 |
+
|
| 197 |
+
# Handle cross_attn_k multiplier by repeating along appropriate dimension
|
| 198 |
+
repeat_dim = 1 if patches_as_queries else -1
|
| 199 |
+
cross_attention_mask = cross_attention_mask.repeat_interleave(cross_attn_k, dim=repeat_dim)
|
| 200 |
+
|
| 201 |
+
# Validate dimensions
|
| 202 |
+
expected_shape = (batch_size, q_len, kv_len)
|
| 203 |
+
if cross_attention_mask.shape != expected_shape:
|
| 204 |
+
raise ValueError(
|
| 205 |
+
f"Cross attention mask shape {cross_attention_mask.shape} doesn't match expected {expected_shape}"
|
| 206 |
+
)
|
| 207 |
+
|
| 208 |
+
# Reshape so it can be used by attn module - add head dimension
|
| 209 |
+
cross_attention_mask = cross_attention_mask.unsqueeze(1) # [batch_size, 1, q_len, kv_len]
|
| 210 |
+
|
| 211 |
+
# Invert the mask (following mllama pattern exactly)
|
| 212 |
+
# True -> 0.0 (attend), False -> 1.0 (will become -inf)
|
| 213 |
+
inverted_cross_attn_mask = 1.0 - cross_attention_mask.to(dtype)
|
| 214 |
+
cross_attention_mask = inverted_cross_attn_mask.masked_fill(
|
| 215 |
+
inverted_cross_attn_mask.to(torch.bool), torch.finfo(dtype).min
|
| 216 |
+
)
|
| 217 |
+
|
| 218 |
+
return cross_attention_mask
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def process_patch_lengths(patch_lengths: torch.Tensor, max_patch_length: int | None) -> torch.Tensor:
|
| 222 |
+
"""
|
| 223 |
+
Splits patch lengths into smaller segments if they exceed `max_patch_length`.
|
| 224 |
+
Pads the result to uniform length across the batch.
|
| 225 |
+
|
| 226 |
+
Args:
|
| 227 |
+
patch_lengths (torch.Tensor): [batch_size, num_patches] tensor of patch lengths.
|
| 228 |
+
max_patch_length (int, optional): Maximum allowed length per patch.
|
| 229 |
+
|
| 230 |
+
Returns:
|
| 231 |
+
torch.Tensor: [batch_size, max_len] tensor of split and padded patch lengths.
|
| 232 |
+
"""
|
| 233 |
+
if max_patch_length is None:
|
| 234 |
+
return patch_lengths
|
| 235 |
+
|
| 236 |
+
batch_size = patch_lengths.size(0)
|
| 237 |
+
processed = []
|
| 238 |
+
|
| 239 |
+
for seq in patch_lengths:
|
| 240 |
+
splits = []
|
| 241 |
+
for length in seq[seq > 0]:
|
| 242 |
+
length = length.item()
|
| 243 |
+
full_chunks, remainder = divmod(length, max_patch_length)
|
| 244 |
+
splits.extend([max_patch_length] * full_chunks)
|
| 245 |
+
if remainder:
|
| 246 |
+
splits.append(remainder)
|
| 247 |
+
processed.append(splits)
|
| 248 |
+
|
| 249 |
+
# Find max length to pad to
|
| 250 |
+
max_len = max(len(splits) for splits in processed)
|
| 251 |
+
padded = torch.zeros((batch_size, max_len), dtype=patch_lengths.dtype, device=patch_lengths.device)
|
| 252 |
+
|
| 253 |
+
for i, splits in enumerate(processed):
|
| 254 |
+
if splits:
|
| 255 |
+
padded[i, : len(splits)] = torch.tensor(splits, dtype=patch_lengths.dtype, device=patch_lengths.device)
|
| 256 |
+
|
| 257 |
+
# Trim zero columns
|
| 258 |
+
if (padded != 0).any(dim=0).sum() < padded.shape[1]:
|
| 259 |
+
last_nonzero = (padded != 0).any(dim=0).nonzero().max().item() + 1
|
| 260 |
+
padded = padded[:, :last_nonzero]
|
| 261 |
+
|
| 262 |
+
return padded
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
class BltMLP(MllamaTextMLP):
|
| 266 |
+
pass
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
class BltRMSNorm(MllamaTextRMSNorm):
|
| 270 |
+
pass
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
class BltRotaryEmbedding(LlamaRotaryEmbedding):
|
| 274 |
+
@torch.no_grad()
|
| 275 |
+
@dynamic_rope_update # power user: used with advanced RoPE types (e.g. dynamic rope)
|
| 276 |
+
def forward(self, x, position_ids):
|
| 277 |
+
inv_freq_expanded = self.inv_freq[None, :, None].float().expand(position_ids.shape[0], -1, 1)
|
| 278 |
+
position_ids_expanded = position_ids[:, None, :].float()
|
| 279 |
+
|
| 280 |
+
device_type = x.device.type if isinstance(x.device.type, str) and x.device.type != "mps" else "cpu"
|
| 281 |
+
with maybe_autocast(device_type=device_type, enabled=False): # Force float32
|
| 282 |
+
freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(1, 2)
|
| 283 |
+
emb = torch.repeat_interleave(freqs, 2, dim=-1) # diff from Llama: we interleave() instead of cat()
|
| 284 |
+
cos = emb.cos() * self.attention_scaling
|
| 285 |
+
sin = emb.sin() * self.attention_scaling
|
| 286 |
+
|
| 287 |
+
return cos.to(dtype=x.dtype), sin.to(dtype=x.dtype)
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
class BltTransformerLayer(MllamaSelfAttentionDecoderLayer):
|
| 291 |
+
def __init__(self, config, layer_idx: int):
|
| 292 |
+
super().__init__()
|
| 293 |
+
|
| 294 |
+
self.self_attn = BltSelfAttention(config=config, layer_idx=layer_idx)
|
| 295 |
+
self.mlp = BltMLP(config)
|
| 296 |
+
self.input_layernorm = BltRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 297 |
+
self.post_attention_layernorm = BltRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
class BltSelfAttention(MllamaTextSelfAttention):
|
| 301 |
+
def __init__(self, config: BltConfig, layer_idx: int):
|
| 302 |
+
super().__init__(config, layer_idx)
|
| 303 |
+
|
| 304 |
+
|
| 305 |
+
class BltCrossAttention(MllamaTextCrossAttention):
|
| 306 |
+
"""Cross-attention module for Blt, following transformers style"""
|
| 307 |
+
|
| 308 |
+
def __init__(self, config: BltConfig, layer_idx: int, hidden_size: int | None = None):
|
| 309 |
+
super().__init__()
|
| 310 |
+
self.is_causal = False
|
| 311 |
+
self.q_norm = BltRMSNorm(self.hidden_size, eps=config.rms_norm_eps)
|
| 312 |
+
self.k_norm = BltRMSNorm(self.hidden_size, eps=config.rms_norm_eps)
|
| 313 |
+
|
| 314 |
+
def forward(
|
| 315 |
+
self,
|
| 316 |
+
hidden_states: torch.Tensor,
|
| 317 |
+
cross_attention_states: torch.Tensor | None = None,
|
| 318 |
+
attention_mask: torch.Tensor | None = None,
|
| 319 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 320 |
+
):
|
| 321 |
+
bsz, q_len, _ = hidden_states.size()
|
| 322 |
+
query_states = self.q_norm(hidden_states)
|
| 323 |
+
query_states = self.q_proj(query_states)
|
| 324 |
+
query_states = query_states.view(bsz, q_len, self.num_heads, self.head_dim).transpose(1, 2)
|
| 325 |
+
|
| 326 |
+
cross_attention_states = self.k_norm(cross_attention_states)
|
| 327 |
+
key_states = self.k_proj(cross_attention_states)
|
| 328 |
+
value_states = self.v_proj(cross_attention_states)
|
| 329 |
+
key_states = key_states.view(bsz, -1, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 330 |
+
value_states = value_states.view(bsz, -1, self.num_key_value_heads, self.head_dim).transpose(1, 2)
|
| 331 |
+
|
| 332 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 333 |
+
self.config._attn_implementation, eager_attention_forward
|
| 334 |
+
)
|
| 335 |
+
|
| 336 |
+
attn_output, attn_weights = attention_interface(
|
| 337 |
+
self,
|
| 338 |
+
query_states,
|
| 339 |
+
key_states,
|
| 340 |
+
value_states,
|
| 341 |
+
attention_mask,
|
| 342 |
+
dropout=0.0 if not self.training else self.dropout,
|
| 343 |
+
scaling=self.scaling,
|
| 344 |
+
**kwargs,
|
| 345 |
+
)
|
| 346 |
+
attn_output = attn_output.reshape(bsz, q_len, -1).contiguous()
|
| 347 |
+
attn_output = self.o_proj(attn_output)
|
| 348 |
+
attn_output = attn_output + hidden_states
|
| 349 |
+
return attn_output, attn_weights
|
| 350 |
+
|
| 351 |
+
|
| 352 |
+
@auto_docstring
|
| 353 |
+
class BltPreTrainedModel(MllamaPreTrainedModel):
|
| 354 |
+
config: BltConfig
|
| 355 |
+
_supports_attention_backend = False
|
| 356 |
+
_supports_flash_attn = False
|
| 357 |
+
_supports_flex_attn = False
|
| 358 |
+
_no_split_modules = ["BltTransformerLayer"]
|
| 359 |
+
_can_record_outputs = {
|
| 360 |
+
"hidden_states": OutputRecorder(BltTransformerLayer, index=0),
|
| 361 |
+
"attentions": OutputRecorder(BltSelfAttention, index=1),
|
| 362 |
+
}
|
| 363 |
+
|
| 364 |
+
# Weight initialization is adapted from:
|
| 365 |
+
# - https://github.com/facebookresearch/blt/blob/main/bytelatent/model/blt.py
|
| 366 |
+
# - https://github.com/pytorch/torchtitan/blob/main/torchtitan/experiments/transformers_modeling_backend/model/model.py
|
| 367 |
+
#
|
| 368 |
+
# Both implementations use truncated normal initialization with std ~ 1 / sqrt(d_model)
|
| 369 |
+
# (or 1 / sqrt(hidden_dim) for FFN outputs), and unit initialization for normalization layers.
|
| 370 |
+
# We follow the same scheme here, but expressed in the Transformers APIs.
|
| 371 |
+
|
| 372 |
+
@torch.no_grad()
|
| 373 |
+
def _init_weights(self, module):
|
| 374 |
+
"""
|
| 375 |
+
Initialize BLT weights following the original ByteLatentTransformer:
|
| 376 |
+
|
| 377 |
+
- Most weights are drawn from a truncated normal.
|
| 378 |
+
- Scale is ~ 1 / sqrt(model_dim) (or 1 / sqrt(hidden_dim) for FFN outputs).
|
| 379 |
+
- Norm layers are set to weight = 1, bias = 0.
|
| 380 |
+
"""
|
| 381 |
+
class_name = module.__class__.__name__
|
| 382 |
+
|
| 383 |
+
# Norms: RMSNorm / LayerNorm
|
| 384 |
+
if isinstance(module, (BltRMSNorm, nn.LayerNorm)) or "RMSNorm" in class_name or "LayerNorm" in class_name:
|
| 385 |
+
if getattr(module, "weight", None) is not None:
|
| 386 |
+
init.ones_(module.weight)
|
| 387 |
+
if getattr(module, "bias", None) is not None:
|
| 388 |
+
init.zeros_(module.bias)
|
| 389 |
+
return
|
| 390 |
+
|
| 391 |
+
# Embeddings (encoder / patcher / hash embeddings)
|
| 392 |
+
if isinstance(module, nn.Embedding):
|
| 393 |
+
hidden_size = getattr(self.config, "hidden_size", None)
|
| 394 |
+
if hidden_size is None and hasattr(self.config, "encoder_config"):
|
| 395 |
+
hidden_size = getattr(self.config.encoder_config, "hidden_size", None)
|
| 396 |
+
if hidden_size is None:
|
| 397 |
+
hidden_size = module.embedding_dim
|
| 398 |
+
|
| 399 |
+
std = hidden_size**-0.5
|
| 400 |
+
init.trunc_normal_(
|
| 401 |
+
module.weight,
|
| 402 |
+
mean=0.0,
|
| 403 |
+
std=std,
|
| 404 |
+
a=-3 * std,
|
| 405 |
+
b=3 * std,
|
| 406 |
+
)
|
| 407 |
+
if module.padding_idx is not None:
|
| 408 |
+
init.zeros_(module.weight[module.padding_idx])
|
| 409 |
+
return
|
| 410 |
+
|
| 411 |
+
# Self-attention / cross-attention projections
|
| 412 |
+
if isinstance(module, (BltSelfAttention, BltCrossAttention)) or class_name in (
|
| 413 |
+
"MllamaTextSelfAttention",
|
| 414 |
+
"MllamaTextCrossAttention",
|
| 415 |
+
):
|
| 416 |
+
dim = getattr(self.config, "hidden_size", None)
|
| 417 |
+
if dim is None and hasattr(module, "hidden_size"):
|
| 418 |
+
dim = module.hidden_size
|
| 419 |
+
if dim is None:
|
| 420 |
+
for name in ("q_proj", "k_proj", "v_proj", "o_proj", "dense"):
|
| 421 |
+
proj = getattr(module, name, None)
|
| 422 |
+
if proj is not None and hasattr(proj, "weight"):
|
| 423 |
+
dim = proj.weight.shape[-1]
|
| 424 |
+
break
|
| 425 |
+
if dim is None:
|
| 426 |
+
return
|
| 427 |
+
|
| 428 |
+
std = dim**-0.5
|
| 429 |
+
|
| 430 |
+
# Input projections (q, k, v)
|
| 431 |
+
for proj_name in ("q_proj", "k_proj", "v_proj"):
|
| 432 |
+
proj = getattr(module, proj_name, None)
|
| 433 |
+
if proj is not None and hasattr(proj, "weight"):
|
| 434 |
+
init.trunc_normal_(
|
| 435 |
+
proj.weight,
|
| 436 |
+
mean=0.0,
|
| 437 |
+
std=std,
|
| 438 |
+
a=-3 * std,
|
| 439 |
+
b=3 * std,
|
| 440 |
+
)
|
| 441 |
+
if getattr(proj, "bias", None) is not None:
|
| 442 |
+
init.zeros_(proj.bias)
|
| 443 |
+
|
| 444 |
+
# Output projection: o_proj or dense
|
| 445 |
+
o_proj = getattr(module, "o_proj", getattr(module, "dense", None))
|
| 446 |
+
if o_proj is not None and hasattr(o_proj, "weight"):
|
| 447 |
+
init.trunc_normal_(
|
| 448 |
+
o_proj.weight,
|
| 449 |
+
mean=0.0,
|
| 450 |
+
std=std,
|
| 451 |
+
a=-3 * std,
|
| 452 |
+
b=3 * std,
|
| 453 |
+
)
|
| 454 |
+
if getattr(o_proj, "bias", None) is not None:
|
| 455 |
+
init.zeros_(o_proj.bias)
|
| 456 |
+
return
|
| 457 |
+
|
| 458 |
+
# MLP / FFN blocks
|
| 459 |
+
if isinstance(module, BltMLP) or class_name == "MllamaTextMLP":
|
| 460 |
+
hidden_size = getattr(self.config, "hidden_size", None)
|
| 461 |
+
if hidden_size is None and hasattr(self.config, "decoder_config"):
|
| 462 |
+
hidden_size = getattr(self.config.decoder_config, "hidden_size", None)
|
| 463 |
+
if hidden_size is None and hasattr(self.config, "encoder_config"):
|
| 464 |
+
hidden_size = getattr(self.config.encoder_config, "hidden_size", None)
|
| 465 |
+
|
| 466 |
+
# Input-side std
|
| 467 |
+
in_std = None
|
| 468 |
+
if hidden_size is not None:
|
| 469 |
+
in_std = hidden_size**-0.5
|
| 470 |
+
|
| 471 |
+
gate_proj = getattr(module, "gate_proj", getattr(module, "fc1", None))
|
| 472 |
+
up_proj = getattr(module, "up_proj", None)
|
| 473 |
+
down_proj = getattr(module, "down_proj", getattr(module, "fc2", None))
|
| 474 |
+
|
| 475 |
+
# gate / input projections
|
| 476 |
+
for proj in (gate_proj, up_proj):
|
| 477 |
+
if proj is not None and hasattr(proj, "weight"):
|
| 478 |
+
std = in_std or (proj.weight.shape[1] ** -0.5)
|
| 479 |
+
init.trunc_normal_(
|
| 480 |
+
proj.weight,
|
| 481 |
+
mean=0.0,
|
| 482 |
+
std=std,
|
| 483 |
+
a=-3 * std,
|
| 484 |
+
b=3 * std,
|
| 485 |
+
)
|
| 486 |
+
if getattr(proj, "bias", None) is not None:
|
| 487 |
+
init.zeros_(proj.bias)
|
| 488 |
+
|
| 489 |
+
# output/ down projections
|
| 490 |
+
if down_proj is not None and hasattr(down_proj, "weight"):
|
| 491 |
+
hidden_dim = down_proj.weight.shape[1]
|
| 492 |
+
out_std = hidden_dim**-0.5
|
| 493 |
+
init.trunc_normal_(
|
| 494 |
+
down_proj.weight,
|
| 495 |
+
mean=0.0,
|
| 496 |
+
std=out_std,
|
| 497 |
+
a=-3 * out_std,
|
| 498 |
+
b=3 * out_std,
|
| 499 |
+
)
|
| 500 |
+
if getattr(down_proj, "bias", None) is not None:
|
| 501 |
+
init.zeros_(down_proj.bias)
|
| 502 |
+
return
|
| 503 |
+
|
| 504 |
+
# Generic Linear layers (projections, lm_head, etc.)
|
| 505 |
+
if isinstance(module, nn.Linear):
|
| 506 |
+
fan_in = module.in_features
|
| 507 |
+
std = fan_in**-0.5
|
| 508 |
+
init.trunc_normal_(
|
| 509 |
+
module.weight,
|
| 510 |
+
mean=0.0,
|
| 511 |
+
std=std,
|
| 512 |
+
a=-3 * std,
|
| 513 |
+
b=3 * std,
|
| 514 |
+
)
|
| 515 |
+
if module.bias is not None:
|
| 516 |
+
init.zeros_(module.bias)
|
| 517 |
+
return
|
| 518 |
+
|
| 519 |
+
if isinstance(module, BltRotaryEmbedding):
|
| 520 |
+
rope_fn = (
|
| 521 |
+
ROPE_INIT_FUNCTIONS[module.rope_type]
|
| 522 |
+
if module.rope_type != "default"
|
| 523 |
+
else module.compute_default_rope_parameters
|
| 524 |
+
)
|
| 525 |
+
buffer_value, _ = rope_fn(module.config)
|
| 526 |
+
init.copy_(module.inv_freq, buffer_value)
|
| 527 |
+
init.copy_(module.original_inv_freq, buffer_value)
|
| 528 |
+
|
| 529 |
+
|
| 530 |
+
class BltLocalEncoder(BltPreTrainedModel):
|
| 531 |
+
config: BltLocalEncoderConfig
|
| 532 |
+
_can_record_outputs = {
|
| 533 |
+
"encoder_attentions": OutputRecorder(BltSelfAttention, index=1, layer_name="local_encoder"),
|
| 534 |
+
}
|
| 535 |
+
|
| 536 |
+
def __init__(self, config: BltLocalEncoderConfig):
|
| 537 |
+
super().__init__(config)
|
| 538 |
+
self.gradient_checkpointing = False
|
| 539 |
+
self.config = config
|
| 540 |
+
self.layers = nn.ModuleList(
|
| 541 |
+
[BltTransformerLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
|
| 542 |
+
)
|
| 543 |
+
self.rotary_emb = BltRotaryEmbedding(config=config)
|
| 544 |
+
self.patch_embedding_projection = nn.Linear(
|
| 545 |
+
in_features=config.hidden_size,
|
| 546 |
+
out_features=config.hidden_size * config.cross_attn_k,
|
| 547 |
+
bias=False,
|
| 548 |
+
)
|
| 549 |
+
self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size)
|
| 550 |
+
self.cross_attn_layers = nn.ModuleList()
|
| 551 |
+
layers_to_add = config.num_hidden_layers if config.cross_attn_all_layers else 1
|
| 552 |
+
for layer_idx in range(layers_to_add):
|
| 553 |
+
self.cross_attn_layers.append(
|
| 554 |
+
BltCrossAttention(config=config, layer_idx=layer_idx, hidden_size=config.hidden_size)
|
| 555 |
+
)
|
| 556 |
+
|
| 557 |
+
self.post_init()
|
| 558 |
+
|
| 559 |
+
def forward(
|
| 560 |
+
self,
|
| 561 |
+
input_ids: torch.LongTensor | None = None,
|
| 562 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 563 |
+
patch_embeds: torch.Tensor | None = None,
|
| 564 |
+
attention_mask: torch.Tensor | None = None,
|
| 565 |
+
position_ids: torch.LongTensor | None = None,
|
| 566 |
+
past_key_values: Cache | None = None,
|
| 567 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 568 |
+
num_patches: int | None = None,
|
| 569 |
+
patch_ids: torch.Tensor | None = None,
|
| 570 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 571 |
+
):
|
| 572 |
+
if inputs_embeds is None:
|
| 573 |
+
inputs_embeds = self.embed_tokens(input_ids)
|
| 574 |
+
|
| 575 |
+
batch_size = inputs_embeds.shape[0]
|
| 576 |
+
hidden_states = F.dropout(inputs_embeds, p=self.config.dropout, training=self.training)
|
| 577 |
+
|
| 578 |
+
if position_ids is None:
|
| 579 |
+
position_ids = (
|
| 580 |
+
torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device).unsqueeze(0).expand(batch_size, -1)
|
| 581 |
+
)
|
| 582 |
+
|
| 583 |
+
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
| 584 |
+
hidden_states = F.dropout(hidden_states, p=self.config.dropout, training=self.training)
|
| 585 |
+
|
| 586 |
+
for idx, layer in enumerate(self.layers):
|
| 587 |
+
hidden_states = layer(
|
| 588 |
+
hidden_states,
|
| 589 |
+
position_embeddings=position_embeddings,
|
| 590 |
+
attention_mask=attention_mask,
|
| 591 |
+
past_key_values=past_key_values,
|
| 592 |
+
**kwargs,
|
| 593 |
+
)
|
| 594 |
+
if idx == len(self.layers) - 1 or self.config.cross_attn_all_layers:
|
| 595 |
+
patch_embeds = self.patch_reduce(hidden_states, num_patches, patch_ids)
|
| 596 |
+
patch_embeds = self.patch_embedding_projection(patch_embeds)
|
| 597 |
+
patch_embeds = patch_embeds.reshape(
|
| 598 |
+
batch_size, patch_embeds.shape[1] * self.config.cross_attn_k, self.config.hidden_size
|
| 599 |
+
)
|
| 600 |
+
layer_idx = idx if self.config.cross_attn_all_layers else 0
|
| 601 |
+
cross_attention_output, _ = self.cross_attn_layers[layer_idx](
|
| 602 |
+
hidden_states=patch_embeds,
|
| 603 |
+
cross_attention_states=hidden_states,
|
| 604 |
+
attention_mask=encoder_attention_mask,
|
| 605 |
+
**kwargs,
|
| 606 |
+
)
|
| 607 |
+
patch_embeds = patch_embeds + cross_attention_output
|
| 608 |
+
encoder_cross_states = patch_embeds
|
| 609 |
+
return hidden_states, encoder_cross_states
|
| 610 |
+
|
| 611 |
+
def patch_reduce(self, hidden_states, max_num_patches, patch_ids):
|
| 612 |
+
"""
|
| 613 |
+
Reduce variable length patches to single embedding per patch
|
| 614 |
+
Note: this works with variable number of patches for different sequences in the batch
|
| 615 |
+
It handles variable length patches by assuming that patch_lengths will be 0 for any
|
| 616 |
+
extra patches on the *right*. Since there can be a variable number of patches
|
| 617 |
+
this function also return the number of patches for each sequence in the batch.
|
| 618 |
+
Any embeddings on the right that are not allocated to a patch
|
| 619 |
+
(i.e. if the sum(patch_lengths[i]) < seq_len for any i)
|
| 620 |
+
will be sent to a dummy patch, which is trimmed before returning.
|
| 621 |
+
"""
|
| 622 |
+
batch_size = hidden_states.shape[0]
|
| 623 |
+
embedding_dim = hidden_states.shape[-1]
|
| 624 |
+
|
| 625 |
+
patch_ids = patch_ids.unsqueeze(-1).expand(-1, -1, hidden_states.shape[-1])
|
| 626 |
+
|
| 627 |
+
reduced_embeddings = torch.zeros(
|
| 628 |
+
(batch_size, max_num_patches, embedding_dim), dtype=hidden_states.dtype, device=hidden_states.device
|
| 629 |
+
)
|
| 630 |
+
|
| 631 |
+
reduced_embeddings = reduced_embeddings.scatter_reduce(
|
| 632 |
+
src=hidden_states,
|
| 633 |
+
dim=1,
|
| 634 |
+
index=patch_ids,
|
| 635 |
+
reduce="amax",
|
| 636 |
+
include_self=False,
|
| 637 |
+
)
|
| 638 |
+
reduced_embeddings = reduced_embeddings[:, :max_num_patches, :]
|
| 639 |
+
|
| 640 |
+
return reduced_embeddings
|
| 641 |
+
|
| 642 |
+
|
| 643 |
+
class BltLocalDecoder(BltPreTrainedModel):
|
| 644 |
+
config: BltLocalDecoderConfig
|
| 645 |
+
|
| 646 |
+
def __init__(self, config: BltLocalDecoderConfig):
|
| 647 |
+
super().__init__(config)
|
| 648 |
+
self.gradient_checkpointing = False
|
| 649 |
+
self.config = config
|
| 650 |
+
self.cross_attn_decoder = True
|
| 651 |
+
self.layers = nn.ModuleList(
|
| 652 |
+
[BltTransformerLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
|
| 653 |
+
)
|
| 654 |
+
self.rotary_emb = BltRotaryEmbedding(config=config)
|
| 655 |
+
self.patch_embedding_projection = nn.Linear(
|
| 656 |
+
in_features=config.hidden_size_global,
|
| 657 |
+
out_features=config.hidden_size * config.cross_attn_k,
|
| 658 |
+
bias=False,
|
| 659 |
+
)
|
| 660 |
+
self.norm = BltRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 661 |
+
self.cross_attn_layers = nn.ModuleList()
|
| 662 |
+
layers_to_add = config.num_hidden_layers if config.cross_attn_all_layers else 1
|
| 663 |
+
for layer_idx in range(layers_to_add):
|
| 664 |
+
self.cross_attn_layers.append(
|
| 665 |
+
BltCrossAttention(config=config, layer_idx=layer_idx, hidden_size=config.hidden_size)
|
| 666 |
+
)
|
| 667 |
+
|
| 668 |
+
self.post_init()
|
| 669 |
+
|
| 670 |
+
def forward(
|
| 671 |
+
self,
|
| 672 |
+
input_ids: torch.LongTensor | None = None,
|
| 673 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 674 |
+
patch_embeds: torch.Tensor | None = None,
|
| 675 |
+
attention_mask: torch.Tensor | None = None,
|
| 676 |
+
position_ids: torch.LongTensor | None = None,
|
| 677 |
+
past_key_values: Cache | None = None,
|
| 678 |
+
encoder_attention_mask: torch.Tensor | None = None,
|
| 679 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 680 |
+
):
|
| 681 |
+
batch_size = inputs_embeds.shape[0]
|
| 682 |
+
hidden_states = inputs_embeds
|
| 683 |
+
patch_embeds = self.patch_embedding_projection(patch_embeds)
|
| 684 |
+
patch_embeds = patch_embeds.reshape(
|
| 685 |
+
batch_size, patch_embeds.shape[1] * self.config.cross_attn_k, self.config.hidden_size
|
| 686 |
+
)
|
| 687 |
+
|
| 688 |
+
if patch_embeds is not None and not self.cross_attn_decoder:
|
| 689 |
+
hidden_states = hidden_states + patch_embeds
|
| 690 |
+
|
| 691 |
+
if position_ids is None:
|
| 692 |
+
position_ids = (
|
| 693 |
+
torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device).unsqueeze(0).expand(batch_size, -1)
|
| 694 |
+
)
|
| 695 |
+
|
| 696 |
+
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
| 697 |
+
hidden_states = F.dropout(hidden_states, p=self.config.dropout, training=self.training)
|
| 698 |
+
|
| 699 |
+
for i, layer in enumerate(self.layers):
|
| 700 |
+
if i == 0 or self.config.cross_attn_all_layers:
|
| 701 |
+
cross_attention_output, _ = self.cross_attn_layers[i](
|
| 702 |
+
hidden_states=hidden_states,
|
| 703 |
+
cross_attention_states=patch_embeds,
|
| 704 |
+
attention_mask=encoder_attention_mask,
|
| 705 |
+
**kwargs,
|
| 706 |
+
)
|
| 707 |
+
hidden_states = hidden_states + cross_attention_output
|
| 708 |
+
hidden_states = layer(
|
| 709 |
+
hidden_states,
|
| 710 |
+
position_embeddings=position_embeddings,
|
| 711 |
+
attention_mask=attention_mask,
|
| 712 |
+
past_key_values=past_key_values,
|
| 713 |
+
**kwargs,
|
| 714 |
+
)
|
| 715 |
+
logits = self.norm(hidden_states)
|
| 716 |
+
return logits
|
| 717 |
+
|
| 718 |
+
|
| 719 |
+
class BltGlobalTransformer(BltPreTrainedModel):
|
| 720 |
+
config: BltGlobalTransformerConfig
|
| 721 |
+
_can_record_outputs = {
|
| 722 |
+
"global_attentions": OutputRecorder(BltSelfAttention, index=1, layer_name="global_transformer"),
|
| 723 |
+
}
|
| 724 |
+
|
| 725 |
+
def __init__(self, config: BltGlobalTransformerConfig):
|
| 726 |
+
super().__init__(config)
|
| 727 |
+
self.config = config
|
| 728 |
+
self.layers = nn.ModuleList()
|
| 729 |
+
for layer_idx in range(config.num_hidden_layers):
|
| 730 |
+
self.layers.append(BltTransformerLayer(config, layer_idx))
|
| 731 |
+
self.rotary_emb = BltRotaryEmbedding(config=config)
|
| 732 |
+
|
| 733 |
+
# Create token embedding projection (use nn.Identity() when no projection needed)
|
| 734 |
+
if getattr(config, "encoder_cross_output_size", None) is not None:
|
| 735 |
+
self.token_embedding_projection = nn.Linear(
|
| 736 |
+
config.encoder_cross_output_size, config.hidden_size, bias=False
|
| 737 |
+
)
|
| 738 |
+
else:
|
| 739 |
+
self.token_embedding_projection = nn.Identity()
|
| 740 |
+
|
| 741 |
+
self.post_init()
|
| 742 |
+
|
| 743 |
+
@deprecate_kwarg("input_embeds", version="5.6.0", new_name="inputs_embeds")
|
| 744 |
+
def forward(
|
| 745 |
+
self,
|
| 746 |
+
inputs_embeds: torch.Tensor,
|
| 747 |
+
attention_mask: torch.Tensor | None = None,
|
| 748 |
+
position_ids: torch.LongTensor | None = None,
|
| 749 |
+
past_key_values: Cache | None = None,
|
| 750 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 751 |
+
):
|
| 752 |
+
batch_size, seq_len, _ = inputs_embeds.shape
|
| 753 |
+
hidden_states = self.token_embedding_projection(inputs_embeds)
|
| 754 |
+
hidden_states = F.dropout(hidden_states, p=self.config.dropout, training=self.training)
|
| 755 |
+
if position_ids is None:
|
| 756 |
+
position_ids = (
|
| 757 |
+
torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device).unsqueeze(0).expand(batch_size, -1)
|
| 758 |
+
)
|
| 759 |
+
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
| 760 |
+
for i, layer in enumerate(self.layers):
|
| 761 |
+
hidden_states = layer(
|
| 762 |
+
hidden_states,
|
| 763 |
+
position_embeddings=position_embeddings,
|
| 764 |
+
attention_mask=attention_mask,
|
| 765 |
+
past_key_values=past_key_values,
|
| 766 |
+
**kwargs,
|
| 767 |
+
)
|
| 768 |
+
return hidden_states
|
| 769 |
+
|
| 770 |
+
|
| 771 |
+
class BltPatcher(BltPreTrainedModel):
|
| 772 |
+
config: BltPatcherConfig
|
| 773 |
+
|
| 774 |
+
def __init__(self, config: BltPatcherConfig):
|
| 775 |
+
super().__init__(config)
|
| 776 |
+
self.rotary_emb = BltRotaryEmbedding(config=self.config)
|
| 777 |
+
self.layers = nn.ModuleList()
|
| 778 |
+
for layer_idx in range(self.config.num_hidden_layers):
|
| 779 |
+
self.layers.append(BltTransformerLayer(self.config, layer_idx))
|
| 780 |
+
self.embed_tokens = nn.Embedding(self.config.vocab_size, self.config.hidden_size)
|
| 781 |
+
self.norm = BltRMSNorm(self.config.hidden_size, eps=self.config.rms_norm_eps)
|
| 782 |
+
self.lm_head = nn.Linear(
|
| 783 |
+
self.config.hidden_size,
|
| 784 |
+
self.config.vocab_size,
|
| 785 |
+
bias=False,
|
| 786 |
+
)
|
| 787 |
+
|
| 788 |
+
self.post_init()
|
| 789 |
+
|
| 790 |
+
def forward(
|
| 791 |
+
self,
|
| 792 |
+
input_ids: torch.LongTensor | None = None,
|
| 793 |
+
attention_mask: torch.Tensor | None = None,
|
| 794 |
+
position_ids: torch.LongTensor | None = None,
|
| 795 |
+
past_key_values: Cache | None = None,
|
| 796 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 797 |
+
use_cache: bool | None = None,
|
| 798 |
+
patch_size: int | None = None,
|
| 799 |
+
threshold: float | None = None,
|
| 800 |
+
max_patch_length: int | None = None,
|
| 801 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 802 |
+
):
|
| 803 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 804 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 805 |
+
|
| 806 |
+
if inputs_embeds is None:
|
| 807 |
+
inputs_embeds = self.embed_tokens(input_ids)
|
| 808 |
+
|
| 809 |
+
if use_cache and past_key_values is None:
|
| 810 |
+
past_key_values = DynamicCache(config=self.config)
|
| 811 |
+
|
| 812 |
+
if position_ids is None:
|
| 813 |
+
past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
|
| 814 |
+
position_ids = torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device) + past_seen_tokens
|
| 815 |
+
position_ids = position_ids.unsqueeze(0)
|
| 816 |
+
|
| 817 |
+
causal_mask = create_causal_mask(
|
| 818 |
+
config=self.config,
|
| 819 |
+
inputs_embeds=inputs_embeds,
|
| 820 |
+
attention_mask=attention_mask,
|
| 821 |
+
past_key_values=past_key_values,
|
| 822 |
+
position_ids=position_ids,
|
| 823 |
+
)
|
| 824 |
+
|
| 825 |
+
hidden_states = inputs_embeds
|
| 826 |
+
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
| 827 |
+
|
| 828 |
+
for layer in self.layers:
|
| 829 |
+
hidden_states = layer(hidden_states, position_embeddings=position_embeddings, attention_mask=causal_mask)
|
| 830 |
+
|
| 831 |
+
logits = self.lm_head(self.norm(hidden_states))
|
| 832 |
+
prediction_entropies = torch.distributions.Categorical(logits=logits).entropy()
|
| 833 |
+
|
| 834 |
+
batch_size, sequence_length = inputs_embeds.shape[:2]
|
| 835 |
+
if patch_size is not None:
|
| 836 |
+
patch_lengths = self.patch_lengths_from_entropies(
|
| 837 |
+
entropies=prediction_entropies,
|
| 838 |
+
sequence_length=sequence_length,
|
| 839 |
+
patch_size=patch_size,
|
| 840 |
+
threshold=threshold,
|
| 841 |
+
)
|
| 842 |
+
else:
|
| 843 |
+
patch_lengths = torch.ones(
|
| 844 |
+
(batch_size, sequence_length), dtype=inputs_embeds.dtype, device=inputs_embeds.device
|
| 845 |
+
)
|
| 846 |
+
patch_lengths = process_patch_lengths(patch_lengths, max_patch_length)
|
| 847 |
+
return prediction_entropies, patch_lengths, logits
|
| 848 |
+
|
| 849 |
+
@staticmethod
|
| 850 |
+
def patch_lengths_from_entropies(
|
| 851 |
+
entropies,
|
| 852 |
+
sequence_length,
|
| 853 |
+
patch_size=None,
|
| 854 |
+
threshold=None,
|
| 855 |
+
):
|
| 856 |
+
"""
|
| 857 |
+
Computes patch lengths from token entropies.
|
| 858 |
+
|
| 859 |
+
Depending on whether a threshold is provided, the function uses either:
|
| 860 |
+
- Thresholding the entropy values (when `threshold` is set).
|
| 861 |
+
"""
|
| 862 |
+
|
| 863 |
+
batch_size = entropies.shape[0]
|
| 864 |
+
|
| 865 |
+
# Always include token 0 and 1 as starting tokens
|
| 866 |
+
init_tokens = (
|
| 867 |
+
torch.tensor([0, 1], dtype=torch.long, device=entropies.device).unsqueeze(0).repeat(batch_size, 1)
|
| 868 |
+
)
|
| 869 |
+
offset = init_tokens.shape[1]
|
| 870 |
+
|
| 871 |
+
# Ignore first token entropy (BOS)
|
| 872 |
+
entropies = entropies[:, 1:]
|
| 873 |
+
|
| 874 |
+
# Threshold the entropy values to define patch start points
|
| 875 |
+
patch_mask = entropies > threshold
|
| 876 |
+
|
| 877 |
+
seq_len = patch_mask.shape[1]
|
| 878 |
+
|
| 879 |
+
# Create patch IDs (token indices), and add a sentinel to ensure alignment
|
| 880 |
+
token_indices = torch.arange(seq_len, device=entropies.device).unsqueeze(0).expand(batch_size, -1)
|
| 881 |
+
sentinel = torch.full_like(token_indices, seq_len)
|
| 882 |
+
padded_indices = torch.cat([token_indices, sentinel], dim=1)
|
| 883 |
+
|
| 884 |
+
# Pad mask with inverse to align sentinel correctly
|
| 885 |
+
padded_mask = torch.cat([patch_mask, ~patch_mask], dim=1)
|
| 886 |
+
|
| 887 |
+
# Select indices where mask is True
|
| 888 |
+
patch_starts = padded_indices[padded_mask].reshape(batch_size, seq_len)
|
| 889 |
+
max_valid_patches = patch_mask.sum(dim=1).max()
|
| 890 |
+
patch_starts = patch_starts[:, :max_valid_patches]
|
| 891 |
+
|
| 892 |
+
# Offset patch starts to account for the two initial tokens
|
| 893 |
+
patch_start_ids = torch.cat((init_tokens, patch_starts + offset), dim=1)
|
| 894 |
+
|
| 895 |
+
# Compute patch end positions by shifting start positions
|
| 896 |
+
last_token = torch.full_like(patch_start_ids[:, :1], sequence_length - 1)
|
| 897 |
+
patch_ends = torch.cat((patch_start_ids[:, 1:] - 1, last_token), dim=1)
|
| 898 |
+
|
| 899 |
+
patch_lengths = patch_ends - patch_start_ids + 1
|
| 900 |
+
|
| 901 |
+
return patch_lengths
|
| 902 |
+
|
| 903 |
+
|
| 904 |
+
class BltModel(BltPreTrainedModel):
|
| 905 |
+
def __init__(self, config: BltConfig):
|
| 906 |
+
super().__init__(config)
|
| 907 |
+
self.gradient_checkpointing = False
|
| 908 |
+
|
| 909 |
+
self.config = config
|
| 910 |
+
self.local_encoder = BltLocalEncoder(config.encoder_config)
|
| 911 |
+
self.global_transformer = BltGlobalTransformer(config.global_config)
|
| 912 |
+
self.local_decoder = BltLocalDecoder(config.decoder_config)
|
| 913 |
+
num_embeddings = config.encoder_hash_byte_group_nb_functions * len(config.encoder_hash_byte_group_size)
|
| 914 |
+
total_vocab_size = config.encoder_hash_byte_group_vocab * num_embeddings
|
| 915 |
+
self.encoder_hash_tok_embedding = nn.Embedding(total_vocab_size, config.encoder_config.hidden_size)
|
| 916 |
+
if self.config.patch_in_forward:
|
| 917 |
+
self.patcher = BltPatcher(config.patcher_config)
|
| 918 |
+
self.patcher.eval()
|
| 919 |
+
for param in self.patcher.parameters():
|
| 920 |
+
param.requires_grad = False
|
| 921 |
+
else:
|
| 922 |
+
self.patcher = None
|
| 923 |
+
self.post_init()
|
| 924 |
+
|
| 925 |
+
@merge_with_config_defaults
|
| 926 |
+
@capture_outputs
|
| 927 |
+
def forward(
|
| 928 |
+
self,
|
| 929 |
+
input_ids: torch.LongTensor | None = None,
|
| 930 |
+
patch_lengths: torch.Tensor | None = None,
|
| 931 |
+
attention_mask: torch.Tensor | None = None,
|
| 932 |
+
position_ids: torch.LongTensor | None = None,
|
| 933 |
+
past_key_values: Cache | None = None,
|
| 934 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 935 |
+
use_cache: bool | None = None,
|
| 936 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 937 |
+
) -> tuple | BaseModelOutputWithPast:
|
| 938 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 939 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 940 |
+
|
| 941 |
+
if use_cache:
|
| 942 |
+
if past_key_values is None:
|
| 943 |
+
past_key_values = EncoderDecoderCache(
|
| 944 |
+
DynamicCache(config=self.config), DynamicCache(config=self.config)
|
| 945 |
+
)
|
| 946 |
+
elif not isinstance(past_key_values, EncoderDecoderCache):
|
| 947 |
+
# BLT uses an encoder-decoder cache even though it is not en encoder-decoder model. Create a cross-cache
|
| 948 |
+
# if not yet created by the user
|
| 949 |
+
past_key_values = EncoderDecoderCache(past_key_values, DynamicCache(config=self.config))
|
| 950 |
+
|
| 951 |
+
# Extract input embeddings as early as possible
|
| 952 |
+
if inputs_embeds is not None:
|
| 953 |
+
encoder_embeds = inputs_embeds
|
| 954 |
+
batch_size, sequence_length, _ = inputs_embeds.shape
|
| 955 |
+
else:
|
| 956 |
+
batch_size, sequence_length = input_ids.shape
|
| 957 |
+
encoder_embeds = compute_hash_embeddings(
|
| 958 |
+
input_ids,
|
| 959 |
+
self.local_encoder,
|
| 960 |
+
self.encoder_hash_tok_embedding,
|
| 961 |
+
self.config.encoder_hash_byte_group_nb_functions,
|
| 962 |
+
self.config.encoder_hash_byte_group_size,
|
| 963 |
+
self.config.encoder_hash_byte_group_vocab,
|
| 964 |
+
)
|
| 965 |
+
|
| 966 |
+
if patch_lengths is None:
|
| 967 |
+
if self.config.patching_mode == "entropy" and self.patcher is not None:
|
| 968 |
+
if input_ids is None:
|
| 969 |
+
raise ValueError("input_ids is required for entropy-based patching")
|
| 970 |
+
_, patch_lengths, _ = self.patcher(
|
| 971 |
+
input_ids,
|
| 972 |
+
patch_size=self.config.patch_size,
|
| 973 |
+
threshold=self.config.patching_threshold,
|
| 974 |
+
max_patch_length=self.config.max_patch_length,
|
| 975 |
+
patching_batch_size=self.config.patching_batch_size,
|
| 976 |
+
device=input_ids.device,
|
| 977 |
+
)
|
| 978 |
+
else:
|
| 979 |
+
device = input_ids.device if input_ids is not None else inputs_embeds.device
|
| 980 |
+
dtype = input_ids.dtype if input_ids is not None else inputs_embeds.dtype
|
| 981 |
+
patch_lengths = process_patch_lengths(
|
| 982 |
+
torch.ones((batch_size, sequence_length + 1), dtype=dtype, device=device),
|
| 983 |
+
self.config.max_patch_length,
|
| 984 |
+
)
|
| 985 |
+
patch_ids = self._patch_ids_from_lengths(patch_lengths, sequence_length)
|
| 986 |
+
|
| 987 |
+
if position_ids is None:
|
| 988 |
+
past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
|
| 989 |
+
position_ids = torch.arange(encoder_embeds.shape[1], device=encoder_embeds.device) + past_seen_tokens
|
| 990 |
+
position_ids = position_ids.unsqueeze(0)
|
| 991 |
+
|
| 992 |
+
causal_mask = create_causal_mask(
|
| 993 |
+
config=self.config,
|
| 994 |
+
inputs_embeds=encoder_embeds,
|
| 995 |
+
attention_mask=attention_mask,
|
| 996 |
+
past_key_values=past_key_values.self_attention_cache if past_key_values is not None else None,
|
| 997 |
+
position_ids=position_ids,
|
| 998 |
+
)
|
| 999 |
+
|
| 1000 |
+
cross_attn_mask_enc = _prepare_patch_cross_attention_mask(
|
| 1001 |
+
patch_ids=patch_ids,
|
| 1002 |
+
num_patches=patch_lengths.shape[1],
|
| 1003 |
+
sequence_length=sequence_length,
|
| 1004 |
+
patches_as_queries=True,
|
| 1005 |
+
cross_attn_k=self.config.cross_attn_k,
|
| 1006 |
+
dtype=encoder_embeds.dtype,
|
| 1007 |
+
)
|
| 1008 |
+
encoder_hidden_states, encoder_cross_states = self.local_encoder(
|
| 1009 |
+
input_ids=input_ids,
|
| 1010 |
+
inputs_embeds=encoder_embeds,
|
| 1011 |
+
attention_mask=causal_mask,
|
| 1012 |
+
position_ids=position_ids,
|
| 1013 |
+
encoder_attention_mask=cross_attn_mask_enc,
|
| 1014 |
+
num_patches=patch_lengths.shape[1],
|
| 1015 |
+
patch_ids=patch_ids,
|
| 1016 |
+
past_key_values=past_key_values.self_attention_cache if past_key_values is not None else None,
|
| 1017 |
+
**kwargs,
|
| 1018 |
+
)
|
| 1019 |
+
encoder_cross_states = encoder_cross_states.view(batch_size, patch_lengths.shape[1], -1)
|
| 1020 |
+
global_position_ids = torch.arange(0, encoder_cross_states.shape[1], device=encoder_cross_states.device)
|
| 1021 |
+
global_position_ids = global_position_ids.unsqueeze(0)
|
| 1022 |
+
global_causal_mask = create_causal_mask(
|
| 1023 |
+
config=self.config,
|
| 1024 |
+
inputs_embeds=encoder_cross_states,
|
| 1025 |
+
attention_mask=None,
|
| 1026 |
+
past_key_values=None,
|
| 1027 |
+
position_ids=None,
|
| 1028 |
+
)
|
| 1029 |
+
|
| 1030 |
+
global_hidden_states = self.global_transformer(
|
| 1031 |
+
inputs_embeds=encoder_cross_states,
|
| 1032 |
+
attention_mask=global_causal_mask,
|
| 1033 |
+
position_ids=global_position_ids,
|
| 1034 |
+
**kwargs,
|
| 1035 |
+
)
|
| 1036 |
+
decoder_patch_ids = self._patch_ids_from_lengths(patch_lengths[:, 1:], sequence_length)
|
| 1037 |
+
cross_attn_mask_dec = _prepare_patch_cross_attention_mask(
|
| 1038 |
+
patch_ids=decoder_patch_ids,
|
| 1039 |
+
num_patches=patch_lengths.shape[1],
|
| 1040 |
+
sequence_length=sequence_length,
|
| 1041 |
+
patches_as_queries=False,
|
| 1042 |
+
cross_attn_k=self.config.cross_attn_k,
|
| 1043 |
+
dtype=encoder_embeds.dtype,
|
| 1044 |
+
)
|
| 1045 |
+
output = self.local_decoder(
|
| 1046 |
+
input_ids=input_ids,
|
| 1047 |
+
inputs_embeds=encoder_hidden_states,
|
| 1048 |
+
patch_embeds=global_hidden_states,
|
| 1049 |
+
attention_mask=causal_mask,
|
| 1050 |
+
position_ids=position_ids,
|
| 1051 |
+
past_key_values=past_key_values.cross_attention_cache if past_key_values is not None else None,
|
| 1052 |
+
encoder_attention_mask=cross_attn_mask_dec,
|
| 1053 |
+
**kwargs,
|
| 1054 |
+
)
|
| 1055 |
+
return BaseModelOutputWithPast(
|
| 1056 |
+
last_hidden_state=output,
|
| 1057 |
+
past_key_values=past_key_values,
|
| 1058 |
+
)
|
| 1059 |
+
|
| 1060 |
+
def get_input_embeddings(self):
|
| 1061 |
+
return self.local_encoder.embed_tokens
|
| 1062 |
+
|
| 1063 |
+
def set_input_embeddings(self, value):
|
| 1064 |
+
self.local_encoder.embed_tokens = value
|
| 1065 |
+
|
| 1066 |
+
def _patch_ids_from_lengths(self, patch_lengths: torch.Tensor, seq_len: int) -> torch.Tensor:
|
| 1067 |
+
batch_size = patch_lengths.shape[0]
|
| 1068 |
+
patch_starts = torch.cat(
|
| 1069 |
+
[
|
| 1070 |
+
torch.zeros(batch_size, 1, dtype=patch_lengths.dtype, device=patch_lengths.device),
|
| 1071 |
+
patch_lengths.cumsum(dim=-1)[:, :-1],
|
| 1072 |
+
],
|
| 1073 |
+
dim=-1,
|
| 1074 |
+
)
|
| 1075 |
+
token_positions = torch.arange(seq_len, device=patch_lengths.device)
|
| 1076 |
+
return (patch_starts.unsqueeze(1) <= token_positions.unsqueeze(0).unsqueeze(-1)).sum(dim=-1) - 1
|
| 1077 |
+
|
| 1078 |
+
|
| 1079 |
+
@auto_docstring(
|
| 1080 |
+
custom_intro="""
|
| 1081 |
+
The Blt Text Model with a language modeling head on top.
|
| 1082 |
+
"""
|
| 1083 |
+
)
|
| 1084 |
+
class BltForCausalLM(BltPreTrainedModel, GenerationMixin):
|
| 1085 |
+
config: BltConfig
|
| 1086 |
+
_can_compile_fullgraph = False
|
| 1087 |
+
base_model_prefix = "model"
|
| 1088 |
+
_tied_weights_keys = {"model.local_encoder.embed_tokens.weight": "lm_head.weight"}
|
| 1089 |
+
|
| 1090 |
+
def __init__(self, config: BltConfig):
|
| 1091 |
+
super().__init__(config)
|
| 1092 |
+
self.text_config = config.get_text_config()
|
| 1093 |
+
self.vocab_size = config.vocab_size
|
| 1094 |
+
self.model = BltModel(config)
|
| 1095 |
+
self.lm_head = nn.Linear(config.decoder_config.hidden_size, config.vocab_size, bias=False)
|
| 1096 |
+
|
| 1097 |
+
self.post_init()
|
| 1098 |
+
|
| 1099 |
+
@can_return_tuple
|
| 1100 |
+
@auto_docstring
|
| 1101 |
+
def forward(
|
| 1102 |
+
self,
|
| 1103 |
+
input_ids: torch.LongTensor | None = None,
|
| 1104 |
+
attention_mask: torch.Tensor | None = None,
|
| 1105 |
+
position_ids: torch.LongTensor | None = None,
|
| 1106 |
+
cross_attention_states: torch.LongTensor | None = None, # Keep for compatibility
|
| 1107 |
+
cross_attention_mask: torch.LongTensor | None = None,
|
| 1108 |
+
full_text_row_masked_out_mask: tuple[torch.Tensor, torch.Tensor] | None = None,
|
| 1109 |
+
past_key_values: Cache | None = None,
|
| 1110 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 1111 |
+
labels: torch.LongTensor | None = None,
|
| 1112 |
+
use_cache: bool | None = None,
|
| 1113 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 1114 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1115 |
+
) -> tuple | CausalLMOutputWithPast:
|
| 1116 |
+
r"""
|
| 1117 |
+
cross_attention_states (`torch.FloatTensor`, *optional*):
|
| 1118 |
+
Output of the vision model, used for cross-attention. This tensor contains the processed image features that
|
| 1119 |
+
the language model will attend to.
|
| 1120 |
+
cross_attention_mask (`torch.Tensor` of shape `(batch_size, seq_length, max_num_images, max_num_tiles)`, *optional*):
|
| 1121 |
+
Cross-attention mask to control the interaction between text tokens and image tiles.
|
| 1122 |
+
This 4D tensor defines which image tiles each text token should attend to.
|
| 1123 |
+
|
| 1124 |
+
For each text token (in seq_length):
|
| 1125 |
+
- 1 indicates the token **should attend** to the corresponding image tile
|
| 1126 |
+
- 0 indicates the token **should not attend** to the corresponding image tile
|
| 1127 |
+
full_text_row_masked_out_mask (`tuple[torch.Tensor, torch.Tensor]`, *optional*):
|
| 1128 |
+
A tuple containing two tensors that mask out rows in the cross-attention mechanism:
|
| 1129 |
+
- The first tensor has shape `(batch_size, 1, seq_length, 1)` and contains values of 0 or 1.
|
| 1130 |
+
A value of 0 indicates that the corresponding text token's entire row in the cross-attention
|
| 1131 |
+
matrix should be masked out (all image tokens ignored).
|
| 1132 |
+
- The second tensor has the same shape and is used internally to apply the masking during
|
| 1133 |
+
the forward pass of cross-attention layers.
|
| 1134 |
+
This mask is derived from the cross_attention_mask and is used to handle cases where a text token
|
| 1135 |
+
should not attend to any image token.
|
| 1136 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 1137 |
+
Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
|
| 1138 |
+
config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
|
| 1139 |
+
(masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
|
| 1140 |
+
|
| 1141 |
+
Example:
|
| 1142 |
+
|
| 1143 |
+
```python
|
| 1144 |
+
>>> from transformers import AutoTokenizer, BltForCausalLM
|
| 1145 |
+
|
| 1146 |
+
>>> model = BltForCausalLM.from_pretrained("itazap/blt-1b-hf")
|
| 1147 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("itazap/blt-1b-hf")
|
| 1148 |
+
|
| 1149 |
+
>>> prompt = "If I had to write a haiku, it would be:"
|
| 1150 |
+
>>> inputs = tokenizer(prompt, return_tensors="pt")
|
| 1151 |
+
|
| 1152 |
+
>>> # Generate
|
| 1153 |
+
>>> generate_ids = model.generate(inputs.input_ids, max_length=40, do_sample=True, temperature=0.6)
|
| 1154 |
+
>>> result = tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
|
| 1155 |
+
>>> print(result)
|
| 1156 |
+
If I had to write a haiku, it would be: "Snowflakes gently fall" - simple, yet peaceful.
|
| 1157 |
+
I love the idea of snowflakes gently falling, each one
|
| 1158 |
+
```
|
| 1159 |
+
"""
|
| 1160 |
+
# Call parent forward but exclude cross_attention_states from model call
|
| 1161 |
+
outputs = self.model(
|
| 1162 |
+
input_ids=input_ids,
|
| 1163 |
+
attention_mask=attention_mask,
|
| 1164 |
+
position_ids=position_ids,
|
| 1165 |
+
cross_attention_mask=cross_attention_mask,
|
| 1166 |
+
full_text_row_masked_out_mask=full_text_row_masked_out_mask,
|
| 1167 |
+
past_key_values=past_key_values,
|
| 1168 |
+
inputs_embeds=inputs_embeds,
|
| 1169 |
+
use_cache=use_cache,
|
| 1170 |
+
**kwargs,
|
| 1171 |
+
)
|
| 1172 |
+
|
| 1173 |
+
hidden_states = outputs.last_hidden_state
|
| 1174 |
+
slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
|
| 1175 |
+
logits = self.lm_head(hidden_states[:, slice_indices, :]).float()
|
| 1176 |
+
|
| 1177 |
+
loss = None
|
| 1178 |
+
if labels is not None:
|
| 1179 |
+
loss = self.loss_function(logits, labels, self.vocab_size, **kwargs)
|
| 1180 |
+
|
| 1181 |
+
return CausalLMOutputWithPast(
|
| 1182 |
+
loss=loss,
|
| 1183 |
+
logits=logits,
|
| 1184 |
+
past_key_values=outputs.past_key_values,
|
| 1185 |
+
hidden_states=outputs.hidden_states,
|
| 1186 |
+
attentions=outputs.attentions,
|
| 1187 |
+
)
|
| 1188 |
+
|
| 1189 |
+
|
| 1190 |
+
__all__ = [
|
| 1191 |
+
"BltPreTrainedModel",
|
| 1192 |
+
"BltModel",
|
| 1193 |
+
"BltPatcher",
|
| 1194 |
+
"BltForCausalLM",
|
| 1195 |
+
]
|
third_party/transformers/src/transformers/models/byt5/__init__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .tokenization_byt5 import *
|
| 22 |
+
else:
|
| 23 |
+
import sys
|
| 24 |
+
|
| 25 |
+
_file = globals()["__file__"]
|
| 26 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/byt5/convert_byt5_original_tf_checkpoint_to_pytorch.py
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2018 The T5 authors and HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Convert T5 checkpoint."""
|
| 15 |
+
|
| 16 |
+
import argparse
|
| 17 |
+
import os
|
| 18 |
+
|
| 19 |
+
import torch
|
| 20 |
+
|
| 21 |
+
from transformers import T5Config, T5ForConditionalGeneration
|
| 22 |
+
from transformers.utils import logging
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
logger = logging.get_logger(__name__)
|
| 26 |
+
logging.set_verbosity_info()
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def load_tf_weights_in_t5(model, config, tf_checkpoint_path):
|
| 30 |
+
"""Load tf checkpoints in a pytorch model."""
|
| 31 |
+
try:
|
| 32 |
+
import re
|
| 33 |
+
|
| 34 |
+
import numpy as np
|
| 35 |
+
import tensorflow as tf
|
| 36 |
+
except ImportError:
|
| 37 |
+
logger.error(
|
| 38 |
+
"Loading a TensorFlow model in PyTorch, requires TensorFlow to be installed. Please see "
|
| 39 |
+
"https://www.tensorflow.org/install/ for installation instructions."
|
| 40 |
+
)
|
| 41 |
+
raise
|
| 42 |
+
tf_path = os.path.abspath(tf_checkpoint_path)
|
| 43 |
+
logger.info(f"Converting TensorFlow checkpoint from {tf_path}")
|
| 44 |
+
# Load weights from TF model
|
| 45 |
+
init_vars = tf.train.list_variables(tf_path)
|
| 46 |
+
names = []
|
| 47 |
+
tf_weights = {}
|
| 48 |
+
for name, shape in init_vars:
|
| 49 |
+
logger.info(f"Loading TF weight {name} with shape {shape}")
|
| 50 |
+
array = tf.train.load_variable(tf_path, name)
|
| 51 |
+
names.append(name)
|
| 52 |
+
tf_weights[name] = array
|
| 53 |
+
|
| 54 |
+
for txt_name in names:
|
| 55 |
+
name = txt_name.split("/")
|
| 56 |
+
# adam_v and adam_m are variables used in AdamWeightDecayOptimizer to calculated m and v
|
| 57 |
+
# which are not required for using pretrained model
|
| 58 |
+
if any(
|
| 59 |
+
n in ["adam_v", "adam_m", "AdamWeightDecayOptimizer", "AdamWeightDecayOptimizer_1", "global_step"]
|
| 60 |
+
for n in name
|
| 61 |
+
):
|
| 62 |
+
logger.info(f"Skipping {'/'.join(name)}")
|
| 63 |
+
tf_weights.pop(txt_name, None)
|
| 64 |
+
continue
|
| 65 |
+
if "_slot_" in name[-1]:
|
| 66 |
+
logger.info(f"Skipping {'/'.join(name)}")
|
| 67 |
+
tf_weights.pop(txt_name, None)
|
| 68 |
+
continue
|
| 69 |
+
pointer = model
|
| 70 |
+
array = tf_weights[txt_name]
|
| 71 |
+
|
| 72 |
+
for m_name in name:
|
| 73 |
+
if re.fullmatch(r"[A-Za-z]+_\d+", m_name):
|
| 74 |
+
scope_names = re.split(r"_(\d+)", m_name)
|
| 75 |
+
else:
|
| 76 |
+
scope_names = [m_name]
|
| 77 |
+
if scope_names[0] in ["kernel", "scale", "embedding"]:
|
| 78 |
+
pointer = getattr(pointer, "weight")
|
| 79 |
+
elif scope_names[0] == "self_attention":
|
| 80 |
+
pointer = getattr(pointer, "layer")
|
| 81 |
+
pointer = pointer[0]
|
| 82 |
+
elif scope_names[0] == "enc_dec_attention":
|
| 83 |
+
pointer = getattr(pointer, "layer")
|
| 84 |
+
pointer = pointer[1]
|
| 85 |
+
elif scope_names[0] == "dense_relu_dense":
|
| 86 |
+
pointer = getattr(pointer, "layer")
|
| 87 |
+
pointer = pointer[2]
|
| 88 |
+
elif scope_names[0] == "rms_norm":
|
| 89 |
+
if hasattr(pointer, "layer_norm"):
|
| 90 |
+
pointer = getattr(pointer, "layer_norm")
|
| 91 |
+
elif hasattr(pointer, "final_layer_norm"):
|
| 92 |
+
pointer = getattr(pointer, "final_layer_norm")
|
| 93 |
+
elif scope_names[0] == "scale":
|
| 94 |
+
pointer = getattr(pointer, "weight")
|
| 95 |
+
elif scope_names[0] == "output_bias" or scope_names[0] == "beta":
|
| 96 |
+
pointer = getattr(pointer, "bias")
|
| 97 |
+
elif scope_names[0] == "squad":
|
| 98 |
+
pointer = getattr(pointer, "classifier")
|
| 99 |
+
elif scope_names[0] == "decoder" and name[1] == "logits":
|
| 100 |
+
continue
|
| 101 |
+
elif scope_names[0] == "logits":
|
| 102 |
+
pointer = getattr(pointer, "lm_head")
|
| 103 |
+
elif scope_names[0] == "wi" and len(scope_names) > 1 and scope_names[1].isdigit():
|
| 104 |
+
pointer = getattr(pointer, f"wi_{scope_names[1]}")
|
| 105 |
+
continue
|
| 106 |
+
else:
|
| 107 |
+
try:
|
| 108 |
+
pointer = getattr(pointer, scope_names[0])
|
| 109 |
+
except AttributeError:
|
| 110 |
+
logger.info(f"Skipping {'/'.join(name)}")
|
| 111 |
+
continue
|
| 112 |
+
if len(scope_names) >= 2:
|
| 113 |
+
num = int(scope_names[1])
|
| 114 |
+
pointer = pointer[num]
|
| 115 |
+
if scope_names[0] not in ["kernel", "scale", "embedding"]:
|
| 116 |
+
pointer = getattr(pointer, "weight")
|
| 117 |
+
if scope_names[0] != "embedding":
|
| 118 |
+
logger.info(f"Transposing numpy weight of shape {array.shape} for {name}")
|
| 119 |
+
array = np.transpose(array)
|
| 120 |
+
try:
|
| 121 |
+
if pointer.shape != array.shape:
|
| 122 |
+
raise ValueError(f"Pointer shape {pointer.shape} and array shape {array.shape} mismatched")
|
| 123 |
+
except AssertionError as e:
|
| 124 |
+
e.args += (pointer.shape, array.shape)
|
| 125 |
+
raise
|
| 126 |
+
logger.info(f"Initialize PyTorch weight {name}")
|
| 127 |
+
pointer.data = torch.from_numpy(array.astype(np.float32))
|
| 128 |
+
tf_weights.pop(txt_name, None)
|
| 129 |
+
|
| 130 |
+
logger.info(f"Weights not copied to PyTorch model: {', '.join(tf_weights.keys())}.")
|
| 131 |
+
return model
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def convert_tf_checkpoint_to_pytorch(tf_checkpoint_path, config_file, pytorch_dump_path):
|
| 135 |
+
# Initialise PyTorch model
|
| 136 |
+
config = T5Config.from_json_file(config_file)
|
| 137 |
+
print(f"Building PyTorch model from configuration: {config}")
|
| 138 |
+
model = T5ForConditionalGeneration(config)
|
| 139 |
+
|
| 140 |
+
# Load weights from tf checkpoint
|
| 141 |
+
load_tf_weights_in_t5(model, config, tf_checkpoint_path)
|
| 142 |
+
|
| 143 |
+
# Save pytorch-model
|
| 144 |
+
print(f"Save PyTorch model to {pytorch_dump_path}")
|
| 145 |
+
model.save_pretrained(pytorch_dump_path)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
if __name__ == "__main__":
|
| 149 |
+
parser = argparse.ArgumentParser()
|
| 150 |
+
# Required parameters
|
| 151 |
+
parser.add_argument(
|
| 152 |
+
"--tf_checkpoint_path", default=None, type=str, required=True, help="Path to the TensorFlow checkpoint path."
|
| 153 |
+
)
|
| 154 |
+
parser.add_argument(
|
| 155 |
+
"--config_file",
|
| 156 |
+
default=None,
|
| 157 |
+
type=str,
|
| 158 |
+
required=True,
|
| 159 |
+
help=(
|
| 160 |
+
"The config json file corresponding to the pre-trained T5 model. \nThis specifies the model architecture."
|
| 161 |
+
),
|
| 162 |
+
)
|
| 163 |
+
parser.add_argument(
|
| 164 |
+
"--pytorch_dump_path", default=None, type=str, required=True, help="Path to the output PyTorch model."
|
| 165 |
+
)
|
| 166 |
+
args = parser.parse_args()
|
| 167 |
+
convert_tf_checkpoint_to_pytorch(args.tf_checkpoint_path, args.config_file, args.pytorch_dump_path)
|
third_party/transformers/src/transformers/models/byt5/tokenization_byt5.py
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2021 T5 Authors and HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Tokenization class for model ByT5."""
|
| 15 |
+
|
| 16 |
+
import warnings
|
| 17 |
+
|
| 18 |
+
from ...tokenization_python import AddedToken, PreTrainedTokenizer
|
| 19 |
+
from ...utils import logging
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
logger = logging.get_logger(__name__)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class ByT5Tokenizer(PreTrainedTokenizer):
|
| 26 |
+
"""
|
| 27 |
+
Construct a ByT5 tokenizer. ByT5 simply uses raw bytes utf-8 encoding.
|
| 28 |
+
|
| 29 |
+
This tokenizer inherits from [`PreTrainedTokenizer`] which contains most of the main methods. Users should refer to
|
| 30 |
+
this superclass for more information regarding those methods.
|
| 31 |
+
|
| 32 |
+
Args:
|
| 33 |
+
eos_token (`str`, *optional*, defaults to `"</s>"`):
|
| 34 |
+
The end of sequence token.
|
| 35 |
+
|
| 36 |
+
<Tip>
|
| 37 |
+
|
| 38 |
+
When building a sequence using special tokens, this is not the token that is used for the end of sequence.
|
| 39 |
+
The token used is the `sep_token`.
|
| 40 |
+
|
| 41 |
+
</Tip>
|
| 42 |
+
|
| 43 |
+
unk_token (`str`, *optional*, defaults to `"<unk>"`):
|
| 44 |
+
The unknown token. A token that is not in the vocabulary cannot be converted to an ID and is set to be this
|
| 45 |
+
token instead.
|
| 46 |
+
pad_token (`str`, *optional*, defaults to `"<pad>"`):
|
| 47 |
+
The token used for padding, for example when batching sequences of different lengths.
|
| 48 |
+
extra_ids (`int`, *optional*, defaults to 125):
|
| 49 |
+
Add a number of extra ids added to the end of the vocabulary for use as sentinels. These tokens are
|
| 50 |
+
accessible as "<extra_id_{%d}>" where "{%d}" is a number between 0 and extra_ids-1. Extra tokens are
|
| 51 |
+
indexed from the end of the vocabulary up to beginning ("<extra_id_0>" is the last token in the vocabulary
|
| 52 |
+
like in ByT5 preprocessing see
|
| 53 |
+
[here](https://github.com/google-research/text-to-text-transfer-transformer/blob/9fd7b14a769417be33bc6c850f9598764913c833/t5/data/preprocessors.py#L2117)).
|
| 54 |
+
additional_special_tokens (`list[str]`, *optional*):
|
| 55 |
+
Additional special tokens used by the tokenizer.
|
| 56 |
+
"""
|
| 57 |
+
|
| 58 |
+
model_input_names = ["input_ids", "attention_mask"]
|
| 59 |
+
|
| 60 |
+
def __init__(
|
| 61 |
+
self,
|
| 62 |
+
eos_token="</s>",
|
| 63 |
+
unk_token="<unk>",
|
| 64 |
+
pad_token="<pad>",
|
| 65 |
+
extra_ids=125,
|
| 66 |
+
additional_special_tokens=None,
|
| 67 |
+
**kwargs,
|
| 68 |
+
) -> None:
|
| 69 |
+
# Add extra_ids to the special token list
|
| 70 |
+
if extra_ids > 0 and additional_special_tokens is None:
|
| 71 |
+
additional_special_tokens = [f"<extra_id_{i}>" for i in range(extra_ids)]
|
| 72 |
+
elif extra_ids > 0 and additional_special_tokens is not None and len(additional_special_tokens) > 0:
|
| 73 |
+
# Check that we have the right number of extra_id special tokens
|
| 74 |
+
extra_tokens = len(set(filter(lambda x: bool("extra_id" in str(x)), additional_special_tokens)))
|
| 75 |
+
if extra_tokens != extra_ids:
|
| 76 |
+
raise ValueError(
|
| 77 |
+
f"Both extra_ids ({extra_ids}) and additional_special_tokens ({additional_special_tokens}) are"
|
| 78 |
+
" provided to ByT5Tokenizer. In this case the additional_special_tokens must include the"
|
| 79 |
+
" extra_ids tokens"
|
| 80 |
+
)
|
| 81 |
+
|
| 82 |
+
pad_token = AddedToken(pad_token, lstrip=True, rstrip=True) if isinstance(pad_token, str) else pad_token
|
| 83 |
+
# we force left and right stripping for backward compatibility. The byt5tests depend on this.
|
| 84 |
+
eos_token = AddedToken(eos_token, lstrip=True, rstrip=True) if isinstance(eos_token, str) else eos_token
|
| 85 |
+
unk_token = AddedToken(unk_token, lstrip=True, rstrip=True) if isinstance(unk_token, str) else unk_token
|
| 86 |
+
# unk token needs to be in the vocab with correct index
|
| 87 |
+
self._added_tokens_decoder = {0: pad_token, 1: eos_token, 2: unk_token}
|
| 88 |
+
self.offset = len(self._added_tokens_decoder)
|
| 89 |
+
self._utf_vocab_size = 2**8 # utf is 8 bits
|
| 90 |
+
super().__init__(
|
| 91 |
+
eos_token=eos_token,
|
| 92 |
+
unk_token=unk_token,
|
| 93 |
+
pad_token=pad_token,
|
| 94 |
+
extra_ids=0,
|
| 95 |
+
additional_special_tokens=additional_special_tokens, # TODO extra ids are not used :sweatywmile:
|
| 96 |
+
**kwargs,
|
| 97 |
+
)
|
| 98 |
+
|
| 99 |
+
@property
|
| 100 |
+
def vocab_size(self):
|
| 101 |
+
return self._utf_vocab_size
|
| 102 |
+
|
| 103 |
+
def get_vocab(self):
|
| 104 |
+
vocab = {self.convert_ids_to_tokens(i): i for i in range(self.vocab_size + self.offset)}
|
| 105 |
+
vocab.update(self.added_tokens_encoder)
|
| 106 |
+
return vocab
|
| 107 |
+
|
| 108 |
+
def get_special_tokens_mask(
|
| 109 |
+
self, token_ids_0: list[int], token_ids_1: list[int] | None = None, already_has_special_tokens: bool = False
|
| 110 |
+
) -> list[int]:
|
| 111 |
+
"""
|
| 112 |
+
Retrieve sequence ids from a token list that has no special tokens added. This method is called when adding
|
| 113 |
+
special tokens using the tokenizer `prepare_for_model` method.
|
| 114 |
+
|
| 115 |
+
Args:
|
| 116 |
+
token_ids_0 (`list[int]`):
|
| 117 |
+
List of IDs.
|
| 118 |
+
token_ids_1 (`list[int]`, *optional*):
|
| 119 |
+
Optional second list of IDs for sequence pairs.
|
| 120 |
+
already_has_special_tokens (`bool`, *optional*, defaults to `False`):
|
| 121 |
+
Whether or not the token list is already formatted with special tokens for the model.
|
| 122 |
+
|
| 123 |
+
Returns:
|
| 124 |
+
`list[int]`: A list of integers in the range [0, 1]: 1 for a special token, 0 for a sequence token.
|
| 125 |
+
"""
|
| 126 |
+
if already_has_special_tokens:
|
| 127 |
+
return super().get_special_tokens_mask(
|
| 128 |
+
token_ids_0=token_ids_0, token_ids_1=token_ids_1, already_has_special_tokens=True
|
| 129 |
+
)
|
| 130 |
+
|
| 131 |
+
# normal case: some special tokens
|
| 132 |
+
if token_ids_1 is None:
|
| 133 |
+
return ([0] * len(token_ids_0)) + [1]
|
| 134 |
+
return ([0] * len(token_ids_0)) + [1] + ([0] * len(token_ids_1)) + [1]
|
| 135 |
+
|
| 136 |
+
def _add_eos_if_not_present(self, token_ids: list[int]) -> list[int]:
|
| 137 |
+
"""Do not add eos again if user already added it."""
|
| 138 |
+
if len(token_ids) > 0 and token_ids[-1] == self.eos_token_id:
|
| 139 |
+
warnings.warn(
|
| 140 |
+
f"This sequence already has {self.eos_token}. In future versions this behavior may lead to duplicated"
|
| 141 |
+
" eos tokens being added."
|
| 142 |
+
)
|
| 143 |
+
return token_ids
|
| 144 |
+
else:
|
| 145 |
+
return token_ids + [self.eos_token_id]
|
| 146 |
+
|
| 147 |
+
def create_token_type_ids_from_sequences(
|
| 148 |
+
self, token_ids_0: list[int], token_ids_1: list[int] | None = None
|
| 149 |
+
) -> list[int]:
|
| 150 |
+
"""
|
| 151 |
+
Create a mask from the two sequences passed to be used in a sequence-pair classification task. ByT5 does not
|
| 152 |
+
make use of token type ids, therefore a list of zeros is returned.
|
| 153 |
+
|
| 154 |
+
Args:
|
| 155 |
+
token_ids_0 (`list[int]`):
|
| 156 |
+
List of IDs.
|
| 157 |
+
token_ids_1 (`list[int]`, *optional*):
|
| 158 |
+
Optional second list of IDs for sequence pairs.
|
| 159 |
+
|
| 160 |
+
Returns:
|
| 161 |
+
`list[int]`: List of zeros.
|
| 162 |
+
"""
|
| 163 |
+
eos = [self.eos_token_id]
|
| 164 |
+
|
| 165 |
+
if token_ids_1 is None:
|
| 166 |
+
return len(token_ids_0 + eos) * [0]
|
| 167 |
+
return len(token_ids_0 + eos + token_ids_1 + eos) * [0]
|
| 168 |
+
|
| 169 |
+
def build_inputs_with_special_tokens(
|
| 170 |
+
self, token_ids_0: list[int], token_ids_1: list[int] | None = None
|
| 171 |
+
) -> list[int]:
|
| 172 |
+
"""
|
| 173 |
+
Build model inputs from a sequence or a pair of sequence for sequence classification tasks by concatenating and
|
| 174 |
+
adding special tokens. A sequence has the following format:
|
| 175 |
+
|
| 176 |
+
- single sequence: `X </s>`
|
| 177 |
+
- pair of sequences: `A </s> B </s>`
|
| 178 |
+
|
| 179 |
+
Args:
|
| 180 |
+
token_ids_0 (`list[int]`):
|
| 181 |
+
List of IDs to which the special tokens will be added.
|
| 182 |
+
token_ids_1 (`list[int]`, *optional*):
|
| 183 |
+
Optional second list of IDs for sequence pairs.
|
| 184 |
+
|
| 185 |
+
Returns:
|
| 186 |
+
`list[int]`: List of [input IDs](../glossary#input-ids) with the appropriate special tokens.
|
| 187 |
+
"""
|
| 188 |
+
token_ids_0 = self._add_eos_if_not_present(token_ids_0)
|
| 189 |
+
if token_ids_1 is None:
|
| 190 |
+
return token_ids_0
|
| 191 |
+
else:
|
| 192 |
+
token_ids_1 = self._add_eos_if_not_present(token_ids_1)
|
| 193 |
+
return token_ids_0 + token_ids_1
|
| 194 |
+
|
| 195 |
+
def _tokenize(self, text: str) -> list[str]:
|
| 196 |
+
"""Take as input a string and return a list of strings (tokens) for words/sub-words"""
|
| 197 |
+
tokens = [chr(i) for i in text.encode("utf-8")]
|
| 198 |
+
return tokens
|
| 199 |
+
|
| 200 |
+
def _convert_token_to_id(self, token):
|
| 201 |
+
"""Converts a token (str) in an id using the vocab."""
|
| 202 |
+
|
| 203 |
+
if len(token) != 1:
|
| 204 |
+
token_id = None
|
| 205 |
+
else:
|
| 206 |
+
token_id = ord(token) + self.offset
|
| 207 |
+
|
| 208 |
+
return token_id
|
| 209 |
+
|
| 210 |
+
def _convert_id_to_token(self, index):
|
| 211 |
+
"""Converts an index (integer) in a token (str) using the vocab."""
|
| 212 |
+
token = chr(index - self.offset)
|
| 213 |
+
return token
|
| 214 |
+
|
| 215 |
+
def convert_tokens_to_string(self, tokens):
|
| 216 |
+
"""Converts a sequence of tokens (string) in a single string."""
|
| 217 |
+
bstring = b""
|
| 218 |
+
for token in tokens:
|
| 219 |
+
if token in self.added_tokens_decoder:
|
| 220 |
+
tok_string = self.added_tokens_decoder[token].encode("utf-8")
|
| 221 |
+
elif token in self.added_tokens_encoder:
|
| 222 |
+
tok_string = token.encode("utf-8")
|
| 223 |
+
else:
|
| 224 |
+
tok_string = bytes([ord(token)])
|
| 225 |
+
bstring += tok_string
|
| 226 |
+
string = bstring.decode("utf-8", errors="ignore")
|
| 227 |
+
return string
|
| 228 |
+
|
| 229 |
+
# ByT5Tokenizer has no vocab file
|
| 230 |
+
def save_vocabulary(self, save_directory: str, filename_prefix: str | None = None) -> tuple[str]:
|
| 231 |
+
return ()
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
__all__ = ["ByT5Tokenizer"]
|
third_party/transformers/src/transformers/models/clip/__init__.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .configuration_clip import *
|
| 22 |
+
from .image_processing_clip import *
|
| 23 |
+
from .image_processing_pil_clip import *
|
| 24 |
+
from .modeling_clip import *
|
| 25 |
+
from .processing_clip import *
|
| 26 |
+
from .tokenization_clip import *
|
| 27 |
+
else:
|
| 28 |
+
import sys
|
| 29 |
+
|
| 30 |
+
_file = globals()["__file__"]
|
| 31 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/clip/configuration_clip.py
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2021 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""CLIP model configuration"""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from ...configuration_utils import PreTrainedConfig
|
| 19 |
+
from ...utils import auto_docstring, logging
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
logger = logging.get_logger(__name__)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
@auto_docstring(checkpoint="openai/clip-vit-base-patch32")
|
| 26 |
+
@strict
|
| 27 |
+
class CLIPTextConfig(PreTrainedConfig):
|
| 28 |
+
r"""
|
| 29 |
+
Example:
|
| 30 |
+
|
| 31 |
+
```python
|
| 32 |
+
>>> from transformers import CLIPTextConfig, CLIPTextModel
|
| 33 |
+
|
| 34 |
+
>>> # Initializing a CLIPTextConfig with openai/clip-vit-base-patch32 style configuration
|
| 35 |
+
>>> configuration = CLIPTextConfig()
|
| 36 |
+
|
| 37 |
+
>>> # Initializing a CLIPTextModel (with random weights) from the openai/clip-vit-base-patch32 style configuration
|
| 38 |
+
>>> model = CLIPTextModel(configuration)
|
| 39 |
+
|
| 40 |
+
>>> # Accessing the model configuration
|
| 41 |
+
>>> configuration = model.config
|
| 42 |
+
```"""
|
| 43 |
+
|
| 44 |
+
model_type = "clip_text_model"
|
| 45 |
+
base_config_key = "text_config"
|
| 46 |
+
|
| 47 |
+
vocab_size: int = 49408
|
| 48 |
+
hidden_size: int = 512
|
| 49 |
+
intermediate_size: int = 2048
|
| 50 |
+
projection_dim: int | None = 512
|
| 51 |
+
num_hidden_layers: int = 12
|
| 52 |
+
num_attention_heads: int = 8
|
| 53 |
+
max_position_embeddings: int = 77
|
| 54 |
+
hidden_act: str = "quick_gelu"
|
| 55 |
+
layer_norm_eps: float | None = 1e-5
|
| 56 |
+
attention_dropout: int | float | None = 0.0
|
| 57 |
+
initializer_range: float = 0.02
|
| 58 |
+
initializer_factor: float | None = 1.0
|
| 59 |
+
|
| 60 |
+
# This differs from `CLIPTokenizer`'s default and from openai/clip
|
| 61 |
+
# See https://github.com/huggingface/transformers/pull/24773#issuecomment-1632287538
|
| 62 |
+
pad_token_id: int | None = 1
|
| 63 |
+
bos_token_id: int | None = 49406
|
| 64 |
+
eos_token_id: int | list[int] | None = 49407
|
| 65 |
+
|
| 66 |
+
def validate_architecture(self):
|
| 67 |
+
"""Part of `@strict`-powered validation. Validates the architecture of the config."""
|
| 68 |
+
if self.hidden_size % self.num_attention_heads != 0:
|
| 69 |
+
raise ValueError(
|
| 70 |
+
f"The hidden size ({self.hidden_size}) is not a multiple of the number of attention "
|
| 71 |
+
f"heads ({self.num_attention_heads})."
|
| 72 |
+
)
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
@auto_docstring(checkpoint="openai/clip-vit-base-patch32")
|
| 76 |
+
@strict
|
| 77 |
+
class CLIPVisionConfig(PreTrainedConfig):
|
| 78 |
+
r"""
|
| 79 |
+
Example:
|
| 80 |
+
|
| 81 |
+
```python
|
| 82 |
+
>>> from transformers import CLIPVisionConfig, CLIPVisionModel
|
| 83 |
+
|
| 84 |
+
>>> # Initializing a CLIPVisionConfig with openai/clip-vit-base-patch32 style configuration
|
| 85 |
+
>>> configuration = CLIPVisionConfig()
|
| 86 |
+
|
| 87 |
+
>>> # Initializing a CLIPVisionModel (with random weights) from the openai/clip-vit-base-patch32 style configuration
|
| 88 |
+
>>> model = CLIPVisionModel(configuration)
|
| 89 |
+
|
| 90 |
+
>>> # Accessing the model configuration
|
| 91 |
+
>>> configuration = model.config
|
| 92 |
+
```"""
|
| 93 |
+
|
| 94 |
+
model_type = "clip_vision_model"
|
| 95 |
+
base_config_key = "vision_config"
|
| 96 |
+
|
| 97 |
+
hidden_size: int = 768
|
| 98 |
+
intermediate_size: int = 3072
|
| 99 |
+
projection_dim: int | None = 512
|
| 100 |
+
num_hidden_layers: int = 12
|
| 101 |
+
num_attention_heads: int = 12
|
| 102 |
+
num_channels: int | None = 3
|
| 103 |
+
image_size: int | None = 224
|
| 104 |
+
patch_size: int | None = 32
|
| 105 |
+
hidden_act: str = "quick_gelu"
|
| 106 |
+
layer_norm_eps: float | None = 1e-5
|
| 107 |
+
attention_dropout: int | float | None = 0.0
|
| 108 |
+
initializer_range: float = 0.02
|
| 109 |
+
initializer_factor: float | None = 1.0
|
| 110 |
+
|
| 111 |
+
def validate_architecture(self):
|
| 112 |
+
"""Part of `@strict`-powered validation. Validates the architecture of the config."""
|
| 113 |
+
if self.hidden_size % self.num_attention_heads != 0:
|
| 114 |
+
raise ValueError(
|
| 115 |
+
f"The hidden size ({self.hidden_size}) is not a multiple of the number of attention "
|
| 116 |
+
f"heads ({self.num_attention_heads})."
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
@auto_docstring(checkpoint="openai/clip-vit-base-patch32")
|
| 121 |
+
@strict
|
| 122 |
+
class CLIPConfig(PreTrainedConfig):
|
| 123 |
+
r"""
|
| 124 |
+
text_config (`dict`, *optional*):
|
| 125 |
+
Dictionary of configuration options used to initialize [`CLIPTextConfig`].
|
| 126 |
+
vision_config (`dict`, *optional*):
|
| 127 |
+
Dictionary of configuration options used to initialize [`CLIPVisionConfig`].
|
| 128 |
+
logit_scale_init_value (`float | int`, *optional*, defaults to 2.6592):
|
| 129 |
+
The initial value of the *logit_scale* parameter. Default is used as per the original CLIP implementation.
|
| 130 |
+
|
| 131 |
+
Example:
|
| 132 |
+
|
| 133 |
+
```python
|
| 134 |
+
>>> from transformers import CLIPConfig, CLIPModel
|
| 135 |
+
|
| 136 |
+
>>> # Initializing a CLIPConfig with openai/clip-vit-base-patch32 style configuration
|
| 137 |
+
>>> configuration = CLIPConfig()
|
| 138 |
+
|
| 139 |
+
>>> # Initializing a CLIPModel (with random weights) from the openai/clip-vit-base-patch32 style configuration
|
| 140 |
+
>>> model = CLIPModel(configuration)
|
| 141 |
+
|
| 142 |
+
>>> # Accessing the model configuration
|
| 143 |
+
>>> configuration = model.config
|
| 144 |
+
|
| 145 |
+
>>> # We can also initialize a CLIPConfig from a CLIPTextConfig and a CLIPVisionConfig
|
| 146 |
+
>>> from transformers import CLIPTextConfig, CLIPVisionConfig
|
| 147 |
+
|
| 148 |
+
>>> # Initializing a CLIPText and CLIPVision configuration
|
| 149 |
+
>>> config_text = CLIPTextConfig()
|
| 150 |
+
>>> config_vision = CLIPVisionConfig()
|
| 151 |
+
|
| 152 |
+
>>> config = CLIPConfig(text_config=config_text, vision_config=config_vision)
|
| 153 |
+
```"""
|
| 154 |
+
|
| 155 |
+
model_type = "clip"
|
| 156 |
+
sub_configs = {"text_config": CLIPTextConfig, "vision_config": CLIPVisionConfig}
|
| 157 |
+
|
| 158 |
+
text_config: dict | CLIPTextConfig | None = None
|
| 159 |
+
vision_config: dict | CLIPVisionConfig | None = None
|
| 160 |
+
projection_dim: int | None = 512
|
| 161 |
+
logit_scale_init_value: float | int | None = 2.6592
|
| 162 |
+
initializer_factor: float | None = 1.0
|
| 163 |
+
|
| 164 |
+
def __post_init__(self, **kwargs):
|
| 165 |
+
if self.text_config is None:
|
| 166 |
+
text_config = {}
|
| 167 |
+
logger.info("`text_config` is `None`. Initializing the `CLIPTextConfig` with default values.")
|
| 168 |
+
elif isinstance(self.text_config, CLIPTextConfig):
|
| 169 |
+
text_config = self.text_config.to_dict()
|
| 170 |
+
else:
|
| 171 |
+
text_config = self.text_config
|
| 172 |
+
|
| 173 |
+
if self.vision_config is None:
|
| 174 |
+
vision_config = {}
|
| 175 |
+
logger.info("`vision_config` is `None`. initializing the `CLIPVisionConfig` with default values.")
|
| 176 |
+
elif isinstance(self.vision_config, CLIPVisionConfig):
|
| 177 |
+
vision_config = self.vision_config.to_dict()
|
| 178 |
+
else:
|
| 179 |
+
vision_config = self.vision_config
|
| 180 |
+
|
| 181 |
+
# For backward compatibility check keyword args
|
| 182 |
+
# Instead of simply assigning `[text|vision]_config_dict` to `[text|vision]_config`, we use the values in
|
| 183 |
+
# `[text|vision]_config_dict` to update the values in `[text|vision]_config`. The values should be same in most
|
| 184 |
+
# cases, but we don't want to break anything regarding `_config_dict` that existed before commit `8827e1b2`.
|
| 185 |
+
text_config_dict = kwargs.pop("text_config_dict", None)
|
| 186 |
+
vision_config_dict = kwargs.pop("vision_config_dict", None)
|
| 187 |
+
|
| 188 |
+
if text_config_dict is not None:
|
| 189 |
+
# This is the complete result when using `text_config_dict`.
|
| 190 |
+
_text_config_dict = CLIPTextConfig(**text_config_dict).to_dict()
|
| 191 |
+
|
| 192 |
+
# Give a warning if the values exist in both `_text_config_dict` and `text_config` but being different.
|
| 193 |
+
for key, value in _text_config_dict.items():
|
| 194 |
+
if key in text_config and value != text_config[key] and key != "transformers_version":
|
| 195 |
+
# If specified in `text_config_dict`
|
| 196 |
+
if key in text_config_dict:
|
| 197 |
+
message = (
|
| 198 |
+
f"`{key}` is found in both `text_config_dict` and `text_config` but with different values. "
|
| 199 |
+
f'The value `text_config_dict["{key}"]` will be used instead.'
|
| 200 |
+
)
|
| 201 |
+
# If inferred from default argument values (just to be super careful)
|
| 202 |
+
else:
|
| 203 |
+
message = (
|
| 204 |
+
f"`text_config_dict` is provided which will be used to initialize `CLIPTextConfig`. The "
|
| 205 |
+
f'value `text_config["{key}"]` will be overridden.'
|
| 206 |
+
)
|
| 207 |
+
logger.info(message)
|
| 208 |
+
|
| 209 |
+
# Update all values in `text_config` with the ones in `_text_config_dict`.
|
| 210 |
+
text_config.update(_text_config_dict)
|
| 211 |
+
|
| 212 |
+
if vision_config_dict is not None:
|
| 213 |
+
# This is the complete result when using `vision_config_dict`.
|
| 214 |
+
_vision_config_dict = CLIPVisionConfig(**vision_config_dict).to_dict()
|
| 215 |
+
# convert keys to string instead of integer
|
| 216 |
+
if "id2label" in _vision_config_dict:
|
| 217 |
+
_vision_config_dict["id2label"] = {
|
| 218 |
+
str(key): value for key, value in _vision_config_dict["id2label"].items()
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
# Give a warning if the values exist in both `_vision_config_dict` and `vision_config` but being different.
|
| 222 |
+
for key, value in _vision_config_dict.items():
|
| 223 |
+
if key in vision_config and value != vision_config[key] and key != "transformers_version":
|
| 224 |
+
# If specified in `vision_config_dict`
|
| 225 |
+
if key in vision_config_dict:
|
| 226 |
+
message = (
|
| 227 |
+
f"`{key}` is found in both `vision_config_dict` and `vision_config` but with different "
|
| 228 |
+
f'values. The value `vision_config_dict["{key}"]` will be used instead.'
|
| 229 |
+
)
|
| 230 |
+
# If inferred from default argument values (just to be super careful)
|
| 231 |
+
else:
|
| 232 |
+
message = (
|
| 233 |
+
f"`vision_config_dict` is provided which will be used to initialize `CLIPVisionConfig`. "
|
| 234 |
+
f'The value `vision_config["{key}"]` will be overridden.'
|
| 235 |
+
)
|
| 236 |
+
logger.info(message)
|
| 237 |
+
|
| 238 |
+
# Update all values in `vision_config` with the ones in `_vision_config_dict`.
|
| 239 |
+
vision_config.update(_vision_config_dict)
|
| 240 |
+
|
| 241 |
+
# Finally we can convert back our unified text/vision configs to `PretrainedConfig`
|
| 242 |
+
self.text_config = CLIPTextConfig(**text_config)
|
| 243 |
+
self.vision_config = CLIPVisionConfig(**vision_config)
|
| 244 |
+
|
| 245 |
+
super().__post_init__(**kwargs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
__all__ = ["CLIPConfig", "CLIPTextConfig", "CLIPVisionConfig"]
|
third_party/transformers/src/transformers/models/clip/convert_clip_original_pytorch_to_hf.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2021 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
import argparse
|
| 16 |
+
|
| 17 |
+
import torch
|
| 18 |
+
from clip import load
|
| 19 |
+
|
| 20 |
+
from transformers import CLIPConfig, CLIPModel
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def copy_attn_layer(hf_attn_layer, pt_attn_layer):
|
| 24 |
+
q_proj, k_proj, v_proj = pt_attn_layer.in_proj_weight.chunk(3, dim=0)
|
| 25 |
+
q_proj_bias, k_proj_bias, v_proj_bias = pt_attn_layer.in_proj_bias.chunk(3, dim=0)
|
| 26 |
+
|
| 27 |
+
out_proj_weights = pt_attn_layer.out_proj.weight
|
| 28 |
+
out_proj_bias = pt_attn_layer.out_proj.bias
|
| 29 |
+
|
| 30 |
+
hf_attn_layer.q_proj.weight.data = q_proj
|
| 31 |
+
hf_attn_layer.q_proj.bias.data = q_proj_bias
|
| 32 |
+
|
| 33 |
+
hf_attn_layer.k_proj.weight.data = k_proj
|
| 34 |
+
hf_attn_layer.k_proj.bias.data = k_proj_bias
|
| 35 |
+
|
| 36 |
+
hf_attn_layer.v_proj.weight.data = v_proj
|
| 37 |
+
hf_attn_layer.v_proj.bias.data = v_proj_bias
|
| 38 |
+
|
| 39 |
+
hf_attn_layer.out_proj.weight = out_proj_weights
|
| 40 |
+
hf_attn_layer.out_proj.bias = out_proj_bias
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def copy_mlp(hf_mlp, pt_mlp):
|
| 44 |
+
copy_linear(hf_mlp.fc1, pt_mlp.c_fc)
|
| 45 |
+
copy_linear(hf_mlp.fc2, pt_mlp.c_proj)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def copy_linear(hf_linear, pt_linear):
|
| 49 |
+
hf_linear.weight = pt_linear.weight
|
| 50 |
+
hf_linear.bias = pt_linear.bias
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def copy_layer(hf_layer, pt_layer):
|
| 54 |
+
# copy layer norms
|
| 55 |
+
copy_linear(hf_layer.layer_norm1, pt_layer.ln_1)
|
| 56 |
+
copy_linear(hf_layer.layer_norm2, pt_layer.ln_2)
|
| 57 |
+
|
| 58 |
+
# copy MLP
|
| 59 |
+
copy_mlp(hf_layer.mlp, pt_layer.mlp)
|
| 60 |
+
|
| 61 |
+
# copy attn
|
| 62 |
+
copy_attn_layer(hf_layer.self_attn, pt_layer.attn)
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def copy_layers(hf_layers, pt_layers):
|
| 66 |
+
for hf_layer, pt_layer in zip(hf_layers, pt_layers):
|
| 67 |
+
copy_layer(hf_layer, pt_layer)
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def copy_encoder(hf_encoder, pt_model):
|
| 71 |
+
# copy embeds
|
| 72 |
+
hf_encoder.embeddings.token_embedding.weight = pt_model.token_embedding.weight
|
| 73 |
+
hf_encoder.embeddings.position_embedding.weight.data = pt_model.positional_embedding
|
| 74 |
+
|
| 75 |
+
# copy layer norm
|
| 76 |
+
copy_linear(hf_encoder.final_layer_norm, pt_model.ln_final)
|
| 77 |
+
|
| 78 |
+
# copy hidden layers
|
| 79 |
+
copy_layers(hf_encoder.encoder.layers, pt_model.transformer.resblocks)
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def copy_text_model_and_projection(hf_model, pt_model):
|
| 83 |
+
# copy projection
|
| 84 |
+
hf_model.text_projection.weight.data = pt_model.text_projection.data.T.contiguous()
|
| 85 |
+
|
| 86 |
+
# copy text encoder
|
| 87 |
+
copy_encoder(hf_model.text_model, pt_model)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def copy_vison_model_and_projection(hf_model, pt_model):
|
| 91 |
+
# copy projection
|
| 92 |
+
hf_model.visual_projection.weight.data = pt_model.visual.proj.data.T.contiguous()
|
| 93 |
+
|
| 94 |
+
# copy layer norms
|
| 95 |
+
copy_linear(hf_model.vision_model.pre_layrnorm, pt_model.visual.ln_pre)
|
| 96 |
+
copy_linear(hf_model.vision_model.post_layernorm, pt_model.visual.ln_post)
|
| 97 |
+
|
| 98 |
+
# copy embeds
|
| 99 |
+
hf_model.vision_model.embeddings.patch_embedding.weight.data = pt_model.visual.conv1.weight.data
|
| 100 |
+
hf_model.vision_model.embeddings.class_embedding = pt_model.visual.class_embedding
|
| 101 |
+
hf_model.vision_model.embeddings.position_embedding.weight.data = pt_model.visual.positional_embedding.data
|
| 102 |
+
|
| 103 |
+
# copy encoder
|
| 104 |
+
copy_layers(hf_model.vision_model.encoder.layers, pt_model.visual.transformer.resblocks)
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
@torch.no_grad()
|
| 108 |
+
def convert_clip_checkpoint(checkpoint_path, pytorch_dump_folder_path, config_path=None):
|
| 109 |
+
"""
|
| 110 |
+
Copy/paste/tweak model's weights to transformers design.
|
| 111 |
+
"""
|
| 112 |
+
if config_path is not None:
|
| 113 |
+
config = CLIPConfig.from_pretrained(config_path)
|
| 114 |
+
else:
|
| 115 |
+
config = CLIPConfig(projection_dim=512, text_config={}, vision_config={})
|
| 116 |
+
|
| 117 |
+
hf_model = CLIPModel(config).eval()
|
| 118 |
+
|
| 119 |
+
pt_model, _ = load(checkpoint_path, device="cpu", jit=False)
|
| 120 |
+
pt_model = pt_model.eval()
|
| 121 |
+
|
| 122 |
+
copy_text_model_and_projection(hf_model, pt_model)
|
| 123 |
+
copy_vison_model_and_projection(hf_model, pt_model)
|
| 124 |
+
hf_model.logit_scale = pt_model.logit_scale
|
| 125 |
+
|
| 126 |
+
# Use `eos_token` so the example is more meaningful
|
| 127 |
+
input_ids = torch.tensor(
|
| 128 |
+
[
|
| 129 |
+
[config.text_config.bos_token_id]
|
| 130 |
+
+ list(range(3, 77))
|
| 131 |
+
+ [config.text_config.eos_token_id]
|
| 132 |
+
+ [config.text_config.pad_token_id]
|
| 133 |
+
]
|
| 134 |
+
)
|
| 135 |
+
pixel_values = torch.randn(1, 3, 224, 224)
|
| 136 |
+
|
| 137 |
+
hf_outputs = hf_model(input_ids=input_ids, pixel_values=pixel_values, return_dict=True)
|
| 138 |
+
hf_logits_per_image = hf_outputs.logits_per_image
|
| 139 |
+
hf_logits_per_text = hf_outputs.logits_per_text
|
| 140 |
+
pt_logits_per_image, pt_logits_per_text = pt_model(pixel_values, input_ids)
|
| 141 |
+
|
| 142 |
+
assert torch.allclose(hf_logits_per_image, pt_logits_per_image, atol=1e-3)
|
| 143 |
+
assert torch.allclose(hf_logits_per_text, pt_logits_per_text, atol=1e-3)
|
| 144 |
+
|
| 145 |
+
hf_model.save_pretrained(pytorch_dump_folder_path)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
if __name__ == "__main__":
|
| 149 |
+
parser = argparse.ArgumentParser()
|
| 150 |
+
parser.add_argument("--pytorch_dump_folder_path", default=None, type=str, help="Path to the output PyTorch model.")
|
| 151 |
+
parser.add_argument("--checkpoint_path", default=None, type=str, help="Path to OpenAI checkpoint")
|
| 152 |
+
parser.add_argument("--config_path", default=None, type=str, help="Path to hf config.json of model to convert")
|
| 153 |
+
args = parser.parse_args()
|
| 154 |
+
|
| 155 |
+
convert_clip_checkpoint(args.checkpoint_path, args.pytorch_dump_folder_path, args.config_path)
|
third_party/transformers/src/transformers/models/clip/image_processing_clip.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2021 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Image processor class for CLIP."""
|
| 15 |
+
|
| 16 |
+
from ...image_processing_backends import TorchvisionBackend
|
| 17 |
+
from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, PILImageResampling
|
| 18 |
+
from ...processing_utils import ImagesKwargs, Unpack
|
| 19 |
+
from ...utils import auto_docstring
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
@auto_docstring
|
| 23 |
+
class CLIPImageProcessor(TorchvisionBackend):
|
| 24 |
+
resample = PILImageResampling.BICUBIC
|
| 25 |
+
image_mean = OPENAI_CLIP_MEAN
|
| 26 |
+
image_std = OPENAI_CLIP_STD
|
| 27 |
+
size = {"shortest_edge": 224}
|
| 28 |
+
default_to_square = False
|
| 29 |
+
crop_size = {"height": 224, "width": 224}
|
| 30 |
+
do_resize = True
|
| 31 |
+
do_center_crop = True
|
| 32 |
+
do_rescale = True
|
| 33 |
+
do_normalize = True
|
| 34 |
+
do_convert_rgb = True
|
| 35 |
+
|
| 36 |
+
def __init__(self, **kwargs: Unpack[ImagesKwargs]):
|
| 37 |
+
# for backwards compatibility of KOSMOS-2
|
| 38 |
+
if "use_square_size" in kwargs and kwargs["use_square_size"]:
|
| 39 |
+
kwargs["size"] = {"height": self.size["shortest_edge"], "width": self.size["shortest_edge"]}
|
| 40 |
+
kwargs.pop("use_square_size")
|
| 41 |
+
|
| 42 |
+
super().__init__(**kwargs)
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
__all__ = ["CLIPImageProcessor"]
|
third_party/transformers/src/transformers/models/clip/image_processing_pil_clip.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2021 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Image processor class for CLIP."""
|
| 15 |
+
|
| 16 |
+
from ...image_processing_backends import PilBackend
|
| 17 |
+
from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, PILImageResampling
|
| 18 |
+
from ...processing_utils import ImagesKwargs, Unpack
|
| 19 |
+
from ...utils import auto_docstring
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
@auto_docstring
|
| 23 |
+
class CLIPImageProcessorPil(PilBackend):
|
| 24 |
+
resample = PILImageResampling.BICUBIC
|
| 25 |
+
image_mean = OPENAI_CLIP_MEAN
|
| 26 |
+
image_std = OPENAI_CLIP_STD
|
| 27 |
+
size = {"shortest_edge": 224}
|
| 28 |
+
default_to_square = False
|
| 29 |
+
crop_size = {"height": 224, "width": 224}
|
| 30 |
+
do_resize = True
|
| 31 |
+
do_center_crop = True
|
| 32 |
+
do_rescale = True
|
| 33 |
+
do_normalize = True
|
| 34 |
+
do_convert_rgb = True
|
| 35 |
+
|
| 36 |
+
def __init__(self, **kwargs: Unpack[ImagesKwargs]):
|
| 37 |
+
# for backwards compatibility of KOSMOS-2
|
| 38 |
+
if "use_square_size" in kwargs and kwargs["use_square_size"]:
|
| 39 |
+
kwargs["size"] = {"height": self.size["shortest_edge"], "width": self.size["shortest_edge"]}
|
| 40 |
+
kwargs.pop("use_square_size")
|
| 41 |
+
|
| 42 |
+
super().__init__(**kwargs)
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
__all__ = ["CLIPImageProcessorPil"]
|
third_party/transformers/src/transformers/models/clip/modeling_clip.py
ADDED
|
@@ -0,0 +1,1148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2021 The OpenAI Team Authors and The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""PyTorch CLIP model."""
|
| 15 |
+
|
| 16 |
+
from collections.abc import Callable
|
| 17 |
+
from dataclasses import dataclass
|
| 18 |
+
from typing import Any
|
| 19 |
+
|
| 20 |
+
import torch
|
| 21 |
+
from torch import nn
|
| 22 |
+
|
| 23 |
+
from ... import initialization as init
|
| 24 |
+
from ...activations import ACT2FN
|
| 25 |
+
from ...masking_utils import create_causal_mask
|
| 26 |
+
from ...modeling_layers import GradientCheckpointingLayer
|
| 27 |
+
from ...modeling_outputs import BaseModelOutput, BaseModelOutputWithPooling, ImageClassifierOutput
|
| 28 |
+
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
|
| 29 |
+
from ...processing_utils import Unpack
|
| 30 |
+
from ...utils import (
|
| 31 |
+
ModelOutput,
|
| 32 |
+
TransformersKwargs,
|
| 33 |
+
auto_docstring,
|
| 34 |
+
logging,
|
| 35 |
+
torch_int,
|
| 36 |
+
)
|
| 37 |
+
from ...utils.generic import can_return_tuple, merge_with_config_defaults
|
| 38 |
+
from ...utils.output_capturing import capture_outputs
|
| 39 |
+
from .configuration_clip import CLIPConfig, CLIPTextConfig, CLIPVisionConfig
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
logger = logging.get_logger(__name__)
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
# contrastive loss function, adapted from
|
| 46 |
+
# https://sachinruk.github.io/blog/2021-03-07-clip.html
|
| 47 |
+
def contrastive_loss(logits: torch.Tensor) -> torch.Tensor:
|
| 48 |
+
return nn.functional.cross_entropy(logits, torch.arange(len(logits), device=logits.device))
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def clip_loss(similarity: torch.Tensor) -> torch.Tensor:
|
| 52 |
+
caption_loss = contrastive_loss(similarity)
|
| 53 |
+
image_loss = contrastive_loss(similarity.t())
|
| 54 |
+
return (caption_loss + image_loss) / 2.0
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def _get_vector_norm(tensor: torch.Tensor) -> torch.Tensor:
|
| 58 |
+
"""
|
| 59 |
+
This method is equivalent to tensor.norm(p=2, dim=-1, keepdim=True) and used to make
|
| 60 |
+
model `executorch` exportable. See issue https://github.com/pytorch/executorch/issues/3566
|
| 61 |
+
"""
|
| 62 |
+
square_tensor = torch.pow(tensor, 2)
|
| 63 |
+
sum_tensor = torch.sum(square_tensor, dim=-1, keepdim=True)
|
| 64 |
+
normed_tensor = torch.pow(sum_tensor, 0.5)
|
| 65 |
+
return normed_tensor
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
@dataclass
|
| 69 |
+
@auto_docstring(
|
| 70 |
+
custom_intro="""
|
| 71 |
+
Base class for vision model's outputs that also contains image embeddings of the pooling of the last hidden states.
|
| 72 |
+
"""
|
| 73 |
+
)
|
| 74 |
+
class CLIPVisionModelOutput(ModelOutput):
|
| 75 |
+
r"""
|
| 76 |
+
image_embeds (`torch.FloatTensor` of shape `(batch_size, output_dim)` *optional* returned when model is initialized with `with_projection=True`):
|
| 77 |
+
The image embeddings obtained by applying the projection layer to the pooler_output.
|
| 78 |
+
"""
|
| 79 |
+
|
| 80 |
+
image_embeds: torch.FloatTensor | None = None
|
| 81 |
+
last_hidden_state: torch.FloatTensor | None = None
|
| 82 |
+
hidden_states: tuple[torch.FloatTensor, ...] | None = None
|
| 83 |
+
attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
@dataclass
|
| 87 |
+
@auto_docstring(
|
| 88 |
+
custom_intro="""
|
| 89 |
+
Base class for text model's outputs that also contains a pooling of the last hidden states.
|
| 90 |
+
"""
|
| 91 |
+
)
|
| 92 |
+
class CLIPTextModelOutput(ModelOutput):
|
| 93 |
+
r"""
|
| 94 |
+
text_embeds (`torch.FloatTensor` of shape `(batch_size, output_dim)` *optional* returned when model is initialized with `with_projection=True`):
|
| 95 |
+
The text embeddings obtained by applying the projection layer to the pooler_output.
|
| 96 |
+
"""
|
| 97 |
+
|
| 98 |
+
text_embeds: torch.FloatTensor | None = None
|
| 99 |
+
last_hidden_state: torch.FloatTensor | None = None
|
| 100 |
+
hidden_states: tuple[torch.FloatTensor, ...] | None = None
|
| 101 |
+
attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
@dataclass
|
| 105 |
+
@auto_docstring
|
| 106 |
+
class CLIPOutput(ModelOutput):
|
| 107 |
+
r"""
|
| 108 |
+
loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `return_loss` is `True`):
|
| 109 |
+
Contrastive loss for image-text similarity.
|
| 110 |
+
logits_per_image (`torch.FloatTensor` of shape `(image_batch_size, text_batch_size)`):
|
| 111 |
+
The scaled dot product scores between `image_embeds` and `text_embeds`. This represents the image-text
|
| 112 |
+
similarity scores.
|
| 113 |
+
logits_per_text (`torch.FloatTensor` of shape `(text_batch_size, image_batch_size)`):
|
| 114 |
+
The scaled dot product scores between `text_embeds` and `image_embeds`. This represents the text-image
|
| 115 |
+
similarity scores.
|
| 116 |
+
text_embeds (`torch.FloatTensor` of shape `(batch_size, output_dim`):
|
| 117 |
+
The text embeddings obtained by applying the projection layer to the pooled output of [`CLIPTextModel`].
|
| 118 |
+
image_embeds (`torch.FloatTensor` of shape `(batch_size, output_dim`):
|
| 119 |
+
The image embeddings obtained by applying the projection layer to the pooled output of [`CLIPVisionModel`].
|
| 120 |
+
text_model_output (`BaseModelOutputWithPooling`):
|
| 121 |
+
The output of the [`CLIPTextModel`].
|
| 122 |
+
vision_model_output (`BaseModelOutputWithPooling`):
|
| 123 |
+
The output of the [`CLIPVisionModel`].
|
| 124 |
+
"""
|
| 125 |
+
|
| 126 |
+
loss: torch.FloatTensor | None = None
|
| 127 |
+
logits_per_image: torch.FloatTensor | None = None
|
| 128 |
+
logits_per_text: torch.FloatTensor | None = None
|
| 129 |
+
text_embeds: torch.FloatTensor | None = None
|
| 130 |
+
image_embeds: torch.FloatTensor | None = None
|
| 131 |
+
text_model_output: BaseModelOutputWithPooling = None
|
| 132 |
+
vision_model_output: BaseModelOutputWithPooling = None
|
| 133 |
+
|
| 134 |
+
def to_tuple(self) -> tuple[Any]:
|
| 135 |
+
return tuple(v.to_tuple() if isinstance(v, ModelOutput) else v for v in self.values())
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
class CLIPVisionEmbeddings(nn.Module):
|
| 139 |
+
def __init__(self, config: CLIPVisionConfig):
|
| 140 |
+
super().__init__()
|
| 141 |
+
self.config = config
|
| 142 |
+
self.embed_dim = config.hidden_size
|
| 143 |
+
self.image_size = config.image_size
|
| 144 |
+
self.patch_size = config.patch_size
|
| 145 |
+
|
| 146 |
+
self.class_embedding = nn.Parameter(torch.randn(self.embed_dim))
|
| 147 |
+
|
| 148 |
+
self.patch_embedding = nn.Conv2d(
|
| 149 |
+
in_channels=config.num_channels,
|
| 150 |
+
out_channels=self.embed_dim,
|
| 151 |
+
kernel_size=self.patch_size,
|
| 152 |
+
stride=self.patch_size,
|
| 153 |
+
bias=False,
|
| 154 |
+
)
|
| 155 |
+
|
| 156 |
+
self.num_patches = (self.image_size // self.patch_size) ** 2
|
| 157 |
+
self.num_positions = self.num_patches + 1
|
| 158 |
+
self.position_embedding = nn.Embedding(self.num_positions, self.embed_dim)
|
| 159 |
+
self.register_buffer("position_ids", torch.arange(self.num_positions).expand((1, -1)), persistent=False)
|
| 160 |
+
|
| 161 |
+
def interpolate_pos_encoding(self, embeddings: torch.Tensor, height: int, width: int) -> torch.Tensor:
|
| 162 |
+
"""
|
| 163 |
+
This method allows to interpolate the pre-trained position encodings, to be able to use the model on higher resolution
|
| 164 |
+
images. This method is also adapted to support torch.jit tracing.
|
| 165 |
+
|
| 166 |
+
Adapted from:
|
| 167 |
+
- https://github.com/facebookresearch/dino/blob/de9ee3df6cf39fac952ab558447af1fa1365362a/vision_transformer.py#L174-L194, and
|
| 168 |
+
- https://github.com/facebookresearch/dinov2/blob/e1277af2ba9496fbadf7aec6eba56e8d882d1e35/dinov2/models/vision_transformer.py#L179-L211
|
| 169 |
+
"""
|
| 170 |
+
|
| 171 |
+
num_patches = embeddings.shape[1] - 1
|
| 172 |
+
position_embedding = self.position_embedding.weight.unsqueeze(0)
|
| 173 |
+
num_positions = position_embedding.shape[1] - 1
|
| 174 |
+
|
| 175 |
+
# always interpolate when tracing to ensure the exported model works for dynamic input shapes
|
| 176 |
+
if not torch.jit.is_tracing() and num_patches == num_positions and height == width:
|
| 177 |
+
return self.position_embedding(self.position_ids)
|
| 178 |
+
|
| 179 |
+
class_pos_embed = position_embedding[:, :1]
|
| 180 |
+
patch_pos_embed = position_embedding[:, 1:]
|
| 181 |
+
|
| 182 |
+
dim = embeddings.shape[-1]
|
| 183 |
+
|
| 184 |
+
new_height = height // self.patch_size
|
| 185 |
+
new_width = width // self.patch_size
|
| 186 |
+
|
| 187 |
+
sqrt_num_positions = torch_int(num_positions**0.5)
|
| 188 |
+
patch_pos_embed = patch_pos_embed.reshape(1, sqrt_num_positions, sqrt_num_positions, dim)
|
| 189 |
+
patch_pos_embed = patch_pos_embed.permute(0, 3, 1, 2)
|
| 190 |
+
|
| 191 |
+
patch_pos_embed = nn.functional.interpolate(
|
| 192 |
+
patch_pos_embed,
|
| 193 |
+
size=(new_height, new_width),
|
| 194 |
+
mode="bicubic",
|
| 195 |
+
align_corners=False,
|
| 196 |
+
)
|
| 197 |
+
|
| 198 |
+
patch_pos_embed = patch_pos_embed.permute(0, 2, 3, 1).view(1, -1, dim)
|
| 199 |
+
|
| 200 |
+
return torch.cat((class_pos_embed, patch_pos_embed), dim=1)
|
| 201 |
+
|
| 202 |
+
def forward(self, pixel_values: torch.FloatTensor, interpolate_pos_encoding=False) -> torch.Tensor:
|
| 203 |
+
batch_size, _, height, width = pixel_values.shape
|
| 204 |
+
if not interpolate_pos_encoding and (height != self.image_size or width != self.image_size):
|
| 205 |
+
raise ValueError(
|
| 206 |
+
f"Input image size ({height}*{width}) doesn't match model ({self.image_size}*{self.image_size})."
|
| 207 |
+
)
|
| 208 |
+
target_dtype = self.patch_embedding.weight.dtype
|
| 209 |
+
patch_embeds = self.patch_embedding(pixel_values.to(dtype=target_dtype)) # shape = [*, width, grid, grid]
|
| 210 |
+
patch_embeds = patch_embeds.flatten(2).transpose(1, 2)
|
| 211 |
+
|
| 212 |
+
class_embeds = self.class_embedding.expand(batch_size, 1, -1)
|
| 213 |
+
embeddings = torch.cat([class_embeds, patch_embeds], dim=1)
|
| 214 |
+
if interpolate_pos_encoding:
|
| 215 |
+
embeddings = embeddings + self.interpolate_pos_encoding(embeddings, height, width)
|
| 216 |
+
else:
|
| 217 |
+
embeddings = embeddings + self.position_embedding(self.position_ids)
|
| 218 |
+
return embeddings
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
class CLIPTextEmbeddings(nn.Module):
|
| 222 |
+
def __init__(self, config: CLIPTextConfig):
|
| 223 |
+
super().__init__()
|
| 224 |
+
embed_dim = config.hidden_size
|
| 225 |
+
|
| 226 |
+
self.token_embedding = nn.Embedding(config.vocab_size, embed_dim)
|
| 227 |
+
self.position_embedding = nn.Embedding(config.max_position_embeddings, embed_dim)
|
| 228 |
+
|
| 229 |
+
# position_ids (1, len position emb) is contiguous in memory and exported when serialized
|
| 230 |
+
self.register_buffer(
|
| 231 |
+
"position_ids", torch.arange(config.max_position_embeddings).expand((1, -1)), persistent=False
|
| 232 |
+
)
|
| 233 |
+
|
| 234 |
+
def forward(
|
| 235 |
+
self,
|
| 236 |
+
input_ids: torch.LongTensor | None = None,
|
| 237 |
+
position_ids: torch.LongTensor | None = None,
|
| 238 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 239 |
+
) -> torch.Tensor:
|
| 240 |
+
seq_length = input_ids.shape[-1] if input_ids is not None else inputs_embeds.shape[-2]
|
| 241 |
+
max_position_embedding = self.position_embedding.weight.shape[0]
|
| 242 |
+
|
| 243 |
+
if seq_length > max_position_embedding:
|
| 244 |
+
raise ValueError(
|
| 245 |
+
f"Sequence length must be less than max_position_embeddings (got `sequence length`: "
|
| 246 |
+
f"{seq_length} and max_position_embeddings: {max_position_embedding}"
|
| 247 |
+
)
|
| 248 |
+
|
| 249 |
+
if position_ids is None:
|
| 250 |
+
position_ids = self.position_ids[:, :seq_length]
|
| 251 |
+
|
| 252 |
+
if inputs_embeds is None:
|
| 253 |
+
inputs_embeds = self.token_embedding(input_ids)
|
| 254 |
+
|
| 255 |
+
position_embeddings = self.position_embedding(position_ids)
|
| 256 |
+
embeddings = inputs_embeds + position_embeddings
|
| 257 |
+
|
| 258 |
+
return embeddings
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
def eager_attention_forward(
|
| 262 |
+
module: nn.Module,
|
| 263 |
+
query: torch.Tensor,
|
| 264 |
+
key: torch.Tensor,
|
| 265 |
+
value: torch.Tensor,
|
| 266 |
+
attention_mask: torch.Tensor | None,
|
| 267 |
+
scaling: float,
|
| 268 |
+
dropout: float = 0.0,
|
| 269 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 270 |
+
):
|
| 271 |
+
attn_weights = torch.matmul(query, key.transpose(-1, -2)) * scaling
|
| 272 |
+
if attention_mask is not None:
|
| 273 |
+
attn_weights = attn_weights + attention_mask
|
| 274 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
|
| 275 |
+
attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
|
| 276 |
+
|
| 277 |
+
attn_output = torch.matmul(attn_weights, value)
|
| 278 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 279 |
+
return attn_output, attn_weights
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
class CLIPAttention(nn.Module):
|
| 283 |
+
"""Multi-headed attention from 'Attention Is All You Need' paper"""
|
| 284 |
+
|
| 285 |
+
def __init__(self, config: CLIPVisionConfig | CLIPTextConfig):
|
| 286 |
+
super().__init__()
|
| 287 |
+
self.config = config
|
| 288 |
+
self.embed_dim = config.hidden_size
|
| 289 |
+
self.num_heads = config.num_attention_heads
|
| 290 |
+
self.head_dim = self.embed_dim // self.num_heads
|
| 291 |
+
self.scale = self.head_dim**-0.5
|
| 292 |
+
self.dropout = config.attention_dropout
|
| 293 |
+
self.is_causal = False
|
| 294 |
+
|
| 295 |
+
self.k_proj = nn.Linear(self.embed_dim, self.embed_dim)
|
| 296 |
+
self.v_proj = nn.Linear(self.embed_dim, self.embed_dim)
|
| 297 |
+
self.q_proj = nn.Linear(self.embed_dim, self.embed_dim)
|
| 298 |
+
self.out_proj = nn.Linear(self.embed_dim, self.embed_dim)
|
| 299 |
+
|
| 300 |
+
def forward(
|
| 301 |
+
self,
|
| 302 |
+
hidden_states: torch.Tensor,
|
| 303 |
+
attention_mask: torch.Tensor | None = None,
|
| 304 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 305 |
+
) -> tuple[torch.Tensor, torch.Tensor | None]:
|
| 306 |
+
"""Input shape: Batch x Time x Channel"""
|
| 307 |
+
|
| 308 |
+
batch_size, seq_length, embed_dim = hidden_states.shape
|
| 309 |
+
|
| 310 |
+
queries = self.q_proj(hidden_states)
|
| 311 |
+
keys = self.k_proj(hidden_states)
|
| 312 |
+
values = self.v_proj(hidden_states)
|
| 313 |
+
|
| 314 |
+
queries = queries.view(batch_size, seq_length, -1, self.head_dim).transpose(1, 2)
|
| 315 |
+
keys = keys.view(batch_size, seq_length, -1, self.head_dim).transpose(1, 2)
|
| 316 |
+
values = values.view(batch_size, seq_length, -1, self.head_dim).transpose(1, 2)
|
| 317 |
+
|
| 318 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 319 |
+
self.config._attn_implementation, eager_attention_forward
|
| 320 |
+
)
|
| 321 |
+
|
| 322 |
+
attn_output, attn_weights = attention_interface(
|
| 323 |
+
self,
|
| 324 |
+
queries,
|
| 325 |
+
keys,
|
| 326 |
+
values,
|
| 327 |
+
attention_mask,
|
| 328 |
+
scaling=self.scale,
|
| 329 |
+
dropout=0.0 if not self.training else self.dropout,
|
| 330 |
+
**kwargs,
|
| 331 |
+
)
|
| 332 |
+
|
| 333 |
+
attn_output = attn_output.reshape(batch_size, seq_length, -1).contiguous()
|
| 334 |
+
attn_output = self.out_proj(attn_output)
|
| 335 |
+
|
| 336 |
+
return attn_output, attn_weights
|
| 337 |
+
|
| 338 |
+
|
| 339 |
+
class CLIPMLP(nn.Module):
|
| 340 |
+
def __init__(self, config):
|
| 341 |
+
super().__init__()
|
| 342 |
+
self.config = config
|
| 343 |
+
self.activation_fn = ACT2FN[config.hidden_act]
|
| 344 |
+
self.fc1 = nn.Linear(config.hidden_size, config.intermediate_size)
|
| 345 |
+
self.fc2 = nn.Linear(config.intermediate_size, config.hidden_size)
|
| 346 |
+
|
| 347 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 348 |
+
hidden_states = self.fc1(hidden_states)
|
| 349 |
+
hidden_states = self.activation_fn(hidden_states)
|
| 350 |
+
hidden_states = self.fc2(hidden_states)
|
| 351 |
+
return hidden_states
|
| 352 |
+
|
| 353 |
+
|
| 354 |
+
class CLIPEncoderLayer(GradientCheckpointingLayer):
|
| 355 |
+
def __init__(self, config: CLIPVisionConfig | CLIPTextConfig):
|
| 356 |
+
super().__init__()
|
| 357 |
+
self.embed_dim = config.hidden_size
|
| 358 |
+
self.self_attn = CLIPAttention(config)
|
| 359 |
+
self.layer_norm1 = nn.LayerNorm(self.embed_dim, eps=config.layer_norm_eps)
|
| 360 |
+
self.mlp = CLIPMLP(config)
|
| 361 |
+
self.layer_norm2 = nn.LayerNorm(self.embed_dim, eps=config.layer_norm_eps)
|
| 362 |
+
|
| 363 |
+
def forward(
|
| 364 |
+
self,
|
| 365 |
+
hidden_states: torch.Tensor,
|
| 366 |
+
attention_mask: torch.Tensor,
|
| 367 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 368 |
+
) -> torch.FloatTensor:
|
| 369 |
+
residual = hidden_states
|
| 370 |
+
|
| 371 |
+
hidden_states = self.layer_norm1(hidden_states)
|
| 372 |
+
hidden_states, _ = self.self_attn(
|
| 373 |
+
hidden_states=hidden_states,
|
| 374 |
+
attention_mask=attention_mask,
|
| 375 |
+
**kwargs,
|
| 376 |
+
)
|
| 377 |
+
hidden_states = residual + hidden_states
|
| 378 |
+
|
| 379 |
+
residual = hidden_states
|
| 380 |
+
hidden_states = self.layer_norm2(hidden_states)
|
| 381 |
+
hidden_states = self.mlp(hidden_states)
|
| 382 |
+
hidden_states = residual + hidden_states
|
| 383 |
+
|
| 384 |
+
return hidden_states
|
| 385 |
+
|
| 386 |
+
|
| 387 |
+
@auto_docstring
|
| 388 |
+
class CLIPPreTrainedModel(PreTrainedModel):
|
| 389 |
+
config: CLIPConfig
|
| 390 |
+
base_model_prefix = "clip"
|
| 391 |
+
input_modalities = ("image", "text")
|
| 392 |
+
supports_gradient_checkpointing = True
|
| 393 |
+
_supports_sdpa = True
|
| 394 |
+
_supports_flash_attn = True
|
| 395 |
+
_supports_flex_attn = True
|
| 396 |
+
_supports_attention_backend = True
|
| 397 |
+
_can_record_outputs = {
|
| 398 |
+
"hidden_states": CLIPEncoderLayer,
|
| 399 |
+
"attentions": CLIPAttention,
|
| 400 |
+
}
|
| 401 |
+
|
| 402 |
+
@torch.no_grad()
|
| 403 |
+
def _init_weights(self, module):
|
| 404 |
+
"""Initialize the weights"""
|
| 405 |
+
factor = self.config.initializer_factor
|
| 406 |
+
if isinstance(module, CLIPTextEmbeddings):
|
| 407 |
+
init.normal_(module.token_embedding.weight, mean=0.0, std=factor * 0.02)
|
| 408 |
+
init.normal_(module.position_embedding.weight, mean=0.0, std=factor * 0.02)
|
| 409 |
+
init.copy_(module.position_ids, torch.arange(module.position_ids.shape[-1]).expand((1, -1)))
|
| 410 |
+
elif isinstance(module, CLIPVisionEmbeddings):
|
| 411 |
+
factor = self.config.initializer_factor
|
| 412 |
+
init.normal_(module.class_embedding, mean=0.0, std=module.embed_dim**-0.5 * factor)
|
| 413 |
+
init.normal_(module.patch_embedding.weight, std=module.config.initializer_range * factor)
|
| 414 |
+
init.normal_(module.position_embedding.weight, std=module.config.initializer_range * factor)
|
| 415 |
+
init.copy_(module.position_ids, torch.arange(module.num_positions).expand((1, -1)))
|
| 416 |
+
elif isinstance(module, CLIPAttention):
|
| 417 |
+
factor = self.config.initializer_factor
|
| 418 |
+
in_proj_std = (module.embed_dim**-0.5) * ((2 * module.config.num_hidden_layers) ** -0.5) * factor
|
| 419 |
+
out_proj_std = (module.embed_dim**-0.5) * factor
|
| 420 |
+
init.normal_(module.q_proj.weight, std=in_proj_std)
|
| 421 |
+
init.normal_(module.k_proj.weight, std=in_proj_std)
|
| 422 |
+
init.normal_(module.v_proj.weight, std=in_proj_std)
|
| 423 |
+
init.normal_(module.out_proj.weight, std=out_proj_std)
|
| 424 |
+
elif isinstance(module, CLIPMLP):
|
| 425 |
+
factor = self.config.initializer_factor
|
| 426 |
+
in_proj_std = (module.config.hidden_size**-0.5) * ((2 * module.config.num_hidden_layers) ** -0.5) * factor
|
| 427 |
+
fc_std = (2 * module.config.hidden_size) ** -0.5 * factor
|
| 428 |
+
init.normal_(module.fc1.weight, std=fc_std)
|
| 429 |
+
init.normal_(module.fc2.weight, std=in_proj_std)
|
| 430 |
+
elif isinstance(module, CLIPModel):
|
| 431 |
+
init.normal_(
|
| 432 |
+
module.text_projection.weight,
|
| 433 |
+
std=module.text_embed_dim**-0.5 * self.config.initializer_factor,
|
| 434 |
+
)
|
| 435 |
+
init.normal_(
|
| 436 |
+
module.visual_projection.weight,
|
| 437 |
+
std=module.vision_embed_dim**-0.5 * self.config.initializer_factor,
|
| 438 |
+
)
|
| 439 |
+
elif isinstance(module, CLIPVisionModelWithProjection):
|
| 440 |
+
init.normal_(
|
| 441 |
+
module.visual_projection.weight,
|
| 442 |
+
std=self.config.hidden_size**-0.5 * self.config.initializer_factor,
|
| 443 |
+
)
|
| 444 |
+
elif isinstance(module, CLIPTextModelWithProjection):
|
| 445 |
+
init.normal_(
|
| 446 |
+
module.text_projection.weight,
|
| 447 |
+
std=self.config.hidden_size**-0.5 * self.config.initializer_factor,
|
| 448 |
+
)
|
| 449 |
+
elif isinstance(module, CLIPForImageClassification):
|
| 450 |
+
init.normal_(
|
| 451 |
+
module.classifier.weight,
|
| 452 |
+
std=self.config.vision_config.hidden_size**-0.5 * self.config.initializer_factor,
|
| 453 |
+
)
|
| 454 |
+
|
| 455 |
+
if isinstance(module, nn.LayerNorm):
|
| 456 |
+
init.zeros_(module.bias)
|
| 457 |
+
init.ones_(module.weight)
|
| 458 |
+
if isinstance(module, nn.Linear) and module.bias is not None:
|
| 459 |
+
init.zeros_(module.bias)
|
| 460 |
+
|
| 461 |
+
|
| 462 |
+
class CLIPEncoder(nn.Module):
|
| 463 |
+
"""
|
| 464 |
+
Transformer encoder consisting of `config.num_hidden_layers` self attention layers. Each layer is a
|
| 465 |
+
[`CLIPEncoderLayer`].
|
| 466 |
+
|
| 467 |
+
Args:
|
| 468 |
+
config: CLIPConfig
|
| 469 |
+
"""
|
| 470 |
+
|
| 471 |
+
def __init__(self, config: CLIPConfig):
|
| 472 |
+
super().__init__()
|
| 473 |
+
self.config = config
|
| 474 |
+
self.layers = nn.ModuleList([CLIPEncoderLayer(config) for _ in range(config.num_hidden_layers)])
|
| 475 |
+
self.gradient_checkpointing = False
|
| 476 |
+
|
| 477 |
+
def forward(
|
| 478 |
+
self,
|
| 479 |
+
inputs_embeds,
|
| 480 |
+
attention_mask: torch.Tensor | None = None,
|
| 481 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 482 |
+
) -> BaseModelOutput:
|
| 483 |
+
r"""
|
| 484 |
+
Args:
|
| 485 |
+
inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
|
| 486 |
+
Optionally, instead of passing `input_ids` you can choose to directly pass an embedded representation.
|
| 487 |
+
This is useful if you want more control over how to convert `input_ids` indices into associated vectors
|
| 488 |
+
than the model's internal embedding lookup matrix.
|
| 489 |
+
attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 490 |
+
Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
|
| 491 |
+
|
| 492 |
+
- 1 for tokens that are **not masked**,
|
| 493 |
+
- 0 for tokens that are **masked**.
|
| 494 |
+
|
| 495 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 496 |
+
"""
|
| 497 |
+
hidden_states = inputs_embeds
|
| 498 |
+
for encoder_layer in self.layers:
|
| 499 |
+
hidden_states = encoder_layer(
|
| 500 |
+
hidden_states,
|
| 501 |
+
attention_mask,
|
| 502 |
+
**kwargs,
|
| 503 |
+
)
|
| 504 |
+
|
| 505 |
+
return BaseModelOutput(
|
| 506 |
+
last_hidden_state=hidden_states,
|
| 507 |
+
)
|
| 508 |
+
|
| 509 |
+
|
| 510 |
+
class CLIPTextTransformer(CLIPPreTrainedModel):
|
| 511 |
+
config: CLIPTextConfig
|
| 512 |
+
input_modalities = ("text",)
|
| 513 |
+
|
| 514 |
+
_no_split_modules = ["CLIPTextEmbeddings", "CLIPEncoderLayer"]
|
| 515 |
+
|
| 516 |
+
def __init__(self, config: CLIPTextConfig):
|
| 517 |
+
super().__init__(config)
|
| 518 |
+
self.config = config
|
| 519 |
+
embed_dim = config.hidden_size
|
| 520 |
+
self.embeddings = CLIPTextEmbeddings(config)
|
| 521 |
+
self.encoder = CLIPEncoder(config)
|
| 522 |
+
self.final_layer_norm = nn.LayerNorm(embed_dim, eps=config.layer_norm_eps)
|
| 523 |
+
|
| 524 |
+
# For `pooled_output` computation
|
| 525 |
+
self.eos_token_id = config.eos_token_id
|
| 526 |
+
self.post_init()
|
| 527 |
+
|
| 528 |
+
@merge_with_config_defaults
|
| 529 |
+
@capture_outputs(tie_last_hidden_states=False)
|
| 530 |
+
@auto_docstring
|
| 531 |
+
def forward(
|
| 532 |
+
self,
|
| 533 |
+
input_ids: torch.Tensor | None = None,
|
| 534 |
+
attention_mask: torch.Tensor | None = None,
|
| 535 |
+
position_ids: torch.Tensor | None = None,
|
| 536 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 537 |
+
) -> BaseModelOutputWithPooling:
|
| 538 |
+
if input_ids is None:
|
| 539 |
+
raise ValueError("You have to specify input_ids")
|
| 540 |
+
|
| 541 |
+
input_shape = input_ids.size()
|
| 542 |
+
input_ids = input_ids.view(-1, input_shape[-1])
|
| 543 |
+
|
| 544 |
+
hidden_states = self.embeddings(input_ids=input_ids, position_ids=position_ids)
|
| 545 |
+
|
| 546 |
+
attention_mask = create_causal_mask(
|
| 547 |
+
config=self.config,
|
| 548 |
+
inputs_embeds=hidden_states,
|
| 549 |
+
attention_mask=attention_mask,
|
| 550 |
+
past_key_values=None,
|
| 551 |
+
)
|
| 552 |
+
|
| 553 |
+
kwargs.pop("is_causal", None)
|
| 554 |
+
encoder_outputs: BaseModelOutput = self.encoder(
|
| 555 |
+
inputs_embeds=hidden_states,
|
| 556 |
+
attention_mask=attention_mask,
|
| 557 |
+
is_causal=True,
|
| 558 |
+
**kwargs,
|
| 559 |
+
)
|
| 560 |
+
|
| 561 |
+
last_hidden_state = encoder_outputs.last_hidden_state
|
| 562 |
+
last_hidden_state = self.final_layer_norm(last_hidden_state)
|
| 563 |
+
|
| 564 |
+
if self.eos_token_id == 2:
|
| 565 |
+
# The `eos_token_id` was incorrect before PR #24773: Let's keep what have been done here.
|
| 566 |
+
# A CLIP model with such `eos_token_id` in the config can't work correctly with extra new tokens added
|
| 567 |
+
# ------------------------------------------------------------
|
| 568 |
+
# text_embeds.shape = [batch_size, sequence_length, transformer.width]
|
| 569 |
+
# take features from the eot embedding (eot_token is the highest number in each sequence)
|
| 570 |
+
# casting to torch.int for onnx compatibility: argmax doesn't support int64 inputs with opset 14
|
| 571 |
+
pooled_output = last_hidden_state[
|
| 572 |
+
torch.arange(last_hidden_state.shape[0], device=last_hidden_state.device),
|
| 573 |
+
input_ids.to(dtype=torch.int, device=last_hidden_state.device).argmax(dim=-1),
|
| 574 |
+
]
|
| 575 |
+
else:
|
| 576 |
+
# The config gets updated `eos_token_id` from PR #24773 (so the use of extra new tokens is possible)
|
| 577 |
+
pooled_output = last_hidden_state[
|
| 578 |
+
torch.arange(last_hidden_state.shape[0], device=last_hidden_state.device),
|
| 579 |
+
# We need to get the first position of `eos_token_id` value (`pad_token_ids` might equal to `eos_token_id`)
|
| 580 |
+
# Note: we assume each sequence (along batch dim.) contains an `eos_token_id` (e.g. prepared by the tokenizer)
|
| 581 |
+
(input_ids.to(dtype=torch.int, device=last_hidden_state.device) == self.eos_token_id)
|
| 582 |
+
.int()
|
| 583 |
+
.argmax(dim=-1),
|
| 584 |
+
]
|
| 585 |
+
|
| 586 |
+
return BaseModelOutputWithPooling(
|
| 587 |
+
last_hidden_state=last_hidden_state,
|
| 588 |
+
pooler_output=pooled_output,
|
| 589 |
+
)
|
| 590 |
+
|
| 591 |
+
|
| 592 |
+
@auto_docstring(
|
| 593 |
+
custom_intro="""
|
| 594 |
+
The text model from CLIP without any head or projection on top.
|
| 595 |
+
"""
|
| 596 |
+
)
|
| 597 |
+
class CLIPTextModel(CLIPPreTrainedModel):
|
| 598 |
+
config: CLIPTextConfig
|
| 599 |
+
input_modalities = ("text",)
|
| 600 |
+
|
| 601 |
+
_no_split_modules = ["CLIPTextEmbeddings", "CLIPEncoderLayer"]
|
| 602 |
+
|
| 603 |
+
def __init__(self, config: CLIPTextConfig):
|
| 604 |
+
super().__init__(config)
|
| 605 |
+
self.text_model = CLIPTextTransformer(config)
|
| 606 |
+
# Initialize weights and apply final processing
|
| 607 |
+
self.post_init()
|
| 608 |
+
|
| 609 |
+
def get_input_embeddings(self) -> nn.Module:
|
| 610 |
+
return self.text_model.embeddings.token_embedding
|
| 611 |
+
|
| 612 |
+
def set_input_embeddings(self, value):
|
| 613 |
+
self.text_model.embeddings.token_embedding = value
|
| 614 |
+
|
| 615 |
+
@auto_docstring
|
| 616 |
+
def forward(
|
| 617 |
+
self,
|
| 618 |
+
input_ids: torch.Tensor | None = None,
|
| 619 |
+
attention_mask: torch.Tensor | None = None,
|
| 620 |
+
position_ids: torch.Tensor | None = None,
|
| 621 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 622 |
+
) -> BaseModelOutputWithPooling:
|
| 623 |
+
r"""
|
| 624 |
+
Examples:
|
| 625 |
+
|
| 626 |
+
```python
|
| 627 |
+
>>> from transformers import AutoTokenizer, CLIPTextModel
|
| 628 |
+
|
| 629 |
+
>>> model = CLIPTextModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 630 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
|
| 631 |
+
|
| 632 |
+
>>> inputs = tokenizer(["a photo of a cat", "a photo of a dog"], padding=True, return_tensors="pt")
|
| 633 |
+
|
| 634 |
+
>>> outputs = model(**inputs)
|
| 635 |
+
>>> last_hidden_state = outputs.last_hidden_state
|
| 636 |
+
>>> pooled_output = outputs.pooler_output # pooled (EOS token) states
|
| 637 |
+
```"""
|
| 638 |
+
|
| 639 |
+
return self.text_model(
|
| 640 |
+
input_ids=input_ids,
|
| 641 |
+
attention_mask=attention_mask,
|
| 642 |
+
position_ids=position_ids,
|
| 643 |
+
**kwargs,
|
| 644 |
+
)
|
| 645 |
+
|
| 646 |
+
|
| 647 |
+
class CLIPVisionTransformer(CLIPPreTrainedModel):
|
| 648 |
+
config: CLIPVisionConfig
|
| 649 |
+
main_input_name = "pixel_values"
|
| 650 |
+
input_modalities = ("image",)
|
| 651 |
+
_no_split_modules = ["CLIPEncoderLayer"]
|
| 652 |
+
|
| 653 |
+
def __init__(self, config: CLIPVisionConfig):
|
| 654 |
+
super().__init__(config)
|
| 655 |
+
self.config = config
|
| 656 |
+
embed_dim = config.hidden_size
|
| 657 |
+
|
| 658 |
+
self.embeddings = CLIPVisionEmbeddings(config)
|
| 659 |
+
self.pre_layrnorm = nn.LayerNorm(embed_dim, eps=config.layer_norm_eps)
|
| 660 |
+
self.encoder = CLIPEncoder(config)
|
| 661 |
+
self.post_layernorm = nn.LayerNorm(embed_dim, eps=config.layer_norm_eps)
|
| 662 |
+
self.post_init()
|
| 663 |
+
|
| 664 |
+
@merge_with_config_defaults
|
| 665 |
+
@capture_outputs(tie_last_hidden_states=False)
|
| 666 |
+
@auto_docstring
|
| 667 |
+
def forward(
|
| 668 |
+
self,
|
| 669 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 670 |
+
interpolate_pos_encoding: bool | None = False,
|
| 671 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 672 |
+
) -> BaseModelOutputWithPooling:
|
| 673 |
+
if pixel_values is None:
|
| 674 |
+
raise ValueError("You have to specify pixel_values")
|
| 675 |
+
|
| 676 |
+
hidden_states = self.embeddings(pixel_values, interpolate_pos_encoding=interpolate_pos_encoding)
|
| 677 |
+
hidden_states = self.pre_layrnorm(hidden_states)
|
| 678 |
+
|
| 679 |
+
encoder_outputs: BaseModelOutput = self.encoder(
|
| 680 |
+
inputs_embeds=hidden_states,
|
| 681 |
+
**kwargs,
|
| 682 |
+
)
|
| 683 |
+
|
| 684 |
+
last_hidden_state = encoder_outputs.last_hidden_state
|
| 685 |
+
pooled_output = last_hidden_state[:, 0, :]
|
| 686 |
+
pooled_output = self.post_layernorm(pooled_output)
|
| 687 |
+
|
| 688 |
+
return BaseModelOutputWithPooling(
|
| 689 |
+
last_hidden_state=last_hidden_state,
|
| 690 |
+
pooler_output=pooled_output,
|
| 691 |
+
)
|
| 692 |
+
|
| 693 |
+
|
| 694 |
+
@auto_docstring(
|
| 695 |
+
custom_intro="""
|
| 696 |
+
The vision model from CLIP without any head or projection on top.
|
| 697 |
+
"""
|
| 698 |
+
)
|
| 699 |
+
class CLIPVisionModel(CLIPPreTrainedModel):
|
| 700 |
+
config: CLIPVisionConfig
|
| 701 |
+
main_input_name = "pixel_values"
|
| 702 |
+
input_modalities = ("image",)
|
| 703 |
+
_no_split_modules = ["CLIPEncoderLayer"]
|
| 704 |
+
|
| 705 |
+
def __init__(self, config: CLIPVisionConfig):
|
| 706 |
+
super().__init__(config)
|
| 707 |
+
self.vision_model = CLIPVisionTransformer(config)
|
| 708 |
+
# Initialize weights and apply final processing
|
| 709 |
+
self.post_init()
|
| 710 |
+
|
| 711 |
+
def get_input_embeddings(self) -> nn.Module:
|
| 712 |
+
return self.vision_model.embeddings.patch_embedding
|
| 713 |
+
|
| 714 |
+
@auto_docstring
|
| 715 |
+
def forward(
|
| 716 |
+
self,
|
| 717 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 718 |
+
interpolate_pos_encoding: bool = False,
|
| 719 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 720 |
+
) -> BaseModelOutputWithPooling:
|
| 721 |
+
r"""
|
| 722 |
+
Example:
|
| 723 |
+
|
| 724 |
+
```python
|
| 725 |
+
>>> from PIL import Image
|
| 726 |
+
>>> import httpx
|
| 727 |
+
>>> from io import BytesIO
|
| 728 |
+
>>> from transformers import AutoProcessor, CLIPVisionModel
|
| 729 |
+
|
| 730 |
+
>>> model = CLIPVisionModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 731 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 732 |
+
|
| 733 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 734 |
+
>>> with httpx.stream("GET", url) as response:
|
| 735 |
+
... image = Image.open(BytesIO(response.read()))
|
| 736 |
+
|
| 737 |
+
>>> inputs = processor(images=image, return_tensors="pt")
|
| 738 |
+
|
| 739 |
+
>>> outputs = model(**inputs)
|
| 740 |
+
>>> last_hidden_state = outputs.last_hidden_state
|
| 741 |
+
>>> pooled_output = outputs.pooler_output # pooled CLS states
|
| 742 |
+
```"""
|
| 743 |
+
|
| 744 |
+
return self.vision_model(
|
| 745 |
+
pixel_values=pixel_values,
|
| 746 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 747 |
+
**kwargs,
|
| 748 |
+
)
|
| 749 |
+
|
| 750 |
+
|
| 751 |
+
@auto_docstring
|
| 752 |
+
class CLIPModel(CLIPPreTrainedModel):
|
| 753 |
+
config: CLIPConfig
|
| 754 |
+
_no_split_modules = ["CLIPTextEmbeddings", "CLIPEncoderLayer", "CLIPVisionEmbeddings"]
|
| 755 |
+
|
| 756 |
+
def __init__(self, config: CLIPConfig):
|
| 757 |
+
super().__init__(config)
|
| 758 |
+
|
| 759 |
+
if not isinstance(config.text_config, CLIPTextConfig):
|
| 760 |
+
raise TypeError(
|
| 761 |
+
"config.text_config is expected to be of type CLIPTextConfig but is of type"
|
| 762 |
+
f" {type(config.text_config)}."
|
| 763 |
+
)
|
| 764 |
+
|
| 765 |
+
if not isinstance(config.vision_config, CLIPVisionConfig):
|
| 766 |
+
raise TypeError(
|
| 767 |
+
"config.vision_config is expected to be of type CLIPVisionConfig but is of type"
|
| 768 |
+
f" {type(config.vision_config)}."
|
| 769 |
+
)
|
| 770 |
+
|
| 771 |
+
text_config = config.text_config
|
| 772 |
+
vision_config = config.vision_config
|
| 773 |
+
|
| 774 |
+
self.projection_dim = config.projection_dim
|
| 775 |
+
self.text_embed_dim = text_config.hidden_size
|
| 776 |
+
self.vision_embed_dim = vision_config.hidden_size
|
| 777 |
+
|
| 778 |
+
text_model = CLIPTextModel._from_config(text_config)
|
| 779 |
+
self.text_model = text_model.text_model
|
| 780 |
+
|
| 781 |
+
vision_model = CLIPVisionModel._from_config(vision_config)
|
| 782 |
+
self.vision_model = vision_model.vision_model
|
| 783 |
+
|
| 784 |
+
self.visual_projection = nn.Linear(self.vision_embed_dim, self.projection_dim, bias=False)
|
| 785 |
+
self.text_projection = nn.Linear(self.text_embed_dim, self.projection_dim, bias=False)
|
| 786 |
+
self.logit_scale = nn.Parameter(torch.tensor(self.config.logit_scale_init_value))
|
| 787 |
+
|
| 788 |
+
# Initialize weights and apply final processing
|
| 789 |
+
self.post_init()
|
| 790 |
+
|
| 791 |
+
@can_return_tuple
|
| 792 |
+
@auto_docstring
|
| 793 |
+
def get_text_features(
|
| 794 |
+
self,
|
| 795 |
+
input_ids: torch.Tensor,
|
| 796 |
+
attention_mask: torch.Tensor | None = None,
|
| 797 |
+
position_ids: torch.Tensor | None = None,
|
| 798 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 799 |
+
) -> tuple | BaseModelOutputWithPooling:
|
| 800 |
+
r"""
|
| 801 |
+
Examples:
|
| 802 |
+
|
| 803 |
+
```python
|
| 804 |
+
>>> import torch
|
| 805 |
+
>>> from transformers import AutoTokenizer, CLIPModel
|
| 806 |
+
|
| 807 |
+
>>> model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 808 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
|
| 809 |
+
|
| 810 |
+
>>> inputs = tokenizer(["a photo of a cat", "a photo of a dog"], padding=True, return_tensors="pt")
|
| 811 |
+
|
| 812 |
+
>>> with torch.inference_mode():
|
| 813 |
+
... text_features = model.get_text_features(**inputs)
|
| 814 |
+
```"""
|
| 815 |
+
text_outputs: BaseModelOutputWithPooling = self.text_model(
|
| 816 |
+
input_ids=input_ids,
|
| 817 |
+
attention_mask=attention_mask,
|
| 818 |
+
position_ids=position_ids,
|
| 819 |
+
return_dict=True,
|
| 820 |
+
**kwargs,
|
| 821 |
+
)
|
| 822 |
+
pooled_output = text_outputs.pooler_output
|
| 823 |
+
text_outputs.pooler_output = self.text_projection(pooled_output)
|
| 824 |
+
|
| 825 |
+
return text_outputs
|
| 826 |
+
|
| 827 |
+
@can_return_tuple
|
| 828 |
+
@auto_docstring
|
| 829 |
+
def get_image_features(
|
| 830 |
+
self,
|
| 831 |
+
pixel_values: torch.FloatTensor,
|
| 832 |
+
interpolate_pos_encoding: bool = False,
|
| 833 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 834 |
+
) -> tuple | BaseModelOutputWithPooling:
|
| 835 |
+
r"""
|
| 836 |
+
Examples:
|
| 837 |
+
|
| 838 |
+
```python
|
| 839 |
+
>>> import torch
|
| 840 |
+
>>> from transformers import AutoProcessor, CLIPModel
|
| 841 |
+
>>> from transformers.image_utils import load_image
|
| 842 |
+
|
| 843 |
+
>>> model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 844 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 845 |
+
|
| 846 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 847 |
+
>>> image = load_image(url)
|
| 848 |
+
|
| 849 |
+
>>> inputs = processor(images=image, return_tensors="pt")
|
| 850 |
+
|
| 851 |
+
>>> with torch.inference_mode():
|
| 852 |
+
... image_features = model.get_image_features(**inputs)
|
| 853 |
+
```"""
|
| 854 |
+
vision_outputs: BaseModelOutputWithPooling = self.vision_model(
|
| 855 |
+
pixel_values=pixel_values,
|
| 856 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 857 |
+
return_dict=True,
|
| 858 |
+
**kwargs,
|
| 859 |
+
)
|
| 860 |
+
pooled_output = vision_outputs.pooler_output
|
| 861 |
+
vision_outputs.pooler_output = self.visual_projection(pooled_output)
|
| 862 |
+
|
| 863 |
+
return vision_outputs
|
| 864 |
+
|
| 865 |
+
@can_return_tuple
|
| 866 |
+
@auto_docstring
|
| 867 |
+
def forward(
|
| 868 |
+
self,
|
| 869 |
+
input_ids: torch.LongTensor | None = None,
|
| 870 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 871 |
+
attention_mask: torch.Tensor | None = None,
|
| 872 |
+
position_ids: torch.LongTensor | None = None,
|
| 873 |
+
return_loss: bool | None = None,
|
| 874 |
+
interpolate_pos_encoding: bool = False,
|
| 875 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 876 |
+
) -> CLIPOutput:
|
| 877 |
+
r"""
|
| 878 |
+
return_loss (`bool`, *optional*):
|
| 879 |
+
Whether or not to return the contrastive loss.
|
| 880 |
+
|
| 881 |
+
Examples:
|
| 882 |
+
|
| 883 |
+
```python
|
| 884 |
+
>>> import torch
|
| 885 |
+
>>> from transformers import AutoProcessor, CLIPModel
|
| 886 |
+
>>> from transformers.image_utils import load_image
|
| 887 |
+
|
| 888 |
+
>>> model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
|
| 889 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 890 |
+
|
| 891 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 892 |
+
>>> image = load_image(url)
|
| 893 |
+
|
| 894 |
+
>>> inputs = processor(
|
| 895 |
+
... text=["a photo of a cat", "a photo of a dog"], images=image, return_tensors="pt", padding=True
|
| 896 |
+
... )
|
| 897 |
+
|
| 898 |
+
>>> with torch.inference_mode():
|
| 899 |
+
... outputs = model(**inputs)
|
| 900 |
+
>>> logits_per_image = outputs.logits_per_image # this is the image-text similarity score
|
| 901 |
+
>>> probs = logits_per_image.softmax(dim=1) # we can take the softmax to get the label probabilities
|
| 902 |
+
```"""
|
| 903 |
+
vision_outputs: BaseModelOutputWithPooling = self.vision_model(
|
| 904 |
+
pixel_values=pixel_values,
|
| 905 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 906 |
+
**kwargs,
|
| 907 |
+
)
|
| 908 |
+
|
| 909 |
+
text_outputs: BaseModelOutputWithPooling = self.text_model(
|
| 910 |
+
input_ids=input_ids,
|
| 911 |
+
attention_mask=attention_mask,
|
| 912 |
+
position_ids=position_ids,
|
| 913 |
+
**kwargs,
|
| 914 |
+
)
|
| 915 |
+
|
| 916 |
+
image_embeds = vision_outputs.pooler_output
|
| 917 |
+
image_embeds = self.visual_projection(image_embeds)
|
| 918 |
+
|
| 919 |
+
text_embeds = text_outputs.pooler_output
|
| 920 |
+
text_embeds = self.text_projection(text_embeds)
|
| 921 |
+
|
| 922 |
+
# normalized features
|
| 923 |
+
image_embeds = image_embeds / _get_vector_norm(image_embeds)
|
| 924 |
+
text_embeds = text_embeds / _get_vector_norm(text_embeds)
|
| 925 |
+
|
| 926 |
+
# cosine similarity as logits
|
| 927 |
+
logits_per_text = torch.matmul(text_embeds, image_embeds.t().to(text_embeds.device))
|
| 928 |
+
logits_per_text = logits_per_text * self.logit_scale.exp().to(text_embeds.device)
|
| 929 |
+
|
| 930 |
+
logits_per_image = logits_per_text.t()
|
| 931 |
+
|
| 932 |
+
loss = None
|
| 933 |
+
if return_loss:
|
| 934 |
+
loss = clip_loss(logits_per_text)
|
| 935 |
+
|
| 936 |
+
return CLIPOutput(
|
| 937 |
+
loss=loss,
|
| 938 |
+
logits_per_image=logits_per_image,
|
| 939 |
+
logits_per_text=logits_per_text,
|
| 940 |
+
text_embeds=text_embeds,
|
| 941 |
+
image_embeds=image_embeds,
|
| 942 |
+
text_model_output=text_outputs,
|
| 943 |
+
vision_model_output=vision_outputs,
|
| 944 |
+
)
|
| 945 |
+
|
| 946 |
+
|
| 947 |
+
@auto_docstring
|
| 948 |
+
class CLIPTextModelWithProjection(CLIPPreTrainedModel):
|
| 949 |
+
config: CLIPTextConfig
|
| 950 |
+
input_modalities = ("text",)
|
| 951 |
+
|
| 952 |
+
_no_split_modules = ["CLIPTextEmbeddings", "CLIPEncoderLayer"]
|
| 953 |
+
|
| 954 |
+
def __init__(self, config: CLIPTextConfig):
|
| 955 |
+
super().__init__(config)
|
| 956 |
+
|
| 957 |
+
text_model = CLIPTextModel._from_config(config)
|
| 958 |
+
self.text_model = text_model.text_model
|
| 959 |
+
|
| 960 |
+
self.text_projection = nn.Linear(config.hidden_size, config.projection_dim, bias=False)
|
| 961 |
+
|
| 962 |
+
# Initialize weights and apply final processing
|
| 963 |
+
self.post_init()
|
| 964 |
+
|
| 965 |
+
def get_input_embeddings(self) -> nn.Module:
|
| 966 |
+
return self.text_model.embeddings.token_embedding
|
| 967 |
+
|
| 968 |
+
def set_input_embeddings(self, value):
|
| 969 |
+
self.text_model.embeddings.token_embedding = value
|
| 970 |
+
|
| 971 |
+
@can_return_tuple
|
| 972 |
+
@auto_docstring
|
| 973 |
+
def forward(
|
| 974 |
+
self,
|
| 975 |
+
input_ids: torch.Tensor | None = None,
|
| 976 |
+
attention_mask: torch.Tensor | None = None,
|
| 977 |
+
position_ids: torch.Tensor | None = None,
|
| 978 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 979 |
+
) -> CLIPTextModelOutput:
|
| 980 |
+
r"""
|
| 981 |
+
Examples:
|
| 982 |
+
|
| 983 |
+
```python
|
| 984 |
+
>>> import torch
|
| 985 |
+
>>> from transformers import AutoTokenizer, CLIPTextModelWithProjection
|
| 986 |
+
|
| 987 |
+
>>> model = CLIPTextModelWithProjection.from_pretrained("openai/clip-vit-base-patch32")
|
| 988 |
+
>>> tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
|
| 989 |
+
|
| 990 |
+
>>> inputs = tokenizer(["a photo of a cat", "a photo of a dog"], padding=True, return_tensors="pt")
|
| 991 |
+
|
| 992 |
+
>>> with torch.inference_mode():
|
| 993 |
+
... outputs = model(**inputs)
|
| 994 |
+
>>> text_embeds = outputs.text_embeds
|
| 995 |
+
```"""
|
| 996 |
+
|
| 997 |
+
text_outputs: BaseModelOutputWithPooling = self.text_model(
|
| 998 |
+
input_ids=input_ids,
|
| 999 |
+
attention_mask=attention_mask,
|
| 1000 |
+
position_ids=position_ids,
|
| 1001 |
+
**kwargs,
|
| 1002 |
+
)
|
| 1003 |
+
pooled_output = text_outputs.pooler_output
|
| 1004 |
+
text_embeds = self.text_projection(pooled_output)
|
| 1005 |
+
|
| 1006 |
+
return CLIPTextModelOutput(
|
| 1007 |
+
text_embeds=text_embeds,
|
| 1008 |
+
last_hidden_state=text_outputs.last_hidden_state,
|
| 1009 |
+
hidden_states=text_outputs.hidden_states,
|
| 1010 |
+
attentions=text_outputs.attentions,
|
| 1011 |
+
)
|
| 1012 |
+
|
| 1013 |
+
|
| 1014 |
+
@auto_docstring
|
| 1015 |
+
class CLIPVisionModelWithProjection(CLIPPreTrainedModel):
|
| 1016 |
+
config: CLIPVisionConfig
|
| 1017 |
+
main_input_name = "pixel_values"
|
| 1018 |
+
input_modalities = ("image",)
|
| 1019 |
+
|
| 1020 |
+
def __init__(self, config: CLIPVisionConfig):
|
| 1021 |
+
super().__init__(config)
|
| 1022 |
+
|
| 1023 |
+
vision_model = CLIPVisionModel._from_config(config)
|
| 1024 |
+
self.vision_model = vision_model.vision_model
|
| 1025 |
+
|
| 1026 |
+
self.visual_projection = nn.Linear(config.hidden_size, config.projection_dim, bias=False)
|
| 1027 |
+
|
| 1028 |
+
# Initialize weights and apply final processing
|
| 1029 |
+
self.post_init()
|
| 1030 |
+
|
| 1031 |
+
def get_input_embeddings(self) -> nn.Module:
|
| 1032 |
+
return self.vision_model.embeddings.patch_embedding
|
| 1033 |
+
|
| 1034 |
+
@can_return_tuple
|
| 1035 |
+
@auto_docstring
|
| 1036 |
+
def forward(
|
| 1037 |
+
self,
|
| 1038 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 1039 |
+
interpolate_pos_encoding: bool = False,
|
| 1040 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1041 |
+
) -> CLIPVisionModelOutput:
|
| 1042 |
+
r"""
|
| 1043 |
+
Examples:
|
| 1044 |
+
|
| 1045 |
+
```python
|
| 1046 |
+
>>> import torch
|
| 1047 |
+
>>> from transformers import AutoProcessor, CLIPVisionModelWithProjection
|
| 1048 |
+
>>> from transformers.image_utils import load_image
|
| 1049 |
+
|
| 1050 |
+
>>> model = CLIPVisionModelWithProjection.from_pretrained("openai/clip-vit-base-patch32")
|
| 1051 |
+
>>> processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
| 1052 |
+
|
| 1053 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 1054 |
+
>>> image = load_image(url)
|
| 1055 |
+
|
| 1056 |
+
>>> inputs = processor(images=image, return_tensors="pt")
|
| 1057 |
+
|
| 1058 |
+
>>> with torch.inference_mode():
|
| 1059 |
+
... outputs = model(**inputs)
|
| 1060 |
+
>>> image_embeds = outputs.image_embeds
|
| 1061 |
+
```"""
|
| 1062 |
+
|
| 1063 |
+
vision_outputs: BaseModelOutputWithPooling = self.vision_model(
|
| 1064 |
+
pixel_values=pixel_values,
|
| 1065 |
+
interpolate_pos_encoding=interpolate_pos_encoding,
|
| 1066 |
+
**kwargs,
|
| 1067 |
+
)
|
| 1068 |
+
pooled_output = vision_outputs.pooler_output
|
| 1069 |
+
image_embeds = self.visual_projection(pooled_output)
|
| 1070 |
+
|
| 1071 |
+
return CLIPVisionModelOutput(
|
| 1072 |
+
image_embeds=image_embeds,
|
| 1073 |
+
last_hidden_state=vision_outputs.last_hidden_state,
|
| 1074 |
+
hidden_states=vision_outputs.hidden_states,
|
| 1075 |
+
attentions=vision_outputs.attentions,
|
| 1076 |
+
)
|
| 1077 |
+
|
| 1078 |
+
|
| 1079 |
+
@auto_docstring(
|
| 1080 |
+
custom_intro="""
|
| 1081 |
+
CLIP vision encoder with an image classification head on top (a linear layer on top of the pooled final hidden states of
|
| 1082 |
+
the patch tokens) e.g. for ImageNet.
|
| 1083 |
+
"""
|
| 1084 |
+
)
|
| 1085 |
+
class CLIPForImageClassification(CLIPPreTrainedModel):
|
| 1086 |
+
main_input_name = "pixel_values"
|
| 1087 |
+
input_modalities = ("image",)
|
| 1088 |
+
|
| 1089 |
+
def __init__(self, config: CLIPConfig) -> None:
|
| 1090 |
+
super().__init__(config)
|
| 1091 |
+
|
| 1092 |
+
self.num_labels = config.num_labels
|
| 1093 |
+
vision_model = CLIPVisionModel._from_config(config.vision_config)
|
| 1094 |
+
self.vision_model = vision_model.vision_model
|
| 1095 |
+
|
| 1096 |
+
# Classifier head
|
| 1097 |
+
self.classifier = (
|
| 1098 |
+
nn.Linear(config.vision_config.hidden_size, config.num_labels) if config.num_labels > 0 else nn.Identity()
|
| 1099 |
+
)
|
| 1100 |
+
|
| 1101 |
+
# Initialize weights and apply final processing
|
| 1102 |
+
self.post_init()
|
| 1103 |
+
|
| 1104 |
+
@can_return_tuple
|
| 1105 |
+
@auto_docstring
|
| 1106 |
+
def forward(
|
| 1107 |
+
self,
|
| 1108 |
+
pixel_values: torch.Tensor | None = None,
|
| 1109 |
+
labels: torch.Tensor | None = None,
|
| 1110 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1111 |
+
) -> ImageClassifierOutput:
|
| 1112 |
+
r"""
|
| 1113 |
+
labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
|
| 1114 |
+
Labels for computing the image classification/regression loss. Indices should be in `[0, ...,
|
| 1115 |
+
config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If
|
| 1116 |
+
`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
| 1117 |
+
"""
|
| 1118 |
+
outputs: BaseModelOutputWithPooling = self.vision_model(
|
| 1119 |
+
pixel_values,
|
| 1120 |
+
**kwargs,
|
| 1121 |
+
)
|
| 1122 |
+
|
| 1123 |
+
sequence_output = outputs.last_hidden_state
|
| 1124 |
+
|
| 1125 |
+
sequence_output = torch.mean(sequence_output[:, 1:, :], dim=1)
|
| 1126 |
+
logits = self.classifier(sequence_output)
|
| 1127 |
+
|
| 1128 |
+
loss = None
|
| 1129 |
+
if labels is not None:
|
| 1130 |
+
loss = self.loss_function(labels, logits, self.config)
|
| 1131 |
+
|
| 1132 |
+
return ImageClassifierOutput(
|
| 1133 |
+
loss=loss,
|
| 1134 |
+
logits=logits,
|
| 1135 |
+
hidden_states=outputs.hidden_states,
|
| 1136 |
+
attentions=outputs.attentions,
|
| 1137 |
+
)
|
| 1138 |
+
|
| 1139 |
+
|
| 1140 |
+
__all__ = [
|
| 1141 |
+
"CLIPModel",
|
| 1142 |
+
"CLIPPreTrainedModel",
|
| 1143 |
+
"CLIPTextModel",
|
| 1144 |
+
"CLIPTextModelWithProjection",
|
| 1145 |
+
"CLIPVisionModel",
|
| 1146 |
+
"CLIPVisionModelWithProjection",
|
| 1147 |
+
"CLIPForImageClassification",
|
| 1148 |
+
]
|
third_party/transformers/src/transformers/models/clip/processing_clip.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2021 The HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""
|
| 15 |
+
Image/Text processor class for CLIP
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
from ...processing_utils import ProcessorMixin
|
| 19 |
+
from ...utils import auto_docstring
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
@auto_docstring
|
| 23 |
+
class CLIPProcessor(ProcessorMixin):
|
| 24 |
+
def __init__(self, image_processor=None, tokenizer=None, **kwargs):
|
| 25 |
+
super().__init__(image_processor, tokenizer)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
__all__ = ["CLIPProcessor"]
|
third_party/transformers/src/transformers/models/clip/tokenization_clip.py
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2021 The Open AI Team Authors and The HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Tokenization classes for CLIP."""
|
| 15 |
+
|
| 16 |
+
from tokenizers import Regex, Tokenizer, decoders, normalizers, pre_tokenizers, processors
|
| 17 |
+
from tokenizers.models import BPE
|
| 18 |
+
|
| 19 |
+
from ...tokenization_utils_tokenizers import TokenizersBackend
|
| 20 |
+
from ...utils import logging
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
logger = logging.get_logger(__name__)
|
| 24 |
+
|
| 25 |
+
VOCAB_FILES_NAMES = {"vocab_file": "vocab.json", "merges_file": "merges.txt", "tokenizer_file": "tokenizer.json"}
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
class CLIPTokenizer(TokenizersBackend):
|
| 29 |
+
"""
|
| 30 |
+
Construct a CLIP tokenizer (backed by HuggingFace's *tokenizers* library). Based on byte-level
|
| 31 |
+
Byte-Pair-Encoding.
|
| 32 |
+
|
| 33 |
+
This tokenizer inherits from [`TokenizersBackend`] which contains most of the main methods. Users should
|
| 34 |
+
refer to this superclass for more information regarding those methods.
|
| 35 |
+
|
| 36 |
+
Args:
|
| 37 |
+
vocab (`str`, `dict` or `list`, *optional*):
|
| 38 |
+
Vocabulary dict to use for the tokenizer.
|
| 39 |
+
merges (`str` or `list`, *optional*):
|
| 40 |
+
Merges list to use for the BPE tokenizer.
|
| 41 |
+
unk_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
|
| 42 |
+
The unknown token. A token that is not in the vocabulary cannot be converted to an ID and is set to be this
|
| 43 |
+
token instead.
|
| 44 |
+
bos_token (`str`, *optional*, defaults to `"<|startoftext|>"`):
|
| 45 |
+
The beginning of sequence token.
|
| 46 |
+
eos_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
|
| 47 |
+
The end of sequence token.
|
| 48 |
+
pad_token (`str`, *optional*, defaults to `"<|endoftext|>"`):
|
| 49 |
+
The token used for padding, for example when batching sequences of different lengths.
|
| 50 |
+
"""
|
| 51 |
+
|
| 52 |
+
vocab_files_names = VOCAB_FILES_NAMES
|
| 53 |
+
model_input_names = ["input_ids", "attention_mask"]
|
| 54 |
+
model = BPE
|
| 55 |
+
|
| 56 |
+
def __init__(
|
| 57 |
+
self,
|
| 58 |
+
vocab: str | dict[str, int] | None = None,
|
| 59 |
+
merges: str | list[str] | None = None,
|
| 60 |
+
unk_token: str = "<|endoftext|>",
|
| 61 |
+
bos_token: str = "<|startoftext|>",
|
| 62 |
+
eos_token: str = "<|endoftext|>",
|
| 63 |
+
pad_token: str = "<|endoftext|>",
|
| 64 |
+
**kwargs,
|
| 65 |
+
):
|
| 66 |
+
_vocab = (
|
| 67 |
+
vocab
|
| 68 |
+
if vocab is not None
|
| 69 |
+
else {
|
| 70 |
+
str(bos_token): 0,
|
| 71 |
+
str(eos_token): 1,
|
| 72 |
+
str(pad_token): 2,
|
| 73 |
+
}
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
+
self._merges = merges or []
|
| 77 |
+
|
| 78 |
+
self._tokenizer = Tokenizer(
|
| 79 |
+
BPE(
|
| 80 |
+
vocab=_vocab,
|
| 81 |
+
merges=self._merges,
|
| 82 |
+
dropout=None,
|
| 83 |
+
continuing_subword_prefix="",
|
| 84 |
+
end_of_word_suffix="</w>",
|
| 85 |
+
fuse_unk=False,
|
| 86 |
+
unk_token=str(unk_token),
|
| 87 |
+
)
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
self._tokenizer.normalizer = normalizers.Sequence(
|
| 91 |
+
[normalizers.NFC(), normalizers.Replace(Regex(r"\s+"), " "), normalizers.Lowercase()]
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
self._tokenizer.pre_tokenizer = pre_tokenizers.Sequence(
|
| 95 |
+
[
|
| 96 |
+
pre_tokenizers.Split(
|
| 97 |
+
Regex(
|
| 98 |
+
r"""<\|startoftext\|>|<\|endoftext\|>|'s|'t|'re|'ve|'m|'ll|'d|[\p{L}]+|[\p{N}]|[^\s\p{L}\p{N}]+"""
|
| 99 |
+
),
|
| 100 |
+
behavior="removed",
|
| 101 |
+
invert=True,
|
| 102 |
+
),
|
| 103 |
+
pre_tokenizers.ByteLevel(add_prefix_space=False),
|
| 104 |
+
]
|
| 105 |
+
)
|
| 106 |
+
|
| 107 |
+
self._tokenizer.decoder = decoders.ByteLevel()
|
| 108 |
+
|
| 109 |
+
super().__init__(
|
| 110 |
+
unk_token=unk_token,
|
| 111 |
+
bos_token=bos_token,
|
| 112 |
+
eos_token=eos_token,
|
| 113 |
+
pad_token=pad_token,
|
| 114 |
+
**kwargs,
|
| 115 |
+
)
|
| 116 |
+
|
| 117 |
+
self._tokenizer.post_processor = processors.RobertaProcessing(
|
| 118 |
+
sep=(str(eos_token), self.eos_token_id),
|
| 119 |
+
cls=(str(bos_token), self.bos_token_id),
|
| 120 |
+
add_prefix_space=False,
|
| 121 |
+
trim_offsets=False,
|
| 122 |
+
)
|
| 123 |
+
|
| 124 |
+
# Very ugly hack to enable padding to have a correct decoding see https://github.com/huggingface/tokenizers/issues/872
|
| 125 |
+
self._wrap_decode_method_backend_tokenizer()
|
| 126 |
+
|
| 127 |
+
def _wrap_decode_method_backend_tokenizer(self):
|
| 128 |
+
orig_decode_method = self.backend_tokenizer.decode
|
| 129 |
+
|
| 130 |
+
## define this as a local variable to avoid circular reference
|
| 131 |
+
## See: https://github.com/huggingface/transformers/issues/30930
|
| 132 |
+
end_of_word_suffix = self.backend_tokenizer.model.end_of_word_suffix
|
| 133 |
+
|
| 134 |
+
def new_decode_method(*args, **kwargs):
|
| 135 |
+
text = orig_decode_method(*args, **kwargs)
|
| 136 |
+
text = text.replace(end_of_word_suffix, " ").strip()
|
| 137 |
+
return text
|
| 138 |
+
|
| 139 |
+
self.backend_tokenizer.decode = new_decode_method
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
__all__ = ["CLIPTokenizer"]
|
third_party/transformers/src/transformers/models/deberta_v2/__init__.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .configuration_deberta_v2 import *
|
| 22 |
+
from .modeling_deberta_v2 import *
|
| 23 |
+
from .tokenization_deberta_v2 import *
|
| 24 |
+
else:
|
| 25 |
+
import sys
|
| 26 |
+
|
| 27 |
+
_file = globals()["__file__"]
|
| 28 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/deberta_v2/configuration_deberta_v2.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020, Microsoft and the HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""DeBERTa-v2 model configuration"""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from ...configuration_utils import PreTrainedConfig
|
| 19 |
+
from ...utils import auto_docstring
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
@auto_docstring(checkpoint="microsoft/deberta-v2-xlarge")
|
| 23 |
+
@strict
|
| 24 |
+
class DebertaV2Config(PreTrainedConfig):
|
| 25 |
+
r"""
|
| 26 |
+
relative_attention (`bool`, *optional*, defaults to `True`):
|
| 27 |
+
Whether use relative position encoding.
|
| 28 |
+
max_relative_positions (`int`, *optional*, defaults to -1):
|
| 29 |
+
The range of relative positions `[-max_position_embeddings, max_position_embeddings]`. Use the same value
|
| 30 |
+
as `max_position_embeddings`.
|
| 31 |
+
position_biased_input (`bool`, *optional*, defaults to `True`):
|
| 32 |
+
Whether add absolute position embedding to content embedding.
|
| 33 |
+
pos_att_type (`list[str]`, *optional*):
|
| 34 |
+
The type of relative position attention, it can be a combination of `["p2c", "c2p"]`, e.g. `["p2c"]`,
|
| 35 |
+
`["p2c", "c2p"]`, `["p2c", "c2p"]`.
|
| 36 |
+
pooler_dropout (`float`, *optional*, defaults to `0`):
|
| 37 |
+
Dropout rate in the pooler module.
|
| 38 |
+
pooler_hidden_act (`str`, *optional*, defaults to `"gelu"`):
|
| 39 |
+
Activation function used in the dropout module.
|
| 40 |
+
legacy (`bool`, *optional*, defaults to `True`):
|
| 41 |
+
Whether or not the model should use the legacy `LegacyDebertaOnlyMLMHead`, which does not work properly
|
| 42 |
+
for mask infilling tasks.
|
| 43 |
+
|
| 44 |
+
Example:
|
| 45 |
+
|
| 46 |
+
```python
|
| 47 |
+
>>> from transformers import DebertaV2Config, DebertaV2Model
|
| 48 |
+
|
| 49 |
+
>>> # Initializing a DeBERTa-v2 microsoft/deberta-v2-xlarge style configuration
|
| 50 |
+
>>> configuration = DebertaV2Config()
|
| 51 |
+
|
| 52 |
+
>>> # Initializing a model (with random weights) from the microsoft/deberta-v2-xlarge style configuration
|
| 53 |
+
>>> model = DebertaV2Model(configuration)
|
| 54 |
+
|
| 55 |
+
>>> # Accessing the model configuration
|
| 56 |
+
>>> configuration = model.config
|
| 57 |
+
```"""
|
| 58 |
+
|
| 59 |
+
model_type = "deberta-v2"
|
| 60 |
+
|
| 61 |
+
vocab_size: int = 128100
|
| 62 |
+
hidden_size: int = 1536
|
| 63 |
+
num_hidden_layers: int = 24
|
| 64 |
+
num_attention_heads: int = 24
|
| 65 |
+
intermediate_size: int = 6144
|
| 66 |
+
hidden_act: str = "gelu"
|
| 67 |
+
hidden_dropout_prob: float | int = 0.1
|
| 68 |
+
attention_probs_dropout_prob: float | int = 0.1
|
| 69 |
+
max_position_embeddings: int = 512
|
| 70 |
+
type_vocab_size: int = 0
|
| 71 |
+
initializer_range: float = 0.02
|
| 72 |
+
layer_norm_eps: float = 1e-7
|
| 73 |
+
relative_attention: bool = False
|
| 74 |
+
max_relative_positions: int = -1
|
| 75 |
+
pad_token_id: int | None = 0
|
| 76 |
+
bos_token_id: int | None = None
|
| 77 |
+
eos_token_id: int | list[int] | None = None
|
| 78 |
+
position_biased_input: bool = True
|
| 79 |
+
pos_att_type: str | list[str] | None = None
|
| 80 |
+
pooler_dropout: float | int = 0.0
|
| 81 |
+
pooler_hidden_act: str = "gelu"
|
| 82 |
+
legacy: bool = True
|
| 83 |
+
tie_word_embeddings: bool = True
|
| 84 |
+
|
| 85 |
+
def __post_init__(self, **kwargs):
|
| 86 |
+
# Backwards compatibility
|
| 87 |
+
if isinstance(self.pos_att_type, str):
|
| 88 |
+
self.pos_att_type = [x.strip() for x in self.pos_att_type.lower().split("|")]
|
| 89 |
+
|
| 90 |
+
self.pooler_hidden_size = kwargs.get("pooler_hidden_size", self.hidden_size)
|
| 91 |
+
super().__post_init__(**kwargs)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
__all__ = ["DebertaV2Config"]
|
third_party/transformers/src/transformers/models/deberta_v2/modeling_deberta_v2.py
ADDED
|
@@ -0,0 +1,1361 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 Microsoft and the Hugging Face Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""PyTorch DeBERTa-v2 model."""
|
| 15 |
+
|
| 16 |
+
from collections.abc import Sequence
|
| 17 |
+
|
| 18 |
+
import torch
|
| 19 |
+
from torch import nn
|
| 20 |
+
from torch.nn import BCEWithLogitsLoss, CrossEntropyLoss, LayerNorm, MSELoss
|
| 21 |
+
|
| 22 |
+
from ... import initialization as init
|
| 23 |
+
from ...activations import ACT2FN
|
| 24 |
+
from ...modeling_layers import GradientCheckpointingLayer
|
| 25 |
+
from ...modeling_outputs import (
|
| 26 |
+
BaseModelOutput,
|
| 27 |
+
MaskedLMOutput,
|
| 28 |
+
MultipleChoiceModelOutput,
|
| 29 |
+
QuestionAnsweringModelOutput,
|
| 30 |
+
SequenceClassifierOutput,
|
| 31 |
+
TokenClassifierOutput,
|
| 32 |
+
)
|
| 33 |
+
from ...modeling_utils import PreTrainedModel
|
| 34 |
+
from ...utils import auto_docstring, logging
|
| 35 |
+
from .configuration_deberta_v2 import DebertaV2Config
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
logger = logging.get_logger(__name__)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
# Copied from transformers.models.deberta.modeling_deberta.DebertaSelfOutput with DebertaLayerNorm->LayerNorm
|
| 42 |
+
class DebertaV2SelfOutput(nn.Module):
|
| 43 |
+
def __init__(self, config):
|
| 44 |
+
super().__init__()
|
| 45 |
+
self.dense = nn.Linear(config.hidden_size, config.hidden_size)
|
| 46 |
+
self.LayerNorm = LayerNorm(config.hidden_size, config.layer_norm_eps)
|
| 47 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 48 |
+
|
| 49 |
+
def forward(self, hidden_states, input_tensor):
|
| 50 |
+
hidden_states = self.dense(hidden_states)
|
| 51 |
+
hidden_states = self.dropout(hidden_states)
|
| 52 |
+
hidden_states = self.LayerNorm(hidden_states + input_tensor)
|
| 53 |
+
return hidden_states
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
@torch.jit.script
|
| 57 |
+
def make_log_bucket_position(relative_pos, bucket_size: int, max_position: int):
|
| 58 |
+
sign = torch.sign(relative_pos)
|
| 59 |
+
mid = bucket_size // 2
|
| 60 |
+
abs_pos = torch.where(
|
| 61 |
+
(relative_pos < mid) & (relative_pos > -mid),
|
| 62 |
+
torch.tensor(mid - 1).type_as(relative_pos),
|
| 63 |
+
torch.abs(relative_pos),
|
| 64 |
+
)
|
| 65 |
+
log_pos = (
|
| 66 |
+
torch.ceil(torch.log(abs_pos / mid) / torch.log(torch.tensor((max_position - 1) / mid)) * (mid - 1)) + mid
|
| 67 |
+
)
|
| 68 |
+
bucket_pos = torch.where(abs_pos <= mid, relative_pos.type_as(log_pos), log_pos * sign)
|
| 69 |
+
return bucket_pos
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def build_relative_position(query_layer, key_layer, bucket_size: int = -1, max_position: int = -1):
|
| 73 |
+
"""
|
| 74 |
+
Build relative position according to the query and key
|
| 75 |
+
|
| 76 |
+
We assume the absolute position of query \\(P_q\\) is range from (0, query_size) and the absolute position of key
|
| 77 |
+
\\(P_k\\) is range from (0, key_size), The relative positions from query to key is \\(R_{q \\rightarrow k} = P_q -
|
| 78 |
+
P_k\\)
|
| 79 |
+
|
| 80 |
+
Args:
|
| 81 |
+
query_size (int): the length of query
|
| 82 |
+
key_size (int): the length of key
|
| 83 |
+
bucket_size (int): the size of position bucket
|
| 84 |
+
max_position (int): the maximum allowed absolute position
|
| 85 |
+
device (`torch.device`): the device on which tensors will be created.
|
| 86 |
+
|
| 87 |
+
Return:
|
| 88 |
+
`torch.LongTensor`: A tensor with shape [1, query_size, key_size]
|
| 89 |
+
"""
|
| 90 |
+
query_size = query_layer.size(-2)
|
| 91 |
+
key_size = key_layer.size(-2)
|
| 92 |
+
|
| 93 |
+
q_ids = torch.arange(query_size, dtype=torch.long, device=query_layer.device)
|
| 94 |
+
k_ids = torch.arange(key_size, dtype=torch.long, device=key_layer.device)
|
| 95 |
+
rel_pos_ids = q_ids[:, None] - k_ids[None, :]
|
| 96 |
+
if bucket_size > 0 and max_position > 0:
|
| 97 |
+
rel_pos_ids = make_log_bucket_position(rel_pos_ids, bucket_size, max_position)
|
| 98 |
+
rel_pos_ids = rel_pos_ids.to(torch.long)
|
| 99 |
+
rel_pos_ids = rel_pos_ids[:query_size, :]
|
| 100 |
+
rel_pos_ids = rel_pos_ids.unsqueeze(0)
|
| 101 |
+
return rel_pos_ids
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
@torch.jit.script
|
| 105 |
+
def c2p_dynamic_expand(c2p_pos, query_layer, relative_pos):
|
| 106 |
+
return c2p_pos.expand([query_layer.size(0), query_layer.size(1), query_layer.size(2), relative_pos.size(-1)])
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
@torch.jit.script
|
| 110 |
+
def p2c_dynamic_expand(c2p_pos, query_layer, key_layer):
|
| 111 |
+
return c2p_pos.expand([query_layer.size(0), query_layer.size(1), key_layer.size(-2), key_layer.size(-2)])
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
@torch.jit.script
|
| 115 |
+
def pos_dynamic_expand(pos_index, p2c_att, key_layer):
|
| 116 |
+
return pos_index.expand(p2c_att.size()[:2] + (pos_index.size(-2), key_layer.size(-2)))
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
@torch.jit.script
|
| 120 |
+
def scaled_size_sqrt(query_layer: torch.Tensor, scale_factor: int):
|
| 121 |
+
return torch.sqrt(torch.tensor(query_layer.size(-1), dtype=torch.float) * scale_factor)
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
@torch.jit.script
|
| 125 |
+
def build_rpos(query_layer, key_layer, relative_pos, position_buckets: int, max_relative_positions: int):
|
| 126 |
+
if key_layer.size(-2) != query_layer.size(-2):
|
| 127 |
+
return build_relative_position(
|
| 128 |
+
key_layer,
|
| 129 |
+
key_layer,
|
| 130 |
+
bucket_size=position_buckets,
|
| 131 |
+
max_position=max_relative_positions,
|
| 132 |
+
)
|
| 133 |
+
else:
|
| 134 |
+
return relative_pos
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
class DisentangledSelfAttention(nn.Module):
|
| 138 |
+
"""
|
| 139 |
+
Disentangled self-attention module
|
| 140 |
+
|
| 141 |
+
Parameters:
|
| 142 |
+
config (`DebertaV2Config`):
|
| 143 |
+
A model config class instance with the configuration to build a new model. The schema is similar to
|
| 144 |
+
*BertConfig*, for more details, please refer [`DebertaV2Config`]
|
| 145 |
+
|
| 146 |
+
"""
|
| 147 |
+
|
| 148 |
+
def __init__(self, config):
|
| 149 |
+
super().__init__()
|
| 150 |
+
if config.hidden_size % config.num_attention_heads != 0:
|
| 151 |
+
raise ValueError(
|
| 152 |
+
f"The hidden size ({config.hidden_size}) is not a multiple of the number of attention "
|
| 153 |
+
f"heads ({config.num_attention_heads})"
|
| 154 |
+
)
|
| 155 |
+
self.num_attention_heads = config.num_attention_heads
|
| 156 |
+
_attention_head_size = config.hidden_size // config.num_attention_heads
|
| 157 |
+
self.attention_head_size = getattr(config, "attention_head_size", _attention_head_size)
|
| 158 |
+
self.all_head_size = self.num_attention_heads * self.attention_head_size
|
| 159 |
+
self.query_proj = nn.Linear(config.hidden_size, self.all_head_size, bias=True)
|
| 160 |
+
self.key_proj = nn.Linear(config.hidden_size, self.all_head_size, bias=True)
|
| 161 |
+
self.value_proj = nn.Linear(config.hidden_size, self.all_head_size, bias=True)
|
| 162 |
+
|
| 163 |
+
self.share_att_key = getattr(config, "share_att_key", False)
|
| 164 |
+
self.pos_att_type = config.pos_att_type if config.pos_att_type is not None else []
|
| 165 |
+
self.relative_attention = getattr(config, "relative_attention", False)
|
| 166 |
+
|
| 167 |
+
if self.relative_attention:
|
| 168 |
+
self.position_buckets = getattr(config, "position_buckets", -1)
|
| 169 |
+
self.max_relative_positions = getattr(config, "max_relative_positions", -1)
|
| 170 |
+
if self.max_relative_positions < 1:
|
| 171 |
+
self.max_relative_positions = config.max_position_embeddings
|
| 172 |
+
self.pos_ebd_size = self.max_relative_positions
|
| 173 |
+
if self.position_buckets > 0:
|
| 174 |
+
self.pos_ebd_size = self.position_buckets
|
| 175 |
+
|
| 176 |
+
self.pos_dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 177 |
+
|
| 178 |
+
if not self.share_att_key:
|
| 179 |
+
if "c2p" in self.pos_att_type:
|
| 180 |
+
self.pos_key_proj = nn.Linear(config.hidden_size, self.all_head_size, bias=True)
|
| 181 |
+
if "p2c" in self.pos_att_type:
|
| 182 |
+
self.pos_query_proj = nn.Linear(config.hidden_size, self.all_head_size)
|
| 183 |
+
|
| 184 |
+
self.dropout = nn.Dropout(config.attention_probs_dropout_prob)
|
| 185 |
+
|
| 186 |
+
def transpose_for_scores(self, x, attention_heads) -> torch.Tensor:
|
| 187 |
+
new_x_shape = x.size()[:-1] + (attention_heads, -1)
|
| 188 |
+
x = x.view(new_x_shape)
|
| 189 |
+
return x.permute(0, 2, 1, 3).contiguous().view(-1, x.size(1), x.size(-1))
|
| 190 |
+
|
| 191 |
+
def forward(
|
| 192 |
+
self,
|
| 193 |
+
hidden_states,
|
| 194 |
+
attention_mask,
|
| 195 |
+
output_attentions=False,
|
| 196 |
+
query_states=None,
|
| 197 |
+
relative_pos=None,
|
| 198 |
+
rel_embeddings=None,
|
| 199 |
+
):
|
| 200 |
+
"""
|
| 201 |
+
Call the module
|
| 202 |
+
|
| 203 |
+
Args:
|
| 204 |
+
hidden_states (`torch.FloatTensor`):
|
| 205 |
+
Input states to the module usually the output from previous layer, it will be the Q,K and V in
|
| 206 |
+
*Attention(Q,K,V)*
|
| 207 |
+
|
| 208 |
+
attention_mask (`torch.BoolTensor`):
|
| 209 |
+
An attention mask matrix of shape [*B*, *N*, *N*] where *B* is the batch size, *N* is the maximum
|
| 210 |
+
sequence length in which element [i,j] = *1* means the *i* th token in the input can attend to the *j*
|
| 211 |
+
th token.
|
| 212 |
+
|
| 213 |
+
output_attentions (`bool`, *optional*):
|
| 214 |
+
Whether return the attention matrix.
|
| 215 |
+
|
| 216 |
+
query_states (`torch.FloatTensor`, *optional*):
|
| 217 |
+
The *Q* state in *Attention(Q,K,V)*.
|
| 218 |
+
|
| 219 |
+
relative_pos (`torch.LongTensor`):
|
| 220 |
+
The relative position encoding between the tokens in the sequence. It's of shape [*B*, *N*, *N*] with
|
| 221 |
+
values ranging in [*-max_relative_positions*, *max_relative_positions*].
|
| 222 |
+
|
| 223 |
+
rel_embeddings (`torch.FloatTensor`):
|
| 224 |
+
The embedding of relative distances. It's a tensor of shape [\\(2 \\times
|
| 225 |
+
\\text{max_relative_positions}\\), *hidden_size*].
|
| 226 |
+
|
| 227 |
+
|
| 228 |
+
"""
|
| 229 |
+
if query_states is None:
|
| 230 |
+
query_states = hidden_states
|
| 231 |
+
query_layer = self.transpose_for_scores(self.query_proj(query_states), self.num_attention_heads)
|
| 232 |
+
key_layer = self.transpose_for_scores(self.key_proj(hidden_states), self.num_attention_heads)
|
| 233 |
+
value_layer = self.transpose_for_scores(self.value_proj(hidden_states), self.num_attention_heads)
|
| 234 |
+
|
| 235 |
+
rel_att = None
|
| 236 |
+
# Take the dot product between "query" and "key" to get the raw attention scores.
|
| 237 |
+
scale_factor = 1
|
| 238 |
+
if "c2p" in self.pos_att_type:
|
| 239 |
+
scale_factor += 1
|
| 240 |
+
if "p2c" in self.pos_att_type:
|
| 241 |
+
scale_factor += 1
|
| 242 |
+
scale = scaled_size_sqrt(query_layer, scale_factor)
|
| 243 |
+
attention_scores = torch.bmm(query_layer, key_layer.transpose(-1, -2) / scale.to(dtype=query_layer.dtype))
|
| 244 |
+
if self.relative_attention:
|
| 245 |
+
rel_embeddings = self.pos_dropout(rel_embeddings)
|
| 246 |
+
rel_att = self.disentangled_attention_bias(
|
| 247 |
+
query_layer, key_layer, relative_pos, rel_embeddings, scale_factor
|
| 248 |
+
)
|
| 249 |
+
|
| 250 |
+
if rel_att is not None:
|
| 251 |
+
attention_scores = attention_scores + rel_att
|
| 252 |
+
attention_scores = attention_scores.view(
|
| 253 |
+
-1, self.num_attention_heads, attention_scores.size(-2), attention_scores.size(-1)
|
| 254 |
+
)
|
| 255 |
+
|
| 256 |
+
attention_mask = attention_mask.bool()
|
| 257 |
+
attention_scores = attention_scores.masked_fill(~(attention_mask), torch.finfo(query_layer.dtype).min)
|
| 258 |
+
# bsz x height x length x dimension
|
| 259 |
+
attention_probs = nn.functional.softmax(attention_scores, dim=-1)
|
| 260 |
+
|
| 261 |
+
attention_probs = self.dropout(attention_probs)
|
| 262 |
+
context_layer = torch.bmm(
|
| 263 |
+
attention_probs.view(-1, attention_probs.size(-2), attention_probs.size(-1)), value_layer
|
| 264 |
+
)
|
| 265 |
+
context_layer = (
|
| 266 |
+
context_layer.view(-1, self.num_attention_heads, context_layer.size(-2), context_layer.size(-1))
|
| 267 |
+
.permute(0, 2, 1, 3)
|
| 268 |
+
.contiguous()
|
| 269 |
+
)
|
| 270 |
+
new_context_layer_shape = context_layer.size()[:-2] + (-1,)
|
| 271 |
+
context_layer = context_layer.view(new_context_layer_shape)
|
| 272 |
+
if not output_attentions:
|
| 273 |
+
return (context_layer, None)
|
| 274 |
+
return (context_layer, attention_probs)
|
| 275 |
+
|
| 276 |
+
def disentangled_attention_bias(self, query_layer, key_layer, relative_pos, rel_embeddings, scale_factor):
|
| 277 |
+
if relative_pos is None:
|
| 278 |
+
relative_pos = build_relative_position(
|
| 279 |
+
query_layer,
|
| 280 |
+
key_layer,
|
| 281 |
+
bucket_size=self.position_buckets,
|
| 282 |
+
max_position=self.max_relative_positions,
|
| 283 |
+
)
|
| 284 |
+
if relative_pos.dim() == 2:
|
| 285 |
+
relative_pos = relative_pos.unsqueeze(0).unsqueeze(0)
|
| 286 |
+
elif relative_pos.dim() == 3:
|
| 287 |
+
relative_pos = relative_pos.unsqueeze(1)
|
| 288 |
+
# bsz x height x query x key
|
| 289 |
+
elif relative_pos.dim() != 4:
|
| 290 |
+
raise ValueError(f"Relative position ids must be of dim 2 or 3 or 4. {relative_pos.dim()}")
|
| 291 |
+
|
| 292 |
+
att_span = self.pos_ebd_size
|
| 293 |
+
relative_pos = relative_pos.to(device=query_layer.device, dtype=torch.long)
|
| 294 |
+
|
| 295 |
+
rel_embeddings = rel_embeddings[0 : att_span * 2, :].unsqueeze(0)
|
| 296 |
+
if self.share_att_key:
|
| 297 |
+
pos_query_layer = self.transpose_for_scores(
|
| 298 |
+
self.query_proj(rel_embeddings), self.num_attention_heads
|
| 299 |
+
).repeat(query_layer.size(0) // self.num_attention_heads, 1, 1)
|
| 300 |
+
pos_key_layer = self.transpose_for_scores(self.key_proj(rel_embeddings), self.num_attention_heads).repeat(
|
| 301 |
+
query_layer.size(0) // self.num_attention_heads, 1, 1
|
| 302 |
+
)
|
| 303 |
+
else:
|
| 304 |
+
if "c2p" in self.pos_att_type:
|
| 305 |
+
pos_key_layer = self.transpose_for_scores(
|
| 306 |
+
self.pos_key_proj(rel_embeddings), self.num_attention_heads
|
| 307 |
+
).repeat(query_layer.size(0) // self.num_attention_heads, 1, 1) # .split(self.all_head_size, dim=-1)
|
| 308 |
+
if "p2c" in self.pos_att_type:
|
| 309 |
+
pos_query_layer = self.transpose_for_scores(
|
| 310 |
+
self.pos_query_proj(rel_embeddings), self.num_attention_heads
|
| 311 |
+
).repeat(query_layer.size(0) // self.num_attention_heads, 1, 1) # .split(self.all_head_size, dim=-1)
|
| 312 |
+
|
| 313 |
+
score = 0
|
| 314 |
+
# content->position
|
| 315 |
+
if "c2p" in self.pos_att_type:
|
| 316 |
+
scale = scaled_size_sqrt(pos_key_layer, scale_factor)
|
| 317 |
+
c2p_att = torch.bmm(query_layer, pos_key_layer.transpose(-1, -2))
|
| 318 |
+
c2p_pos = torch.clamp(relative_pos + att_span, 0, att_span * 2 - 1)
|
| 319 |
+
c2p_att = torch.gather(
|
| 320 |
+
c2p_att,
|
| 321 |
+
dim=-1,
|
| 322 |
+
index=c2p_pos.squeeze(0).expand([query_layer.size(0), query_layer.size(1), relative_pos.size(-1)]),
|
| 323 |
+
)
|
| 324 |
+
score += c2p_att / scale.to(dtype=c2p_att.dtype)
|
| 325 |
+
|
| 326 |
+
# position->content
|
| 327 |
+
if "p2c" in self.pos_att_type:
|
| 328 |
+
scale = scaled_size_sqrt(pos_query_layer, scale_factor)
|
| 329 |
+
r_pos = build_rpos(
|
| 330 |
+
query_layer,
|
| 331 |
+
key_layer,
|
| 332 |
+
relative_pos,
|
| 333 |
+
self.max_relative_positions,
|
| 334 |
+
self.position_buckets,
|
| 335 |
+
)
|
| 336 |
+
p2c_pos = torch.clamp(-r_pos + att_span, 0, att_span * 2 - 1)
|
| 337 |
+
p2c_att = torch.bmm(key_layer, pos_query_layer.transpose(-1, -2))
|
| 338 |
+
p2c_att = torch.gather(
|
| 339 |
+
p2c_att,
|
| 340 |
+
dim=-1,
|
| 341 |
+
index=p2c_pos.squeeze(0).expand([query_layer.size(0), key_layer.size(-2), key_layer.size(-2)]),
|
| 342 |
+
).transpose(-1, -2)
|
| 343 |
+
score += p2c_att / scale.to(dtype=p2c_att.dtype)
|
| 344 |
+
|
| 345 |
+
return score
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
# Copied from transformers.models.deberta.modeling_deberta.DebertaAttention with Deberta->DebertaV2
|
| 349 |
+
class DebertaV2Attention(nn.Module):
|
| 350 |
+
def __init__(self, config):
|
| 351 |
+
super().__init__()
|
| 352 |
+
self.self = DisentangledSelfAttention(config)
|
| 353 |
+
self.output = DebertaV2SelfOutput(config)
|
| 354 |
+
self.config = config
|
| 355 |
+
|
| 356 |
+
def forward(
|
| 357 |
+
self,
|
| 358 |
+
hidden_states,
|
| 359 |
+
attention_mask,
|
| 360 |
+
output_attentions: bool = False,
|
| 361 |
+
query_states=None,
|
| 362 |
+
relative_pos=None,
|
| 363 |
+
rel_embeddings=None,
|
| 364 |
+
) -> tuple[torch.Tensor, torch.Tensor | None]:
|
| 365 |
+
self_output, att_matrix = self.self(
|
| 366 |
+
hidden_states,
|
| 367 |
+
attention_mask,
|
| 368 |
+
output_attentions,
|
| 369 |
+
query_states=query_states,
|
| 370 |
+
relative_pos=relative_pos,
|
| 371 |
+
rel_embeddings=rel_embeddings,
|
| 372 |
+
)
|
| 373 |
+
if query_states is None:
|
| 374 |
+
query_states = hidden_states
|
| 375 |
+
attention_output = self.output(self_output, query_states)
|
| 376 |
+
|
| 377 |
+
if output_attentions:
|
| 378 |
+
return (attention_output, att_matrix)
|
| 379 |
+
else:
|
| 380 |
+
return (attention_output, None)
|
| 381 |
+
|
| 382 |
+
|
| 383 |
+
# Copied from transformers.models.bert.modeling_bert.BertIntermediate with Bert->DebertaV2
|
| 384 |
+
class DebertaV2Intermediate(nn.Module):
|
| 385 |
+
def __init__(self, config):
|
| 386 |
+
super().__init__()
|
| 387 |
+
self.dense = nn.Linear(config.hidden_size, config.intermediate_size)
|
| 388 |
+
if isinstance(config.hidden_act, str):
|
| 389 |
+
self.intermediate_act_fn = ACT2FN[config.hidden_act]
|
| 390 |
+
else:
|
| 391 |
+
self.intermediate_act_fn = config.hidden_act
|
| 392 |
+
|
| 393 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 394 |
+
hidden_states = self.dense(hidden_states)
|
| 395 |
+
hidden_states = self.intermediate_act_fn(hidden_states)
|
| 396 |
+
return hidden_states
|
| 397 |
+
|
| 398 |
+
|
| 399 |
+
# Copied from transformers.models.deberta.modeling_deberta.DebertaOutput with DebertaLayerNorm->LayerNorm
|
| 400 |
+
class DebertaV2Output(nn.Module):
|
| 401 |
+
def __init__(self, config):
|
| 402 |
+
super().__init__()
|
| 403 |
+
self.dense = nn.Linear(config.intermediate_size, config.hidden_size)
|
| 404 |
+
self.LayerNorm = LayerNorm(config.hidden_size, config.layer_norm_eps)
|
| 405 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 406 |
+
self.config = config
|
| 407 |
+
|
| 408 |
+
def forward(self, hidden_states, input_tensor):
|
| 409 |
+
hidden_states = self.dense(hidden_states)
|
| 410 |
+
hidden_states = self.dropout(hidden_states)
|
| 411 |
+
hidden_states = self.LayerNorm(hidden_states + input_tensor)
|
| 412 |
+
return hidden_states
|
| 413 |
+
|
| 414 |
+
|
| 415 |
+
# Copied from transformers.models.deberta.modeling_deberta.DebertaLayer with Deberta->DebertaV2
|
| 416 |
+
class DebertaV2Layer(GradientCheckpointingLayer):
|
| 417 |
+
def __init__(self, config):
|
| 418 |
+
super().__init__()
|
| 419 |
+
self.attention = DebertaV2Attention(config)
|
| 420 |
+
self.intermediate = DebertaV2Intermediate(config)
|
| 421 |
+
self.output = DebertaV2Output(config)
|
| 422 |
+
|
| 423 |
+
def forward(
|
| 424 |
+
self,
|
| 425 |
+
hidden_states,
|
| 426 |
+
attention_mask,
|
| 427 |
+
query_states=None,
|
| 428 |
+
relative_pos=None,
|
| 429 |
+
rel_embeddings=None,
|
| 430 |
+
output_attentions: bool = False,
|
| 431 |
+
) -> tuple[torch.Tensor, torch.Tensor | None]:
|
| 432 |
+
attention_output, att_matrix = self.attention(
|
| 433 |
+
hidden_states,
|
| 434 |
+
attention_mask,
|
| 435 |
+
output_attentions=output_attentions,
|
| 436 |
+
query_states=query_states,
|
| 437 |
+
relative_pos=relative_pos,
|
| 438 |
+
rel_embeddings=rel_embeddings,
|
| 439 |
+
)
|
| 440 |
+
intermediate_output = self.intermediate(attention_output)
|
| 441 |
+
layer_output = self.output(intermediate_output, attention_output)
|
| 442 |
+
|
| 443 |
+
if output_attentions:
|
| 444 |
+
return (layer_output, att_matrix)
|
| 445 |
+
else:
|
| 446 |
+
return (layer_output, None)
|
| 447 |
+
|
| 448 |
+
|
| 449 |
+
class ConvLayer(nn.Module):
|
| 450 |
+
def __init__(self, config):
|
| 451 |
+
super().__init__()
|
| 452 |
+
kernel_size = getattr(config, "conv_kernel_size", 3)
|
| 453 |
+
groups = getattr(config, "conv_groups", 1)
|
| 454 |
+
self.conv_act = getattr(config, "conv_act", "tanh")
|
| 455 |
+
self.conv = nn.Conv1d(
|
| 456 |
+
config.hidden_size, config.hidden_size, kernel_size, padding=(kernel_size - 1) // 2, groups=groups
|
| 457 |
+
)
|
| 458 |
+
self.LayerNorm = LayerNorm(config.hidden_size, config.layer_norm_eps)
|
| 459 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 460 |
+
self.config = config
|
| 461 |
+
|
| 462 |
+
def forward(self, hidden_states, residual_states, input_mask):
|
| 463 |
+
out = self.conv(hidden_states.permute(0, 2, 1).contiguous()).permute(0, 2, 1).contiguous()
|
| 464 |
+
rmask = (1 - input_mask).bool()
|
| 465 |
+
out.masked_fill_(rmask.unsqueeze(-1).expand(out.size()), 0)
|
| 466 |
+
out = ACT2FN[self.conv_act](self.dropout(out))
|
| 467 |
+
|
| 468 |
+
layer_norm_input = residual_states + out
|
| 469 |
+
output = self.LayerNorm(layer_norm_input).to(layer_norm_input)
|
| 470 |
+
|
| 471 |
+
if input_mask is None:
|
| 472 |
+
output_states = output
|
| 473 |
+
else:
|
| 474 |
+
if input_mask.dim() != layer_norm_input.dim():
|
| 475 |
+
if input_mask.dim() == 4:
|
| 476 |
+
input_mask = input_mask.squeeze(1).squeeze(1)
|
| 477 |
+
input_mask = input_mask.unsqueeze(2)
|
| 478 |
+
|
| 479 |
+
input_mask = input_mask.to(output.dtype)
|
| 480 |
+
output_states = output * input_mask
|
| 481 |
+
|
| 482 |
+
return output_states
|
| 483 |
+
|
| 484 |
+
|
| 485 |
+
# Copied from transformers.models.deberta.modeling_deberta.DebertaEmbeddings with DebertaLayerNorm->LayerNorm,Deberta->DebertaV2
|
| 486 |
+
class DebertaV2Embeddings(nn.Module):
|
| 487 |
+
"""Construct the embeddings from word, position and token_type embeddings."""
|
| 488 |
+
|
| 489 |
+
def __init__(self, config):
|
| 490 |
+
super().__init__()
|
| 491 |
+
pad_token_id = getattr(config, "pad_token_id", 0)
|
| 492 |
+
self.embedding_size = getattr(config, "embedding_size", config.hidden_size)
|
| 493 |
+
self.word_embeddings = nn.Embedding(config.vocab_size, self.embedding_size, padding_idx=pad_token_id)
|
| 494 |
+
|
| 495 |
+
self.position_biased_input = getattr(config, "position_biased_input", True)
|
| 496 |
+
if not self.position_biased_input:
|
| 497 |
+
self.position_embeddings = None
|
| 498 |
+
else:
|
| 499 |
+
self.position_embeddings = nn.Embedding(config.max_position_embeddings, self.embedding_size)
|
| 500 |
+
|
| 501 |
+
if config.type_vocab_size > 0:
|
| 502 |
+
self.token_type_embeddings = nn.Embedding(config.type_vocab_size, self.embedding_size)
|
| 503 |
+
else:
|
| 504 |
+
self.token_type_embeddings = None
|
| 505 |
+
|
| 506 |
+
if self.embedding_size != config.hidden_size:
|
| 507 |
+
self.embed_proj = nn.Linear(self.embedding_size, config.hidden_size, bias=False)
|
| 508 |
+
else:
|
| 509 |
+
self.embed_proj = None
|
| 510 |
+
|
| 511 |
+
self.LayerNorm = LayerNorm(config.hidden_size, config.layer_norm_eps)
|
| 512 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 513 |
+
self.config = config
|
| 514 |
+
|
| 515 |
+
# position_ids (1, len position emb) is contiguous in memory and exported when serialized
|
| 516 |
+
self.register_buffer(
|
| 517 |
+
"position_ids", torch.arange(config.max_position_embeddings).expand((1, -1)), persistent=False
|
| 518 |
+
)
|
| 519 |
+
|
| 520 |
+
def forward(self, input_ids=None, token_type_ids=None, position_ids=None, mask=None, inputs_embeds=None):
|
| 521 |
+
if input_ids is not None:
|
| 522 |
+
input_shape = input_ids.size()
|
| 523 |
+
else:
|
| 524 |
+
input_shape = inputs_embeds.size()[:-1]
|
| 525 |
+
|
| 526 |
+
seq_length = input_shape[1]
|
| 527 |
+
|
| 528 |
+
if position_ids is None:
|
| 529 |
+
position_ids = self.position_ids[:, :seq_length]
|
| 530 |
+
|
| 531 |
+
if token_type_ids is None:
|
| 532 |
+
token_type_ids = torch.zeros(input_shape, dtype=torch.long, device=self.position_ids.device)
|
| 533 |
+
|
| 534 |
+
if inputs_embeds is None:
|
| 535 |
+
inputs_embeds = self.word_embeddings(input_ids)
|
| 536 |
+
|
| 537 |
+
if self.position_embeddings is not None:
|
| 538 |
+
position_embeddings = self.position_embeddings(position_ids.long())
|
| 539 |
+
else:
|
| 540 |
+
position_embeddings = torch.zeros_like(inputs_embeds)
|
| 541 |
+
|
| 542 |
+
embeddings = inputs_embeds
|
| 543 |
+
if self.position_biased_input:
|
| 544 |
+
embeddings = embeddings + position_embeddings
|
| 545 |
+
if self.token_type_embeddings is not None:
|
| 546 |
+
token_type_embeddings = self.token_type_embeddings(token_type_ids)
|
| 547 |
+
embeddings = embeddings + token_type_embeddings
|
| 548 |
+
|
| 549 |
+
if self.embed_proj is not None:
|
| 550 |
+
embeddings = self.embed_proj(embeddings)
|
| 551 |
+
|
| 552 |
+
embeddings = self.LayerNorm(embeddings)
|
| 553 |
+
|
| 554 |
+
if mask is not None:
|
| 555 |
+
if mask.dim() != embeddings.dim():
|
| 556 |
+
if mask.dim() == 4:
|
| 557 |
+
mask = mask.squeeze(1).squeeze(1)
|
| 558 |
+
mask = mask.unsqueeze(2)
|
| 559 |
+
mask = mask.to(embeddings.dtype)
|
| 560 |
+
|
| 561 |
+
embeddings = embeddings * mask
|
| 562 |
+
|
| 563 |
+
embeddings = self.dropout(embeddings)
|
| 564 |
+
return embeddings
|
| 565 |
+
|
| 566 |
+
|
| 567 |
+
class DebertaV2Encoder(nn.Module):
|
| 568 |
+
"""Modified BertEncoder with relative position bias support"""
|
| 569 |
+
|
| 570 |
+
def __init__(self, config):
|
| 571 |
+
super().__init__()
|
| 572 |
+
|
| 573 |
+
self.layer = nn.ModuleList([DebertaV2Layer(config) for _ in range(config.num_hidden_layers)])
|
| 574 |
+
self.relative_attention = getattr(config, "relative_attention", False)
|
| 575 |
+
|
| 576 |
+
if self.relative_attention:
|
| 577 |
+
self.max_relative_positions = getattr(config, "max_relative_positions", -1)
|
| 578 |
+
if self.max_relative_positions < 1:
|
| 579 |
+
self.max_relative_positions = config.max_position_embeddings
|
| 580 |
+
|
| 581 |
+
self.position_buckets = getattr(config, "position_buckets", -1)
|
| 582 |
+
pos_ebd_size = self.max_relative_positions * 2
|
| 583 |
+
|
| 584 |
+
if self.position_buckets > 0:
|
| 585 |
+
pos_ebd_size = self.position_buckets * 2
|
| 586 |
+
|
| 587 |
+
self.rel_embeddings = nn.Embedding(pos_ebd_size, config.hidden_size)
|
| 588 |
+
|
| 589 |
+
self.norm_rel_ebd = [x.strip() for x in getattr(config, "norm_rel_ebd", "none").lower().split("|")]
|
| 590 |
+
|
| 591 |
+
if "layer_norm" in self.norm_rel_ebd:
|
| 592 |
+
self.LayerNorm = LayerNorm(config.hidden_size, config.layer_norm_eps, elementwise_affine=True)
|
| 593 |
+
|
| 594 |
+
self.conv = ConvLayer(config) if getattr(config, "conv_kernel_size", 0) > 0 else None
|
| 595 |
+
self.gradient_checkpointing = False
|
| 596 |
+
|
| 597 |
+
def get_rel_embedding(self):
|
| 598 |
+
rel_embeddings = self.rel_embeddings.weight if self.relative_attention else None
|
| 599 |
+
if rel_embeddings is not None and ("layer_norm" in self.norm_rel_ebd):
|
| 600 |
+
rel_embeddings = self.LayerNorm(rel_embeddings)
|
| 601 |
+
return rel_embeddings
|
| 602 |
+
|
| 603 |
+
def get_attention_mask(self, attention_mask):
|
| 604 |
+
if attention_mask.dim() <= 2:
|
| 605 |
+
extended_attention_mask = attention_mask.unsqueeze(1).unsqueeze(2)
|
| 606 |
+
attention_mask = extended_attention_mask * extended_attention_mask.squeeze(-2).unsqueeze(-1)
|
| 607 |
+
elif attention_mask.dim() == 3:
|
| 608 |
+
attention_mask = attention_mask.unsqueeze(1)
|
| 609 |
+
|
| 610 |
+
return attention_mask
|
| 611 |
+
|
| 612 |
+
def get_rel_pos(self, hidden_states, query_states=None, relative_pos=None):
|
| 613 |
+
if self.relative_attention and relative_pos is None:
|
| 614 |
+
if query_states is not None:
|
| 615 |
+
relative_pos = build_relative_position(
|
| 616 |
+
query_states,
|
| 617 |
+
hidden_states,
|
| 618 |
+
bucket_size=self.position_buckets,
|
| 619 |
+
max_position=self.max_relative_positions,
|
| 620 |
+
)
|
| 621 |
+
else:
|
| 622 |
+
relative_pos = build_relative_position(
|
| 623 |
+
hidden_states,
|
| 624 |
+
hidden_states,
|
| 625 |
+
bucket_size=self.position_buckets,
|
| 626 |
+
max_position=self.max_relative_positions,
|
| 627 |
+
)
|
| 628 |
+
return relative_pos
|
| 629 |
+
|
| 630 |
+
def forward(
|
| 631 |
+
self,
|
| 632 |
+
hidden_states,
|
| 633 |
+
attention_mask,
|
| 634 |
+
output_hidden_states=True,
|
| 635 |
+
output_attentions=False,
|
| 636 |
+
query_states=None,
|
| 637 |
+
relative_pos=None,
|
| 638 |
+
return_dict=True,
|
| 639 |
+
):
|
| 640 |
+
if attention_mask.dim() <= 2:
|
| 641 |
+
input_mask = attention_mask
|
| 642 |
+
else:
|
| 643 |
+
input_mask = attention_mask.sum(-2) > 0
|
| 644 |
+
attention_mask = self.get_attention_mask(attention_mask)
|
| 645 |
+
relative_pos = self.get_rel_pos(hidden_states, query_states, relative_pos)
|
| 646 |
+
|
| 647 |
+
all_hidden_states: tuple[torch.Tensor] | None = (hidden_states,) if output_hidden_states else None
|
| 648 |
+
all_attentions = () if output_attentions else None
|
| 649 |
+
|
| 650 |
+
next_kv = hidden_states
|
| 651 |
+
rel_embeddings = self.get_rel_embedding()
|
| 652 |
+
for i, layer_module in enumerate(self.layer):
|
| 653 |
+
output_states, attn_weights = layer_module(
|
| 654 |
+
next_kv,
|
| 655 |
+
attention_mask,
|
| 656 |
+
query_states=query_states,
|
| 657 |
+
relative_pos=relative_pos,
|
| 658 |
+
rel_embeddings=rel_embeddings,
|
| 659 |
+
output_attentions=output_attentions,
|
| 660 |
+
)
|
| 661 |
+
|
| 662 |
+
if output_attentions:
|
| 663 |
+
all_attentions = all_attentions + (attn_weights,)
|
| 664 |
+
|
| 665 |
+
if i == 0 and self.conv is not None:
|
| 666 |
+
output_states = self.conv(hidden_states, output_states, input_mask)
|
| 667 |
+
|
| 668 |
+
if output_hidden_states:
|
| 669 |
+
all_hidden_states = all_hidden_states + (output_states,)
|
| 670 |
+
|
| 671 |
+
if query_states is not None:
|
| 672 |
+
query_states = output_states
|
| 673 |
+
if isinstance(hidden_states, Sequence):
|
| 674 |
+
next_kv = hidden_states[i + 1] if i + 1 < len(self.layer) else None
|
| 675 |
+
else:
|
| 676 |
+
next_kv = output_states
|
| 677 |
+
|
| 678 |
+
if not return_dict:
|
| 679 |
+
return tuple(v for v in [output_states, all_hidden_states, all_attentions] if v is not None)
|
| 680 |
+
return BaseModelOutput(
|
| 681 |
+
last_hidden_state=output_states, hidden_states=all_hidden_states, attentions=all_attentions
|
| 682 |
+
)
|
| 683 |
+
|
| 684 |
+
|
| 685 |
+
@auto_docstring
|
| 686 |
+
class DebertaV2PreTrainedModel(PreTrainedModel):
|
| 687 |
+
config: DebertaV2Config
|
| 688 |
+
base_model_prefix = "deberta"
|
| 689 |
+
_keys_to_ignore_on_load_unexpected = ["position_embeddings"]
|
| 690 |
+
supports_gradient_checkpointing = True
|
| 691 |
+
|
| 692 |
+
@torch.no_grad()
|
| 693 |
+
def _init_weights(self, module):
|
| 694 |
+
"""Initialize the weights."""
|
| 695 |
+
super()._init_weights(module)
|
| 696 |
+
if isinstance(module, (LegacyDebertaV2LMPredictionHead, DebertaV2LMPredictionHead)):
|
| 697 |
+
init.zeros_(module.bias)
|
| 698 |
+
elif isinstance(module, DebertaV2Embeddings):
|
| 699 |
+
init.copy_(module.position_ids, torch.arange(module.position_ids.shape[-1]).expand((1, -1)))
|
| 700 |
+
|
| 701 |
+
|
| 702 |
+
@auto_docstring
|
| 703 |
+
# Copied from transformers.models.deberta.modeling_deberta.DebertaModel with Deberta->DebertaV2
|
| 704 |
+
class DebertaV2Model(DebertaV2PreTrainedModel):
|
| 705 |
+
def __init__(self, config):
|
| 706 |
+
super().__init__(config)
|
| 707 |
+
|
| 708 |
+
self.embeddings = DebertaV2Embeddings(config)
|
| 709 |
+
self.encoder = DebertaV2Encoder(config)
|
| 710 |
+
self.z_steps = 0
|
| 711 |
+
self.config = config
|
| 712 |
+
# Initialize weights and apply final processing
|
| 713 |
+
self.post_init()
|
| 714 |
+
|
| 715 |
+
def get_input_embeddings(self):
|
| 716 |
+
return self.embeddings.word_embeddings
|
| 717 |
+
|
| 718 |
+
def set_input_embeddings(self, new_embeddings):
|
| 719 |
+
self.embeddings.word_embeddings = new_embeddings
|
| 720 |
+
|
| 721 |
+
@auto_docstring
|
| 722 |
+
def forward(
|
| 723 |
+
self,
|
| 724 |
+
input_ids: torch.Tensor | None = None,
|
| 725 |
+
attention_mask: torch.Tensor | None = None,
|
| 726 |
+
token_type_ids: torch.Tensor | None = None,
|
| 727 |
+
position_ids: torch.Tensor | None = None,
|
| 728 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 729 |
+
output_attentions: bool | None = None,
|
| 730 |
+
output_hidden_states: bool | None = None,
|
| 731 |
+
return_dict: bool | None = None,
|
| 732 |
+
**kwargs,
|
| 733 |
+
) -> tuple | BaseModelOutput:
|
| 734 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 735 |
+
output_hidden_states = (
|
| 736 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 737 |
+
)
|
| 738 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 739 |
+
|
| 740 |
+
if input_ids is not None and inputs_embeds is not None:
|
| 741 |
+
raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
|
| 742 |
+
elif input_ids is not None:
|
| 743 |
+
self.warn_if_padding_and_no_attention_mask(input_ids, attention_mask)
|
| 744 |
+
input_shape = input_ids.size()
|
| 745 |
+
elif inputs_embeds is not None:
|
| 746 |
+
input_shape = inputs_embeds.size()[:-1]
|
| 747 |
+
else:
|
| 748 |
+
raise ValueError("You have to specify either input_ids or inputs_embeds")
|
| 749 |
+
|
| 750 |
+
device = input_ids.device if input_ids is not None else inputs_embeds.device
|
| 751 |
+
|
| 752 |
+
if attention_mask is None:
|
| 753 |
+
attention_mask = torch.ones(input_shape, device=device)
|
| 754 |
+
if token_type_ids is None:
|
| 755 |
+
token_type_ids = torch.zeros(input_shape, dtype=torch.long, device=device)
|
| 756 |
+
|
| 757 |
+
embedding_output = self.embeddings(
|
| 758 |
+
input_ids=input_ids,
|
| 759 |
+
token_type_ids=token_type_ids,
|
| 760 |
+
position_ids=position_ids,
|
| 761 |
+
mask=attention_mask,
|
| 762 |
+
inputs_embeds=inputs_embeds,
|
| 763 |
+
)
|
| 764 |
+
|
| 765 |
+
encoder_outputs = self.encoder(
|
| 766 |
+
embedding_output,
|
| 767 |
+
attention_mask,
|
| 768 |
+
output_hidden_states=True,
|
| 769 |
+
output_attentions=output_attentions,
|
| 770 |
+
return_dict=return_dict,
|
| 771 |
+
)
|
| 772 |
+
encoded_layers = encoder_outputs[1]
|
| 773 |
+
|
| 774 |
+
if self.z_steps > 1:
|
| 775 |
+
hidden_states = encoded_layers[-2]
|
| 776 |
+
layers = [self.encoder.layer[-1] for _ in range(self.z_steps)]
|
| 777 |
+
query_states = encoded_layers[-1]
|
| 778 |
+
rel_embeddings = self.encoder.get_rel_embedding()
|
| 779 |
+
attention_mask = self.encoder.get_attention_mask(attention_mask)
|
| 780 |
+
rel_pos = self.encoder.get_rel_pos(embedding_output)
|
| 781 |
+
for layer in layers[1:]:
|
| 782 |
+
query_states = layer(
|
| 783 |
+
hidden_states,
|
| 784 |
+
attention_mask,
|
| 785 |
+
output_attentions=False,
|
| 786 |
+
query_states=query_states,
|
| 787 |
+
relative_pos=rel_pos,
|
| 788 |
+
rel_embeddings=rel_embeddings,
|
| 789 |
+
)
|
| 790 |
+
encoded_layers.append(query_states)
|
| 791 |
+
|
| 792 |
+
sequence_output = encoded_layers[-1]
|
| 793 |
+
|
| 794 |
+
if not return_dict:
|
| 795 |
+
return (sequence_output,) + encoder_outputs[(1 if output_hidden_states else 2) :]
|
| 796 |
+
|
| 797 |
+
return BaseModelOutput(
|
| 798 |
+
last_hidden_state=sequence_output,
|
| 799 |
+
hidden_states=encoder_outputs.hidden_states if output_hidden_states else None,
|
| 800 |
+
attentions=encoder_outputs.attentions,
|
| 801 |
+
)
|
| 802 |
+
|
| 803 |
+
|
| 804 |
+
# Copied from transformers.models.deberta.modeling_deberta.LegacyDebertaPredictionHeadTransform with Deberta->DebertaV2
|
| 805 |
+
class LegacyDebertaV2PredictionHeadTransform(nn.Module):
|
| 806 |
+
def __init__(self, config):
|
| 807 |
+
super().__init__()
|
| 808 |
+
self.embedding_size = getattr(config, "embedding_size", config.hidden_size)
|
| 809 |
+
|
| 810 |
+
self.dense = nn.Linear(config.hidden_size, self.embedding_size)
|
| 811 |
+
if isinstance(config.hidden_act, str):
|
| 812 |
+
self.transform_act_fn = ACT2FN[config.hidden_act]
|
| 813 |
+
else:
|
| 814 |
+
self.transform_act_fn = config.hidden_act
|
| 815 |
+
self.LayerNorm = nn.LayerNorm(self.embedding_size, eps=config.layer_norm_eps)
|
| 816 |
+
|
| 817 |
+
def forward(self, hidden_states):
|
| 818 |
+
hidden_states = self.dense(hidden_states)
|
| 819 |
+
hidden_states = self.transform_act_fn(hidden_states)
|
| 820 |
+
hidden_states = self.LayerNorm(hidden_states)
|
| 821 |
+
return hidden_states
|
| 822 |
+
|
| 823 |
+
|
| 824 |
+
class LegacyDebertaV2LMPredictionHead(nn.Module):
|
| 825 |
+
def __init__(self, config):
|
| 826 |
+
super().__init__()
|
| 827 |
+
self.transform = LegacyDebertaV2PredictionHeadTransform(config)
|
| 828 |
+
|
| 829 |
+
self.embedding_size = getattr(config, "embedding_size", config.hidden_size)
|
| 830 |
+
# The output weights are the same as the input embeddings, but there is
|
| 831 |
+
# an output-only bias for each token.
|
| 832 |
+
self.decoder = nn.Linear(self.embedding_size, config.vocab_size)
|
| 833 |
+
|
| 834 |
+
self.bias = nn.Parameter(torch.zeros(config.vocab_size))
|
| 835 |
+
|
| 836 |
+
def forward(self, hidden_states):
|
| 837 |
+
hidden_states = self.transform(hidden_states)
|
| 838 |
+
hidden_states = self.decoder(hidden_states)
|
| 839 |
+
return hidden_states
|
| 840 |
+
|
| 841 |
+
|
| 842 |
+
class LegacyDebertaV2OnlyMLMHead(nn.Module):
|
| 843 |
+
def __init__(self, config):
|
| 844 |
+
super().__init__()
|
| 845 |
+
self.predictions = LegacyDebertaV2LMPredictionHead(config)
|
| 846 |
+
|
| 847 |
+
def forward(self, sequence_output):
|
| 848 |
+
prediction_scores = self.predictions(sequence_output)
|
| 849 |
+
return prediction_scores
|
| 850 |
+
|
| 851 |
+
|
| 852 |
+
class DebertaV2LMPredictionHead(nn.Module):
|
| 853 |
+
"""https://github.com/microsoft/DeBERTa/blob/master/DeBERTa/deberta/bert.py#L270"""
|
| 854 |
+
|
| 855 |
+
def __init__(self, config):
|
| 856 |
+
super().__init__()
|
| 857 |
+
self.dense = nn.Linear(config.hidden_size, config.hidden_size)
|
| 858 |
+
|
| 859 |
+
if isinstance(config.hidden_act, str):
|
| 860 |
+
self.transform_act_fn = ACT2FN[config.hidden_act]
|
| 861 |
+
else:
|
| 862 |
+
self.transform_act_fn = config.hidden_act
|
| 863 |
+
|
| 864 |
+
self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps, elementwise_affine=True)
|
| 865 |
+
|
| 866 |
+
self.bias = nn.Parameter(torch.zeros(config.vocab_size))
|
| 867 |
+
|
| 868 |
+
# note that the input embeddings must be passed as an argument
|
| 869 |
+
def forward(self, hidden_states, word_embeddings):
|
| 870 |
+
hidden_states = self.dense(hidden_states)
|
| 871 |
+
hidden_states = self.transform_act_fn(hidden_states)
|
| 872 |
+
hidden_states = self.LayerNorm(hidden_states)
|
| 873 |
+
hidden_states = torch.matmul(hidden_states, word_embeddings.weight.t()) + self.bias
|
| 874 |
+
return hidden_states
|
| 875 |
+
|
| 876 |
+
|
| 877 |
+
class DebertaV2OnlyMLMHead(nn.Module):
|
| 878 |
+
def __init__(self, config):
|
| 879 |
+
super().__init__()
|
| 880 |
+
self.lm_head = DebertaV2LMPredictionHead(config)
|
| 881 |
+
|
| 882 |
+
# note that the input embeddings must be passed as an argument
|
| 883 |
+
def forward(self, sequence_output, word_embeddings):
|
| 884 |
+
prediction_scores = self.lm_head(sequence_output, word_embeddings)
|
| 885 |
+
return prediction_scores
|
| 886 |
+
|
| 887 |
+
|
| 888 |
+
@auto_docstring
|
| 889 |
+
class DebertaV2ForMaskedLM(DebertaV2PreTrainedModel):
|
| 890 |
+
_tied_weights_keys = {
|
| 891 |
+
"cls.predictions.decoder.bias": "cls.predictions.bias",
|
| 892 |
+
"cls.predictions.decoder.weight": "deberta.embeddings.word_embeddings.weight",
|
| 893 |
+
}
|
| 894 |
+
_keys_to_ignore_on_load_unexpected = [r"mask_predictions.*"]
|
| 895 |
+
|
| 896 |
+
def __init__(self, config):
|
| 897 |
+
super().__init__(config)
|
| 898 |
+
self.legacy = config.legacy
|
| 899 |
+
self.deberta = DebertaV2Model(config)
|
| 900 |
+
if self.legacy:
|
| 901 |
+
self.cls = LegacyDebertaV2OnlyMLMHead(config)
|
| 902 |
+
else:
|
| 903 |
+
self._tied_weights_keys = {
|
| 904 |
+
"lm_predictions.lm_head.weight": "deberta.embeddings.word_embeddings.weight",
|
| 905 |
+
}
|
| 906 |
+
self.lm_predictions = DebertaV2OnlyMLMHead(config)
|
| 907 |
+
# Initialize weights and apply final processing
|
| 908 |
+
self.post_init()
|
| 909 |
+
|
| 910 |
+
def get_output_embeddings(self):
|
| 911 |
+
if self.legacy:
|
| 912 |
+
return self.cls.predictions.decoder
|
| 913 |
+
else:
|
| 914 |
+
return self.lm_predictions.lm_head.dense
|
| 915 |
+
|
| 916 |
+
def set_output_embeddings(self, new_embeddings):
|
| 917 |
+
if self.legacy:
|
| 918 |
+
self.cls.predictions.decoder = new_embeddings
|
| 919 |
+
self.cls.predictions.bias = new_embeddings.bias
|
| 920 |
+
else:
|
| 921 |
+
self.lm_predictions.lm_head.dense = new_embeddings
|
| 922 |
+
self.lm_predictions.lm_head.bias = new_embeddings.bias
|
| 923 |
+
|
| 924 |
+
@auto_docstring
|
| 925 |
+
# Copied from transformers.models.deberta.modeling_deberta.DebertaForMaskedLM.forward with Deberta->DebertaV2
|
| 926 |
+
def forward(
|
| 927 |
+
self,
|
| 928 |
+
input_ids: torch.Tensor | None = None,
|
| 929 |
+
attention_mask: torch.Tensor | None = None,
|
| 930 |
+
token_type_ids: torch.Tensor | None = None,
|
| 931 |
+
position_ids: torch.Tensor | None = None,
|
| 932 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 933 |
+
labels: torch.Tensor | None = None,
|
| 934 |
+
output_attentions: bool | None = None,
|
| 935 |
+
output_hidden_states: bool | None = None,
|
| 936 |
+
return_dict: bool | None = None,
|
| 937 |
+
**kwargs,
|
| 938 |
+
) -> tuple | MaskedLMOutput:
|
| 939 |
+
r"""
|
| 940 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 941 |
+
Labels for computing the masked language modeling loss. Indices should be in `[-100, 0, ...,
|
| 942 |
+
config.vocab_size]` (see `input_ids` docstring) Tokens with indices set to `-100` are ignored (masked), the
|
| 943 |
+
loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`
|
| 944 |
+
"""
|
| 945 |
+
|
| 946 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 947 |
+
|
| 948 |
+
outputs = self.deberta(
|
| 949 |
+
input_ids,
|
| 950 |
+
attention_mask=attention_mask,
|
| 951 |
+
token_type_ids=token_type_ids,
|
| 952 |
+
position_ids=position_ids,
|
| 953 |
+
inputs_embeds=inputs_embeds,
|
| 954 |
+
output_attentions=output_attentions,
|
| 955 |
+
output_hidden_states=output_hidden_states,
|
| 956 |
+
return_dict=return_dict,
|
| 957 |
+
)
|
| 958 |
+
|
| 959 |
+
sequence_output = outputs[0]
|
| 960 |
+
if self.legacy:
|
| 961 |
+
prediction_scores = self.cls(sequence_output)
|
| 962 |
+
else:
|
| 963 |
+
prediction_scores = self.lm_predictions(sequence_output, self.deberta.embeddings.word_embeddings)
|
| 964 |
+
|
| 965 |
+
masked_lm_loss = None
|
| 966 |
+
if labels is not None:
|
| 967 |
+
loss_fct = CrossEntropyLoss() # -100 index = padding token
|
| 968 |
+
masked_lm_loss = loss_fct(prediction_scores.view(-1, self.config.vocab_size), labels.view(-1))
|
| 969 |
+
|
| 970 |
+
if not return_dict:
|
| 971 |
+
output = (prediction_scores,) + outputs[1:]
|
| 972 |
+
return ((masked_lm_loss,) + output) if masked_lm_loss is not None else output
|
| 973 |
+
|
| 974 |
+
return MaskedLMOutput(
|
| 975 |
+
loss=masked_lm_loss,
|
| 976 |
+
logits=prediction_scores,
|
| 977 |
+
hidden_states=outputs.hidden_states,
|
| 978 |
+
attentions=outputs.attentions,
|
| 979 |
+
)
|
| 980 |
+
|
| 981 |
+
|
| 982 |
+
# Copied from transformers.models.deberta.modeling_deberta.ContextPooler
|
| 983 |
+
class ContextPooler(nn.Module):
|
| 984 |
+
def __init__(self, config):
|
| 985 |
+
super().__init__()
|
| 986 |
+
self.dense = nn.Linear(config.pooler_hidden_size, config.pooler_hidden_size)
|
| 987 |
+
self.dropout = nn.Dropout(config.pooler_dropout)
|
| 988 |
+
self.config = config
|
| 989 |
+
|
| 990 |
+
def forward(self, hidden_states):
|
| 991 |
+
# We "pool" the model by simply taking the hidden state corresponding
|
| 992 |
+
# to the first token.
|
| 993 |
+
|
| 994 |
+
context_token = hidden_states[:, 0]
|
| 995 |
+
context_token = self.dropout(context_token)
|
| 996 |
+
pooled_output = self.dense(context_token)
|
| 997 |
+
pooled_output = ACT2FN[self.config.pooler_hidden_act](pooled_output)
|
| 998 |
+
return pooled_output
|
| 999 |
+
|
| 1000 |
+
@property
|
| 1001 |
+
def output_dim(self):
|
| 1002 |
+
return self.config.hidden_size
|
| 1003 |
+
|
| 1004 |
+
|
| 1005 |
+
@auto_docstring(
|
| 1006 |
+
custom_intro="""
|
| 1007 |
+
DeBERTa Model transformer with a sequence classification/regression head on top (a linear layer on top of the
|
| 1008 |
+
pooled output) e.g. for GLUE tasks.
|
| 1009 |
+
"""
|
| 1010 |
+
)
|
| 1011 |
+
class DebertaV2ForSequenceClassification(DebertaV2PreTrainedModel):
|
| 1012 |
+
def __init__(self, config):
|
| 1013 |
+
super().__init__(config)
|
| 1014 |
+
|
| 1015 |
+
num_labels = getattr(config, "num_labels", 2)
|
| 1016 |
+
self.num_labels = num_labels
|
| 1017 |
+
|
| 1018 |
+
self.deberta = DebertaV2Model(config)
|
| 1019 |
+
self.pooler = ContextPooler(config)
|
| 1020 |
+
output_dim = self.pooler.output_dim
|
| 1021 |
+
|
| 1022 |
+
self.classifier = nn.Linear(output_dim, num_labels)
|
| 1023 |
+
drop_out = getattr(config, "cls_dropout", None)
|
| 1024 |
+
drop_out = self.config.hidden_dropout_prob if drop_out is None else drop_out
|
| 1025 |
+
self.dropout = nn.Dropout(drop_out)
|
| 1026 |
+
|
| 1027 |
+
# Initialize weights and apply final processing
|
| 1028 |
+
self.post_init()
|
| 1029 |
+
|
| 1030 |
+
def get_input_embeddings(self):
|
| 1031 |
+
return self.deberta.get_input_embeddings()
|
| 1032 |
+
|
| 1033 |
+
def set_input_embeddings(self, new_embeddings):
|
| 1034 |
+
self.deberta.set_input_embeddings(new_embeddings)
|
| 1035 |
+
|
| 1036 |
+
@auto_docstring
|
| 1037 |
+
# Copied from transformers.models.deberta.modeling_deberta.DebertaForSequenceClassification.forward with Deberta->DebertaV2
|
| 1038 |
+
def forward(
|
| 1039 |
+
self,
|
| 1040 |
+
input_ids: torch.Tensor | None = None,
|
| 1041 |
+
attention_mask: torch.Tensor | None = None,
|
| 1042 |
+
token_type_ids: torch.Tensor | None = None,
|
| 1043 |
+
position_ids: torch.Tensor | None = None,
|
| 1044 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 1045 |
+
labels: torch.Tensor | None = None,
|
| 1046 |
+
output_attentions: bool | None = None,
|
| 1047 |
+
output_hidden_states: bool | None = None,
|
| 1048 |
+
return_dict: bool | None = None,
|
| 1049 |
+
**kwargs,
|
| 1050 |
+
) -> tuple | SequenceClassifierOutput:
|
| 1051 |
+
r"""
|
| 1052 |
+
labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
|
| 1053 |
+
Labels for computing the sequence classification/regression loss. Indices should be in `[0, ...,
|
| 1054 |
+
config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If
|
| 1055 |
+
`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
| 1056 |
+
"""
|
| 1057 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 1058 |
+
|
| 1059 |
+
outputs = self.deberta(
|
| 1060 |
+
input_ids,
|
| 1061 |
+
token_type_ids=token_type_ids,
|
| 1062 |
+
attention_mask=attention_mask,
|
| 1063 |
+
position_ids=position_ids,
|
| 1064 |
+
inputs_embeds=inputs_embeds,
|
| 1065 |
+
output_attentions=output_attentions,
|
| 1066 |
+
output_hidden_states=output_hidden_states,
|
| 1067 |
+
return_dict=return_dict,
|
| 1068 |
+
)
|
| 1069 |
+
|
| 1070 |
+
encoder_layer = outputs[0]
|
| 1071 |
+
pooled_output = self.pooler(encoder_layer)
|
| 1072 |
+
pooled_output = self.dropout(pooled_output)
|
| 1073 |
+
logits = self.classifier(pooled_output)
|
| 1074 |
+
|
| 1075 |
+
loss = None
|
| 1076 |
+
if labels is not None:
|
| 1077 |
+
if self.config.problem_type is None:
|
| 1078 |
+
if self.num_labels == 1:
|
| 1079 |
+
# regression task
|
| 1080 |
+
loss_fn = nn.MSELoss()
|
| 1081 |
+
logits = logits.view(-1).to(labels.dtype)
|
| 1082 |
+
loss = loss_fn(logits, labels.view(-1))
|
| 1083 |
+
elif labels.dim() == 1 or labels.size(-1) == 1:
|
| 1084 |
+
label_index = (labels >= 0).nonzero()
|
| 1085 |
+
labels = labels.long()
|
| 1086 |
+
if label_index.size(0) > 0:
|
| 1087 |
+
labeled_logits = torch.gather(
|
| 1088 |
+
logits, 0, label_index.expand(label_index.size(0), logits.size(1))
|
| 1089 |
+
)
|
| 1090 |
+
labels = torch.gather(labels, 0, label_index.view(-1))
|
| 1091 |
+
loss_fct = CrossEntropyLoss()
|
| 1092 |
+
loss = loss_fct(labeled_logits.view(-1, self.num_labels).float(), labels.view(-1))
|
| 1093 |
+
else:
|
| 1094 |
+
loss = torch.tensor(0).to(logits)
|
| 1095 |
+
else:
|
| 1096 |
+
log_softmax = nn.LogSoftmax(-1)
|
| 1097 |
+
loss = -((log_softmax(logits) * labels).sum(-1)).mean()
|
| 1098 |
+
elif self.config.problem_type == "regression":
|
| 1099 |
+
loss_fct = MSELoss()
|
| 1100 |
+
if self.num_labels == 1:
|
| 1101 |
+
loss = loss_fct(logits.squeeze(), labels.squeeze())
|
| 1102 |
+
else:
|
| 1103 |
+
loss = loss_fct(logits, labels)
|
| 1104 |
+
elif self.config.problem_type == "single_label_classification":
|
| 1105 |
+
loss_fct = CrossEntropyLoss()
|
| 1106 |
+
loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
|
| 1107 |
+
elif self.config.problem_type == "multi_label_classification":
|
| 1108 |
+
loss_fct = BCEWithLogitsLoss()
|
| 1109 |
+
loss = loss_fct(logits, labels)
|
| 1110 |
+
if not return_dict:
|
| 1111 |
+
output = (logits,) + outputs[1:]
|
| 1112 |
+
return ((loss,) + output) if loss is not None else output
|
| 1113 |
+
|
| 1114 |
+
return SequenceClassifierOutput(
|
| 1115 |
+
loss=loss, logits=logits, hidden_states=outputs.hidden_states, attentions=outputs.attentions
|
| 1116 |
+
)
|
| 1117 |
+
|
| 1118 |
+
|
| 1119 |
+
@auto_docstring
|
| 1120 |
+
# Copied from transformers.models.deberta.modeling_deberta.DebertaForTokenClassification with Deberta->DebertaV2
|
| 1121 |
+
class DebertaV2ForTokenClassification(DebertaV2PreTrainedModel):
|
| 1122 |
+
def __init__(self, config):
|
| 1123 |
+
super().__init__(config)
|
| 1124 |
+
self.num_labels = config.num_labels
|
| 1125 |
+
|
| 1126 |
+
self.deberta = DebertaV2Model(config)
|
| 1127 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 1128 |
+
self.classifier = nn.Linear(config.hidden_size, config.num_labels)
|
| 1129 |
+
|
| 1130 |
+
# Initialize weights and apply final processing
|
| 1131 |
+
self.post_init()
|
| 1132 |
+
|
| 1133 |
+
@auto_docstring
|
| 1134 |
+
def forward(
|
| 1135 |
+
self,
|
| 1136 |
+
input_ids: torch.Tensor | None = None,
|
| 1137 |
+
attention_mask: torch.Tensor | None = None,
|
| 1138 |
+
token_type_ids: torch.Tensor | None = None,
|
| 1139 |
+
position_ids: torch.Tensor | None = None,
|
| 1140 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 1141 |
+
labels: torch.Tensor | None = None,
|
| 1142 |
+
output_attentions: bool | None = None,
|
| 1143 |
+
output_hidden_states: bool | None = None,
|
| 1144 |
+
return_dict: bool | None = None,
|
| 1145 |
+
**kwargs,
|
| 1146 |
+
) -> tuple | TokenClassifierOutput:
|
| 1147 |
+
r"""
|
| 1148 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 1149 |
+
Labels for computing the token classification loss. Indices should be in `[0, ..., config.num_labels - 1]`.
|
| 1150 |
+
"""
|
| 1151 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 1152 |
+
|
| 1153 |
+
outputs = self.deberta(
|
| 1154 |
+
input_ids,
|
| 1155 |
+
attention_mask=attention_mask,
|
| 1156 |
+
token_type_ids=token_type_ids,
|
| 1157 |
+
position_ids=position_ids,
|
| 1158 |
+
inputs_embeds=inputs_embeds,
|
| 1159 |
+
output_attentions=output_attentions,
|
| 1160 |
+
output_hidden_states=output_hidden_states,
|
| 1161 |
+
return_dict=return_dict,
|
| 1162 |
+
)
|
| 1163 |
+
|
| 1164 |
+
sequence_output = outputs[0]
|
| 1165 |
+
|
| 1166 |
+
sequence_output = self.dropout(sequence_output)
|
| 1167 |
+
logits = self.classifier(sequence_output)
|
| 1168 |
+
|
| 1169 |
+
loss = None
|
| 1170 |
+
if labels is not None:
|
| 1171 |
+
loss_fct = CrossEntropyLoss()
|
| 1172 |
+
loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
|
| 1173 |
+
|
| 1174 |
+
if not return_dict:
|
| 1175 |
+
output = (logits,) + outputs[1:]
|
| 1176 |
+
return ((loss,) + output) if loss is not None else output
|
| 1177 |
+
|
| 1178 |
+
return TokenClassifierOutput(
|
| 1179 |
+
loss=loss, logits=logits, hidden_states=outputs.hidden_states, attentions=outputs.attentions
|
| 1180 |
+
)
|
| 1181 |
+
|
| 1182 |
+
|
| 1183 |
+
@auto_docstring
|
| 1184 |
+
class DebertaV2ForQuestionAnswering(DebertaV2PreTrainedModel):
|
| 1185 |
+
def __init__(self, config):
|
| 1186 |
+
super().__init__(config)
|
| 1187 |
+
self.num_labels = config.num_labels
|
| 1188 |
+
|
| 1189 |
+
self.deberta = DebertaV2Model(config)
|
| 1190 |
+
self.qa_outputs = nn.Linear(config.hidden_size, config.num_labels)
|
| 1191 |
+
|
| 1192 |
+
# Initialize weights and apply final processing
|
| 1193 |
+
self.post_init()
|
| 1194 |
+
|
| 1195 |
+
@auto_docstring
|
| 1196 |
+
# Copied from transformers.models.deberta.modeling_deberta.DebertaForQuestionAnswering.forward with Deberta->DebertaV2
|
| 1197 |
+
def forward(
|
| 1198 |
+
self,
|
| 1199 |
+
input_ids: torch.Tensor | None = None,
|
| 1200 |
+
attention_mask: torch.Tensor | None = None,
|
| 1201 |
+
token_type_ids: torch.Tensor | None = None,
|
| 1202 |
+
position_ids: torch.Tensor | None = None,
|
| 1203 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 1204 |
+
start_positions: torch.Tensor | None = None,
|
| 1205 |
+
end_positions: torch.Tensor | None = None,
|
| 1206 |
+
output_attentions: bool | None = None,
|
| 1207 |
+
output_hidden_states: bool | None = None,
|
| 1208 |
+
return_dict: bool | None = None,
|
| 1209 |
+
**kwargs,
|
| 1210 |
+
) -> tuple | QuestionAnsweringModelOutput:
|
| 1211 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 1212 |
+
|
| 1213 |
+
outputs = self.deberta(
|
| 1214 |
+
input_ids,
|
| 1215 |
+
attention_mask=attention_mask,
|
| 1216 |
+
token_type_ids=token_type_ids,
|
| 1217 |
+
position_ids=position_ids,
|
| 1218 |
+
inputs_embeds=inputs_embeds,
|
| 1219 |
+
output_attentions=output_attentions,
|
| 1220 |
+
output_hidden_states=output_hidden_states,
|
| 1221 |
+
return_dict=return_dict,
|
| 1222 |
+
)
|
| 1223 |
+
|
| 1224 |
+
sequence_output = outputs[0]
|
| 1225 |
+
|
| 1226 |
+
logits = self.qa_outputs(sequence_output)
|
| 1227 |
+
start_logits, end_logits = logits.split(1, dim=-1)
|
| 1228 |
+
start_logits = start_logits.squeeze(-1).contiguous()
|
| 1229 |
+
end_logits = end_logits.squeeze(-1).contiguous()
|
| 1230 |
+
|
| 1231 |
+
total_loss = None
|
| 1232 |
+
if start_positions is not None and end_positions is not None:
|
| 1233 |
+
# If we are on multi-GPU, split add a dimension
|
| 1234 |
+
if len(start_positions.size()) > 1:
|
| 1235 |
+
start_positions = start_positions.squeeze(-1)
|
| 1236 |
+
if len(end_positions.size()) > 1:
|
| 1237 |
+
end_positions = end_positions.squeeze(-1)
|
| 1238 |
+
# sometimes the start/end positions are outside our model inputs, we ignore these terms
|
| 1239 |
+
ignored_index = start_logits.size(1)
|
| 1240 |
+
start_positions = start_positions.clamp(0, ignored_index)
|
| 1241 |
+
end_positions = end_positions.clamp(0, ignored_index)
|
| 1242 |
+
|
| 1243 |
+
loss_fct = CrossEntropyLoss(ignore_index=ignored_index)
|
| 1244 |
+
start_loss = loss_fct(start_logits, start_positions)
|
| 1245 |
+
end_loss = loss_fct(end_logits, end_positions)
|
| 1246 |
+
total_loss = (start_loss + end_loss) / 2
|
| 1247 |
+
|
| 1248 |
+
if not return_dict:
|
| 1249 |
+
output = (start_logits, end_logits) + outputs[1:]
|
| 1250 |
+
return ((total_loss,) + output) if total_loss is not None else output
|
| 1251 |
+
|
| 1252 |
+
return QuestionAnsweringModelOutput(
|
| 1253 |
+
loss=total_loss,
|
| 1254 |
+
start_logits=start_logits,
|
| 1255 |
+
end_logits=end_logits,
|
| 1256 |
+
hidden_states=outputs.hidden_states,
|
| 1257 |
+
attentions=outputs.attentions,
|
| 1258 |
+
)
|
| 1259 |
+
|
| 1260 |
+
|
| 1261 |
+
@auto_docstring
|
| 1262 |
+
class DebertaV2ForMultipleChoice(DebertaV2PreTrainedModel):
|
| 1263 |
+
def __init__(self, config):
|
| 1264 |
+
super().__init__(config)
|
| 1265 |
+
|
| 1266 |
+
num_labels = getattr(config, "num_labels", 2)
|
| 1267 |
+
self.num_labels = num_labels
|
| 1268 |
+
|
| 1269 |
+
self.deberta = DebertaV2Model(config)
|
| 1270 |
+
self.pooler = ContextPooler(config)
|
| 1271 |
+
output_dim = self.pooler.output_dim
|
| 1272 |
+
|
| 1273 |
+
self.classifier = nn.Linear(output_dim, 1)
|
| 1274 |
+
drop_out = getattr(config, "cls_dropout", None)
|
| 1275 |
+
drop_out = self.config.hidden_dropout_prob if drop_out is None else drop_out
|
| 1276 |
+
self.dropout = nn.Dropout(drop_out)
|
| 1277 |
+
|
| 1278 |
+
self.post_init()
|
| 1279 |
+
|
| 1280 |
+
def get_input_embeddings(self):
|
| 1281 |
+
return self.deberta.get_input_embeddings()
|
| 1282 |
+
|
| 1283 |
+
def set_input_embeddings(self, new_embeddings):
|
| 1284 |
+
self.deberta.set_input_embeddings(new_embeddings)
|
| 1285 |
+
|
| 1286 |
+
@auto_docstring
|
| 1287 |
+
def forward(
|
| 1288 |
+
self,
|
| 1289 |
+
input_ids: torch.Tensor | None = None,
|
| 1290 |
+
attention_mask: torch.Tensor | None = None,
|
| 1291 |
+
token_type_ids: torch.Tensor | None = None,
|
| 1292 |
+
position_ids: torch.Tensor | None = None,
|
| 1293 |
+
inputs_embeds: torch.Tensor | None = None,
|
| 1294 |
+
labels: torch.Tensor | None = None,
|
| 1295 |
+
output_attentions: bool | None = None,
|
| 1296 |
+
output_hidden_states: bool | None = None,
|
| 1297 |
+
return_dict: bool | None = None,
|
| 1298 |
+
**kwargs,
|
| 1299 |
+
) -> tuple | MultipleChoiceModelOutput:
|
| 1300 |
+
r"""
|
| 1301 |
+
labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
|
| 1302 |
+
Labels for computing the multiple choice classification loss. Indices should be in `[0, ...,
|
| 1303 |
+
num_choices-1]` where `num_choices` is the size of the second dimension of the input tensors. (See
|
| 1304 |
+
`input_ids` above)
|
| 1305 |
+
"""
|
| 1306 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 1307 |
+
num_choices = input_ids.shape[1] if input_ids is not None else inputs_embeds.shape[1]
|
| 1308 |
+
|
| 1309 |
+
flat_input_ids = input_ids.view(-1, input_ids.size(-1)) if input_ids is not None else None
|
| 1310 |
+
flat_position_ids = position_ids.view(-1, position_ids.size(-1)) if position_ids is not None else None
|
| 1311 |
+
flat_token_type_ids = token_type_ids.view(-1, token_type_ids.size(-1)) if token_type_ids is not None else None
|
| 1312 |
+
flat_attention_mask = attention_mask.view(-1, attention_mask.size(-1)) if attention_mask is not None else None
|
| 1313 |
+
flat_inputs_embeds = (
|
| 1314 |
+
inputs_embeds.view(-1, inputs_embeds.size(-2), inputs_embeds.size(-1))
|
| 1315 |
+
if inputs_embeds is not None
|
| 1316 |
+
else None
|
| 1317 |
+
)
|
| 1318 |
+
|
| 1319 |
+
outputs = self.deberta(
|
| 1320 |
+
flat_input_ids,
|
| 1321 |
+
position_ids=flat_position_ids,
|
| 1322 |
+
token_type_ids=flat_token_type_ids,
|
| 1323 |
+
attention_mask=flat_attention_mask,
|
| 1324 |
+
inputs_embeds=flat_inputs_embeds,
|
| 1325 |
+
output_attentions=output_attentions,
|
| 1326 |
+
output_hidden_states=output_hidden_states,
|
| 1327 |
+
return_dict=return_dict,
|
| 1328 |
+
)
|
| 1329 |
+
|
| 1330 |
+
encoder_layer = outputs[0]
|
| 1331 |
+
pooled_output = self.pooler(encoder_layer)
|
| 1332 |
+
pooled_output = self.dropout(pooled_output)
|
| 1333 |
+
logits = self.classifier(pooled_output)
|
| 1334 |
+
reshaped_logits = logits.view(-1, num_choices)
|
| 1335 |
+
|
| 1336 |
+
loss = None
|
| 1337 |
+
if labels is not None:
|
| 1338 |
+
loss_fct = CrossEntropyLoss()
|
| 1339 |
+
loss = loss_fct(reshaped_logits, labels)
|
| 1340 |
+
|
| 1341 |
+
if not return_dict:
|
| 1342 |
+
output = (reshaped_logits,) + outputs[1:]
|
| 1343 |
+
return ((loss,) + output) if loss is not None else output
|
| 1344 |
+
|
| 1345 |
+
return MultipleChoiceModelOutput(
|
| 1346 |
+
loss=loss,
|
| 1347 |
+
logits=reshaped_logits,
|
| 1348 |
+
hidden_states=outputs.hidden_states,
|
| 1349 |
+
attentions=outputs.attentions,
|
| 1350 |
+
)
|
| 1351 |
+
|
| 1352 |
+
|
| 1353 |
+
__all__ = [
|
| 1354 |
+
"DebertaV2ForMaskedLM",
|
| 1355 |
+
"DebertaV2ForMultipleChoice",
|
| 1356 |
+
"DebertaV2ForQuestionAnswering",
|
| 1357 |
+
"DebertaV2ForSequenceClassification",
|
| 1358 |
+
"DebertaV2ForTokenClassification",
|
| 1359 |
+
"DebertaV2Model",
|
| 1360 |
+
"DebertaV2PreTrainedModel",
|
| 1361 |
+
]
|
third_party/transformers/src/transformers/models/deberta_v2/tokenization_deberta_v2.py
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 Microsoft and the HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Tokenization class for model DeBERTa-v2."""
|
| 15 |
+
|
| 16 |
+
from tokenizers import Regex, Tokenizer, decoders, normalizers, pre_tokenizers, processors
|
| 17 |
+
from tokenizers.models import Unigram
|
| 18 |
+
|
| 19 |
+
from ...tokenization_utils_tokenizers import TokenizersBackend
|
| 20 |
+
from ...utils import logging
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
logger = logging.get_logger(__name__)
|
| 24 |
+
|
| 25 |
+
VOCAB_FILES_NAMES = {"vocab_file": "spm.model", "tokenizer_file": "tokenizer.json"}
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
class DebertaV2Tokenizer(TokenizersBackend):
|
| 29 |
+
"""
|
| 30 |
+
Construct a DeBERTa-v2 tokenizer (backed by HuggingFace's *tokenizers* library). Based on Unigram tokenization.
|
| 31 |
+
|
| 32 |
+
This tokenizer inherits from [`TokenizersBackend`] which contains most of the main methods. Users should
|
| 33 |
+
refer to this superclass for more information regarding those methods.
|
| 34 |
+
|
| 35 |
+
Args:
|
| 36 |
+
vocab_file (`str`, *optional*):
|
| 37 |
+
Path to the vocabulary file (SentencePiece model file). Not used directly but kept for compatibility.
|
| 38 |
+
vocab (`str`, `dict` or `list`, *optional*):
|
| 39 |
+
List of tuples (piece, score) for the vocabulary.
|
| 40 |
+
precompiled_charsmap (`bytes`, *optional*):
|
| 41 |
+
Precompiled character map for normalization.
|
| 42 |
+
do_lower_case (`bool`, *optional*, defaults to `False`):
|
| 43 |
+
Whether or not to lowercase the input when tokenizing.
|
| 44 |
+
split_by_punct (`bool`, *optional*, defaults to `False`):
|
| 45 |
+
Whether to split by punctuation.
|
| 46 |
+
bos_token (`str`, *optional*, defaults to `"[CLS]"`):
|
| 47 |
+
The beginning of sequence token.
|
| 48 |
+
eos_token (`str`, *optional*, defaults to `"[SEP]"`):
|
| 49 |
+
The end of sequence token.
|
| 50 |
+
unk_token (`str`, *optional*, defaults to `"[UNK]"`):
|
| 51 |
+
The unknown token. A token that is not in the vocabulary cannot be converted to an ID and is set to be this
|
| 52 |
+
token instead.
|
| 53 |
+
sep_token (`str`, *optional*, defaults to `"[SEP]"`):
|
| 54 |
+
The separator token, which is used when building a sequence from multiple sequences, e.g. two sequences for
|
| 55 |
+
sequence classification or for a text and a question for question answering. It is also used as the last
|
| 56 |
+
token of a sequence built with special tokens.
|
| 57 |
+
pad_token (`str`, *optional*, defaults to `"[PAD]"`):
|
| 58 |
+
The token used for padding, for example when batching sequences of different lengths.
|
| 59 |
+
cls_token (`str`, *optional*, defaults to `"[CLS]"`):
|
| 60 |
+
The classifier token which is used when doing sequence classification (classification of the whole sequence
|
| 61 |
+
instead of per-token classification). It is the first token of the sequence when built with special tokens.
|
| 62 |
+
mask_token (`str`, *optional*, defaults to `"[MASK]"`):
|
| 63 |
+
The token used for masking values. This is the token used when training this model with masked language
|
| 64 |
+
modeling. This is the token which the model will try to predict.
|
| 65 |
+
add_prefix_space (`bool`, *optional*, defaults to `True`):
|
| 66 |
+
Whether or not to add an initial space to the input. This allows to treat the leading word just as any
|
| 67 |
+
other word.
|
| 68 |
+
unk_id (`int`, *optional*, defaults to index of `unk_token` in vocab):
|
| 69 |
+
The ID of the unknown token in the vocabulary.
|
| 70 |
+
"""
|
| 71 |
+
|
| 72 |
+
vocab_files_names = VOCAB_FILES_NAMES
|
| 73 |
+
model_input_names = ["input_ids", "attention_mask", "token_type_ids"]
|
| 74 |
+
model = Unigram
|
| 75 |
+
|
| 76 |
+
def __init__(
|
| 77 |
+
self,
|
| 78 |
+
vocab: str | dict | list | None = None,
|
| 79 |
+
do_lower_case=False,
|
| 80 |
+
split_by_punct=False,
|
| 81 |
+
bos_token="[CLS]",
|
| 82 |
+
eos_token="[SEP]",
|
| 83 |
+
unk_token="[UNK]",
|
| 84 |
+
sep_token="[SEP]",
|
| 85 |
+
pad_token="[PAD]",
|
| 86 |
+
cls_token="[CLS]",
|
| 87 |
+
mask_token="[MASK]",
|
| 88 |
+
add_prefix_space=True,
|
| 89 |
+
unk_id=1,
|
| 90 |
+
**kwargs,
|
| 91 |
+
):
|
| 92 |
+
self.do_lower_case = do_lower_case
|
| 93 |
+
self.split_by_punct = split_by_punct
|
| 94 |
+
self.add_prefix_space = add_prefix_space
|
| 95 |
+
|
| 96 |
+
if vocab is None:
|
| 97 |
+
vocab = [
|
| 98 |
+
(str(pad_token), 0.0),
|
| 99 |
+
(str(unk_token), 0.0),
|
| 100 |
+
(str(bos_token), 0.0),
|
| 101 |
+
(str(eos_token), 0.0),
|
| 102 |
+
(str(sep_token), 0.0),
|
| 103 |
+
(str(cls_token), 0.0),
|
| 104 |
+
(str(mask_token), 0.0),
|
| 105 |
+
]
|
| 106 |
+
unk_id = 1
|
| 107 |
+
elif isinstance(vocab, list):
|
| 108 |
+
unk_id = vocab.index((str(unk_token), 0.0)) if (str(unk_token), 0.0) in vocab else unk_id
|
| 109 |
+
|
| 110 |
+
self._vocab = vocab
|
| 111 |
+
self._tokenizer = Tokenizer(
|
| 112 |
+
Unigram(
|
| 113 |
+
self._vocab,
|
| 114 |
+
unk_id=unk_id,
|
| 115 |
+
byte_fallback=False,
|
| 116 |
+
)
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
list_normalizers = []
|
| 120 |
+
if do_lower_case:
|
| 121 |
+
list_normalizers.append(normalizers.Lowercase())
|
| 122 |
+
|
| 123 |
+
list_normalizers.extend(
|
| 124 |
+
[
|
| 125 |
+
normalizers.Replace(Regex(r"\s{2,}|[\n\r\t]"), " "),
|
| 126 |
+
normalizers.NFC(),
|
| 127 |
+
normalizers.Strip(left=False, right=True),
|
| 128 |
+
]
|
| 129 |
+
)
|
| 130 |
+
self._tokenizer.normalizer = normalizers.Sequence(list_normalizers)
|
| 131 |
+
|
| 132 |
+
list_pretokenizers = []
|
| 133 |
+
if split_by_punct:
|
| 134 |
+
list_pretokenizers.append(pre_tokenizers.Punctuation(behavior="isolated"))
|
| 135 |
+
|
| 136 |
+
prepend_scheme = "always" if add_prefix_space else "first"
|
| 137 |
+
list_pretokenizers.append(pre_tokenizers.Metaspace(replacement="▁", prepend_scheme=prepend_scheme))
|
| 138 |
+
|
| 139 |
+
self._tokenizer.pre_tokenizer = pre_tokenizers.Sequence(list_pretokenizers)
|
| 140 |
+
self._tokenizer.decoder = decoders.Metaspace(replacement="▁", prepend_scheme=prepend_scheme)
|
| 141 |
+
super().__init__(
|
| 142 |
+
bos_token=bos_token,
|
| 143 |
+
eos_token=eos_token,
|
| 144 |
+
unk_token=unk_token,
|
| 145 |
+
sep_token=sep_token,
|
| 146 |
+
cls_token=cls_token,
|
| 147 |
+
pad_token=pad_token,
|
| 148 |
+
mask_token=mask_token,
|
| 149 |
+
unk_id=unk_id,
|
| 150 |
+
do_lower_case=do_lower_case,
|
| 151 |
+
split_by_punct=split_by_punct,
|
| 152 |
+
add_prefix_space=add_prefix_space,
|
| 153 |
+
**kwargs,
|
| 154 |
+
)
|
| 155 |
+
|
| 156 |
+
cls_token_id = self.cls_token_id if self.cls_token_id is not None else 0
|
| 157 |
+
sep_token_id = self.sep_token_id if self.sep_token_id is not None else 0
|
| 158 |
+
|
| 159 |
+
self._tokenizer.post_processor = processors.TemplateProcessing(
|
| 160 |
+
single=f"{str(self.cls_token)}:0 $A:0 {str(self.sep_token)}:0",
|
| 161 |
+
pair=f"{str(self.cls_token)}:0 $A:0 {str(self.sep_token)}:0 $B:1 {str(self.sep_token)}:1",
|
| 162 |
+
special_tokens=[
|
| 163 |
+
(str(self.cls_token), cls_token_id),
|
| 164 |
+
(str(self.sep_token), sep_token_id),
|
| 165 |
+
],
|
| 166 |
+
)
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
__all__ = ["DebertaV2Tokenizer"]
|
third_party/transformers/src/transformers/models/depth_anything/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .configuration_depth_anything import *
|
| 22 |
+
from .modeling_depth_anything import *
|
| 23 |
+
else:
|
| 24 |
+
import sys
|
| 25 |
+
|
| 26 |
+
_file = globals()["__file__"]
|
| 27 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/depth_anything/configuration_depth_anything.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""DepthAnything model configuration"""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from ...backbone_utils import consolidate_backbone_kwargs_to_config
|
| 19 |
+
from ...configuration_utils import PreTrainedConfig
|
| 20 |
+
from ...utils import auto_docstring
|
| 21 |
+
from ..auto.configuration_auto import AutoConfig
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
@auto_docstring(checkpoint="LiheYoung/depth-anything-small-hf")
|
| 25 |
+
@strict
|
| 26 |
+
class DepthAnythingConfig(PreTrainedConfig):
|
| 27 |
+
r"""
|
| 28 |
+
reassemble_hidden_size (`int`, *optional*, defaults to 384):
|
| 29 |
+
The number of input channels of the reassemble layers.
|
| 30 |
+
reassemble_factors (`list[int]`, *optional*, defaults to `[4, 2, 1, 0.5]`):
|
| 31 |
+
The up/downsampling factors of the reassemble layers.
|
| 32 |
+
neck_hidden_sizes (`list[str]`, *optional*, defaults to `[48, 96, 192, 384]`):
|
| 33 |
+
The hidden sizes to project to for the feature maps of the backbone.
|
| 34 |
+
fusion_hidden_size (`int`, *optional*, defaults to 64):
|
| 35 |
+
The number of channels before fusion.
|
| 36 |
+
head_in_index (`int`, *optional*, defaults to -1):
|
| 37 |
+
The index of the features to use in the depth estimation head.
|
| 38 |
+
head_hidden_size (`int`, *optional*, defaults to 32):
|
| 39 |
+
The number of output channels in the second convolution of the depth estimation head.
|
| 40 |
+
depth_estimation_type (`str`, *optional*, defaults to `"relative"`):
|
| 41 |
+
The type of depth estimation to use. Can be one of `["relative", "metric"]`.
|
| 42 |
+
max_depth (`float`, *optional*):
|
| 43 |
+
The maximum depth to use for the "metric" depth estimation head. 20 should be used for indoor models
|
| 44 |
+
and 80 for outdoor models. For "relative" depth estimation, this value is ignored.
|
| 45 |
+
|
| 46 |
+
Example:
|
| 47 |
+
|
| 48 |
+
```python
|
| 49 |
+
>>> from transformers import DepthAnythingConfig, DepthAnythingForDepthEstimation
|
| 50 |
+
|
| 51 |
+
>>> # Initializing a DepthAnything small style configuration
|
| 52 |
+
>>> configuration = DepthAnythingConfig()
|
| 53 |
+
|
| 54 |
+
>>> # Initializing a model from the DepthAnything small style configuration
|
| 55 |
+
>>> model = DepthAnythingForDepthEstimation(configuration)
|
| 56 |
+
|
| 57 |
+
>>> # Accessing the model configuration
|
| 58 |
+
>>> configuration = model.config
|
| 59 |
+
```"""
|
| 60 |
+
|
| 61 |
+
model_type = "depth_anything"
|
| 62 |
+
sub_configs = {"backbone_config": AutoConfig}
|
| 63 |
+
|
| 64 |
+
backbone_config: dict | PreTrainedConfig | None = None
|
| 65 |
+
patch_size: int | list[int] | tuple[int, int] = 14
|
| 66 |
+
initializer_range: float = 0.02
|
| 67 |
+
reassemble_hidden_size: int = 384
|
| 68 |
+
reassemble_factors: list[int | float] | tuple[int | float, ...] = (4, 2, 1, 0.5)
|
| 69 |
+
neck_hidden_sizes: list[int] | tuple[int, ...] = (48, 96, 192, 384)
|
| 70 |
+
fusion_hidden_size: int = 64
|
| 71 |
+
head_in_index: int = -1
|
| 72 |
+
head_hidden_size: int = 32
|
| 73 |
+
depth_estimation_type: str = "relative"
|
| 74 |
+
max_depth: int | None = None
|
| 75 |
+
|
| 76 |
+
def __post_init__(self, **kwargs):
|
| 77 |
+
self.backbone_config, kwargs = consolidate_backbone_kwargs_to_config(
|
| 78 |
+
backbone_config=self.backbone_config,
|
| 79 |
+
default_config_type="dinov2",
|
| 80 |
+
default_config_kwargs={
|
| 81 |
+
"image_size": 518,
|
| 82 |
+
"hidden_size": 384,
|
| 83 |
+
"num_attention_heads": 6,
|
| 84 |
+
"out_indices": [9, 10, 11, 12],
|
| 85 |
+
"reshape_hidden_states": False,
|
| 86 |
+
},
|
| 87 |
+
**kwargs,
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
self.max_depth = self.max_depth if self.max_depth else 1
|
| 91 |
+
super().__post_init__(**kwargs)
|
| 92 |
+
|
| 93 |
+
def validate_architecture(self):
|
| 94 |
+
"""Part of `@strict`-powered validation. Validates the architecture of the config."""
|
| 95 |
+
if self.depth_estimation_type not in ["relative", "metric"]:
|
| 96 |
+
raise ValueError("depth_estimation_type must be one of ['relative', 'metric']")
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
__all__ = ["DepthAnythingConfig"]
|
third_party/transformers/src/transformers/models/depth_anything/convert_depth_anything_to_hf.py
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Convert Depth Anything checkpoints from the original repository. URL:
|
| 15 |
+
https://github.com/LiheYoung/Depth-Anything"""
|
| 16 |
+
|
| 17 |
+
import argparse
|
| 18 |
+
from io import BytesIO
|
| 19 |
+
from pathlib import Path
|
| 20 |
+
|
| 21 |
+
import httpx
|
| 22 |
+
import torch
|
| 23 |
+
from huggingface_hub import hf_hub_download
|
| 24 |
+
from PIL import Image
|
| 25 |
+
|
| 26 |
+
from transformers import DepthAnythingConfig, DepthAnythingForDepthEstimation, Dinov2Config, DPTImageProcessor
|
| 27 |
+
from transformers.utils import logging
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
logging.set_verbosity_info()
|
| 31 |
+
logger = logging.get_logger(__name__)
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def get_dpt_config(model_name):
|
| 35 |
+
if "small" in model_name:
|
| 36 |
+
out_indices = [3, 6, 9, 12] if "v2" in model_name else [9, 10, 11, 12]
|
| 37 |
+
backbone_config = Dinov2Config.from_pretrained(
|
| 38 |
+
"facebook/dinov2-small", out_indices=out_indices, apply_layernorm=True, reshape_hidden_states=False
|
| 39 |
+
)
|
| 40 |
+
fusion_hidden_size = 64
|
| 41 |
+
neck_hidden_sizes = [48, 96, 192, 384]
|
| 42 |
+
elif "base" in model_name:
|
| 43 |
+
out_indices = [3, 6, 9, 12] if "v2" in model_name else [9, 10, 11, 12]
|
| 44 |
+
backbone_config = Dinov2Config.from_pretrained(
|
| 45 |
+
"facebook/dinov2-base", out_indices=out_indices, apply_layernorm=True, reshape_hidden_states=False
|
| 46 |
+
)
|
| 47 |
+
fusion_hidden_size = 128
|
| 48 |
+
neck_hidden_sizes = [96, 192, 384, 768]
|
| 49 |
+
elif "large" in model_name:
|
| 50 |
+
out_indices = [5, 12, 18, 24] if "v2" in model_name else [21, 22, 23, 24]
|
| 51 |
+
backbone_config = Dinov2Config.from_pretrained(
|
| 52 |
+
"facebook/dinov2-large", out_indices=out_indices, apply_layernorm=True, reshape_hidden_states=False
|
| 53 |
+
)
|
| 54 |
+
fusion_hidden_size = 256
|
| 55 |
+
neck_hidden_sizes = [256, 512, 1024, 1024]
|
| 56 |
+
else:
|
| 57 |
+
raise NotImplementedError(f"Model not supported: {model_name}")
|
| 58 |
+
|
| 59 |
+
if "metric" in model_name:
|
| 60 |
+
depth_estimation_type = "metric"
|
| 61 |
+
max_depth = 20 if "indoor" in model_name else 80
|
| 62 |
+
else:
|
| 63 |
+
depth_estimation_type = "relative"
|
| 64 |
+
max_depth = None
|
| 65 |
+
|
| 66 |
+
config = DepthAnythingConfig(
|
| 67 |
+
reassemble_hidden_size=backbone_config.hidden_size,
|
| 68 |
+
patch_size=backbone_config.patch_size,
|
| 69 |
+
backbone_config=backbone_config,
|
| 70 |
+
fusion_hidden_size=fusion_hidden_size,
|
| 71 |
+
neck_hidden_sizes=neck_hidden_sizes,
|
| 72 |
+
depth_estimation_type=depth_estimation_type,
|
| 73 |
+
max_depth=max_depth,
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
+
return config
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def create_rename_keys(config):
|
| 80 |
+
rename_keys = []
|
| 81 |
+
|
| 82 |
+
# fmt: off
|
| 83 |
+
# stem
|
| 84 |
+
rename_keys.append(("pretrained.cls_token", "backbone.embeddings.cls_token"))
|
| 85 |
+
rename_keys.append(("pretrained.mask_token", "backbone.embeddings.mask_token"))
|
| 86 |
+
rename_keys.append(("pretrained.pos_embed", "backbone.embeddings.position_embeddings"))
|
| 87 |
+
rename_keys.append(("pretrained.patch_embed.proj.weight", "backbone.embeddings.patch_embeddings.projection.weight"))
|
| 88 |
+
rename_keys.append(("pretrained.patch_embed.proj.bias", "backbone.embeddings.patch_embeddings.projection.bias"))
|
| 89 |
+
|
| 90 |
+
# Transformer encoder
|
| 91 |
+
for i in range(config.backbone_config.num_hidden_layers):
|
| 92 |
+
rename_keys.append((f"pretrained.blocks.{i}.ls1.gamma", f"backbone.encoder.layer.{i}.layer_scale1.lambda1"))
|
| 93 |
+
rename_keys.append((f"pretrained.blocks.{i}.ls2.gamma", f"backbone.encoder.layer.{i}.layer_scale2.lambda1"))
|
| 94 |
+
rename_keys.append((f"pretrained.blocks.{i}.norm1.weight", f"backbone.encoder.layer.{i}.norm1.weight"))
|
| 95 |
+
rename_keys.append((f"pretrained.blocks.{i}.norm1.bias", f"backbone.encoder.layer.{i}.norm1.bias"))
|
| 96 |
+
rename_keys.append((f"pretrained.blocks.{i}.norm2.weight", f"backbone.encoder.layer.{i}.norm2.weight"))
|
| 97 |
+
rename_keys.append((f"pretrained.blocks.{i}.norm2.bias", f"backbone.encoder.layer.{i}.norm2.bias"))
|
| 98 |
+
rename_keys.append((f"pretrained.blocks.{i}.mlp.fc1.weight", f"backbone.encoder.layer.{i}.mlp.fc1.weight"))
|
| 99 |
+
rename_keys.append((f"pretrained.blocks.{i}.mlp.fc1.bias", f"backbone.encoder.layer.{i}.mlp.fc1.bias"))
|
| 100 |
+
rename_keys.append((f"pretrained.blocks.{i}.mlp.fc2.weight", f"backbone.encoder.layer.{i}.mlp.fc2.weight"))
|
| 101 |
+
rename_keys.append((f"pretrained.blocks.{i}.mlp.fc2.bias", f"backbone.encoder.layer.{i}.mlp.fc2.bias"))
|
| 102 |
+
rename_keys.append((f"pretrained.blocks.{i}.attn.proj.weight", f"backbone.encoder.layer.{i}.attention.output.dense.weight"))
|
| 103 |
+
rename_keys.append((f"pretrained.blocks.{i}.attn.proj.bias", f"backbone.encoder.layer.{i}.attention.output.dense.bias"))
|
| 104 |
+
|
| 105 |
+
# Head
|
| 106 |
+
rename_keys.append(("pretrained.norm.weight", "backbone.layernorm.weight"))
|
| 107 |
+
rename_keys.append(("pretrained.norm.bias", "backbone.layernorm.bias"))
|
| 108 |
+
|
| 109 |
+
# activation postprocessing (readout projections + resize blocks)
|
| 110 |
+
# Depth Anything does not use CLS token => readout_projects not required
|
| 111 |
+
|
| 112 |
+
for i in range(4):
|
| 113 |
+
rename_keys.append((f"depth_head.projects.{i}.weight", f"neck.reassemble_stage.layers.{i}.projection.weight"))
|
| 114 |
+
rename_keys.append((f"depth_head.projects.{i}.bias", f"neck.reassemble_stage.layers.{i}.projection.bias"))
|
| 115 |
+
|
| 116 |
+
if i != 2:
|
| 117 |
+
rename_keys.append((f"depth_head.resize_layers.{i}.weight", f"neck.reassemble_stage.layers.{i}.resize.weight"))
|
| 118 |
+
rename_keys.append((f"depth_head.resize_layers.{i}.bias", f"neck.reassemble_stage.layers.{i}.resize.bias"))
|
| 119 |
+
|
| 120 |
+
# refinenet (tricky here)
|
| 121 |
+
mapping = {1:3, 2:2, 3:1, 4:0}
|
| 122 |
+
|
| 123 |
+
for i in range(1, 5):
|
| 124 |
+
j = mapping[i]
|
| 125 |
+
rename_keys.append((f"depth_head.scratch.refinenet{i}.out_conv.weight", f"neck.fusion_stage.layers.{j}.projection.weight"))
|
| 126 |
+
rename_keys.append((f"depth_head.scratch.refinenet{i}.out_conv.bias", f"neck.fusion_stage.layers.{j}.projection.bias"))
|
| 127 |
+
rename_keys.append((f"depth_head.scratch.refinenet{i}.resConfUnit1.conv1.weight", f"neck.fusion_stage.layers.{j}.residual_layer1.convolution1.weight"))
|
| 128 |
+
rename_keys.append((f"depth_head.scratch.refinenet{i}.resConfUnit1.conv1.bias", f"neck.fusion_stage.layers.{j}.residual_layer1.convolution1.bias"))
|
| 129 |
+
rename_keys.append((f"depth_head.scratch.refinenet{i}.resConfUnit1.conv2.weight", f"neck.fusion_stage.layers.{j}.residual_layer1.convolution2.weight"))
|
| 130 |
+
rename_keys.append((f"depth_head.scratch.refinenet{i}.resConfUnit1.conv2.bias", f"neck.fusion_stage.layers.{j}.residual_layer1.convolution2.bias"))
|
| 131 |
+
rename_keys.append((f"depth_head.scratch.refinenet{i}.resConfUnit2.conv1.weight", f"neck.fusion_stage.layers.{j}.residual_layer2.convolution1.weight"))
|
| 132 |
+
rename_keys.append((f"depth_head.scratch.refinenet{i}.resConfUnit2.conv1.bias", f"neck.fusion_stage.layers.{j}.residual_layer2.convolution1.bias"))
|
| 133 |
+
rename_keys.append((f"depth_head.scratch.refinenet{i}.resConfUnit2.conv2.weight", f"neck.fusion_stage.layers.{j}.residual_layer2.convolution2.weight"))
|
| 134 |
+
rename_keys.append((f"depth_head.scratch.refinenet{i}.resConfUnit2.conv2.bias", f"neck.fusion_stage.layers.{j}.residual_layer2.convolution2.bias"))
|
| 135 |
+
|
| 136 |
+
# scratch convolutions
|
| 137 |
+
for i in range(4):
|
| 138 |
+
rename_keys.append((f"depth_head.scratch.layer{i+1}_rn.weight", f"neck.convs.{i}.weight"))
|
| 139 |
+
|
| 140 |
+
# head
|
| 141 |
+
rename_keys.append(("depth_head.scratch.output_conv1.weight", "head.conv1.weight"))
|
| 142 |
+
rename_keys.append(("depth_head.scratch.output_conv1.bias", "head.conv1.bias"))
|
| 143 |
+
rename_keys.append(("depth_head.scratch.output_conv2.0.weight", "head.conv2.weight"))
|
| 144 |
+
rename_keys.append(("depth_head.scratch.output_conv2.0.bias", "head.conv2.bias"))
|
| 145 |
+
rename_keys.append(("depth_head.scratch.output_conv2.2.weight", "head.conv3.weight"))
|
| 146 |
+
rename_keys.append(("depth_head.scratch.output_conv2.2.bias", "head.conv3.bias"))
|
| 147 |
+
|
| 148 |
+
return rename_keys
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
# we split up the matrix of each encoder layer into queries, keys and values
|
| 152 |
+
def read_in_q_k_v(state_dict, config):
|
| 153 |
+
hidden_size = config.backbone_config.hidden_size
|
| 154 |
+
for i in range(config.backbone_config.num_hidden_layers):
|
| 155 |
+
# read in weights + bias of input projection layer (in original implementation, this is a single matrix + bias)
|
| 156 |
+
in_proj_weight = state_dict.pop(f"pretrained.blocks.{i}.attn.qkv.weight")
|
| 157 |
+
in_proj_bias = state_dict.pop(f"pretrained.blocks.{i}.attn.qkv.bias")
|
| 158 |
+
# next, add query, keys and values (in that order) to the state dict
|
| 159 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.query.weight"] = in_proj_weight[:hidden_size, :]
|
| 160 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.query.bias"] = in_proj_bias[:hidden_size]
|
| 161 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.key.weight"] = in_proj_weight[
|
| 162 |
+
hidden_size : hidden_size * 2, :
|
| 163 |
+
]
|
| 164 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.key.bias"] = in_proj_bias[
|
| 165 |
+
hidden_size : hidden_size * 2
|
| 166 |
+
]
|
| 167 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.value.weight"] = in_proj_weight[-hidden_size:, :]
|
| 168 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.value.bias"] = in_proj_bias[-hidden_size:]
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
def rename_key(dct, old, new):
|
| 172 |
+
val = dct.pop(old)
|
| 173 |
+
dct[new] = val
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
# We will verify our results on an image of cute cats
|
| 177 |
+
def prepare_img():
|
| 178 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 179 |
+
with httpx.stream("GET", url) as response:
|
| 180 |
+
image = Image.open(BytesIO(response.read()))
|
| 181 |
+
return image
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
name_to_checkpoint = {
|
| 185 |
+
"depth-anything-small": "pytorch_model.bin",
|
| 186 |
+
"depth-anything-base": "pytorch_model.bin",
|
| 187 |
+
"depth-anything-large": "pytorch_model.bin",
|
| 188 |
+
"depth-anything-v2-small": "depth_anything_v2_vits.pth",
|
| 189 |
+
"depth-anything-v2-base": "depth_anything_v2_vitb.pth",
|
| 190 |
+
"depth-anything-v2-large": "depth_anything_v2_vitl.pth",
|
| 191 |
+
"depth-anything-v2-metric-indoor-small": "depth_anything_v2_metric_hypersim_vits.pth",
|
| 192 |
+
"depth-anything-v2-metric-indoor-base": "depth_anything_v2_metric_hypersim_vitb.pth",
|
| 193 |
+
"depth-anything-v2-metric-indoor-large": "depth_anything_v2_metric_hypersim_vitl.pth",
|
| 194 |
+
"depth-anything-v2-metric-outdoor-small": "depth_anything_v2_metric_vkitti_vits.pth",
|
| 195 |
+
"depth-anything-v2-metric-outdoor-base": "depth_anything_v2_metric_vkitti_vitb.pth",
|
| 196 |
+
"depth-anything-v2-metric-outdoor-large": "depth_anything_v2_metric_vkitti_vitl.pth",
|
| 197 |
+
# v2-giant pending
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
|
| 201 |
+
@torch.no_grad()
|
| 202 |
+
def convert_dpt_checkpoint(model_name, pytorch_dump_folder_path, push_to_hub, verify_logits):
|
| 203 |
+
"""
|
| 204 |
+
Copy/paste/tweak model's weights to our DPT structure.
|
| 205 |
+
"""
|
| 206 |
+
|
| 207 |
+
# define DPT configuration
|
| 208 |
+
config = get_dpt_config(model_name)
|
| 209 |
+
|
| 210 |
+
model_name_to_repo = {
|
| 211 |
+
"depth-anything-small": "LiheYoung/depth_anything_vits14",
|
| 212 |
+
"depth-anything-base": "LiheYoung/depth_anything_vitb14",
|
| 213 |
+
"depth-anything-large": "LiheYoung/depth_anything_vitl14",
|
| 214 |
+
"depth-anything-v2-small": "depth-anything/Depth-Anything-V2-Small",
|
| 215 |
+
"depth-anything-v2-base": "depth-anything/Depth-Anything-V2-Base",
|
| 216 |
+
"depth-anything-v2-large": "depth-anything/Depth-Anything-V2-Large",
|
| 217 |
+
"depth-anything-v2-metric-indoor-small": "depth-anything/Depth-Anything-V2-Metric-Hypersim-Small",
|
| 218 |
+
"depth-anything-v2-metric-indoor-base": "depth-anything/Depth-Anything-V2-Metric-Hypersim-Base",
|
| 219 |
+
"depth-anything-v2-metric-indoor-large": "depth-anything/Depth-Anything-V2-Metric-Hypersim-Large",
|
| 220 |
+
"depth-anything-v2-metric-outdoor-small": "depth-anything/Depth-Anything-V2-Metric-VKITTI-Small",
|
| 221 |
+
"depth-anything-v2-metric-outdoor-base": "depth-anything/Depth-Anything-V2-Metric-VKITTI-Base",
|
| 222 |
+
"depth-anything-v2-metric-outdoor-large": "depth-anything/Depth-Anything-V2-Metric-VKITTI-Large",
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
# load original state_dict
|
| 226 |
+
repo_id = model_name_to_repo[model_name]
|
| 227 |
+
filename = name_to_checkpoint[model_name]
|
| 228 |
+
filepath = hf_hub_download(
|
| 229 |
+
repo_id=repo_id,
|
| 230 |
+
filename=f"{filename}",
|
| 231 |
+
)
|
| 232 |
+
|
| 233 |
+
state_dict = torch.load(filepath, map_location="cpu", weights_only=True)
|
| 234 |
+
# rename keys
|
| 235 |
+
rename_keys = create_rename_keys(config)
|
| 236 |
+
for src, dest in rename_keys:
|
| 237 |
+
rename_key(state_dict, src, dest)
|
| 238 |
+
# read in qkv matrices
|
| 239 |
+
read_in_q_k_v(state_dict, config)
|
| 240 |
+
|
| 241 |
+
# load HuggingFace model
|
| 242 |
+
model = DepthAnythingForDepthEstimation(config)
|
| 243 |
+
model.load_state_dict(state_dict)
|
| 244 |
+
model.eval()
|
| 245 |
+
|
| 246 |
+
processor = DPTImageProcessor(
|
| 247 |
+
do_resize=True,
|
| 248 |
+
size={"height": 518, "width": 518},
|
| 249 |
+
ensure_multiple_of=14,
|
| 250 |
+
keep_aspect_ratio=True,
|
| 251 |
+
do_rescale=True,
|
| 252 |
+
do_normalize=True,
|
| 253 |
+
image_mean=[0.485, 0.456, 0.406],
|
| 254 |
+
image_std=[0.229, 0.224, 0.225],
|
| 255 |
+
)
|
| 256 |
+
|
| 257 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 258 |
+
with httpx.stream("GET", url) as response:
|
| 259 |
+
image = Image.open(BytesIO(response.read()))
|
| 260 |
+
|
| 261 |
+
pixel_values = processor(image, return_tensors="pt").pixel_values
|
| 262 |
+
|
| 263 |
+
# Verify forward pass
|
| 264 |
+
with torch.no_grad():
|
| 265 |
+
outputs = model(pixel_values)
|
| 266 |
+
predicted_depth = outputs.predicted_depth
|
| 267 |
+
|
| 268 |
+
print("Shape of predicted depth:", predicted_depth.shape)
|
| 269 |
+
print("First values:", predicted_depth[0, :3, :3])
|
| 270 |
+
|
| 271 |
+
# assert logits
|
| 272 |
+
if verify_logits:
|
| 273 |
+
expected_shape = torch.Size([1, 518, 686])
|
| 274 |
+
if model_name == "depth-anything-small":
|
| 275 |
+
expected_slice = torch.tensor(
|
| 276 |
+
[[8.8204, 8.6468, 8.6195], [8.3313, 8.6027, 8.7526], [8.6526, 8.6866, 8.7453]],
|
| 277 |
+
)
|
| 278 |
+
elif model_name == "depth-anything-base":
|
| 279 |
+
expected_slice = torch.tensor(
|
| 280 |
+
[[26.3997, 26.3004, 26.3928], [26.2260, 26.2092, 26.3427], [26.0719, 26.0483, 26.1254]],
|
| 281 |
+
)
|
| 282 |
+
elif model_name == "depth-anything-large":
|
| 283 |
+
expected_slice = torch.tensor(
|
| 284 |
+
[[87.9968, 87.7493, 88.2704], [87.1927, 87.6611, 87.3640], [86.7789, 86.9469, 86.7991]]
|
| 285 |
+
)
|
| 286 |
+
elif model_name == "depth-anything-v2-small":
|
| 287 |
+
expected_slice = torch.tensor(
|
| 288 |
+
[[2.6751, 2.6211, 2.6571], [2.5820, 2.6138, 2.6271], [2.6160, 2.6141, 2.6306]]
|
| 289 |
+
)
|
| 290 |
+
elif model_name == "depth-anything-v2-base":
|
| 291 |
+
expected_slice = torch.tensor(
|
| 292 |
+
[[4.3576, 4.3723, 4.3908], [4.3231, 4.3146, 4.3611], [4.3016, 4.3170, 4.3121]]
|
| 293 |
+
)
|
| 294 |
+
elif model_name == "depth-anything-v2-large":
|
| 295 |
+
expected_slice = torch.tensor(
|
| 296 |
+
[[162.2751, 161.8504, 162.8788], [160.3138, 160.8050, 161.9835], [159.3812, 159.9884, 160.0768]]
|
| 297 |
+
)
|
| 298 |
+
elif model_name == "depth-anything-v2-metric-indoor-small":
|
| 299 |
+
expected_slice = torch.tensor(
|
| 300 |
+
[[1.3349, 1.2946, 1.2801], [1.2793, 1.2337, 1.2899], [1.2629, 1.2218, 1.2476]]
|
| 301 |
+
)
|
| 302 |
+
elif model_name == "depth-anything-v2-metric-indoor-base":
|
| 303 |
+
expected_slice = torch.tensor(
|
| 304 |
+
[[1.4601, 1.3824, 1.4904], [1.5031, 1.4349, 1.4274], [1.4570, 1.4578, 1.4200]]
|
| 305 |
+
)
|
| 306 |
+
elif model_name == "depth-anything-v2-metric-indoor-large":
|
| 307 |
+
expected_slice = torch.tensor(
|
| 308 |
+
[[1.5040, 1.5019, 1.5218], [1.5087, 1.5195, 1.5149], [1.5437, 1.5128, 1.5252]]
|
| 309 |
+
)
|
| 310 |
+
elif model_name == "depth-anything-v2-metric-outdoor-small":
|
| 311 |
+
expected_slice = torch.tensor(
|
| 312 |
+
[[9.5804, 8.0339, 7.7386], [7.9890, 7.2464, 7.7149], [7.7021, 7.2330, 7.3304]]
|
| 313 |
+
)
|
| 314 |
+
elif model_name == "depth-anything-v2-metric-outdoor-base":
|
| 315 |
+
expected_slice = torch.tensor(
|
| 316 |
+
[[10.2916, 9.0933, 8.8622], [9.1964, 9.3393, 9.0644], [8.9618, 9.4201, 9.2262]]
|
| 317 |
+
)
|
| 318 |
+
elif model_name == "depth-anything-v2-metric-outdoor-large":
|
| 319 |
+
expected_slice = torch.tensor(
|
| 320 |
+
[[14.0137, 13.3627, 13.1080], [13.2522, 13.3943, 13.3705], [13.0581, 13.4505, 13.3925]]
|
| 321 |
+
)
|
| 322 |
+
else:
|
| 323 |
+
raise ValueError("Not supported")
|
| 324 |
+
|
| 325 |
+
assert predicted_depth.shape == torch.Size(expected_shape)
|
| 326 |
+
assert torch.allclose(predicted_depth[0, :3, :3], expected_slice, atol=1e-4)
|
| 327 |
+
print("Looks ok!")
|
| 328 |
+
|
| 329 |
+
if pytorch_dump_folder_path is not None:
|
| 330 |
+
Path(pytorch_dump_folder_path).mkdir(exist_ok=True)
|
| 331 |
+
print(f"Saving model and processor to {pytorch_dump_folder_path}")
|
| 332 |
+
model.save_pretrained(pytorch_dump_folder_path)
|
| 333 |
+
processor.save_pretrained(pytorch_dump_folder_path)
|
| 334 |
+
|
| 335 |
+
if push_to_hub:
|
| 336 |
+
print("Pushing model and processor to hub...")
|
| 337 |
+
model.push_to_hub(repo_id=f"{model_name.title()}-hf")
|
| 338 |
+
processor.push_to_hub(repo_id=f"{model_name.title()}-hf")
|
| 339 |
+
|
| 340 |
+
|
| 341 |
+
if __name__ == "__main__":
|
| 342 |
+
parser = argparse.ArgumentParser()
|
| 343 |
+
# Required parameters
|
| 344 |
+
parser.add_argument(
|
| 345 |
+
"--model_name",
|
| 346 |
+
default="depth-anything-small",
|
| 347 |
+
type=str,
|
| 348 |
+
choices=name_to_checkpoint.keys(),
|
| 349 |
+
help="Name of the model you'd like to convert.",
|
| 350 |
+
)
|
| 351 |
+
parser.add_argument(
|
| 352 |
+
"--pytorch_dump_folder_path",
|
| 353 |
+
default=None,
|
| 354 |
+
type=str,
|
| 355 |
+
help="Path to the output PyTorch model directory.",
|
| 356 |
+
)
|
| 357 |
+
parser.add_argument(
|
| 358 |
+
"--push_to_hub",
|
| 359 |
+
action="store_true",
|
| 360 |
+
help="Whether to push the model to the hub after conversion.",
|
| 361 |
+
)
|
| 362 |
+
parser.add_argument(
|
| 363 |
+
"--verify_logits",
|
| 364 |
+
action="store_false",
|
| 365 |
+
required=False,
|
| 366 |
+
help="Whether to verify the logits after conversion.",
|
| 367 |
+
)
|
| 368 |
+
|
| 369 |
+
args = parser.parse_args()
|
| 370 |
+
convert_dpt_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.push_to_hub, args.verify_logits)
|
third_party/transformers/src/transformers/models/depth_anything/convert_distill_any_depth_to_hf.py
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2025 The HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Convert Distill Any Depth checkpoints from the original repository. URL:
|
| 15 |
+
https://github.com/Westlake-AGI-Lab/Distill-Any-Depth"""
|
| 16 |
+
|
| 17 |
+
import argparse
|
| 18 |
+
import re
|
| 19 |
+
from io import BytesIO
|
| 20 |
+
from pathlib import Path
|
| 21 |
+
|
| 22 |
+
import httpx
|
| 23 |
+
import torch
|
| 24 |
+
from huggingface_hub import hf_hub_download
|
| 25 |
+
from PIL import Image
|
| 26 |
+
from safetensors.torch import load_file
|
| 27 |
+
|
| 28 |
+
from transformers import DepthAnythingConfig, DepthAnythingForDepthEstimation, Dinov2Config, DPTImageProcessor
|
| 29 |
+
from transformers.utils import logging
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
logging.set_verbosity_info()
|
| 33 |
+
logger = logging.get_logger(__name__)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
ORIGINAL_TO_CONVERTED_KEY_MAPPING = {
|
| 37 |
+
r"(backbone|pretrained)\.cls_token": r"backbone.embeddings.cls_token",
|
| 38 |
+
r"(backbone|pretrained)\.mask_token": r"backbone.embeddings.mask_token",
|
| 39 |
+
r"(backbone|pretrained)\.pos_embed": r"backbone.embeddings.position_embeddings",
|
| 40 |
+
r"(backbone|pretrained)\.patch_embed\.proj\.(weight|bias)": r"backbone.embeddings.patch_embeddings.projection.\2",
|
| 41 |
+
r"(backbone|pretrained)\.norm\.(weight|bias)": r"backbone.layernorm.\2",
|
| 42 |
+
r"(backbone|pretrained)(\.blocks(\.\d+)?)?\.(\d+)\.attn\.proj\.(weight|bias)": r"backbone.encoder.layer.\4.attention.output.dense.\5",
|
| 43 |
+
r"(backbone|pretrained)(\.blocks(\.\d+)?)?\.(\d+)\.ls(1|2)\.gamma": r"backbone.encoder.layer.\4.layer_scale\5.lambda1",
|
| 44 |
+
r"(backbone|pretrained)(\.blocks(\.\d+)?)?\.(\d+)\.mlp\.fc(1|2)\.(weight|bias)": r"backbone.encoder.layer.\4.mlp.fc\5.\6",
|
| 45 |
+
r"(backbone|pretrained)(\.blocks(\.\d+)?)?\.(\d+)\.norm(1|2)\.(weight|bias)": r"backbone.encoder.layer.\4.norm\5.\6",
|
| 46 |
+
r"depth_head\.projects\.(\d+)\.(weight|bias)": r"neck.reassemble_stage.layers.\1.projection.\2",
|
| 47 |
+
r"depth_head\.resize_layers\.(?!2)(\d+)\.(weight|bias)": r"neck.reassemble_stage.layers.\1.resize.\2",
|
| 48 |
+
r"depth_head\.scratch\.layer(\d+)_rn\.weight": lambda m: f"neck.convs.{int(m[1]) - 1}.weight",
|
| 49 |
+
r"depth_head\.scratch\.output_conv(\d+)(?:\.(\d+))?\.(weight|bias)": lambda m: (
|
| 50 |
+
f"head.conv{int(m[1]) + (int(m[2]) // 2 if m[2] else 0)}.{m[3]}" if m[1] == "2" else f"head.conv{m[1]}.{m[3]}"
|
| 51 |
+
),
|
| 52 |
+
r"depth_head\.scratch\.refinenet(\d+)\.out_conv\.(weight|bias)": lambda m: f"neck.fusion_stage.layers.{3 - (int(m[1]) - 1)}.projection.{m[2]}",
|
| 53 |
+
r"depth_head\.scratch\.refinenet(\d+)\.resConfUnit(\d+)\.conv(\d+)\.(weight|bias)": lambda m: f"neck.fusion_stage.layers.{3 - (int(m[1]) - 1)}.residual_layer{m[2]}.convolution{m[3]}.{m[4]}",
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def get_dpt_config(model_name):
|
| 58 |
+
if "small" in model_name:
|
| 59 |
+
out_indices = [3, 6, 9, 12]
|
| 60 |
+
backbone_config = Dinov2Config.from_pretrained(
|
| 61 |
+
"facebook/dinov2-small", out_indices=out_indices, apply_layernorm=True, reshape_hidden_states=False
|
| 62 |
+
)
|
| 63 |
+
fusion_hidden_size = 64
|
| 64 |
+
neck_hidden_sizes = [48, 96, 192, 384]
|
| 65 |
+
elif "base" in model_name:
|
| 66 |
+
out_indices = [3, 6, 9, 12]
|
| 67 |
+
backbone_config = Dinov2Config.from_pretrained(
|
| 68 |
+
"facebook/dinov2-base", out_indices=out_indices, apply_layernorm=True, reshape_hidden_states=False
|
| 69 |
+
)
|
| 70 |
+
fusion_hidden_size = 128
|
| 71 |
+
neck_hidden_sizes = [96, 192, 384, 768]
|
| 72 |
+
elif "large" in model_name:
|
| 73 |
+
out_indices = [5, 12, 18, 24]
|
| 74 |
+
backbone_config = Dinov2Config.from_pretrained(
|
| 75 |
+
"facebook/dinov2-large", out_indices=out_indices, apply_layernorm=True, reshape_hidden_states=False
|
| 76 |
+
)
|
| 77 |
+
fusion_hidden_size = 256
|
| 78 |
+
neck_hidden_sizes = [256, 512, 1024, 1024]
|
| 79 |
+
else:
|
| 80 |
+
raise NotImplementedError(f"Model not supported: {model_name}")
|
| 81 |
+
|
| 82 |
+
depth_estimation_type = "relative"
|
| 83 |
+
max_depth = None
|
| 84 |
+
|
| 85 |
+
config = DepthAnythingConfig(
|
| 86 |
+
reassemble_hidden_size=backbone_config.hidden_size,
|
| 87 |
+
patch_size=backbone_config.patch_size,
|
| 88 |
+
backbone_config=backbone_config,
|
| 89 |
+
fusion_hidden_size=fusion_hidden_size,
|
| 90 |
+
neck_hidden_sizes=neck_hidden_sizes,
|
| 91 |
+
depth_estimation_type=depth_estimation_type,
|
| 92 |
+
max_depth=max_depth,
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
return config
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def convert_key_pattern(key, mapping):
|
| 99 |
+
for pattern, replacement in mapping.items():
|
| 100 |
+
match = re.fullmatch(pattern, key)
|
| 101 |
+
if match:
|
| 102 |
+
if callable(replacement):
|
| 103 |
+
return replacement(match)
|
| 104 |
+
return re.sub(pattern, replacement, key)
|
| 105 |
+
return None
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def convert_keys(state_dict, config):
|
| 109 |
+
new_state_dict = {}
|
| 110 |
+
qkv_pattern = r"(backbone|pretrained)(\.blocks(\.\d+)?)?\.(\d+)\.attn\.qkv\.(weight|bias)"
|
| 111 |
+
qkv_keys = [k for k in list(state_dict.keys()) if re.match(qkv_pattern, k)]
|
| 112 |
+
for old_key in qkv_keys:
|
| 113 |
+
value = state_dict.pop(old_key)
|
| 114 |
+
match = re.match(qkv_pattern, old_key)
|
| 115 |
+
_, _, _, layer, attr = match.groups()
|
| 116 |
+
hidden_size = config.backbone_config.hidden_size
|
| 117 |
+
q = value[:hidden_size]
|
| 118 |
+
k = value[hidden_size : hidden_size * 2]
|
| 119 |
+
v = value[-hidden_size:]
|
| 120 |
+
|
| 121 |
+
for proj, tensor in zip(["query", "key", "value"], [q, k, v]):
|
| 122 |
+
new_key = f"backbone.encoder.layer.{layer}.attention.attention.{proj}.{attr}"
|
| 123 |
+
new_state_dict[new_key] = tensor
|
| 124 |
+
|
| 125 |
+
for old_key in list(state_dict.keys()):
|
| 126 |
+
value = state_dict.pop(old_key)
|
| 127 |
+
new_key = convert_key_pattern(old_key, ORIGINAL_TO_CONVERTED_KEY_MAPPING)
|
| 128 |
+
|
| 129 |
+
new_state_dict[new_key] = value
|
| 130 |
+
|
| 131 |
+
return new_state_dict
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def prepare_img():
|
| 135 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 136 |
+
with httpx.stream("GET", url) as response:
|
| 137 |
+
image = Image.open(BytesIO(response.read()))
|
| 138 |
+
return image
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
name_to_checkpoint = {
|
| 142 |
+
"distill-any-depth-small": "small/model.safetensors",
|
| 143 |
+
"distill-any-depth-base": "base/model.safetensors",
|
| 144 |
+
"distill-any-depth-large": "large/model.safetensors",
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
@torch.no_grad()
|
| 149 |
+
def convert_dpt_checkpoint(model_name, pytorch_dump_folder_path, push_to_hub, verify_logits):
|
| 150 |
+
config = get_dpt_config(model_name)
|
| 151 |
+
|
| 152 |
+
repo_id = "xingyang1/Distill-Any-Depth"
|
| 153 |
+
filepath = hf_hub_download(repo_id=repo_id, filename=name_to_checkpoint[model_name])
|
| 154 |
+
state_dict = load_file(filepath)
|
| 155 |
+
|
| 156 |
+
converted_state_dict = convert_keys(state_dict, config)
|
| 157 |
+
|
| 158 |
+
model = DepthAnythingForDepthEstimation(config)
|
| 159 |
+
model.load_state_dict(converted_state_dict)
|
| 160 |
+
model.eval()
|
| 161 |
+
|
| 162 |
+
processor = DPTImageProcessor(
|
| 163 |
+
do_resize=True,
|
| 164 |
+
size={"height": 518, "width": 518},
|
| 165 |
+
ensure_multiple_of=14,
|
| 166 |
+
keep_aspect_ratio=True,
|
| 167 |
+
do_rescale=True,
|
| 168 |
+
do_normalize=True,
|
| 169 |
+
image_mean=[0.485, 0.456, 0.406],
|
| 170 |
+
image_std=[0.229, 0.224, 0.225],
|
| 171 |
+
)
|
| 172 |
+
|
| 173 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 174 |
+
with httpx.stream("GET", url) as response:
|
| 175 |
+
image = Image.open(BytesIO(response.read()))
|
| 176 |
+
|
| 177 |
+
pixel_values = processor(image, return_tensors="pt").pixel_values
|
| 178 |
+
|
| 179 |
+
with torch.no_grad():
|
| 180 |
+
outputs = model(pixel_values)
|
| 181 |
+
predicted_depth = outputs.predicted_depth
|
| 182 |
+
|
| 183 |
+
print("Shape of predicted depth:", predicted_depth.shape)
|
| 184 |
+
print("First values:", predicted_depth[0, :3, :3])
|
| 185 |
+
|
| 186 |
+
if verify_logits:
|
| 187 |
+
print("Verifying logits...")
|
| 188 |
+
expected_shape = torch.Size([1, 518, 686])
|
| 189 |
+
|
| 190 |
+
if model_name == "distill-any-depth-small":
|
| 191 |
+
expected_slice = torch.tensor(
|
| 192 |
+
[[2.5653, 2.5249, 2.5570], [2.4897, 2.5235, 2.5355], [2.5255, 2.5261, 2.5422]]
|
| 193 |
+
)
|
| 194 |
+
elif model_name == "distill-any-depth-base":
|
| 195 |
+
expected_slice = torch.tensor(
|
| 196 |
+
[[4.8976, 4.9075, 4.9403], [4.8872, 4.8906, 4.9448], [4.8712, 4.8898, 4.8838]]
|
| 197 |
+
)
|
| 198 |
+
elif model_name == "distill-any-depth-large":
|
| 199 |
+
expected_slice = torch.tensor(
|
| 200 |
+
[[55.1067, 51.1828, 51.6803], [51.9098, 50.7529, 51.4494], [50.1745, 50.5491, 50.8818]]
|
| 201 |
+
)
|
| 202 |
+
else:
|
| 203 |
+
raise ValueError("Not supported")
|
| 204 |
+
|
| 205 |
+
assert predicted_depth.shape == torch.Size(expected_shape)
|
| 206 |
+
assert torch.allclose(predicted_depth[0, :3, :3], expected_slice, atol=1e-4)
|
| 207 |
+
print("Looks ok!")
|
| 208 |
+
|
| 209 |
+
if pytorch_dump_folder_path is not None:
|
| 210 |
+
Path(pytorch_dump_folder_path).mkdir(exist_ok=True)
|
| 211 |
+
print(f"Saving model and processor to {pytorch_dump_folder_path}")
|
| 212 |
+
model.save_pretrained(pytorch_dump_folder_path)
|
| 213 |
+
processor.save_pretrained(pytorch_dump_folder_path)
|
| 214 |
+
|
| 215 |
+
if push_to_hub:
|
| 216 |
+
print("Pushing model and processor to hub...")
|
| 217 |
+
model.push_to_hub(repo_id=f"{model_name.title()}-hf")
|
| 218 |
+
processor.push_to_hub(repo_id=f"{model_name.title()}-hf")
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
if __name__ == "__main__":
|
| 222 |
+
parser = argparse.ArgumentParser()
|
| 223 |
+
parser.add_argument(
|
| 224 |
+
"--model_name",
|
| 225 |
+
default="distill-any-depth-small",
|
| 226 |
+
type=str,
|
| 227 |
+
choices=name_to_checkpoint.keys(),
|
| 228 |
+
help="Name of the model you'd like to convert.",
|
| 229 |
+
)
|
| 230 |
+
parser.add_argument(
|
| 231 |
+
"--pytorch_dump_folder_path",
|
| 232 |
+
default=None,
|
| 233 |
+
type=str,
|
| 234 |
+
help="Path to the output PyTorch model directory.",
|
| 235 |
+
)
|
| 236 |
+
parser.add_argument(
|
| 237 |
+
"--push_to_hub",
|
| 238 |
+
action="store_true",
|
| 239 |
+
help="Whether to push the model to the hub after conversion.",
|
| 240 |
+
)
|
| 241 |
+
parser.add_argument(
|
| 242 |
+
"--verify_logits",
|
| 243 |
+
action="store_true",
|
| 244 |
+
required=False,
|
| 245 |
+
help="Whether to verify the logits after conversion.",
|
| 246 |
+
)
|
| 247 |
+
|
| 248 |
+
args = parser.parse_args()
|
| 249 |
+
convert_dpt_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.push_to_hub, args.verify_logits)
|
third_party/transformers/src/transformers/models/depth_anything/modeling_depth_anything.py
ADDED
|
@@ -0,0 +1,416 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 TikTok and The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""PyTorch Depth Anything model."""
|
| 15 |
+
|
| 16 |
+
import torch
|
| 17 |
+
from torch import nn
|
| 18 |
+
|
| 19 |
+
from ...backbone_utils import load_backbone
|
| 20 |
+
from ...modeling_outputs import DepthEstimatorOutput
|
| 21 |
+
from ...modeling_utils import PreTrainedModel
|
| 22 |
+
from ...utils import auto_docstring, logging
|
| 23 |
+
from .configuration_depth_anything import DepthAnythingConfig
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
logger = logging.get_logger(__name__)
|
| 27 |
+
|
| 28 |
+
# General docstring
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
class DepthAnythingReassembleLayer(nn.Module):
|
| 32 |
+
def __init__(self, config, channels, factor):
|
| 33 |
+
super().__init__()
|
| 34 |
+
self.projection = nn.Conv2d(in_channels=config.reassemble_hidden_size, out_channels=channels, kernel_size=1)
|
| 35 |
+
|
| 36 |
+
# up/down sampling depending on factor
|
| 37 |
+
if factor > 1:
|
| 38 |
+
self.resize = nn.ConvTranspose2d(channels, channels, kernel_size=factor, stride=factor, padding=0)
|
| 39 |
+
elif factor == 1:
|
| 40 |
+
self.resize = nn.Identity()
|
| 41 |
+
elif factor < 1:
|
| 42 |
+
# so should downsample
|
| 43 |
+
self.resize = nn.Conv2d(channels, channels, kernel_size=3, stride=int(1 / factor), padding=1)
|
| 44 |
+
|
| 45 |
+
# Copied from transformers.models.dpt.modeling_dpt.DPTReassembleLayer.forward
|
| 46 |
+
def forward(self, hidden_state):
|
| 47 |
+
hidden_state = self.projection(hidden_state)
|
| 48 |
+
hidden_state = self.resize(hidden_state)
|
| 49 |
+
|
| 50 |
+
return hidden_state
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
class DepthAnythingReassembleStage(nn.Module):
|
| 54 |
+
"""
|
| 55 |
+
This class reassembles the hidden states of the backbone into image-like feature representations at various
|
| 56 |
+
resolutions.
|
| 57 |
+
|
| 58 |
+
This happens in 3 stages:
|
| 59 |
+
1. Take the patch embeddings and reshape them to image-like feature representations.
|
| 60 |
+
2. Project the channel dimension of the hidden states according to `config.neck_hidden_sizes`.
|
| 61 |
+
3. Resizing the spatial dimensions (height, width).
|
| 62 |
+
|
| 63 |
+
Args:
|
| 64 |
+
config (`[DepthAnythingConfig]`):
|
| 65 |
+
Model configuration class defining the model architecture.
|
| 66 |
+
"""
|
| 67 |
+
|
| 68 |
+
def __init__(self, config):
|
| 69 |
+
super().__init__()
|
| 70 |
+
|
| 71 |
+
self.config = config
|
| 72 |
+
self.layers = nn.ModuleList()
|
| 73 |
+
for channels, factor in zip(config.neck_hidden_sizes, config.reassemble_factors):
|
| 74 |
+
self.layers.append(DepthAnythingReassembleLayer(config, channels=channels, factor=factor))
|
| 75 |
+
|
| 76 |
+
def forward(self, hidden_states: list[torch.Tensor], patch_height=None, patch_width=None) -> list[torch.Tensor]:
|
| 77 |
+
"""
|
| 78 |
+
Args:
|
| 79 |
+
hidden_states (`list[torch.FloatTensor]`, each of shape `(batch_size, sequence_length + 1, hidden_size)`):
|
| 80 |
+
List of hidden states from the backbone.
|
| 81 |
+
"""
|
| 82 |
+
out = []
|
| 83 |
+
|
| 84 |
+
for i, hidden_state in enumerate(hidden_states):
|
| 85 |
+
# reshape to (batch_size, num_channels, height, width)
|
| 86 |
+
hidden_state = hidden_state[:, 1:]
|
| 87 |
+
batch_size, _, num_channels = hidden_state.shape
|
| 88 |
+
hidden_state = hidden_state.reshape(batch_size, patch_height, patch_width, num_channels)
|
| 89 |
+
hidden_state = hidden_state.permute(0, 3, 1, 2).contiguous()
|
| 90 |
+
hidden_state = self.layers[i](hidden_state)
|
| 91 |
+
out.append(hidden_state)
|
| 92 |
+
|
| 93 |
+
return out
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
class DepthAnythingPreActResidualLayer(nn.Module):
|
| 97 |
+
"""
|
| 98 |
+
ResidualConvUnit, pre-activate residual unit.
|
| 99 |
+
|
| 100 |
+
Args:
|
| 101 |
+
config (`[DepthAnythingConfig]`):
|
| 102 |
+
Model configuration class defining the model architecture.
|
| 103 |
+
"""
|
| 104 |
+
|
| 105 |
+
def __init__(self, config):
|
| 106 |
+
super().__init__()
|
| 107 |
+
|
| 108 |
+
self.activation1 = nn.ReLU()
|
| 109 |
+
self.convolution1 = nn.Conv2d(
|
| 110 |
+
config.fusion_hidden_size,
|
| 111 |
+
config.fusion_hidden_size,
|
| 112 |
+
kernel_size=3,
|
| 113 |
+
stride=1,
|
| 114 |
+
padding=1,
|
| 115 |
+
bias=True,
|
| 116 |
+
)
|
| 117 |
+
|
| 118 |
+
self.activation2 = nn.ReLU()
|
| 119 |
+
self.convolution2 = nn.Conv2d(
|
| 120 |
+
config.fusion_hidden_size,
|
| 121 |
+
config.fusion_hidden_size,
|
| 122 |
+
kernel_size=3,
|
| 123 |
+
stride=1,
|
| 124 |
+
padding=1,
|
| 125 |
+
bias=True,
|
| 126 |
+
)
|
| 127 |
+
|
| 128 |
+
def forward(self, hidden_state: torch.Tensor) -> torch.Tensor:
|
| 129 |
+
residual = hidden_state
|
| 130 |
+
hidden_state = self.activation1(hidden_state)
|
| 131 |
+
hidden_state = self.convolution1(hidden_state)
|
| 132 |
+
hidden_state = self.activation2(hidden_state)
|
| 133 |
+
hidden_state = self.convolution2(hidden_state)
|
| 134 |
+
|
| 135 |
+
return hidden_state + residual
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
class DepthAnythingFeatureFusionLayer(nn.Module):
|
| 139 |
+
"""Feature fusion layer, merges feature maps from different stages.
|
| 140 |
+
|
| 141 |
+
Args:
|
| 142 |
+
config (`[DepthAnythingConfig]`):
|
| 143 |
+
Model configuration class defining the model architecture.
|
| 144 |
+
"""
|
| 145 |
+
|
| 146 |
+
def __init__(self, config):
|
| 147 |
+
super().__init__()
|
| 148 |
+
|
| 149 |
+
self.projection = nn.Conv2d(config.fusion_hidden_size, config.fusion_hidden_size, kernel_size=1, bias=True)
|
| 150 |
+
|
| 151 |
+
self.residual_layer1 = DepthAnythingPreActResidualLayer(config)
|
| 152 |
+
self.residual_layer2 = DepthAnythingPreActResidualLayer(config)
|
| 153 |
+
|
| 154 |
+
def forward(self, hidden_state, residual=None, size=None):
|
| 155 |
+
if residual is not None:
|
| 156 |
+
if hidden_state.shape != residual.shape:
|
| 157 |
+
residual = nn.functional.interpolate(
|
| 158 |
+
residual, size=(hidden_state.shape[2], hidden_state.shape[3]), mode="bilinear", align_corners=False
|
| 159 |
+
)
|
| 160 |
+
hidden_state = hidden_state + self.residual_layer1(residual)
|
| 161 |
+
|
| 162 |
+
hidden_state = self.residual_layer2(hidden_state)
|
| 163 |
+
|
| 164 |
+
modifier = {"scale_factor": 2} if size is None else {"size": size}
|
| 165 |
+
|
| 166 |
+
hidden_state = nn.functional.interpolate(
|
| 167 |
+
hidden_state,
|
| 168 |
+
**modifier,
|
| 169 |
+
mode="bilinear",
|
| 170 |
+
align_corners=True,
|
| 171 |
+
)
|
| 172 |
+
hidden_state = self.projection(hidden_state)
|
| 173 |
+
|
| 174 |
+
return hidden_state
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
class DepthAnythingFeatureFusionStage(nn.Module):
|
| 178 |
+
# Copied from transformers.models.dpt.modeling_dpt.DPTFeatureFusionStage.__init__ with DPT->DepthAnything
|
| 179 |
+
def __init__(self, config: DepthAnythingConfig):
|
| 180 |
+
super().__init__()
|
| 181 |
+
self.layers = nn.ModuleList()
|
| 182 |
+
for _ in range(len(config.neck_hidden_sizes)):
|
| 183 |
+
self.layers.append(DepthAnythingFeatureFusionLayer(config))
|
| 184 |
+
|
| 185 |
+
def forward(self, hidden_states, size=None):
|
| 186 |
+
# reversing the hidden_states, we start from the last
|
| 187 |
+
hidden_states = hidden_states[::-1]
|
| 188 |
+
|
| 189 |
+
fused_hidden_states = []
|
| 190 |
+
fused_hidden_state = None
|
| 191 |
+
|
| 192 |
+
for idx, (hidden_state, layer) in enumerate(zip(hidden_states, self.layers)):
|
| 193 |
+
size = hidden_states[idx + 1].shape[2:] if idx != (len(hidden_states) - 1) else None
|
| 194 |
+
|
| 195 |
+
if fused_hidden_state is None:
|
| 196 |
+
# first layer only uses the last hidden_state
|
| 197 |
+
fused_hidden_state = layer(hidden_state, size=size)
|
| 198 |
+
else:
|
| 199 |
+
fused_hidden_state = layer(fused_hidden_state, hidden_state, size=size)
|
| 200 |
+
|
| 201 |
+
fused_hidden_states.append(fused_hidden_state)
|
| 202 |
+
|
| 203 |
+
return fused_hidden_states
|
| 204 |
+
|
| 205 |
+
|
| 206 |
+
# Modified from transformers.models.dpt.modeling_dpt.DPTPreTrainedModel with DPT->DepthAnything,dpt->depth_anything
|
| 207 |
+
# avoiding sdpa and flash_attn_2 support, it's done in the backend
|
| 208 |
+
@auto_docstring
|
| 209 |
+
class DepthAnythingPreTrainedModel(PreTrainedModel):
|
| 210 |
+
config: DepthAnythingConfig
|
| 211 |
+
base_model_prefix = "depth_anything"
|
| 212 |
+
main_input_name = "pixel_values"
|
| 213 |
+
input_modalities = ("image",)
|
| 214 |
+
supports_gradient_checkpointing = True
|
| 215 |
+
|
| 216 |
+
|
| 217 |
+
class DepthAnythingNeck(nn.Module):
|
| 218 |
+
"""
|
| 219 |
+
DepthAnythingNeck. A neck is a module that is normally used between the backbone and the head. It takes a list of tensors as
|
| 220 |
+
input and produces another list of tensors as output. For DepthAnything, it includes 2 stages:
|
| 221 |
+
|
| 222 |
+
* DepthAnythingReassembleStage
|
| 223 |
+
* DepthAnythingFeatureFusionStage.
|
| 224 |
+
|
| 225 |
+
Args:
|
| 226 |
+
config (dict): config dict.
|
| 227 |
+
"""
|
| 228 |
+
|
| 229 |
+
def __init__(self, config):
|
| 230 |
+
super().__init__()
|
| 231 |
+
self.config = config
|
| 232 |
+
|
| 233 |
+
self.reassemble_stage = DepthAnythingReassembleStage(config)
|
| 234 |
+
|
| 235 |
+
self.convs = nn.ModuleList()
|
| 236 |
+
for channel in config.neck_hidden_sizes:
|
| 237 |
+
self.convs.append(nn.Conv2d(channel, config.fusion_hidden_size, kernel_size=3, padding=1, bias=False))
|
| 238 |
+
|
| 239 |
+
# fusion
|
| 240 |
+
self.fusion_stage = DepthAnythingFeatureFusionStage(config)
|
| 241 |
+
|
| 242 |
+
def forward(self, hidden_states: list[torch.Tensor], patch_height=None, patch_width=None) -> list[torch.Tensor]:
|
| 243 |
+
"""
|
| 244 |
+
Args:
|
| 245 |
+
hidden_states (`list[torch.FloatTensor]`, each of shape `(batch_size, sequence_length, hidden_size)` or `(batch_size, hidden_size, height, width)`):
|
| 246 |
+
List of hidden states from the backbone.
|
| 247 |
+
"""
|
| 248 |
+
if not isinstance(hidden_states, (tuple, list)):
|
| 249 |
+
raise TypeError("hidden_states should be a tuple or list of tensors")
|
| 250 |
+
|
| 251 |
+
if len(hidden_states) != len(self.config.neck_hidden_sizes):
|
| 252 |
+
raise ValueError("The number of hidden states should be equal to the number of neck hidden sizes.")
|
| 253 |
+
|
| 254 |
+
# postprocess hidden states
|
| 255 |
+
hidden_states = self.reassemble_stage(hidden_states, patch_height, patch_width)
|
| 256 |
+
|
| 257 |
+
features = [self.convs[i](feature) for i, feature in enumerate(hidden_states)]
|
| 258 |
+
|
| 259 |
+
# fusion blocks
|
| 260 |
+
output = self.fusion_stage(features)
|
| 261 |
+
|
| 262 |
+
return output
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
class DepthAnythingDepthEstimationHead(nn.Module):
|
| 266 |
+
"""
|
| 267 |
+
Output head consisting of 3 convolutional layers. It progressively halves the feature dimension and upsamples
|
| 268 |
+
the predictions to the input resolution after the first convolutional layer (details can be found in the DPT paper's
|
| 269 |
+
supplementary material). The final activation function is either ReLU or Sigmoid, depending on the depth estimation
|
| 270 |
+
type (relative or metric). For metric depth estimation, the output is scaled by the maximum depth used during pretraining.
|
| 271 |
+
"""
|
| 272 |
+
|
| 273 |
+
def __init__(self, config):
|
| 274 |
+
super().__init__()
|
| 275 |
+
|
| 276 |
+
self.head_in_index = config.head_in_index
|
| 277 |
+
self.patch_size = config.patch_size
|
| 278 |
+
|
| 279 |
+
features = config.fusion_hidden_size
|
| 280 |
+
self.conv1 = nn.Conv2d(features, features // 2, kernel_size=3, stride=1, padding=1)
|
| 281 |
+
self.conv2 = nn.Conv2d(features // 2, config.head_hidden_size, kernel_size=3, stride=1, padding=1)
|
| 282 |
+
self.activation1 = nn.ReLU()
|
| 283 |
+
self.conv3 = nn.Conv2d(config.head_hidden_size, 1, kernel_size=1, stride=1, padding=0)
|
| 284 |
+
if config.depth_estimation_type == "relative":
|
| 285 |
+
self.activation2 = nn.ReLU()
|
| 286 |
+
elif config.depth_estimation_type == "metric":
|
| 287 |
+
self.activation2 = nn.Sigmoid()
|
| 288 |
+
else:
|
| 289 |
+
raise ValueError(f"Unknown depth estimation type: {config.depth_estimation_type}")
|
| 290 |
+
self.max_depth = config.max_depth
|
| 291 |
+
|
| 292 |
+
def forward(self, hidden_states: list[torch.Tensor], patch_height, patch_width) -> torch.Tensor:
|
| 293 |
+
hidden_states = hidden_states[self.head_in_index]
|
| 294 |
+
|
| 295 |
+
predicted_depth = self.conv1(hidden_states)
|
| 296 |
+
predicted_depth = nn.functional.interpolate(
|
| 297 |
+
predicted_depth,
|
| 298 |
+
(int(patch_height * self.patch_size), int(patch_width * self.patch_size)),
|
| 299 |
+
mode="bilinear",
|
| 300 |
+
align_corners=True,
|
| 301 |
+
)
|
| 302 |
+
predicted_depth = self.conv2(predicted_depth)
|
| 303 |
+
predicted_depth = self.activation1(predicted_depth)
|
| 304 |
+
predicted_depth = self.conv3(predicted_depth)
|
| 305 |
+
predicted_depth = self.activation2(predicted_depth) * self.max_depth
|
| 306 |
+
predicted_depth = predicted_depth.squeeze(dim=1) # shape (batch_size, height, width)
|
| 307 |
+
|
| 308 |
+
return predicted_depth
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
@auto_docstring(
|
| 312 |
+
custom_intro="""
|
| 313 |
+
Depth Anything Model with a depth estimation head on top (consisting of 3 convolutional layers) e.g. for KITTI, NYUv2.
|
| 314 |
+
"""
|
| 315 |
+
)
|
| 316 |
+
class DepthAnythingForDepthEstimation(DepthAnythingPreTrainedModel):
|
| 317 |
+
_no_split_modules = ["DPTViTEmbeddings"]
|
| 318 |
+
|
| 319 |
+
def __init__(self, config):
|
| 320 |
+
super().__init__(config)
|
| 321 |
+
|
| 322 |
+
self.backbone = load_backbone(config)
|
| 323 |
+
self.neck = DepthAnythingNeck(config)
|
| 324 |
+
self.head = DepthAnythingDepthEstimationHead(config)
|
| 325 |
+
|
| 326 |
+
# Initialize weights and apply final processing
|
| 327 |
+
self.post_init()
|
| 328 |
+
|
| 329 |
+
@auto_docstring
|
| 330 |
+
def forward(
|
| 331 |
+
self,
|
| 332 |
+
pixel_values: torch.FloatTensor,
|
| 333 |
+
labels: torch.LongTensor | None = None,
|
| 334 |
+
output_attentions: bool | None = None,
|
| 335 |
+
output_hidden_states: bool | None = None,
|
| 336 |
+
return_dict: bool | None = None,
|
| 337 |
+
**kwargs,
|
| 338 |
+
) -> tuple[torch.Tensor] | DepthEstimatorOutput:
|
| 339 |
+
r"""
|
| 340 |
+
labels (`torch.LongTensor` of shape `(batch_size, height, width)`, *optional*):
|
| 341 |
+
Ground truth depth estimation maps for computing the loss.
|
| 342 |
+
|
| 343 |
+
Examples:
|
| 344 |
+
```python
|
| 345 |
+
>>> from transformers import AutoImageProcessor, AutoModelForDepthEstimation
|
| 346 |
+
>>> import torch
|
| 347 |
+
>>> import numpy as np
|
| 348 |
+
>>> from PIL import Image
|
| 349 |
+
>>> import httpx
|
| 350 |
+
>>> from io import BytesIO
|
| 351 |
+
|
| 352 |
+
>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 353 |
+
>>> with httpx.stream("GET", url) as response:
|
| 354 |
+
... image = Image.open(BytesIO(response.read()))
|
| 355 |
+
|
| 356 |
+
>>> image_processor = AutoImageProcessor.from_pretrained("LiheYoung/depth-anything-small-hf")
|
| 357 |
+
>>> model = AutoModelForDepthEstimation.from_pretrained("LiheYoung/depth-anything-small-hf")
|
| 358 |
+
|
| 359 |
+
>>> # prepare image for the model
|
| 360 |
+
>>> inputs = image_processor(images=image, return_tensors="pt")
|
| 361 |
+
|
| 362 |
+
>>> with torch.no_grad():
|
| 363 |
+
... outputs = model(**inputs)
|
| 364 |
+
|
| 365 |
+
>>> # interpolate to original size
|
| 366 |
+
>>> post_processed_output = image_processor.post_process_depth_estimation(
|
| 367 |
+
... outputs,
|
| 368 |
+
... target_sizes=[(image.height, image.width)],
|
| 369 |
+
... )
|
| 370 |
+
|
| 371 |
+
>>> # visualize the prediction
|
| 372 |
+
>>> predicted_depth = post_processed_output[0]["predicted_depth"]
|
| 373 |
+
>>> depth = predicted_depth * 255 / predicted_depth.max()
|
| 374 |
+
>>> depth = depth.detach().cpu().numpy()
|
| 375 |
+
>>> depth = Image.fromarray(depth.astype("uint8"))
|
| 376 |
+
```"""
|
| 377 |
+
loss = None
|
| 378 |
+
if labels is not None:
|
| 379 |
+
raise NotImplementedError("Training is not implemented yet")
|
| 380 |
+
|
| 381 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 382 |
+
output_hidden_states = (
|
| 383 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 384 |
+
)
|
| 385 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 386 |
+
|
| 387 |
+
outputs = self.backbone.forward_with_filtered_kwargs(
|
| 388 |
+
pixel_values, output_hidden_states=output_hidden_states, output_attentions=output_attentions
|
| 389 |
+
)
|
| 390 |
+
hidden_states = outputs.feature_maps
|
| 391 |
+
|
| 392 |
+
_, _, height, width = pixel_values.shape
|
| 393 |
+
patch_size = self.config.patch_size
|
| 394 |
+
patch_height = height // patch_size
|
| 395 |
+
patch_width = width // patch_size
|
| 396 |
+
|
| 397 |
+
hidden_states = self.neck(hidden_states, patch_height, patch_width)
|
| 398 |
+
|
| 399 |
+
predicted_depth = self.head(hidden_states, patch_height, patch_width)
|
| 400 |
+
|
| 401 |
+
if not return_dict:
|
| 402 |
+
if output_hidden_states:
|
| 403 |
+
output = (predicted_depth,) + outputs[1:]
|
| 404 |
+
else:
|
| 405 |
+
output = (predicted_depth,) + outputs[2:]
|
| 406 |
+
return ((loss,) + output) if loss is not None else output
|
| 407 |
+
|
| 408 |
+
return DepthEstimatorOutput(
|
| 409 |
+
loss=loss,
|
| 410 |
+
predicted_depth=predicted_depth,
|
| 411 |
+
hidden_states=outputs.hidden_states if output_hidden_states else None,
|
| 412 |
+
attentions=outputs.attentions,
|
| 413 |
+
)
|
| 414 |
+
|
| 415 |
+
|
| 416 |
+
__all__ = ["DepthAnythingForDepthEstimation", "DepthAnythingPreTrainedModel"]
|
third_party/transformers/src/transformers/models/dpr/__init__.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .configuration_dpr import *
|
| 22 |
+
from .modeling_dpr import *
|
| 23 |
+
from .tokenization_dpr import *
|
| 24 |
+
from .tokenization_dpr_fast import *
|
| 25 |
+
else:
|
| 26 |
+
import sys
|
| 27 |
+
|
| 28 |
+
_file = globals()["__file__"]
|
| 29 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/dpr/configuration_dpr.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2010, DPR authors, The Hugging Face Team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""DPR model configuration"""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from ...configuration_utils import PreTrainedConfig
|
| 19 |
+
from ...utils import auto_docstring
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
@auto_docstring(checkpoint="facebook/dpr-ctx_encoder-single-nq-base")
|
| 23 |
+
@strict
|
| 24 |
+
class DPRConfig(PreTrainedConfig):
|
| 25 |
+
r"""
|
| 26 |
+
Example:
|
| 27 |
+
|
| 28 |
+
```python
|
| 29 |
+
>>> from transformers import DPRConfig, DPRContextEncoder
|
| 30 |
+
|
| 31 |
+
>>> # Initializing a DPR facebook/dpr-ctx_encoder-single-nq-base style configuration
|
| 32 |
+
>>> configuration = DPRConfig()
|
| 33 |
+
|
| 34 |
+
>>> # Initializing a model (with random weights) from the facebook/dpr-ctx_encoder-single-nq-base style configuration
|
| 35 |
+
>>> model = DPRContextEncoder(configuration)
|
| 36 |
+
|
| 37 |
+
>>> # Accessing the model configuration
|
| 38 |
+
>>> configuration = model.config
|
| 39 |
+
```"""
|
| 40 |
+
|
| 41 |
+
model_type = "dpr"
|
| 42 |
+
|
| 43 |
+
vocab_size: int = 30522
|
| 44 |
+
hidden_size: int = 768
|
| 45 |
+
num_hidden_layers: int = 12
|
| 46 |
+
num_attention_heads: int = 12
|
| 47 |
+
intermediate_size: int = 3072
|
| 48 |
+
hidden_act: str = "gelu"
|
| 49 |
+
hidden_dropout_prob: float | int = 0.1
|
| 50 |
+
attention_probs_dropout_prob: float | int = 0.1
|
| 51 |
+
max_position_embeddings: int = 512
|
| 52 |
+
type_vocab_size: int = 2
|
| 53 |
+
initializer_range: float = 0.02
|
| 54 |
+
layer_norm_eps: float = 1e-12
|
| 55 |
+
pad_token_id: int | None = 0
|
| 56 |
+
bos_token_id: int | None = None
|
| 57 |
+
eos_token_id: int | list[int] | None = None
|
| 58 |
+
projection_dim: int = 0
|
| 59 |
+
is_decoder: bool = False
|
| 60 |
+
add_cross_attention: bool = False
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
__all__ = ["DPRConfig"]
|
third_party/transformers/src/transformers/models/dpr/convert_dpr_original_checkpoint_to_pytorch.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
import argparse
|
| 16 |
+
import collections
|
| 17 |
+
from pathlib import Path
|
| 18 |
+
|
| 19 |
+
import torch
|
| 20 |
+
from torch.serialization import default_restore_location
|
| 21 |
+
|
| 22 |
+
from transformers import BertConfig, DPRConfig, DPRContextEncoder, DPRQuestionEncoder, DPRReader
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
CheckpointState = collections.namedtuple(
|
| 26 |
+
"CheckpointState", ["model_dict", "optimizer_dict", "scheduler_dict", "offset", "epoch", "encoder_params"]
|
| 27 |
+
)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def load_states_from_checkpoint(model_file: str) -> CheckpointState:
|
| 31 |
+
print(f"Reading saved model from {model_file}")
|
| 32 |
+
state_dict = torch.load(
|
| 33 |
+
model_file, map_location=lambda s, l: default_restore_location(s, "cpu"), weights_only=True
|
| 34 |
+
)
|
| 35 |
+
return CheckpointState(**state_dict)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class DPRState:
|
| 39 |
+
def __init__(self, src_file: Path):
|
| 40 |
+
self.src_file = src_file
|
| 41 |
+
|
| 42 |
+
def load_dpr_model(self):
|
| 43 |
+
raise NotImplementedError
|
| 44 |
+
|
| 45 |
+
@staticmethod
|
| 46 |
+
def from_type(comp_type: str, *args, **kwargs) -> "DPRState":
|
| 47 |
+
if comp_type.startswith("c"):
|
| 48 |
+
return DPRContextEncoderState(*args, **kwargs)
|
| 49 |
+
if comp_type.startswith("q"):
|
| 50 |
+
return DPRQuestionEncoderState(*args, **kwargs)
|
| 51 |
+
if comp_type.startswith("r"):
|
| 52 |
+
return DPRReaderState(*args, **kwargs)
|
| 53 |
+
else:
|
| 54 |
+
raise ValueError("Component type must be either 'ctx_encoder', 'question_encoder' or 'reader'.")
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
class DPRContextEncoderState(DPRState):
|
| 58 |
+
def load_dpr_model(self):
|
| 59 |
+
model = DPRContextEncoder(DPRConfig(**BertConfig.get_config_dict("google-bert/bert-base-uncased")[0]))
|
| 60 |
+
print(f"Loading DPR biencoder from {self.src_file}")
|
| 61 |
+
saved_state = load_states_from_checkpoint(self.src_file)
|
| 62 |
+
encoder, prefix = model.ctx_encoder, "ctx_model."
|
| 63 |
+
# Fix changes from https://github.com/huggingface/transformers/commit/614fef1691edb806de976756d4948ecbcd0c0ca3
|
| 64 |
+
state_dict = {"bert_model.embeddings.position_ids": model.ctx_encoder.bert_model.embeddings.position_ids}
|
| 65 |
+
for key, value in saved_state.model_dict.items():
|
| 66 |
+
if key.startswith(prefix):
|
| 67 |
+
key = key[len(prefix) :]
|
| 68 |
+
if not key.startswith("encode_proj."):
|
| 69 |
+
key = "bert_model." + key
|
| 70 |
+
state_dict[key] = value
|
| 71 |
+
encoder.load_state_dict(state_dict)
|
| 72 |
+
return model
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
class DPRQuestionEncoderState(DPRState):
|
| 76 |
+
def load_dpr_model(self):
|
| 77 |
+
model = DPRQuestionEncoder(DPRConfig(**BertConfig.get_config_dict("google-bert/bert-base-uncased")[0]))
|
| 78 |
+
print(f"Loading DPR biencoder from {self.src_file}")
|
| 79 |
+
saved_state = load_states_from_checkpoint(self.src_file)
|
| 80 |
+
encoder, prefix = model.question_encoder, "question_model."
|
| 81 |
+
# Fix changes from https://github.com/huggingface/transformers/commit/614fef1691edb806de976756d4948ecbcd0c0ca3
|
| 82 |
+
state_dict = {"bert_model.embeddings.position_ids": model.question_encoder.bert_model.embeddings.position_ids}
|
| 83 |
+
for key, value in saved_state.model_dict.items():
|
| 84 |
+
if key.startswith(prefix):
|
| 85 |
+
key = key[len(prefix) :]
|
| 86 |
+
if not key.startswith("encode_proj."):
|
| 87 |
+
key = "bert_model." + key
|
| 88 |
+
state_dict[key] = value
|
| 89 |
+
encoder.load_state_dict(state_dict)
|
| 90 |
+
return model
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
class DPRReaderState(DPRState):
|
| 94 |
+
def load_dpr_model(self):
|
| 95 |
+
model = DPRReader(DPRConfig(**BertConfig.get_config_dict("google-bert/bert-base-uncased")[0]))
|
| 96 |
+
print(f"Loading DPR reader from {self.src_file}")
|
| 97 |
+
saved_state = load_states_from_checkpoint(self.src_file)
|
| 98 |
+
# Fix changes from https://github.com/huggingface/transformers/commit/614fef1691edb806de976756d4948ecbcd0c0ca3
|
| 99 |
+
state_dict = {
|
| 100 |
+
"encoder.bert_model.embeddings.position_ids": model.span_predictor.encoder.bert_model.embeddings.position_ids
|
| 101 |
+
}
|
| 102 |
+
for key, value in saved_state.model_dict.items():
|
| 103 |
+
if key.startswith("encoder.") and not key.startswith("encoder.encode_proj"):
|
| 104 |
+
key = "encoder.bert_model." + key[len("encoder.") :]
|
| 105 |
+
state_dict[key] = value
|
| 106 |
+
model.span_predictor.load_state_dict(state_dict)
|
| 107 |
+
return model
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def convert(comp_type: str, src_file: Path, dest_dir: Path):
|
| 111 |
+
dest_dir = Path(dest_dir)
|
| 112 |
+
dest_dir.mkdir(exist_ok=True)
|
| 113 |
+
|
| 114 |
+
dpr_state = DPRState.from_type(comp_type, src_file=src_file)
|
| 115 |
+
model = dpr_state.load_dpr_model()
|
| 116 |
+
model.save_pretrained(dest_dir)
|
| 117 |
+
model.from_pretrained(dest_dir) # sanity check
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
if __name__ == "__main__":
|
| 121 |
+
parser = argparse.ArgumentParser()
|
| 122 |
+
# Required parameters
|
| 123 |
+
parser.add_argument(
|
| 124 |
+
"--type", type=str, help="Type of the component to convert: 'ctx_encoder', 'question_encoder' or 'reader'."
|
| 125 |
+
)
|
| 126 |
+
parser.add_argument(
|
| 127 |
+
"--src",
|
| 128 |
+
type=str,
|
| 129 |
+
help=(
|
| 130 |
+
"Path to the dpr checkpoint file. They can be downloaded from the official DPR repo"
|
| 131 |
+
" https://github.com/facebookresearch/DPR. Note that in the official repo, both encoders are stored in the"
|
| 132 |
+
" 'retriever' checkpoints."
|
| 133 |
+
),
|
| 134 |
+
)
|
| 135 |
+
parser.add_argument("--dest", type=str, default=None, help="Path to the output PyTorch model directory.")
|
| 136 |
+
args = parser.parse_args()
|
| 137 |
+
|
| 138 |
+
src_file = Path(args.src)
|
| 139 |
+
dest_dir = f"converted-{src_file.name}" if args.dest is None else args.dest
|
| 140 |
+
dest_dir = Path(dest_dir)
|
| 141 |
+
assert src_file.exists()
|
| 142 |
+
assert args.type is not None, (
|
| 143 |
+
"Please specify the component type of the DPR model to convert: 'ctx_encoder', 'question_encoder' or 'reader'."
|
| 144 |
+
)
|
| 145 |
+
convert(args.type, src_file, dest_dir)
|
third_party/transformers/src/transformers/models/dpr/modeling_dpr.py
ADDED
|
@@ -0,0 +1,576 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2018 DPR Authors, The Hugging Face Team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""PyTorch DPR model for Open Domain Question Answering."""
|
| 15 |
+
|
| 16 |
+
from dataclasses import dataclass
|
| 17 |
+
|
| 18 |
+
import torch
|
| 19 |
+
from torch import Tensor, nn
|
| 20 |
+
|
| 21 |
+
from ...modeling_outputs import BaseModelOutputWithPooling
|
| 22 |
+
from ...modeling_utils import PreTrainedModel
|
| 23 |
+
from ...utils import (
|
| 24 |
+
ModelOutput,
|
| 25 |
+
auto_docstring,
|
| 26 |
+
logging,
|
| 27 |
+
)
|
| 28 |
+
from ..bert.modeling_bert import BertModel
|
| 29 |
+
from .configuration_dpr import DPRConfig
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
logger = logging.get_logger(__name__)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
##########
|
| 36 |
+
# Outputs
|
| 37 |
+
##########
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
@dataclass
|
| 41 |
+
@auto_docstring(
|
| 42 |
+
custom_intro="""
|
| 43 |
+
Class for outputs of [`DPRQuestionEncoder`].
|
| 44 |
+
"""
|
| 45 |
+
)
|
| 46 |
+
class DPRContextEncoderOutput(ModelOutput):
|
| 47 |
+
r"""
|
| 48 |
+
pooler_output (`torch.FloatTensor` of shape `(batch_size, embeddings_size)`):
|
| 49 |
+
The DPR encoder outputs the *pooler_output* that corresponds to the context representation. Last layer
|
| 50 |
+
hidden-state of the first token of the sequence (classification token) further processed by a Linear layer.
|
| 51 |
+
This output is to be used to embed contexts for nearest neighbors queries with questions embeddings.
|
| 52 |
+
"""
|
| 53 |
+
|
| 54 |
+
pooler_output: torch.FloatTensor
|
| 55 |
+
hidden_states: tuple[torch.FloatTensor, ...] | None = None
|
| 56 |
+
attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
@dataclass
|
| 60 |
+
@auto_docstring(
|
| 61 |
+
custom_intro="""
|
| 62 |
+
Class for outputs of [`DPRQuestionEncoder`].
|
| 63 |
+
"""
|
| 64 |
+
)
|
| 65 |
+
class DPRQuestionEncoderOutput(ModelOutput):
|
| 66 |
+
r"""
|
| 67 |
+
pooler_output (`torch.FloatTensor` of shape `(batch_size, embeddings_size)`):
|
| 68 |
+
The DPR encoder outputs the *pooler_output* that corresponds to the question representation. Last layer
|
| 69 |
+
hidden-state of the first token of the sequence (classification token) further processed by a Linear layer.
|
| 70 |
+
This output is to be used to embed questions for nearest neighbors queries with context embeddings.
|
| 71 |
+
"""
|
| 72 |
+
|
| 73 |
+
pooler_output: torch.FloatTensor
|
| 74 |
+
hidden_states: tuple[torch.FloatTensor, ...] | None = None
|
| 75 |
+
attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
@dataclass
|
| 79 |
+
@auto_docstring(
|
| 80 |
+
custom_intro="""
|
| 81 |
+
Class for outputs of [`DPRQuestionEncoder`].
|
| 82 |
+
"""
|
| 83 |
+
)
|
| 84 |
+
class DPRReaderOutput(ModelOutput):
|
| 85 |
+
r"""
|
| 86 |
+
start_logits (`torch.FloatTensor` of shape `(n_passages, sequence_length)`):
|
| 87 |
+
Logits of the start index of the span for each passage.
|
| 88 |
+
end_logits (`torch.FloatTensor` of shape `(n_passages, sequence_length)`):
|
| 89 |
+
Logits of the end index of the span for each passage.
|
| 90 |
+
relevance_logits (`torch.FloatTensor` of shape `(n_passages, )`):
|
| 91 |
+
Outputs of the QA classifier of the DPRReader that corresponds to the scores of each passage to answer the
|
| 92 |
+
question, compared to all the other passages.
|
| 93 |
+
"""
|
| 94 |
+
|
| 95 |
+
start_logits: torch.FloatTensor
|
| 96 |
+
end_logits: torch.FloatTensor | None = None
|
| 97 |
+
relevance_logits: torch.FloatTensor | None = None
|
| 98 |
+
hidden_states: tuple[torch.FloatTensor, ...] | None = None
|
| 99 |
+
attentions: tuple[torch.FloatTensor, ...] | None = None
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
@auto_docstring
|
| 103 |
+
class DPRPreTrainedModel(PreTrainedModel):
|
| 104 |
+
_supports_sdpa = True
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
class DPREncoder(DPRPreTrainedModel):
|
| 108 |
+
base_model_prefix = "bert_model"
|
| 109 |
+
|
| 110 |
+
def __init__(self, config: DPRConfig):
|
| 111 |
+
super().__init__(config)
|
| 112 |
+
self.bert_model = BertModel(config, add_pooling_layer=False)
|
| 113 |
+
if self.bert_model.config.hidden_size <= 0:
|
| 114 |
+
raise ValueError("Encoder hidden_size can't be zero")
|
| 115 |
+
self.projection_dim = config.projection_dim
|
| 116 |
+
if self.projection_dim > 0:
|
| 117 |
+
self.encode_proj = nn.Linear(self.bert_model.config.hidden_size, config.projection_dim)
|
| 118 |
+
# Initialize weights and apply final processing
|
| 119 |
+
self.post_init()
|
| 120 |
+
|
| 121 |
+
def forward(
|
| 122 |
+
self,
|
| 123 |
+
input_ids: Tensor,
|
| 124 |
+
attention_mask: Tensor | None = None,
|
| 125 |
+
token_type_ids: Tensor | None = None,
|
| 126 |
+
inputs_embeds: Tensor | None = None,
|
| 127 |
+
output_attentions: bool = False,
|
| 128 |
+
output_hidden_states: bool = False,
|
| 129 |
+
return_dict: bool = False,
|
| 130 |
+
**kwargs,
|
| 131 |
+
) -> BaseModelOutputWithPooling | tuple[Tensor, ...]:
|
| 132 |
+
outputs = self.bert_model(
|
| 133 |
+
input_ids=input_ids,
|
| 134 |
+
attention_mask=attention_mask,
|
| 135 |
+
token_type_ids=token_type_ids,
|
| 136 |
+
inputs_embeds=inputs_embeds,
|
| 137 |
+
output_attentions=output_attentions,
|
| 138 |
+
output_hidden_states=output_hidden_states,
|
| 139 |
+
return_dict=return_dict,
|
| 140 |
+
)
|
| 141 |
+
sequence_output = outputs[0]
|
| 142 |
+
pooled_output = sequence_output[:, 0, :]
|
| 143 |
+
|
| 144 |
+
if self.projection_dim > 0:
|
| 145 |
+
pooled_output = self.encode_proj(pooled_output)
|
| 146 |
+
|
| 147 |
+
if not return_dict:
|
| 148 |
+
return (sequence_output, pooled_output) + outputs[2:]
|
| 149 |
+
|
| 150 |
+
return BaseModelOutputWithPooling(
|
| 151 |
+
last_hidden_state=sequence_output,
|
| 152 |
+
pooler_output=pooled_output,
|
| 153 |
+
hidden_states=outputs.hidden_states,
|
| 154 |
+
attentions=outputs.attentions,
|
| 155 |
+
)
|
| 156 |
+
|
| 157 |
+
@property
|
| 158 |
+
def embeddings_size(self) -> int:
|
| 159 |
+
if self.projection_dim > 0:
|
| 160 |
+
return self.encode_proj.out_features
|
| 161 |
+
return self.bert_model.config.hidden_size
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
class DPRSpanPredictor(DPRPreTrainedModel):
|
| 165 |
+
base_model_prefix = "encoder"
|
| 166 |
+
|
| 167 |
+
def __init__(self, config: DPRConfig):
|
| 168 |
+
super().__init__(config)
|
| 169 |
+
self.encoder = DPREncoder(config)
|
| 170 |
+
self.qa_outputs = nn.Linear(self.encoder.embeddings_size, 2)
|
| 171 |
+
self.qa_classifier = nn.Linear(self.encoder.embeddings_size, 1)
|
| 172 |
+
# Initialize weights and apply final processing
|
| 173 |
+
self.post_init()
|
| 174 |
+
|
| 175 |
+
def forward(
|
| 176 |
+
self,
|
| 177 |
+
input_ids: Tensor,
|
| 178 |
+
attention_mask: Tensor,
|
| 179 |
+
inputs_embeds: Tensor | None = None,
|
| 180 |
+
output_attentions: bool = False,
|
| 181 |
+
output_hidden_states: bool = False,
|
| 182 |
+
return_dict: bool = False,
|
| 183 |
+
**kwargs,
|
| 184 |
+
) -> DPRReaderOutput | tuple[Tensor, ...]:
|
| 185 |
+
# notations: N - number of questions in a batch, M - number of passages per questions, L - sequence length
|
| 186 |
+
n_passages, sequence_length = input_ids.size() if input_ids is not None else inputs_embeds.size()[:2]
|
| 187 |
+
# feed encoder
|
| 188 |
+
outputs = self.encoder(
|
| 189 |
+
input_ids,
|
| 190 |
+
attention_mask=attention_mask,
|
| 191 |
+
inputs_embeds=inputs_embeds,
|
| 192 |
+
output_attentions=output_attentions,
|
| 193 |
+
output_hidden_states=output_hidden_states,
|
| 194 |
+
return_dict=return_dict,
|
| 195 |
+
)
|
| 196 |
+
sequence_output = outputs[0]
|
| 197 |
+
|
| 198 |
+
# compute logits
|
| 199 |
+
logits = self.qa_outputs(sequence_output)
|
| 200 |
+
start_logits, end_logits = logits.split(1, dim=-1)
|
| 201 |
+
start_logits = start_logits.squeeze(-1).contiguous()
|
| 202 |
+
end_logits = end_logits.squeeze(-1).contiguous()
|
| 203 |
+
relevance_logits = self.qa_classifier(sequence_output[:, 0, :])
|
| 204 |
+
|
| 205 |
+
# resize
|
| 206 |
+
start_logits = start_logits.view(n_passages, sequence_length)
|
| 207 |
+
end_logits = end_logits.view(n_passages, sequence_length)
|
| 208 |
+
relevance_logits = relevance_logits.view(n_passages)
|
| 209 |
+
|
| 210 |
+
if not return_dict:
|
| 211 |
+
return (start_logits, end_logits, relevance_logits) + outputs[2:]
|
| 212 |
+
|
| 213 |
+
return DPRReaderOutput(
|
| 214 |
+
start_logits=start_logits,
|
| 215 |
+
end_logits=end_logits,
|
| 216 |
+
relevance_logits=relevance_logits,
|
| 217 |
+
hidden_states=outputs.hidden_states,
|
| 218 |
+
attentions=outputs.attentions,
|
| 219 |
+
)
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
##################
|
| 223 |
+
# PreTrainedModel
|
| 224 |
+
##################
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
class DPRPretrainedContextEncoder(DPRPreTrainedModel):
|
| 228 |
+
"""
|
| 229 |
+
An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained
|
| 230 |
+
models.
|
| 231 |
+
"""
|
| 232 |
+
|
| 233 |
+
config: DPRConfig
|
| 234 |
+
base_model_prefix = "ctx_encoder"
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
class DPRPretrainedQuestionEncoder(DPRPreTrainedModel):
|
| 238 |
+
"""
|
| 239 |
+
An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained
|
| 240 |
+
models.
|
| 241 |
+
"""
|
| 242 |
+
|
| 243 |
+
config: DPRConfig
|
| 244 |
+
base_model_prefix = "question_encoder"
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
class DPRPretrainedReader(DPRPreTrainedModel):
|
| 248 |
+
"""
|
| 249 |
+
An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained
|
| 250 |
+
models.
|
| 251 |
+
"""
|
| 252 |
+
|
| 253 |
+
config: DPRConfig
|
| 254 |
+
base_model_prefix = "span_predictor"
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
###############
|
| 258 |
+
# Actual Models
|
| 259 |
+
###############
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
@auto_docstring(
|
| 263 |
+
custom_intro="""
|
| 264 |
+
The bare DPRContextEncoder transformer outputting pooler outputs as context representations.
|
| 265 |
+
"""
|
| 266 |
+
)
|
| 267 |
+
class DPRContextEncoder(DPRPretrainedContextEncoder):
|
| 268 |
+
def __init__(self, config: DPRConfig):
|
| 269 |
+
super().__init__(config)
|
| 270 |
+
self.config = config
|
| 271 |
+
self.ctx_encoder = DPREncoder(config)
|
| 272 |
+
# Initialize weights and apply final processing
|
| 273 |
+
self.post_init()
|
| 274 |
+
|
| 275 |
+
@auto_docstring
|
| 276 |
+
def forward(
|
| 277 |
+
self,
|
| 278 |
+
input_ids: Tensor | None = None,
|
| 279 |
+
attention_mask: Tensor | None = None,
|
| 280 |
+
token_type_ids: Tensor | None = None,
|
| 281 |
+
inputs_embeds: Tensor | None = None,
|
| 282 |
+
output_attentions: bool | None = None,
|
| 283 |
+
output_hidden_states: bool | None = None,
|
| 284 |
+
return_dict: bool | None = None,
|
| 285 |
+
**kwargs,
|
| 286 |
+
) -> DPRContextEncoderOutput | tuple[Tensor, ...]:
|
| 287 |
+
r"""
|
| 288 |
+
input_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`):
|
| 289 |
+
Indices of input sequence tokens in the vocabulary. To match pretraining, DPR input sequence should be
|
| 290 |
+
formatted with [CLS] and [SEP] tokens as follows:
|
| 291 |
+
|
| 292 |
+
(a) For sequence pairs (for a pair title+text for example):
|
| 293 |
+
|
| 294 |
+
```
|
| 295 |
+
tokens: [CLS] is this jack ##son ##ville ? [SEP] no it is not . [SEP]
|
| 296 |
+
token_type_ids: 0 0 0 0 0 0 0 0 1 1 1 1 1 1
|
| 297 |
+
```
|
| 298 |
+
|
| 299 |
+
(b) For single sequences (for a question for example):
|
| 300 |
+
|
| 301 |
+
```
|
| 302 |
+
tokens: [CLS] the dog is hairy . [SEP]
|
| 303 |
+
token_type_ids: 0 0 0 0 0 0 0
|
| 304 |
+
```
|
| 305 |
+
|
| 306 |
+
DPR is a model with absolute position embeddings so it's usually advised to pad the inputs on the right
|
| 307 |
+
rather than the left.
|
| 308 |
+
|
| 309 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
|
| 310 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 311 |
+
|
| 312 |
+
[What are input IDs?](../glossary#input-ids)
|
| 313 |
+
|
| 314 |
+
Examples:
|
| 315 |
+
|
| 316 |
+
```python
|
| 317 |
+
>>> from transformers import DPRContextEncoder, DPRContextEncoderTokenizer
|
| 318 |
+
|
| 319 |
+
>>> tokenizer = DPRContextEncoderTokenizer.from_pretrained("facebook/dpr-ctx_encoder-single-nq-base")
|
| 320 |
+
>>> model = DPRContextEncoder.from_pretrained("facebook/dpr-ctx_encoder-single-nq-base")
|
| 321 |
+
>>> input_ids = tokenizer("Hello, is my dog cute ?", return_tensors="pt")["input_ids"]
|
| 322 |
+
>>> embeddings = model(input_ids).pooler_output
|
| 323 |
+
```"""
|
| 324 |
+
|
| 325 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 326 |
+
output_hidden_states = (
|
| 327 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 328 |
+
)
|
| 329 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 330 |
+
|
| 331 |
+
if input_ids is not None and inputs_embeds is not None:
|
| 332 |
+
raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
|
| 333 |
+
elif input_ids is not None:
|
| 334 |
+
input_shape = input_ids.size()
|
| 335 |
+
elif inputs_embeds is not None:
|
| 336 |
+
input_shape = inputs_embeds.size()[:-1]
|
| 337 |
+
else:
|
| 338 |
+
raise ValueError("You have to specify either input_ids or inputs_embeds")
|
| 339 |
+
|
| 340 |
+
device = input_ids.device if input_ids is not None else inputs_embeds.device
|
| 341 |
+
|
| 342 |
+
if attention_mask is None:
|
| 343 |
+
attention_mask = (
|
| 344 |
+
torch.ones(input_shape, device=device)
|
| 345 |
+
if input_ids is None
|
| 346 |
+
else (input_ids != self.config.pad_token_id)
|
| 347 |
+
)
|
| 348 |
+
if token_type_ids is None:
|
| 349 |
+
token_type_ids = torch.zeros(input_shape, dtype=torch.long, device=device)
|
| 350 |
+
|
| 351 |
+
outputs = self.ctx_encoder(
|
| 352 |
+
input_ids=input_ids,
|
| 353 |
+
attention_mask=attention_mask,
|
| 354 |
+
token_type_ids=token_type_ids,
|
| 355 |
+
inputs_embeds=inputs_embeds,
|
| 356 |
+
output_attentions=output_attentions,
|
| 357 |
+
output_hidden_states=output_hidden_states,
|
| 358 |
+
return_dict=return_dict,
|
| 359 |
+
)
|
| 360 |
+
|
| 361 |
+
if not return_dict:
|
| 362 |
+
return outputs[1:]
|
| 363 |
+
return DPRContextEncoderOutput(
|
| 364 |
+
pooler_output=outputs.pooler_output, hidden_states=outputs.hidden_states, attentions=outputs.attentions
|
| 365 |
+
)
|
| 366 |
+
|
| 367 |
+
|
| 368 |
+
@auto_docstring(
|
| 369 |
+
custom_intro="""
|
| 370 |
+
The bare DPRQuestionEncoder transformer outputting pooler outputs as question representations.
|
| 371 |
+
"""
|
| 372 |
+
)
|
| 373 |
+
class DPRQuestionEncoder(DPRPretrainedQuestionEncoder):
|
| 374 |
+
def __init__(self, config: DPRConfig):
|
| 375 |
+
super().__init__(config)
|
| 376 |
+
self.config = config
|
| 377 |
+
self.question_encoder = DPREncoder(config)
|
| 378 |
+
# Initialize weights and apply final processing
|
| 379 |
+
self.post_init()
|
| 380 |
+
|
| 381 |
+
@auto_docstring
|
| 382 |
+
def forward(
|
| 383 |
+
self,
|
| 384 |
+
input_ids: Tensor | None = None,
|
| 385 |
+
attention_mask: Tensor | None = None,
|
| 386 |
+
token_type_ids: Tensor | None = None,
|
| 387 |
+
inputs_embeds: Tensor | None = None,
|
| 388 |
+
output_attentions: bool | None = None,
|
| 389 |
+
output_hidden_states: bool | None = None,
|
| 390 |
+
return_dict: bool | None = None,
|
| 391 |
+
**kwargs,
|
| 392 |
+
) -> DPRQuestionEncoderOutput | tuple[Tensor, ...]:
|
| 393 |
+
r"""
|
| 394 |
+
input_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`):
|
| 395 |
+
Indices of input sequence tokens in the vocabulary. To match pretraining, DPR input sequence should be
|
| 396 |
+
formatted with [CLS] and [SEP] tokens as follows:
|
| 397 |
+
|
| 398 |
+
(a) For sequence pairs (for a pair title+text for example):
|
| 399 |
+
|
| 400 |
+
```
|
| 401 |
+
tokens: [CLS] is this jack ##son ##ville ? [SEP] no it is not . [SEP]
|
| 402 |
+
token_type_ids: 0 0 0 0 0 0 0 0 1 1 1 1 1 1
|
| 403 |
+
```
|
| 404 |
+
|
| 405 |
+
(b) For single sequences (for a question for example):
|
| 406 |
+
|
| 407 |
+
```
|
| 408 |
+
tokens: [CLS] the dog is hairy . [SEP]
|
| 409 |
+
token_type_ids: 0 0 0 0 0 0 0
|
| 410 |
+
```
|
| 411 |
+
|
| 412 |
+
DPR is a model with absolute position embeddings so it's usually advised to pad the inputs on the right
|
| 413 |
+
rather than the left.
|
| 414 |
+
|
| 415 |
+
Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and
|
| 416 |
+
[`PreTrainedTokenizer.__call__`] for details.
|
| 417 |
+
|
| 418 |
+
[What are input IDs?](../glossary#input-ids)
|
| 419 |
+
|
| 420 |
+
Examples:
|
| 421 |
+
|
| 422 |
+
```python
|
| 423 |
+
>>> from transformers import DPRQuestionEncoder, DPRQuestionEncoderTokenizer
|
| 424 |
+
|
| 425 |
+
>>> tokenizer = DPRQuestionEncoderTokenizer.from_pretrained("facebook/dpr-question_encoder-single-nq-base")
|
| 426 |
+
>>> model = DPRQuestionEncoder.from_pretrained("facebook/dpr-question_encoder-single-nq-base")
|
| 427 |
+
>>> input_ids = tokenizer("Hello, is my dog cute ?", return_tensors="pt")["input_ids"]
|
| 428 |
+
>>> embeddings = model(input_ids).pooler_output
|
| 429 |
+
```
|
| 430 |
+
"""
|
| 431 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 432 |
+
output_hidden_states = (
|
| 433 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 434 |
+
)
|
| 435 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 436 |
+
|
| 437 |
+
if input_ids is not None and inputs_embeds is not None:
|
| 438 |
+
raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
|
| 439 |
+
elif input_ids is not None:
|
| 440 |
+
self.warn_if_padding_and_no_attention_mask(input_ids, attention_mask)
|
| 441 |
+
input_shape = input_ids.size()
|
| 442 |
+
elif inputs_embeds is not None:
|
| 443 |
+
input_shape = inputs_embeds.size()[:-1]
|
| 444 |
+
else:
|
| 445 |
+
raise ValueError("You have to specify either input_ids or inputs_embeds")
|
| 446 |
+
|
| 447 |
+
device = input_ids.device if input_ids is not None else inputs_embeds.device
|
| 448 |
+
|
| 449 |
+
if attention_mask is None:
|
| 450 |
+
attention_mask = (
|
| 451 |
+
torch.ones(input_shape, device=device)
|
| 452 |
+
if input_ids is None
|
| 453 |
+
else (input_ids != self.config.pad_token_id)
|
| 454 |
+
)
|
| 455 |
+
if token_type_ids is None:
|
| 456 |
+
token_type_ids = torch.zeros(input_shape, dtype=torch.long, device=device)
|
| 457 |
+
|
| 458 |
+
outputs = self.question_encoder(
|
| 459 |
+
input_ids=input_ids,
|
| 460 |
+
attention_mask=attention_mask,
|
| 461 |
+
token_type_ids=token_type_ids,
|
| 462 |
+
inputs_embeds=inputs_embeds,
|
| 463 |
+
output_attentions=output_attentions,
|
| 464 |
+
output_hidden_states=output_hidden_states,
|
| 465 |
+
return_dict=return_dict,
|
| 466 |
+
)
|
| 467 |
+
|
| 468 |
+
if not return_dict:
|
| 469 |
+
return outputs[1:]
|
| 470 |
+
return DPRQuestionEncoderOutput(
|
| 471 |
+
pooler_output=outputs.pooler_output, hidden_states=outputs.hidden_states, attentions=outputs.attentions
|
| 472 |
+
)
|
| 473 |
+
|
| 474 |
+
|
| 475 |
+
@auto_docstring(
|
| 476 |
+
custom_intro="""
|
| 477 |
+
The bare DPRReader transformer outputting span predictions.
|
| 478 |
+
"""
|
| 479 |
+
)
|
| 480 |
+
class DPRReader(DPRPretrainedReader):
|
| 481 |
+
def __init__(self, config: DPRConfig):
|
| 482 |
+
super().__init__(config)
|
| 483 |
+
self.config = config
|
| 484 |
+
self.span_predictor = DPRSpanPredictor(config)
|
| 485 |
+
# Initialize weights and apply final processing
|
| 486 |
+
self.post_init()
|
| 487 |
+
|
| 488 |
+
@auto_docstring
|
| 489 |
+
def forward(
|
| 490 |
+
self,
|
| 491 |
+
input_ids: Tensor | None = None,
|
| 492 |
+
attention_mask: Tensor | None = None,
|
| 493 |
+
inputs_embeds: Tensor | None = None,
|
| 494 |
+
output_attentions: bool | None = None,
|
| 495 |
+
output_hidden_states: bool | None = None,
|
| 496 |
+
return_dict: bool | None = None,
|
| 497 |
+
**kwargs,
|
| 498 |
+
) -> DPRReaderOutput | tuple[Tensor, ...]:
|
| 499 |
+
r"""
|
| 500 |
+
input_ids (`tuple[torch.LongTensor]` of shapes `(n_passages, sequence_length)`):
|
| 501 |
+
Indices of input sequence tokens in the vocabulary. It has to be a sequence triplet with 1) the question
|
| 502 |
+
and 2) the passages titles and 3) the passages texts To match pretraining, DPR `input_ids` sequence should
|
| 503 |
+
be formatted with [CLS] and [SEP] with the format:
|
| 504 |
+
|
| 505 |
+
`[CLS] <question token ids> [SEP] <titles ids> [SEP] <texts ids>`
|
| 506 |
+
|
| 507 |
+
DPR is a model with absolute position embeddings so it's usually advised to pad the inputs on the right
|
| 508 |
+
rather than the left.
|
| 509 |
+
|
| 510 |
+
Indices can be obtained using [`DPRReaderTokenizer`]. See this class documentation for more details.
|
| 511 |
+
|
| 512 |
+
[What are input IDs?](../glossary#input-ids)
|
| 513 |
+
inputs_embeds (`torch.FloatTensor` of shape `(n_passages, sequence_length, hidden_size)`, *optional*):
|
| 514 |
+
Optionally, instead of passing `input_ids` you can choose to directly pass an embedded representation. This
|
| 515 |
+
is useful if you want more control over how to convert `input_ids` indices into associated vectors than the
|
| 516 |
+
model's internal embedding lookup matrix.
|
| 517 |
+
|
| 518 |
+
Examples:
|
| 519 |
+
|
| 520 |
+
```python
|
| 521 |
+
>>> from transformers import DPRReader, DPRReaderTokenizer
|
| 522 |
+
|
| 523 |
+
>>> tokenizer = DPRReaderTokenizer.from_pretrained("facebook/dpr-reader-single-nq-base")
|
| 524 |
+
>>> model = DPRReader.from_pretrained("facebook/dpr-reader-single-nq-base")
|
| 525 |
+
>>> encoded_inputs = tokenizer(
|
| 526 |
+
... questions=["What is love ?"],
|
| 527 |
+
... titles=["Haddaway"],
|
| 528 |
+
... texts=["'What Is Love' is a song recorded by the artist Haddaway"],
|
| 529 |
+
... return_tensors="pt",
|
| 530 |
+
... )
|
| 531 |
+
>>> outputs = model(**encoded_inputs)
|
| 532 |
+
>>> start_logits = outputs.start_logits
|
| 533 |
+
>>> end_logits = outputs.end_logits
|
| 534 |
+
>>> relevance_logits = outputs.relevance_logits
|
| 535 |
+
```
|
| 536 |
+
"""
|
| 537 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 538 |
+
output_hidden_states = (
|
| 539 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 540 |
+
)
|
| 541 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 542 |
+
|
| 543 |
+
if input_ids is not None and inputs_embeds is not None:
|
| 544 |
+
raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
|
| 545 |
+
elif input_ids is not None:
|
| 546 |
+
self.warn_if_padding_and_no_attention_mask(input_ids, attention_mask)
|
| 547 |
+
input_shape = input_ids.size()
|
| 548 |
+
elif inputs_embeds is not None:
|
| 549 |
+
input_shape = inputs_embeds.size()[:-1]
|
| 550 |
+
else:
|
| 551 |
+
raise ValueError("You have to specify either input_ids or inputs_embeds")
|
| 552 |
+
|
| 553 |
+
device = input_ids.device if input_ids is not None else inputs_embeds.device
|
| 554 |
+
|
| 555 |
+
if attention_mask is None:
|
| 556 |
+
attention_mask = torch.ones(input_shape, device=device)
|
| 557 |
+
|
| 558 |
+
return self.span_predictor(
|
| 559 |
+
input_ids,
|
| 560 |
+
attention_mask,
|
| 561 |
+
inputs_embeds=inputs_embeds,
|
| 562 |
+
output_attentions=output_attentions,
|
| 563 |
+
output_hidden_states=output_hidden_states,
|
| 564 |
+
return_dict=return_dict,
|
| 565 |
+
)
|
| 566 |
+
|
| 567 |
+
|
| 568 |
+
__all__ = [
|
| 569 |
+
"DPRContextEncoder",
|
| 570 |
+
"DPRPretrainedContextEncoder",
|
| 571 |
+
"DPRPreTrainedModel",
|
| 572 |
+
"DPRPretrainedQuestionEncoder",
|
| 573 |
+
"DPRPretrainedReader",
|
| 574 |
+
"DPRQuestionEncoder",
|
| 575 |
+
"DPRReader",
|
| 576 |
+
]
|
third_party/transformers/src/transformers/models/dpr/tokenization_dpr.py
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2018 The HuggingFace Inc. team, The Hugging Face Team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Tokenization classes for DPR."""
|
| 15 |
+
|
| 16 |
+
import collections
|
| 17 |
+
|
| 18 |
+
from ...tokenization_utils_base import BatchEncoding
|
| 19 |
+
from ...utils import TensorType, add_end_docstrings, add_start_docstrings, logging
|
| 20 |
+
from ..bert.tokenization_bert import BertTokenizer
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
logger = logging.get_logger(__name__)
|
| 24 |
+
|
| 25 |
+
VOCAB_FILES_NAMES = {"vocab_file": "vocab.txt", "tokenizer_file": "tokenizer.json"}
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
class DPRContextEncoderTokenizer(BertTokenizer):
|
| 29 |
+
r"""
|
| 30 |
+
Construct a DPRContextEncoder tokenizer.
|
| 31 |
+
|
| 32 |
+
[`DPRContextEncoderTokenizer`] is identical to [`BertTokenizer`] and runs end-to-end tokenization: punctuation
|
| 33 |
+
splitting and wordpiece.
|
| 34 |
+
|
| 35 |
+
Refer to superclass [`BertTokenizer`] for usage examples and documentation concerning parameters.
|
| 36 |
+
"""
|
| 37 |
+
|
| 38 |
+
vocab_files_names = VOCAB_FILES_NAMES
|
| 39 |
+
|
| 40 |
+
def __init__(self, *args, do_lower_case=False, **kwargs):
|
| 41 |
+
super().__init__(*args, **kwargs)
|
| 42 |
+
self.do_lower_case = do_lower_case
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
class DPRQuestionEncoderTokenizer(BertTokenizer):
|
| 46 |
+
r"""
|
| 47 |
+
Constructs a DPRQuestionEncoder tokenizer.
|
| 48 |
+
|
| 49 |
+
[`DPRQuestionEncoderTokenizer`] is identical to [`BertTokenizer`] and runs end-to-end tokenization: punctuation
|
| 50 |
+
splitting and wordpiece.
|
| 51 |
+
|
| 52 |
+
Refer to superclass [`BertTokenizer`] for usage examples and documentation concerning parameters.
|
| 53 |
+
"""
|
| 54 |
+
|
| 55 |
+
vocab_files_names = VOCAB_FILES_NAMES
|
| 56 |
+
|
| 57 |
+
def __init__(self, *args, do_lower_case=False, **kwargs):
|
| 58 |
+
super().__init__(*args, **kwargs)
|
| 59 |
+
self.do_lower_case = do_lower_case
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
DPRSpanPrediction = collections.namedtuple(
|
| 63 |
+
"DPRSpanPrediction", ["span_score", "relevance_score", "doc_id", "start_index", "end_index", "text"]
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
DPRReaderOutput = collections.namedtuple("DPRReaderOutput", ["start_logits", "end_logits", "relevance_logits"])
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
CUSTOM_DPR_READER_DOCSTRING = r"""
|
| 70 |
+
Return a dictionary with the token ids of the input strings and other information to give to `.decode_best_spans`.
|
| 71 |
+
It converts the strings of a question and different passages (title and text) in a sequence of IDs (integers),
|
| 72 |
+
using the tokenizer and vocabulary. The resulting `input_ids` is a matrix of size `(n_passages, sequence_length)`
|
| 73 |
+
with the format:
|
| 74 |
+
|
| 75 |
+
```
|
| 76 |
+
[CLS] <question token ids> [SEP] <titles ids> [SEP] <texts ids>
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
Args:
|
| 80 |
+
questions (`str` or `list[str]`):
|
| 81 |
+
The questions to be encoded. You can specify one question for many passages. In this case, the question
|
| 82 |
+
will be duplicated like `[questions] * n_passages`. Otherwise you have to specify as many questions as in
|
| 83 |
+
`titles` or `texts`.
|
| 84 |
+
titles (`str` or `list[str]`):
|
| 85 |
+
The passages titles to be encoded. This can be a string or a list of strings if there are several passages.
|
| 86 |
+
texts (`str` or `list[str]`):
|
| 87 |
+
The passages texts to be encoded. This can be a string or a list of strings if there are several passages.
|
| 88 |
+
padding (`bool`, `str` or [`~utils.PaddingStrategy`], *optional*, defaults to `False`):
|
| 89 |
+
Activates and controls padding. Accepts the following values:
|
| 90 |
+
|
| 91 |
+
- `True` or `'longest'`: Pad to the longest sequence in the batch (or no padding if only a single sequence
|
| 92 |
+
if provided).
|
| 93 |
+
- `'max_length'`: Pad to a maximum length specified with the argument `max_length` or to the maximum
|
| 94 |
+
acceptable input length for the model if that argument is not provided.
|
| 95 |
+
- `False` or `'do_not_pad'` (default): No padding (i.e., can output a batch with sequences of different
|
| 96 |
+
lengths).
|
| 97 |
+
truncation (`bool`, `str` or [`~tokenization_utils_base.TruncationStrategy`], *optional*, defaults to `False`):
|
| 98 |
+
Activates and controls truncation. Accepts the following values:
|
| 99 |
+
|
| 100 |
+
- `True` or `'longest_first'`: Truncate to a maximum length specified with the argument `max_length` or to
|
| 101 |
+
the maximum acceptable input length for the model if that argument is not provided. This will truncate
|
| 102 |
+
token by token, removing a token from the longest sequence in the pair if a pair of sequences (or a batch
|
| 103 |
+
of pairs) is provided.
|
| 104 |
+
- `'only_first'`: Truncate to a maximum length specified with the argument `max_length` or to the maximum
|
| 105 |
+
acceptable input length for the model if that argument is not provided. This will only truncate the first
|
| 106 |
+
sequence of a pair if a pair of sequences (or a batch of pairs) is provided.
|
| 107 |
+
- `'only_second'`: Truncate to a maximum length specified with the argument `max_length` or to the maximum
|
| 108 |
+
acceptable input length for the model if that argument is not provided. This will only truncate the
|
| 109 |
+
second sequence of a pair if a pair of sequences (or a batch of pairs) is provided.
|
| 110 |
+
- `False` or `'do_not_truncate'` (default): No truncation (i.e., can output batch with sequence lengths
|
| 111 |
+
greater than the model maximum admissible input size).
|
| 112 |
+
max_length (`int`, *optional*):
|
| 113 |
+
Controls the maximum length to use by one of the truncation/padding parameters.
|
| 114 |
+
|
| 115 |
+
If left unset or set to `None`, this will use the predefined model maximum length if a maximum length
|
| 116 |
+
is required by one of the truncation/padding parameters. If the model has no specific maximum input
|
| 117 |
+
length (like XLNet) truncation/padding to a maximum length will be deactivated.
|
| 118 |
+
return_tensors (`str` or [`~utils.TensorType`], *optional*):
|
| 119 |
+
If set, will return tensors instead of list of python integers. Acceptable values are:
|
| 120 |
+
|
| 121 |
+
- `'pt'`: Return PyTorch `torch.Tensor` objects.
|
| 122 |
+
- `'np'`: Return Numpy `np.ndarray` objects.
|
| 123 |
+
return_attention_mask (`bool`, *optional*):
|
| 124 |
+
Whether or not to return the attention mask. If not set, will return the attention mask according to the
|
| 125 |
+
specific tokenizer's default, defined by the `return_outputs` attribute.
|
| 126 |
+
|
| 127 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 128 |
+
|
| 129 |
+
Returns:
|
| 130 |
+
`dict[str, list[list[int]]]`: A dictionary with the following keys:
|
| 131 |
+
|
| 132 |
+
- `input_ids`: List of token ids to be fed to a model.
|
| 133 |
+
- `attention_mask`: List of indices specifying which tokens should be attended to by the model.
|
| 134 |
+
"""
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
@add_start_docstrings(CUSTOM_DPR_READER_DOCSTRING)
|
| 138 |
+
class CustomDPRReaderTokenizerMixin:
|
| 139 |
+
def __call__(
|
| 140 |
+
self,
|
| 141 |
+
questions,
|
| 142 |
+
titles: str | None = None,
|
| 143 |
+
texts: str | None = None,
|
| 144 |
+
padding: bool | str = False,
|
| 145 |
+
truncation: bool | str = False,
|
| 146 |
+
max_length: int | None = None,
|
| 147 |
+
return_tensors: str | TensorType | None = None,
|
| 148 |
+
return_attention_mask: bool | None = None,
|
| 149 |
+
**kwargs,
|
| 150 |
+
) -> BatchEncoding:
|
| 151 |
+
if titles is None and texts is None:
|
| 152 |
+
return super().__call__(
|
| 153 |
+
questions,
|
| 154 |
+
padding=padding,
|
| 155 |
+
truncation=truncation,
|
| 156 |
+
max_length=max_length,
|
| 157 |
+
return_tensors=return_tensors,
|
| 158 |
+
return_attention_mask=return_attention_mask,
|
| 159 |
+
**kwargs,
|
| 160 |
+
)
|
| 161 |
+
elif titles is None or texts is None:
|
| 162 |
+
text_pair = titles if texts is None else texts
|
| 163 |
+
return super().__call__(
|
| 164 |
+
questions,
|
| 165 |
+
text_pair,
|
| 166 |
+
padding=padding,
|
| 167 |
+
truncation=truncation,
|
| 168 |
+
max_length=max_length,
|
| 169 |
+
return_tensors=return_tensors,
|
| 170 |
+
return_attention_mask=return_attention_mask,
|
| 171 |
+
**kwargs,
|
| 172 |
+
)
|
| 173 |
+
titles = titles if not isinstance(titles, str) else [titles]
|
| 174 |
+
texts = texts if not isinstance(texts, str) else [texts]
|
| 175 |
+
n_passages = len(titles)
|
| 176 |
+
questions = questions if not isinstance(questions, str) else [questions] * n_passages
|
| 177 |
+
if len(titles) != len(texts):
|
| 178 |
+
raise ValueError(
|
| 179 |
+
f"There should be as many titles than texts but got {len(titles)} titles and {len(texts)} texts."
|
| 180 |
+
)
|
| 181 |
+
encoded_question_and_titles = super().__call__(questions, titles, padding=False, truncation=False)["input_ids"]
|
| 182 |
+
encoded_texts = super().__call__(texts, add_special_tokens=False, padding=False, truncation=False)["input_ids"]
|
| 183 |
+
encoded_inputs = {
|
| 184 |
+
"input_ids": [
|
| 185 |
+
(encoded_question_and_title + encoded_text)[:max_length]
|
| 186 |
+
if max_length is not None and truncation
|
| 187 |
+
else encoded_question_and_title + encoded_text
|
| 188 |
+
for encoded_question_and_title, encoded_text in zip(encoded_question_and_titles, encoded_texts)
|
| 189 |
+
]
|
| 190 |
+
}
|
| 191 |
+
if return_attention_mask is not False:
|
| 192 |
+
attention_mask = []
|
| 193 |
+
for input_ids in encoded_inputs["input_ids"]:
|
| 194 |
+
attention_mask.append([int(input_id != self.pad_token_id) for input_id in input_ids])
|
| 195 |
+
encoded_inputs["attention_mask"] = attention_mask
|
| 196 |
+
return self.pad(encoded_inputs, padding=padding, max_length=max_length, return_tensors=return_tensors)
|
| 197 |
+
|
| 198 |
+
def decode_best_spans(
|
| 199 |
+
self,
|
| 200 |
+
reader_input: BatchEncoding,
|
| 201 |
+
reader_output: DPRReaderOutput,
|
| 202 |
+
num_spans: int = 16,
|
| 203 |
+
max_answer_length: int = 64,
|
| 204 |
+
num_spans_per_passage: int = 4,
|
| 205 |
+
) -> list[DPRSpanPrediction]:
|
| 206 |
+
"""
|
| 207 |
+
Get the span predictions for the extractive Q&A model.
|
| 208 |
+
|
| 209 |
+
Returns: *List* of *DPRReaderOutput* sorted by descending *(relevance_score, span_score)*. Each
|
| 210 |
+
*DPRReaderOutput* is a *Tuple* with:
|
| 211 |
+
|
| 212 |
+
- **span_score**: `float` that corresponds to the score given by the reader for this span compared to other
|
| 213 |
+
spans in the same passage. It corresponds to the sum of the start and end logits of the span.
|
| 214 |
+
- **relevance_score**: `float` that corresponds to the score of the each passage to answer the question,
|
| 215 |
+
compared to all the other passages. It corresponds to the output of the QA classifier of the DPRReader.
|
| 216 |
+
- **doc_id**: `int` the id of the passage. - **start_index**: `int` the start index of the span
|
| 217 |
+
(inclusive). - **end_index**: `int` the end index of the span (inclusive).
|
| 218 |
+
|
| 219 |
+
Examples:
|
| 220 |
+
|
| 221 |
+
```python
|
| 222 |
+
>>> from transformers import DPRReader, DPRReaderTokenizer
|
| 223 |
+
|
| 224 |
+
>>> tokenizer = DPRReaderTokenizer.from_pretrained("facebook/dpr-reader-single-nq-base")
|
| 225 |
+
>>> model = DPRReader.from_pretrained("facebook/dpr-reader-single-nq-base")
|
| 226 |
+
>>> encoded_inputs = tokenizer(
|
| 227 |
+
... questions=["What is love ?"],
|
| 228 |
+
... titles=["Haddaway"],
|
| 229 |
+
... texts=["'What Is Love' is a song recorded by the artist Haddaway"],
|
| 230 |
+
... return_tensors="pt",
|
| 231 |
+
... )
|
| 232 |
+
>>> outputs = model(**encoded_inputs)
|
| 233 |
+
>>> predicted_spans = tokenizer.decode_best_spans(encoded_inputs, outputs)
|
| 234 |
+
>>> print(predicted_spans[0].text) # best span
|
| 235 |
+
a song
|
| 236 |
+
```"""
|
| 237 |
+
input_ids = reader_input["input_ids"]
|
| 238 |
+
start_logits, end_logits, relevance_logits = reader_output[:3]
|
| 239 |
+
n_passages = len(relevance_logits)
|
| 240 |
+
sorted_docs = sorted(range(n_passages), reverse=True, key=relevance_logits.__getitem__)
|
| 241 |
+
nbest_spans_predictions: list[DPRReaderOutput] = []
|
| 242 |
+
for doc_id in sorted_docs:
|
| 243 |
+
sequence_ids = list(input_ids[doc_id])
|
| 244 |
+
# assuming question & title information is at the beginning of the sequence
|
| 245 |
+
passage_offset = sequence_ids.index(self.sep_token_id, 2) + 1 # second sep id
|
| 246 |
+
if sequence_ids[-1] == self.pad_token_id:
|
| 247 |
+
sequence_len = sequence_ids.index(self.pad_token_id)
|
| 248 |
+
else:
|
| 249 |
+
sequence_len = len(sequence_ids)
|
| 250 |
+
|
| 251 |
+
best_spans = self._get_best_spans(
|
| 252 |
+
start_logits=start_logits[doc_id][passage_offset:sequence_len],
|
| 253 |
+
end_logits=end_logits[doc_id][passage_offset:sequence_len],
|
| 254 |
+
max_answer_length=max_answer_length,
|
| 255 |
+
top_spans=num_spans_per_passage,
|
| 256 |
+
)
|
| 257 |
+
for start_index, end_index in best_spans:
|
| 258 |
+
start_index += passage_offset
|
| 259 |
+
end_index += passage_offset
|
| 260 |
+
nbest_spans_predictions.append(
|
| 261 |
+
DPRSpanPrediction(
|
| 262 |
+
span_score=start_logits[doc_id][start_index] + end_logits[doc_id][end_index],
|
| 263 |
+
relevance_score=relevance_logits[doc_id],
|
| 264 |
+
doc_id=doc_id,
|
| 265 |
+
start_index=start_index,
|
| 266 |
+
end_index=end_index,
|
| 267 |
+
text=self.decode(sequence_ids[start_index : end_index + 1]),
|
| 268 |
+
)
|
| 269 |
+
)
|
| 270 |
+
if len(nbest_spans_predictions) >= num_spans:
|
| 271 |
+
break
|
| 272 |
+
return nbest_spans_predictions[:num_spans]
|
| 273 |
+
|
| 274 |
+
def _get_best_spans(
|
| 275 |
+
self,
|
| 276 |
+
start_logits: list[int],
|
| 277 |
+
end_logits: list[int],
|
| 278 |
+
max_answer_length: int,
|
| 279 |
+
top_spans: int,
|
| 280 |
+
) -> list[DPRSpanPrediction]:
|
| 281 |
+
"""
|
| 282 |
+
Finds the best answer span for the extractive Q&A model for one passage. It returns the best span by descending
|
| 283 |
+
`span_score` order and keeping max `top_spans` spans. Spans longer that `max_answer_length` are ignored.
|
| 284 |
+
"""
|
| 285 |
+
scores = []
|
| 286 |
+
for start_index, start_score in enumerate(start_logits):
|
| 287 |
+
for answer_length, end_score in enumerate(end_logits[start_index : start_index + max_answer_length]):
|
| 288 |
+
scores.append(((start_index, start_index + answer_length), start_score + end_score))
|
| 289 |
+
scores = sorted(scores, key=lambda x: x[1], reverse=True)
|
| 290 |
+
chosen_span_intervals = []
|
| 291 |
+
for (start_index, end_index), score in scores:
|
| 292 |
+
if start_index > end_index:
|
| 293 |
+
raise ValueError(f"Wrong span indices: [{start_index}:{end_index}]")
|
| 294 |
+
length = end_index - start_index + 1
|
| 295 |
+
if length > max_answer_length:
|
| 296 |
+
raise ValueError(f"Span is too long: {length} > {max_answer_length}")
|
| 297 |
+
if any(
|
| 298 |
+
start_index <= prev_start_index <= prev_end_index <= end_index
|
| 299 |
+
or prev_start_index <= start_index <= end_index <= prev_end_index
|
| 300 |
+
for (prev_start_index, prev_end_index) in chosen_span_intervals
|
| 301 |
+
):
|
| 302 |
+
continue
|
| 303 |
+
chosen_span_intervals.append((start_index, end_index))
|
| 304 |
+
|
| 305 |
+
if len(chosen_span_intervals) == top_spans:
|
| 306 |
+
break
|
| 307 |
+
return chosen_span_intervals
|
| 308 |
+
|
| 309 |
+
|
| 310 |
+
@add_end_docstrings(CUSTOM_DPR_READER_DOCSTRING)
|
| 311 |
+
class DPRReaderTokenizer(CustomDPRReaderTokenizerMixin, BertTokenizer):
|
| 312 |
+
r"""
|
| 313 |
+
Construct a DPRReader tokenizer.
|
| 314 |
+
|
| 315 |
+
[`DPRReaderTokenizer`] is almost identical to [`BertTokenizer`] and runs end-to-end tokenization: punctuation
|
| 316 |
+
splitting and wordpiece. The difference is that is has three inputs strings: question, titles and texts that are
|
| 317 |
+
combined to be fed to the [`DPRReader`] model.
|
| 318 |
+
|
| 319 |
+
Refer to superclass [`BertTokenizer`] for usage examples and documentation concerning parameters.
|
| 320 |
+
"""
|
| 321 |
+
|
| 322 |
+
vocab_files_names = VOCAB_FILES_NAMES
|
| 323 |
+
model_input_names = ["input_ids", "attention_mask"]
|
| 324 |
+
|
| 325 |
+
def __init__(self, *args, do_lower_case=False, **kwargs):
|
| 326 |
+
super().__init__(*args, **kwargs)
|
| 327 |
+
self.do_lower_case = do_lower_case
|
| 328 |
+
|
| 329 |
+
|
| 330 |
+
__all__ = ["DPRContextEncoderTokenizer", "DPRQuestionEncoderTokenizer", "DPRReaderOutput", "DPRReaderTokenizer"]
|
third_party/transformers/src/transformers/models/dpr/tokenization_dpr_fast.py
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2018 The HuggingFace Inc. team, The Hugging Face Team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Tokenization classes for DPR."""
|
| 15 |
+
|
| 16 |
+
import collections
|
| 17 |
+
|
| 18 |
+
from ...tokenization_utils_base import BatchEncoding
|
| 19 |
+
from ...utils import TensorType, add_end_docstrings, add_start_docstrings, logging
|
| 20 |
+
from ..bert.tokenization_bert import BertTokenizer
|
| 21 |
+
from .tokenization_dpr import DPRContextEncoderTokenizer, DPRQuestionEncoderTokenizer, DPRReaderTokenizer
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
logger = logging.get_logger(__name__)
|
| 25 |
+
|
| 26 |
+
VOCAB_FILES_NAMES = {"vocab_file": "vocab.txt", "tokenizer_file": "tokenizer.json"}
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class DPRContextEncoderTokenizerFast(BertTokenizer):
|
| 30 |
+
r"""
|
| 31 |
+
Construct a "fast" DPRContextEncoder tokenizer (backed by HuggingFace's *tokenizers* library).
|
| 32 |
+
|
| 33 |
+
[`DPRContextEncoderTokenizerFast`] is identical to [`BertTokenizer`] and runs end-to-end tokenization:
|
| 34 |
+
punctuation splitting and wordpiece.
|
| 35 |
+
|
| 36 |
+
Refer to superclass [`BertTokenizer`] for usage examples and documentation concerning parameters.
|
| 37 |
+
"""
|
| 38 |
+
|
| 39 |
+
vocab_files_names = VOCAB_FILES_NAMES
|
| 40 |
+
slow_tokenizer_class = DPRContextEncoderTokenizer
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
class DPRQuestionEncoderTokenizerFast(BertTokenizer):
|
| 44 |
+
r"""
|
| 45 |
+
Constructs a "fast" DPRQuestionEncoder tokenizer (backed by HuggingFace's *tokenizers* library).
|
| 46 |
+
|
| 47 |
+
[`DPRQuestionEncoderTokenizerFast`] is identical to [`BertTokenizer`] and runs end-to-end tokenization:
|
| 48 |
+
punctuation splitting and wordpiece.
|
| 49 |
+
|
| 50 |
+
Refer to superclass [`BertTokenizer`] for usage examples and documentation concerning parameters.
|
| 51 |
+
"""
|
| 52 |
+
|
| 53 |
+
vocab_files_names = VOCAB_FILES_NAMES
|
| 54 |
+
slow_tokenizer_class = DPRQuestionEncoderTokenizer
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
DPRSpanPrediction = collections.namedtuple(
|
| 58 |
+
"DPRSpanPrediction", ["span_score", "relevance_score", "doc_id", "start_index", "end_index", "text"]
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
DPRReaderOutput = collections.namedtuple("DPRReaderOutput", ["start_logits", "end_logits", "relevance_logits"])
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
CUSTOM_DPR_READER_DOCSTRING = r"""
|
| 65 |
+
Return a dictionary with the token ids of the input strings and other information to give to `.decode_best_spans`.
|
| 66 |
+
It converts the strings of a question and different passages (title and text) in a sequence of IDs (integers),
|
| 67 |
+
using the tokenizer and vocabulary. The resulting `input_ids` is a matrix of size `(n_passages, sequence_length)`
|
| 68 |
+
with the format:
|
| 69 |
+
|
| 70 |
+
[CLS] <question token ids> [SEP] <titles ids> [SEP] <texts ids>
|
| 71 |
+
|
| 72 |
+
Args:
|
| 73 |
+
questions (`str` or `list[str]`):
|
| 74 |
+
The questions to be encoded. You can specify one question for many passages. In this case, the question
|
| 75 |
+
will be duplicated like `[questions] * n_passages`. Otherwise you have to specify as many questions as in
|
| 76 |
+
`titles` or `texts`.
|
| 77 |
+
titles (`str` or `list[str]`):
|
| 78 |
+
The passages titles to be encoded. This can be a string or a list of strings if there are several passages.
|
| 79 |
+
texts (`str` or `list[str]`):
|
| 80 |
+
The passages texts to be encoded. This can be a string or a list of strings if there are several passages.
|
| 81 |
+
padding (`bool`, `str` or [`~utils.PaddingStrategy`], *optional*, defaults to `False`):
|
| 82 |
+
Activates and controls padding. Accepts the following values:
|
| 83 |
+
|
| 84 |
+
- `True` or `'longest'`: Pad to the longest sequence in the batch (or no padding if only a single sequence
|
| 85 |
+
if provided).
|
| 86 |
+
- `'max_length'`: Pad to a maximum length specified with the argument `max_length` or to the maximum
|
| 87 |
+
acceptable input length for the model if that argument is not provided.
|
| 88 |
+
- `False` or `'do_not_pad'` (default): No padding (i.e., can output a batch with sequences of different
|
| 89 |
+
lengths).
|
| 90 |
+
truncation (`bool`, `str` or [`~tokenization_utils_base.TruncationStrategy`], *optional*, defaults to `False`):
|
| 91 |
+
Activates and controls truncation. Accepts the following values:
|
| 92 |
+
|
| 93 |
+
- `True` or `'longest_first'`: Truncate to a maximum length specified with the argument `max_length` or to
|
| 94 |
+
the maximum acceptable input length for the model if that argument is not provided. This will truncate
|
| 95 |
+
token by token, removing a token from the longest sequence in the pair if a pair of sequences (or a batch
|
| 96 |
+
of pairs) is provided.
|
| 97 |
+
- `'only_first'`: Truncate to a maximum length specified with the argument `max_length` or to the maximum
|
| 98 |
+
acceptable input length for the model if that argument is not provided. This will only truncate the first
|
| 99 |
+
sequence of a pair if a pair of sequences (or a batch of pairs) is provided.
|
| 100 |
+
- `'only_second'`: Truncate to a maximum length specified with the argument `max_length` or to the maximum
|
| 101 |
+
acceptable input length for the model if that argument is not provided. This will only truncate the
|
| 102 |
+
second sequence of a pair if a pair of sequences (or a batch of pairs) is provided.
|
| 103 |
+
- `False` or `'do_not_truncate'` (default): No truncation (i.e., can output batch with sequence lengths
|
| 104 |
+
greater than the model maximum admissible input size).
|
| 105 |
+
max_length (`int`, *optional*):
|
| 106 |
+
Controls the maximum length to use by one of the truncation/padding parameters.
|
| 107 |
+
|
| 108 |
+
If left unset or set to `None`, this will use the predefined model maximum length if a maximum length
|
| 109 |
+
is required by one of the truncation/padding parameters. If the model has no specific maximum input
|
| 110 |
+
length (like XLNet) truncation/padding to a maximum length will be deactivated.
|
| 111 |
+
return_tensors (`str` or [`~utils.TensorType`], *optional*):
|
| 112 |
+
If set, will return tensors instead of list of python integers. Acceptable values are:
|
| 113 |
+
|
| 114 |
+
- `'pt'`: Return PyTorch `torch.Tensor` objects.
|
| 115 |
+
- `'np'`: Return Numpy `np.ndarray` objects.
|
| 116 |
+
return_attention_mask (`bool`, *optional*):
|
| 117 |
+
Whether or not to return the attention mask. If not set, will return the attention mask according to the
|
| 118 |
+
specific tokenizer's default, defined by the `return_outputs` attribute.
|
| 119 |
+
|
| 120 |
+
[What are attention masks?](../glossary#attention-mask)
|
| 121 |
+
|
| 122 |
+
Return:
|
| 123 |
+
`dict[str, list[list[int]]]`: A dictionary with the following keys:
|
| 124 |
+
|
| 125 |
+
- `input_ids`: List of token ids to be fed to a model.
|
| 126 |
+
- `attention_mask`: List of indices specifying which tokens should be attended to by the model.
|
| 127 |
+
"""
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
@add_start_docstrings(CUSTOM_DPR_READER_DOCSTRING)
|
| 131 |
+
class CustomDPRReaderTokenizerMixin:
|
| 132 |
+
def __call__(
|
| 133 |
+
self,
|
| 134 |
+
questions,
|
| 135 |
+
titles: str | None = None,
|
| 136 |
+
texts: str | None = None,
|
| 137 |
+
padding: bool | str = False,
|
| 138 |
+
truncation: bool | str = False,
|
| 139 |
+
max_length: int | None = None,
|
| 140 |
+
return_tensors: str | TensorType | None = None,
|
| 141 |
+
return_attention_mask: bool | None = None,
|
| 142 |
+
**kwargs,
|
| 143 |
+
) -> BatchEncoding:
|
| 144 |
+
if titles is None and texts is None:
|
| 145 |
+
return super().__call__(
|
| 146 |
+
questions,
|
| 147 |
+
padding=padding,
|
| 148 |
+
truncation=truncation,
|
| 149 |
+
max_length=max_length,
|
| 150 |
+
return_tensors=return_tensors,
|
| 151 |
+
return_attention_mask=return_attention_mask,
|
| 152 |
+
**kwargs,
|
| 153 |
+
)
|
| 154 |
+
elif titles is None or texts is None:
|
| 155 |
+
text_pair = titles if texts is None else texts
|
| 156 |
+
return super().__call__(
|
| 157 |
+
questions,
|
| 158 |
+
text_pair,
|
| 159 |
+
padding=padding,
|
| 160 |
+
truncation=truncation,
|
| 161 |
+
max_length=max_length,
|
| 162 |
+
return_tensors=return_tensors,
|
| 163 |
+
return_attention_mask=return_attention_mask,
|
| 164 |
+
**kwargs,
|
| 165 |
+
)
|
| 166 |
+
titles = titles if not isinstance(titles, str) else [titles]
|
| 167 |
+
texts = texts if not isinstance(texts, str) else [texts]
|
| 168 |
+
n_passages = len(titles)
|
| 169 |
+
questions = questions if not isinstance(questions, str) else [questions] * n_passages
|
| 170 |
+
assert len(titles) == len(texts), (
|
| 171 |
+
f"There should be as many titles than texts but got {len(titles)} titles and {len(texts)} texts."
|
| 172 |
+
)
|
| 173 |
+
encoded_question_and_titles = super().__call__(questions, titles, padding=False, truncation=False)["input_ids"]
|
| 174 |
+
encoded_texts = super().__call__(texts, add_special_tokens=False, padding=False, truncation=False)["input_ids"]
|
| 175 |
+
encoded_inputs = {
|
| 176 |
+
"input_ids": [
|
| 177 |
+
(encoded_question_and_title + encoded_text)[:max_length]
|
| 178 |
+
if max_length is not None and truncation
|
| 179 |
+
else encoded_question_and_title + encoded_text
|
| 180 |
+
for encoded_question_and_title, encoded_text in zip(encoded_question_and_titles, encoded_texts)
|
| 181 |
+
]
|
| 182 |
+
}
|
| 183 |
+
if return_attention_mask is not False:
|
| 184 |
+
attention_mask = []
|
| 185 |
+
for input_ids in encoded_inputs["input_ids"]:
|
| 186 |
+
attention_mask.append([int(input_id != self.pad_token_id) for input_id in input_ids])
|
| 187 |
+
encoded_inputs["attention_mask"] = attention_mask
|
| 188 |
+
return self.pad(encoded_inputs, padding=padding, max_length=max_length, return_tensors=return_tensors)
|
| 189 |
+
|
| 190 |
+
def decode_best_spans(
|
| 191 |
+
self,
|
| 192 |
+
reader_input: BatchEncoding,
|
| 193 |
+
reader_output: DPRReaderOutput,
|
| 194 |
+
num_spans: int = 16,
|
| 195 |
+
max_answer_length: int = 64,
|
| 196 |
+
num_spans_per_passage: int = 4,
|
| 197 |
+
) -> list[DPRSpanPrediction]:
|
| 198 |
+
"""
|
| 199 |
+
Get the span predictions for the extractive Q&A model.
|
| 200 |
+
|
| 201 |
+
Returns: *List* of *DPRReaderOutput* sorted by descending *(relevance_score, span_score)*. Each
|
| 202 |
+
*DPRReaderOutput* is a *Tuple* with:
|
| 203 |
+
|
| 204 |
+
- **span_score**: `float` that corresponds to the score given by the reader for this span compared to other
|
| 205 |
+
spans in the same passage. It corresponds to the sum of the start and end logits of the span.
|
| 206 |
+
- **relevance_score**: `float` that corresponds to the score of the each passage to answer the question,
|
| 207 |
+
compared to all the other passages. It corresponds to the output of the QA classifier of the DPRReader.
|
| 208 |
+
- **doc_id**: `int` the id of the passage. - ***start_index**: `int` the start index of the span
|
| 209 |
+
(inclusive). - **end_index**: `int` the end index of the span (inclusive).
|
| 210 |
+
|
| 211 |
+
Examples:
|
| 212 |
+
|
| 213 |
+
```python
|
| 214 |
+
>>> from transformers import DPRReader, DPRReaderTokenizer
|
| 215 |
+
|
| 216 |
+
>>> tokenizer = DPRReaderTokenizer.from_pretrained("facebook/dpr-reader-single-nq-base")
|
| 217 |
+
>>> model = DPRReader.from_pretrained("facebook/dpr-reader-single-nq-base")
|
| 218 |
+
>>> encoded_inputs = tokenizer(
|
| 219 |
+
... questions=["What is love ?"],
|
| 220 |
+
... titles=["Haddaway"],
|
| 221 |
+
... texts=["'What Is Love' is a song recorded by the artist Haddaway"],
|
| 222 |
+
... return_tensors="pt",
|
| 223 |
+
... )
|
| 224 |
+
>>> outputs = model(**encoded_inputs)
|
| 225 |
+
>>> predicted_spans = tokenizer.decode_best_spans(encoded_inputs, outputs)
|
| 226 |
+
>>> print(predicted_spans[0].text) # best span
|
| 227 |
+
a song
|
| 228 |
+
```"""
|
| 229 |
+
input_ids = reader_input["input_ids"]
|
| 230 |
+
start_logits, end_logits, relevance_logits = reader_output[:3]
|
| 231 |
+
n_passages = len(relevance_logits)
|
| 232 |
+
sorted_docs = sorted(range(n_passages), reverse=True, key=relevance_logits.__getitem__)
|
| 233 |
+
nbest_spans_predictions: list[DPRReaderOutput] = []
|
| 234 |
+
for doc_id in sorted_docs:
|
| 235 |
+
sequence_ids = list(input_ids[doc_id])
|
| 236 |
+
# assuming question & title information is at the beginning of the sequence
|
| 237 |
+
passage_offset = sequence_ids.index(self.sep_token_id, 2) + 1 # second sep id
|
| 238 |
+
if sequence_ids[-1] == self.pad_token_id:
|
| 239 |
+
sequence_len = sequence_ids.index(self.pad_token_id)
|
| 240 |
+
else:
|
| 241 |
+
sequence_len = len(sequence_ids)
|
| 242 |
+
|
| 243 |
+
best_spans = self._get_best_spans(
|
| 244 |
+
start_logits=start_logits[doc_id][passage_offset:sequence_len],
|
| 245 |
+
end_logits=end_logits[doc_id][passage_offset:sequence_len],
|
| 246 |
+
max_answer_length=max_answer_length,
|
| 247 |
+
top_spans=num_spans_per_passage,
|
| 248 |
+
)
|
| 249 |
+
for start_index, end_index in best_spans:
|
| 250 |
+
start_index += passage_offset
|
| 251 |
+
end_index += passage_offset
|
| 252 |
+
nbest_spans_predictions.append(
|
| 253 |
+
DPRSpanPrediction(
|
| 254 |
+
span_score=start_logits[doc_id][start_index] + end_logits[doc_id][end_index],
|
| 255 |
+
relevance_score=relevance_logits[doc_id],
|
| 256 |
+
doc_id=doc_id,
|
| 257 |
+
start_index=start_index,
|
| 258 |
+
end_index=end_index,
|
| 259 |
+
text=self.decode(sequence_ids[start_index : end_index + 1]),
|
| 260 |
+
)
|
| 261 |
+
)
|
| 262 |
+
if len(nbest_spans_predictions) >= num_spans:
|
| 263 |
+
break
|
| 264 |
+
return nbest_spans_predictions[:num_spans]
|
| 265 |
+
|
| 266 |
+
def _get_best_spans(
|
| 267 |
+
self,
|
| 268 |
+
start_logits: list[int],
|
| 269 |
+
end_logits: list[int],
|
| 270 |
+
max_answer_length: int,
|
| 271 |
+
top_spans: int,
|
| 272 |
+
) -> list[DPRSpanPrediction]:
|
| 273 |
+
"""
|
| 274 |
+
Finds the best answer span for the extractive Q&A model for one passage. It returns the best span by descending
|
| 275 |
+
`span_score` order and keeping max `top_spans` spans. Spans longer that `max_answer_length` are ignored.
|
| 276 |
+
"""
|
| 277 |
+
scores = []
|
| 278 |
+
for start_index, start_score in enumerate(start_logits):
|
| 279 |
+
for answer_length, end_score in enumerate(end_logits[start_index : start_index + max_answer_length]):
|
| 280 |
+
scores.append(((start_index, start_index + answer_length), start_score + end_score))
|
| 281 |
+
scores = sorted(scores, key=lambda x: x[1], reverse=True)
|
| 282 |
+
chosen_span_intervals = []
|
| 283 |
+
for (start_index, end_index), score in scores:
|
| 284 |
+
assert start_index <= end_index, f"Wrong span indices: [{start_index}:{end_index}]"
|
| 285 |
+
length = end_index - start_index + 1
|
| 286 |
+
assert length <= max_answer_length, f"Span is too long: {length} > {max_answer_length}"
|
| 287 |
+
if any(
|
| 288 |
+
start_index <= prev_start_index <= prev_end_index <= end_index
|
| 289 |
+
or prev_start_index <= start_index <= end_index <= prev_end_index
|
| 290 |
+
for (prev_start_index, prev_end_index) in chosen_span_intervals
|
| 291 |
+
):
|
| 292 |
+
continue
|
| 293 |
+
chosen_span_intervals.append((start_index, end_index))
|
| 294 |
+
|
| 295 |
+
if len(chosen_span_intervals) == top_spans:
|
| 296 |
+
break
|
| 297 |
+
return chosen_span_intervals
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
@add_end_docstrings(CUSTOM_DPR_READER_DOCSTRING)
|
| 301 |
+
class DPRReaderTokenizerFast(CustomDPRReaderTokenizerMixin, BertTokenizer):
|
| 302 |
+
r"""
|
| 303 |
+
Constructs a "fast" DPRReader tokenizer (backed by HuggingFace's *tokenizers* library).
|
| 304 |
+
|
| 305 |
+
[`DPRReaderTokenizerFast`] is almost identical to [`BertTokenizer`] and runs end-to-end tokenization:
|
| 306 |
+
punctuation splitting and wordpiece. The difference is that is has three inputs strings: question, titles and texts
|
| 307 |
+
that are combined to be fed to the [`DPRReader`] model.
|
| 308 |
+
|
| 309 |
+
Refer to superclass [`BertTokenizer`] for usage examples and documentation concerning parameters.
|
| 310 |
+
|
| 311 |
+
"""
|
| 312 |
+
|
| 313 |
+
vocab_files_names = VOCAB_FILES_NAMES
|
| 314 |
+
model_input_names = ["input_ids", "attention_mask"]
|
| 315 |
+
slow_tokenizer_class = DPRReaderTokenizer
|
| 316 |
+
|
| 317 |
+
|
| 318 |
+
__all__ = ["DPRContextEncoderTokenizerFast", "DPRQuestionEncoderTokenizerFast", "DPRReaderTokenizerFast"]
|
third_party/transformers/src/transformers/models/dpt/__init__.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .configuration_dpt import *
|
| 22 |
+
from .image_processing_dpt import *
|
| 23 |
+
from .image_processing_pil_dpt import *
|
| 24 |
+
from .modeling_dpt import *
|
| 25 |
+
else:
|
| 26 |
+
import sys
|
| 27 |
+
|
| 28 |
+
_file = globals()["__file__"]
|
| 29 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
third_party/transformers/src/transformers/models/dpt/configuration_dpt.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""DPT model configuration"""
|
| 15 |
+
|
| 16 |
+
from huggingface_hub.dataclasses import strict
|
| 17 |
+
|
| 18 |
+
from ...backbone_utils import consolidate_backbone_kwargs_to_config
|
| 19 |
+
from ...configuration_utils import PreTrainedConfig
|
| 20 |
+
from ...utils import auto_docstring
|
| 21 |
+
from ..auto.configuration_auto import AutoConfig
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
@auto_docstring(checkpoint="Intel/dpt-large")
|
| 25 |
+
@strict
|
| 26 |
+
class DPTConfig(PreTrainedConfig):
|
| 27 |
+
r"""
|
| 28 |
+
is_hybrid (`bool`, *optional*, defaults to `False`):
|
| 29 |
+
Whether to use a hybrid backbone. Useful in the context of loading DPT-Hybrid models.
|
| 30 |
+
backbone_out_indices (`list[int]`, *optional*, defaults to `[2, 5, 8, 11]`):
|
| 31 |
+
Indices of the intermediate hidden states to use from backbone.
|
| 32 |
+
readout_type (`str`, *optional*, defaults to `"project"`):
|
| 33 |
+
The readout type to use when processing the readout token (CLS token) of the intermediate hidden states of
|
| 34 |
+
the ViT backbone. Can be one of [`"ignore"`, `"add"`, `"project"`].
|
| 35 |
+
- "ignore" simply ignores the CLS token.
|
| 36 |
+
- "add" passes the information from the CLS token to all other tokens by adding the representations.
|
| 37 |
+
- "project" passes information to the other tokens by concatenating the readout to all other tokens before
|
| 38 |
+
projecting the
|
| 39 |
+
representation to the original feature dimension D using a linear layer followed by a GELU non-linearity.
|
| 40 |
+
reassemble_factors (`list[int]`, *optional*, defaults to `[4, 2, 1, 0.5]`):
|
| 41 |
+
The up/downsampling factors of the reassemble layers.
|
| 42 |
+
neck_hidden_sizes (`list[str]`, *optional*, defaults to `[96, 192, 384, 768]`):
|
| 43 |
+
The hidden sizes to project to for the feature maps of the backbone.
|
| 44 |
+
fusion_hidden_size (`int`, *optional*, defaults to 256):
|
| 45 |
+
The number of channels before fusion.
|
| 46 |
+
head_in_index (`int`, *optional*, defaults to -1):
|
| 47 |
+
The index of the features to use in the heads.
|
| 48 |
+
use_batch_norm_in_fusion_residual (`bool`, *optional*, defaults to `False`):
|
| 49 |
+
Whether to use batch normalization in the pre-activate residual units of the fusion blocks.
|
| 50 |
+
use_bias_in_fusion_residual (`bool`, *optional*, defaults to `True`):
|
| 51 |
+
Whether to use bias in the pre-activate residual units of the fusion blocks.
|
| 52 |
+
add_projection (`bool`, *optional*, defaults to `False`):
|
| 53 |
+
Whether to add a projection layer before the depth estimation head.
|
| 54 |
+
use_auxiliary_head (`bool`, *optional*, defaults to `True`):
|
| 55 |
+
Whether to use an auxiliary head during training.
|
| 56 |
+
auxiliary_loss_weight (`float`, *optional*, defaults to 0.4):
|
| 57 |
+
Weight of the cross-entropy loss of the auxiliary head.
|
| 58 |
+
semantic_classifier_dropout (`float`, *optional*, defaults to 0.1):
|
| 59 |
+
The dropout ratio for the semantic classification head.
|
| 60 |
+
backbone_featmap_shape (`list[int]`, *optional*, defaults to `[1, 1024, 24, 24]`):
|
| 61 |
+
Used only for the `hybrid` embedding type. The shape of the feature maps of the backbone.
|
| 62 |
+
neck_ignore_stages (`list[int]`, *optional*, defaults to `[0, 1]`):
|
| 63 |
+
Used only for the `hybrid` embedding type. The stages of the readout layers to ignore.
|
| 64 |
+
pooler_output_size (`int`, *optional*):
|
| 65 |
+
Dimensionality of the pooler layer. If None, defaults to `hidden_size`.
|
| 66 |
+
pooler_act (`str`, *optional*, defaults to `"tanh"`):
|
| 67 |
+
The activation function to be used by the pooler.
|
| 68 |
+
|
| 69 |
+
Example:
|
| 70 |
+
|
| 71 |
+
```python
|
| 72 |
+
>>> from transformers import DPTModel, DPTConfig
|
| 73 |
+
|
| 74 |
+
>>> # Initializing a DPT dpt-large style configuration
|
| 75 |
+
>>> configuration = DPTConfig()
|
| 76 |
+
|
| 77 |
+
>>> # Initializing a model from the dpt-large style configuration
|
| 78 |
+
>>> model = DPTModel(configuration)
|
| 79 |
+
|
| 80 |
+
>>> # Accessing the model configuration
|
| 81 |
+
>>> configuration = model.config
|
| 82 |
+
```"""
|
| 83 |
+
|
| 84 |
+
model_type = "dpt"
|
| 85 |
+
sub_configs = {"backbone_config": AutoConfig}
|
| 86 |
+
|
| 87 |
+
# NOTE: some values are typed as `None` on purpose
|
| 88 |
+
# DPT creates one of: backbone or the general model only
|
| 89 |
+
# so official checkpoint saved them as `None`
|
| 90 |
+
hidden_size: int = 768
|
| 91 |
+
num_hidden_layers: None | int = 12
|
| 92 |
+
num_attention_heads: int | None = 12
|
| 93 |
+
intermediate_size: int | None = 3072
|
| 94 |
+
hidden_act: str = "gelu"
|
| 95 |
+
hidden_dropout_prob: float | int | None = 0.0
|
| 96 |
+
attention_probs_dropout_prob: float | int | None = 0.0
|
| 97 |
+
initializer_range: float = 0.02
|
| 98 |
+
layer_norm_eps: float | None = 1e-12
|
| 99 |
+
image_size: int | list[int] | tuple[int, int] | None = 384
|
| 100 |
+
patch_size: int | list[int] | tuple[int, int] | None = 16
|
| 101 |
+
num_channels: int | None = 3
|
| 102 |
+
is_hybrid: bool = False
|
| 103 |
+
qkv_bias: bool | None = True
|
| 104 |
+
backbone_out_indices: list[int] | tuple[int, ...] | None = (2, 5, 8, 11)
|
| 105 |
+
readout_type: str = "project"
|
| 106 |
+
reassemble_factors: list[int | float] | tuple[int | float, ...] = (4, 2, 1, 0.5)
|
| 107 |
+
neck_hidden_sizes: list[int] | tuple[int, ...] = (96, 192, 384, 768)
|
| 108 |
+
fusion_hidden_size: int = 256
|
| 109 |
+
head_in_index: int = -1
|
| 110 |
+
use_batch_norm_in_fusion_residual: bool | None = False
|
| 111 |
+
use_bias_in_fusion_residual: bool | None = None
|
| 112 |
+
add_projection: bool = False
|
| 113 |
+
use_auxiliary_head: bool | None = True
|
| 114 |
+
auxiliary_loss_weight: float = 0.4
|
| 115 |
+
semantic_loss_ignore_index: int = 255
|
| 116 |
+
semantic_classifier_dropout: float | int = 0.1
|
| 117 |
+
backbone_featmap_shape: list[int] | tuple[int, ...] | None = (1, 1024, 24, 24)
|
| 118 |
+
neck_ignore_stages: list[int] | tuple[int, ...] = (0, 1)
|
| 119 |
+
backbone_config: dict | PreTrainedConfig | None = None
|
| 120 |
+
pooler_output_size: int | None = None
|
| 121 |
+
pooler_act: str = "tanh"
|
| 122 |
+
|
| 123 |
+
def __post_init__(self, **kwargs):
|
| 124 |
+
if self.readout_type not in ["ignore", "add", "project"]:
|
| 125 |
+
raise ValueError("Readout_type must be one of ['ignore', 'add', 'project']")
|
| 126 |
+
|
| 127 |
+
if self.is_hybrid:
|
| 128 |
+
if isinstance(self.backbone_config, dict):
|
| 129 |
+
self.backbone_config.setdefault("model_type", "bit")
|
| 130 |
+
|
| 131 |
+
self.backbone_config, kwargs = consolidate_backbone_kwargs_to_config(
|
| 132 |
+
backbone_config=self.backbone_config,
|
| 133 |
+
default_config_type="bit",
|
| 134 |
+
default_config_kwargs={
|
| 135 |
+
"global_padding": "same",
|
| 136 |
+
"layer_type": "bottleneck",
|
| 137 |
+
"depths": [3, 4, 9],
|
| 138 |
+
"out_features": ["stage1", "stage2", "stage3"],
|
| 139 |
+
"embedding_dynamic_padding": True,
|
| 140 |
+
},
|
| 141 |
+
**kwargs,
|
| 142 |
+
)
|
| 143 |
+
if self.readout_type != "project":
|
| 144 |
+
raise ValueError("Readout type must be 'project' when using `DPT-hybrid` mode.")
|
| 145 |
+
elif kwargs.get("backbone") is not None or self.backbone_config is not None:
|
| 146 |
+
self.backbone_config, kwargs = consolidate_backbone_kwargs_to_config(
|
| 147 |
+
backbone_config=self.backbone_config,
|
| 148 |
+
**kwargs,
|
| 149 |
+
)
|
| 150 |
+
self.backbone_out_indices = None
|
| 151 |
+
|
| 152 |
+
self.backbone_featmap_shape = self.backbone_featmap_shape if self.is_hybrid else None
|
| 153 |
+
self.neck_ignore_stages = self.neck_ignore_stages if self.is_hybrid else []
|
| 154 |
+
self.pooler_output_size = self.pooler_output_size if self.pooler_output_size else self.hidden_size
|
| 155 |
+
super().__post_init__(**kwargs)
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
__all__ = ["DPTConfig"]
|
third_party/transformers/src/transformers/models/dpt/convert_dinov2_depth_to_hf.py
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023 The HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Convert DINOv2 + DPT checkpoints from the original repository. URL:
|
| 15 |
+
https://github.com/facebookresearch/dinov2/tree/main"""
|
| 16 |
+
|
| 17 |
+
import argparse
|
| 18 |
+
import itertools
|
| 19 |
+
import math
|
| 20 |
+
from io import BytesIO
|
| 21 |
+
from pathlib import Path
|
| 22 |
+
|
| 23 |
+
import httpx
|
| 24 |
+
import torch
|
| 25 |
+
from PIL import Image
|
| 26 |
+
from torchvision import transforms
|
| 27 |
+
|
| 28 |
+
from transformers import Dinov2Config, DPTConfig, DPTForDepthEstimation, DPTImageProcessor
|
| 29 |
+
from transformers.utils import logging
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
logging.set_verbosity_info()
|
| 33 |
+
logger = logging.get_logger(__name__)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def get_dpt_config(model_name):
|
| 37 |
+
if "small" in model_name:
|
| 38 |
+
# equivalent to stage 3, stage 6, stage 9, stage 12
|
| 39 |
+
backbone_config = Dinov2Config.from_pretrained(
|
| 40 |
+
"facebook/dinov2-small", out_indices=[3, 6, 9, 12], apply_layernorm=False, reshape_hidden_states=False
|
| 41 |
+
)
|
| 42 |
+
neck_hidden_sizes = [48, 96, 192, 384]
|
| 43 |
+
elif "base" in model_name:
|
| 44 |
+
backbone_config = Dinov2Config.from_pretrained(
|
| 45 |
+
"facebook/dinov2-base", out_indices=[3, 6, 9, 12], apply_layernorm=False, reshape_hidden_states=False
|
| 46 |
+
)
|
| 47 |
+
neck_hidden_sizes = [96, 192, 384, 768]
|
| 48 |
+
elif "large" in model_name:
|
| 49 |
+
backbone_config = Dinov2Config.from_pretrained(
|
| 50 |
+
"facebook/dinov2-large", out_indices=[5, 12, 18, 24], apply_layernorm=False, reshape_hidden_states=False
|
| 51 |
+
)
|
| 52 |
+
neck_hidden_sizes = [128, 256, 512, 1024]
|
| 53 |
+
elif "giant" in model_name:
|
| 54 |
+
backbone_config = Dinov2Config.from_pretrained(
|
| 55 |
+
"facebook/dinov2-giant", out_indices=[10, 20, 30, 40], apply_layernorm=False, reshape_hidden_states=False
|
| 56 |
+
)
|
| 57 |
+
neck_hidden_sizes = [192, 384, 768, 1536]
|
| 58 |
+
else:
|
| 59 |
+
raise NotImplementedError("To do")
|
| 60 |
+
|
| 61 |
+
config = DPTConfig(
|
| 62 |
+
backbone_config=backbone_config,
|
| 63 |
+
neck_hidden_sizes=neck_hidden_sizes,
|
| 64 |
+
use_bias_in_fusion_residual=False,
|
| 65 |
+
add_projection=True,
|
| 66 |
+
)
|
| 67 |
+
|
| 68 |
+
return config
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
# here we list all DPT keys to be renamed (original name on the left, our name on the right)
|
| 72 |
+
def create_rename_keys_dpt(config):
|
| 73 |
+
rename_keys = []
|
| 74 |
+
|
| 75 |
+
# fmt: off
|
| 76 |
+
# activation postprocessing (projections, readout projections + resize blocks)
|
| 77 |
+
for i in range(4):
|
| 78 |
+
rename_keys.append((f"decode_head.reassemble_blocks.projects.{i}.conv.weight", f"neck.reassemble_stage.layers.{i}.projection.weight"))
|
| 79 |
+
rename_keys.append((f"decode_head.reassemble_blocks.projects.{i}.conv.bias", f"neck.reassemble_stage.layers.{i}.projection.bias"))
|
| 80 |
+
|
| 81 |
+
rename_keys.append((f"decode_head.reassemble_blocks.readout_projects.{i}.0.weight", f"neck.reassemble_stage.readout_projects.{i}.0.weight"))
|
| 82 |
+
rename_keys.append((f"decode_head.reassemble_blocks.readout_projects.{i}.0.bias", f"neck.reassemble_stage.readout_projects.{i}.0.bias"))
|
| 83 |
+
|
| 84 |
+
if i != 2:
|
| 85 |
+
rename_keys.append((f"decode_head.reassemble_blocks.resize_layers.{i}.weight", f"neck.reassemble_stage.layers.{i}.resize.weight"))
|
| 86 |
+
rename_keys.append((f"decode_head.reassemble_blocks.resize_layers.{i}.bias", f"neck.reassemble_stage.layers.{i}.resize.bias"))
|
| 87 |
+
|
| 88 |
+
# fusion layers
|
| 89 |
+
for i in range(4):
|
| 90 |
+
rename_keys.append((f"decode_head.fusion_blocks.{i}.project.conv.weight", f"neck.fusion_stage.layers.{i}.projection.weight"))
|
| 91 |
+
rename_keys.append((f"decode_head.fusion_blocks.{i}.project.conv.bias", f"neck.fusion_stage.layers.{i}.projection.bias"))
|
| 92 |
+
if i != 0:
|
| 93 |
+
rename_keys.append((f"decode_head.fusion_blocks.{i}.res_conv_unit1.conv1.conv.weight", f"neck.fusion_stage.layers.{i}.residual_layer1.convolution1.weight"))
|
| 94 |
+
rename_keys.append((f"decode_head.fusion_blocks.{i}.res_conv_unit1.conv2.conv.weight", f"neck.fusion_stage.layers.{i}.residual_layer1.convolution2.weight"))
|
| 95 |
+
rename_keys.append((f"decode_head.fusion_blocks.{i}.res_conv_unit2.conv1.conv.weight", f"neck.fusion_stage.layers.{i}.residual_layer2.convolution1.weight"))
|
| 96 |
+
rename_keys.append((f"decode_head.fusion_blocks.{i}.res_conv_unit2.conv2.conv.weight", f"neck.fusion_stage.layers.{i}.residual_layer2.convolution2.weight"))
|
| 97 |
+
|
| 98 |
+
# neck convolutions
|
| 99 |
+
for i in range(4):
|
| 100 |
+
rename_keys.append((f"decode_head.convs.{i}.conv.weight", f"neck.convs.{i}.weight"))
|
| 101 |
+
|
| 102 |
+
# head
|
| 103 |
+
rename_keys.append(("decode_head.project.conv.weight", "head.projection.weight"))
|
| 104 |
+
rename_keys.append(("decode_head.project.conv.bias", "head.projection.bias"))
|
| 105 |
+
|
| 106 |
+
for i in range(0, 5, 2):
|
| 107 |
+
rename_keys.append((f"decode_head.conv_depth.head.{i}.weight", f"head.head.{i}.weight"))
|
| 108 |
+
rename_keys.append((f"decode_head.conv_depth.head.{i}.bias", f"head.head.{i}.bias"))
|
| 109 |
+
# fmt: on
|
| 110 |
+
|
| 111 |
+
return rename_keys
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
# here we list all backbone keys to be renamed (original name on the left, our name on the right)
|
| 115 |
+
def create_rename_keys_backbone(config):
|
| 116 |
+
rename_keys = []
|
| 117 |
+
|
| 118 |
+
# fmt: off
|
| 119 |
+
# patch embedding layer
|
| 120 |
+
rename_keys.append(("cls_token", "backbone.embeddings.cls_token"))
|
| 121 |
+
rename_keys.append(("mask_token", "backbone.embeddings.mask_token"))
|
| 122 |
+
rename_keys.append(("pos_embed", "backbone.embeddings.position_embeddings"))
|
| 123 |
+
rename_keys.append(("patch_embed.proj.weight", "backbone.embeddings.patch_embeddings.projection.weight"))
|
| 124 |
+
rename_keys.append(("patch_embed.proj.bias", "backbone.embeddings.patch_embeddings.projection.bias"))
|
| 125 |
+
|
| 126 |
+
# Transformer encoder
|
| 127 |
+
for i in range(config.backbone_config.num_hidden_layers):
|
| 128 |
+
# layernorms
|
| 129 |
+
rename_keys.append((f"blocks.{i}.norm1.weight", f"backbone.encoder.layer.{i}.norm1.weight"))
|
| 130 |
+
rename_keys.append((f"blocks.{i}.norm1.bias", f"backbone.encoder.layer.{i}.norm1.bias"))
|
| 131 |
+
rename_keys.append((f"blocks.{i}.norm2.weight", f"backbone.encoder.layer.{i}.norm2.weight"))
|
| 132 |
+
rename_keys.append((f"blocks.{i}.norm2.bias", f"backbone.encoder.layer.{i}.norm2.bias"))
|
| 133 |
+
# MLP
|
| 134 |
+
if config.backbone_config.use_swiglu_ffn:
|
| 135 |
+
rename_keys.append((f"blocks.{i}.mlp.w12.weight", f"backbone.encoder.layer.{i}.mlp.w12.weight"))
|
| 136 |
+
rename_keys.append((f"blocks.{i}.mlp.w12.bias", f"backbone.encoder.layer.{i}.mlp.w12.bias"))
|
| 137 |
+
rename_keys.append((f"blocks.{i}.mlp.w3.weight", f"backbone.encoder.layer.{i}.mlp.w3.weight"))
|
| 138 |
+
rename_keys.append((f"blocks.{i}.mlp.w3.bias", f"backbone.encoder.layer.{i}.mlp.w3.bias"))
|
| 139 |
+
else:
|
| 140 |
+
rename_keys.append((f"blocks.{i}.mlp.fc1.weight", f"backbone.encoder.layer.{i}.mlp.fc1.weight"))
|
| 141 |
+
rename_keys.append((f"blocks.{i}.mlp.fc1.bias", f"backbone.encoder.layer.{i}.mlp.fc1.bias"))
|
| 142 |
+
rename_keys.append((f"blocks.{i}.mlp.fc2.weight", f"backbone.encoder.layer.{i}.mlp.fc2.weight"))
|
| 143 |
+
rename_keys.append((f"blocks.{i}.mlp.fc2.bias", f"backbone.encoder.layer.{i}.mlp.fc2.bias"))
|
| 144 |
+
# layerscale
|
| 145 |
+
rename_keys.append((f"blocks.{i}.ls1.gamma", f"backbone.encoder.layer.{i}.layer_scale1.lambda1"))
|
| 146 |
+
rename_keys.append((f"blocks.{i}.ls2.gamma", f"backbone.encoder.layer.{i}.layer_scale2.lambda1"))
|
| 147 |
+
# attention projection layer
|
| 148 |
+
rename_keys.append((f"blocks.{i}.attn.proj.weight", f"backbone.encoder.layer.{i}.attention.output.dense.weight"))
|
| 149 |
+
rename_keys.append((f"blocks.{i}.attn.proj.bias", f"backbone.encoder.layer.{i}.attention.output.dense.bias"))
|
| 150 |
+
# fmt: on
|
| 151 |
+
|
| 152 |
+
rename_keys.append(("norm.weight", "backbone.layernorm.weight"))
|
| 153 |
+
rename_keys.append(("norm.bias", "backbone.layernorm.bias"))
|
| 154 |
+
|
| 155 |
+
return rename_keys
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
# we split up the matrix of each encoder layer into queries, keys and values
|
| 159 |
+
def read_in_q_k_v(state_dict, config):
|
| 160 |
+
for i in range(config.backbone_config.num_hidden_layers):
|
| 161 |
+
# read in weights + bias of input projection layer (in timm, this is a single matrix + bias)
|
| 162 |
+
in_proj_weight = state_dict.pop(f"blocks.{i}.attn.qkv.weight")
|
| 163 |
+
in_proj_bias = state_dict.pop(f"blocks.{i}.attn.qkv.bias")
|
| 164 |
+
hidden_size = config.backbone_config.hidden_size
|
| 165 |
+
# next, add query, keys and values (in that order) to the state dict
|
| 166 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.query.weight"] = in_proj_weight[:hidden_size, :]
|
| 167 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.query.bias"] = in_proj_bias[:hidden_size]
|
| 168 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.key.weight"] = in_proj_weight[
|
| 169 |
+
hidden_size : hidden_size * 2, :
|
| 170 |
+
]
|
| 171 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.key.bias"] = in_proj_bias[
|
| 172 |
+
hidden_size : hidden_size * 2
|
| 173 |
+
]
|
| 174 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.value.weight"] = in_proj_weight[-hidden_size:, :]
|
| 175 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.value.bias"] = in_proj_bias[-hidden_size:]
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
def rename_key(dct, old, new):
|
| 179 |
+
val = dct.pop(old)
|
| 180 |
+
dct[new] = val
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
# We will verify our results on an image of cute cats
|
| 184 |
+
def prepare_img():
|
| 185 |
+
url = "https://dl.fbaipublicfiles.com/dinov2/images/example.jpg"
|
| 186 |
+
with httpx.stream("GET", url) as response:
|
| 187 |
+
image = Image.open(BytesIO(response.read()))
|
| 188 |
+
return image
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
name_to_url = {
|
| 192 |
+
"dpt-dinov2-small-nyu": "https://dl.fbaipublicfiles.com/dinov2/dinov2_vits14/dinov2_vits14_nyu_dpt_head.pth",
|
| 193 |
+
"dpt-dinov2-small-kitti": "https://dl.fbaipublicfiles.com/dinov2/dinov2_vits14/dinov2_vits14_kitti_dpt_head.pth",
|
| 194 |
+
"dpt-dinov2-base-nyu": "https://dl.fbaipublicfiles.com/dinov2/dinov2_vitb14/dinov2_vitb14_nyu_dpt_head.pth",
|
| 195 |
+
"dpt-dinov2-base-kitti": "https://dl.fbaipublicfiles.com/dinov2/dinov2_vitb14/dinov2_vitb14_kitti_dpt_head.pth",
|
| 196 |
+
"dpt-dinov2-large-nyu": "https://dl.fbaipublicfiles.com/dinov2/dinov2_vitl14/dinov2_vitl14_nyu_dpt_head.pth",
|
| 197 |
+
"dpt-dinov2-large-kitti": "https://dl.fbaipublicfiles.com/dinov2/dinov2_vitl14/dinov2_vitl14_kitti_dpt_head.pth",
|
| 198 |
+
"dpt-dinov2-giant-nyu": "https://dl.fbaipublicfiles.com/dinov2/dinov2_vitg14/dinov2_vitg14_nyu_dpt_head.pth",
|
| 199 |
+
"dpt-dinov2-giant-kitti": "https://dl.fbaipublicfiles.com/dinov2/dinov2_vitg14/dinov2_vitg14_kitti_dpt_head.pth",
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
def get_original_pixel_values(image):
|
| 204 |
+
class CenterPadding:
|
| 205 |
+
def __init__(self, multiple):
|
| 206 |
+
super().__init__()
|
| 207 |
+
self.multiple = multiple
|
| 208 |
+
|
| 209 |
+
def _get_pad(self, size):
|
| 210 |
+
new_size = math.ceil(size / self.multiple) * self.multiple
|
| 211 |
+
pad_size = new_size - size
|
| 212 |
+
pad_size_left = pad_size // 2
|
| 213 |
+
pad_size_right = pad_size - pad_size_left
|
| 214 |
+
return pad_size_left, pad_size_right
|
| 215 |
+
|
| 216 |
+
def __call__(self, img):
|
| 217 |
+
pads = list(itertools.chain.from_iterable(self._get_pad(m) for m in img.shape[-2:][::-1]))
|
| 218 |
+
output = torch.nn.functional.pad(img, pads)
|
| 219 |
+
return output
|
| 220 |
+
|
| 221 |
+
def __repr__(self):
|
| 222 |
+
return self.__class__.__name__ + "()"
|
| 223 |
+
|
| 224 |
+
def make_depth_transform() -> transforms.Compose:
|
| 225 |
+
return transforms.Compose(
|
| 226 |
+
[
|
| 227 |
+
transforms.ToTensor(),
|
| 228 |
+
lambda x: 255.0 * x[:3], # Discard alpha component and scale by 255
|
| 229 |
+
transforms.Normalize(
|
| 230 |
+
mean=(123.675, 116.28, 103.53),
|
| 231 |
+
std=(58.395, 57.12, 57.375),
|
| 232 |
+
),
|
| 233 |
+
CenterPadding(multiple=14),
|
| 234 |
+
]
|
| 235 |
+
)
|
| 236 |
+
|
| 237 |
+
transform = make_depth_transform()
|
| 238 |
+
original_pixel_values = transform(image).unsqueeze(0)
|
| 239 |
+
|
| 240 |
+
return original_pixel_values
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
@torch.no_grad()
|
| 244 |
+
def convert_dpt_checkpoint(model_name, pytorch_dump_folder_path, push_to_hub, verify_logits):
|
| 245 |
+
"""
|
| 246 |
+
Copy/paste/tweak model's weights to our DPT structure.
|
| 247 |
+
"""
|
| 248 |
+
|
| 249 |
+
# define DPT configuration based on URL
|
| 250 |
+
checkpoint_url = name_to_url[model_name]
|
| 251 |
+
config = get_dpt_config(model_name)
|
| 252 |
+
|
| 253 |
+
# load original DPT state_dict from URL
|
| 254 |
+
print("URL:", checkpoint_url)
|
| 255 |
+
dpt_state_dict = torch.hub.load_state_dict_from_url(checkpoint_url, map_location="cpu")["state_dict"]
|
| 256 |
+
# rename keys
|
| 257 |
+
rename_keys = create_rename_keys_dpt(config)
|
| 258 |
+
for src, dest in rename_keys:
|
| 259 |
+
rename_key(dpt_state_dict, src, dest)
|
| 260 |
+
|
| 261 |
+
# load original backbone state_dict from URL
|
| 262 |
+
if "small" in model_name:
|
| 263 |
+
original_model = torch.hub.load("facebookresearch/dinov2", "dinov2_vits14")
|
| 264 |
+
elif "base" in model_name:
|
| 265 |
+
original_model = torch.hub.load("facebookresearch/dinov2", "dinov2_vitb14")
|
| 266 |
+
elif "large" in model_name:
|
| 267 |
+
original_model = torch.hub.load("facebookresearch/dinov2", "dinov2_vitl14")
|
| 268 |
+
elif "giant" in model_name:
|
| 269 |
+
original_model = torch.hub.load("facebookresearch/dinov2", "dinov2_vitg14")
|
| 270 |
+
else:
|
| 271 |
+
raise NotImplementedError("To do")
|
| 272 |
+
original_model.eval()
|
| 273 |
+
backbone_state_dict = original_model.state_dict()
|
| 274 |
+
|
| 275 |
+
# rename keys
|
| 276 |
+
rename_keys = create_rename_keys_backbone(config)
|
| 277 |
+
for src, dest in rename_keys:
|
| 278 |
+
rename_key(backbone_state_dict, src, dest)
|
| 279 |
+
|
| 280 |
+
# read in qkv matrices
|
| 281 |
+
read_in_q_k_v(backbone_state_dict, config)
|
| 282 |
+
|
| 283 |
+
for key, val in backbone_state_dict.copy().items():
|
| 284 |
+
val = backbone_state_dict.pop(key)
|
| 285 |
+
if "w12" in key:
|
| 286 |
+
key = key.replace("w12", "weights_in")
|
| 287 |
+
if "w3" in key:
|
| 288 |
+
key = key.replace("w3", "weights_out")
|
| 289 |
+
backbone_state_dict[key] = val
|
| 290 |
+
|
| 291 |
+
# merge state_dicts
|
| 292 |
+
state_dict = {**backbone_state_dict, **dpt_state_dict}
|
| 293 |
+
|
| 294 |
+
# load HuggingFace model
|
| 295 |
+
model = DPTForDepthEstimation(config)
|
| 296 |
+
missing_keys, unexpected_keys = model.load_state_dict(state_dict, strict=False)
|
| 297 |
+
print("Missing keys:", missing_keys)
|
| 298 |
+
print("Unexpected keys:", unexpected_keys)
|
| 299 |
+
assert missing_keys == [
|
| 300 |
+
"neck.fusion_stage.layers.0.residual_layer1.convolution1.weight",
|
| 301 |
+
"neck.fusion_stage.layers.0.residual_layer1.convolution2.weight",
|
| 302 |
+
]
|
| 303 |
+
model.eval()
|
| 304 |
+
|
| 305 |
+
# Verify image processor
|
| 306 |
+
processor = DPTImageProcessor(
|
| 307 |
+
do_resize=False,
|
| 308 |
+
do_rescale=False,
|
| 309 |
+
do_pad=True,
|
| 310 |
+
size_divisor=14,
|
| 311 |
+
do_normalize=True,
|
| 312 |
+
image_mean=(123.675, 116.28, 103.53),
|
| 313 |
+
image_std=(58.395, 57.12, 57.375),
|
| 314 |
+
)
|
| 315 |
+
|
| 316 |
+
image = prepare_img()
|
| 317 |
+
pixel_values = processor(image, return_tensors="pt").pixel_values.float()
|
| 318 |
+
original_pixel_values = get_original_pixel_values(image)
|
| 319 |
+
|
| 320 |
+
assert torch.allclose(pixel_values, original_pixel_values)
|
| 321 |
+
|
| 322 |
+
# Verify forward pass
|
| 323 |
+
with torch.no_grad():
|
| 324 |
+
outputs = model(pixel_values)
|
| 325 |
+
|
| 326 |
+
predicted_depth = outputs.predicted_depth
|
| 327 |
+
|
| 328 |
+
print("Shape of predicted depth:", predicted_depth.shape)
|
| 329 |
+
print("First values of predicted depth:", predicted_depth[0, :3, :3])
|
| 330 |
+
|
| 331 |
+
# assert logits
|
| 332 |
+
if verify_logits:
|
| 333 |
+
if model_name == "dpt-dinov2-small-nyu":
|
| 334 |
+
expected_shape = torch.Size([1, 576, 736])
|
| 335 |
+
expected_slice = torch.tensor(
|
| 336 |
+
[[3.3576, 3.4741, 3.4345], [3.4324, 3.5012, 3.2775], [3.2560, 3.3563, 3.2354]]
|
| 337 |
+
)
|
| 338 |
+
|
| 339 |
+
assert predicted_depth.shape == torch.Size(expected_shape)
|
| 340 |
+
assert torch.allclose(predicted_depth[0, :3, :3], expected_slice, atol=1e-5)
|
| 341 |
+
print("Looks ok!")
|
| 342 |
+
|
| 343 |
+
if pytorch_dump_folder_path is not None:
|
| 344 |
+
Path(pytorch_dump_folder_path).mkdir(exist_ok=True)
|
| 345 |
+
print(f"Saving model and processor to {pytorch_dump_folder_path}")
|
| 346 |
+
model.save_pretrained(pytorch_dump_folder_path)
|
| 347 |
+
processor.save_pretrained(pytorch_dump_folder_path)
|
| 348 |
+
|
| 349 |
+
if push_to_hub:
|
| 350 |
+
print("Pushing model and processor to hub...")
|
| 351 |
+
model.push_to_hub(repo_id=f"facebook/{model_name}")
|
| 352 |
+
processor.push_to_hub(repo_id=f"facebook/{model_name}")
|
| 353 |
+
|
| 354 |
+
|
| 355 |
+
if __name__ == "__main__":
|
| 356 |
+
parser = argparse.ArgumentParser()
|
| 357 |
+
# Required parameters
|
| 358 |
+
parser.add_argument(
|
| 359 |
+
"--model_name",
|
| 360 |
+
default="dpt-dinov2-small-nyu",
|
| 361 |
+
type=str,
|
| 362 |
+
choices=name_to_url.keys(),
|
| 363 |
+
help="Name of the model you'd like to convert.",
|
| 364 |
+
)
|
| 365 |
+
parser.add_argument(
|
| 366 |
+
"--pytorch_dump_folder_path",
|
| 367 |
+
default=None,
|
| 368 |
+
type=str,
|
| 369 |
+
help="Path to the output PyTorch model directory.",
|
| 370 |
+
)
|
| 371 |
+
parser.add_argument(
|
| 372 |
+
"--push_to_hub",
|
| 373 |
+
action="store_true",
|
| 374 |
+
help="Whether to push the model to the hub after conversion.",
|
| 375 |
+
)
|
| 376 |
+
parser.add_argument(
|
| 377 |
+
"--verify_logits",
|
| 378 |
+
action="store_true",
|
| 379 |
+
required=False,
|
| 380 |
+
help="Path to the output PyTorch model directory.",
|
| 381 |
+
)
|
| 382 |
+
|
| 383 |
+
args = parser.parse_args()
|
| 384 |
+
convert_dpt_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.push_to_hub, args.verify_logits)
|
third_party/transformers/src/transformers/models/dpt/convert_dpt_beit_to_hf.py
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023 The HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Convert DPT 3.1 checkpoints from the MiDaS repository. URL: https://github.com/isl-org/MiDaS"""
|
| 15 |
+
|
| 16 |
+
import argparse
|
| 17 |
+
from io import BytesIO
|
| 18 |
+
from pathlib import Path
|
| 19 |
+
|
| 20 |
+
import httpx
|
| 21 |
+
import torch
|
| 22 |
+
from PIL import Image
|
| 23 |
+
|
| 24 |
+
from transformers import BeitConfig, DPTConfig, DPTForDepthEstimation, DPTImageProcessor
|
| 25 |
+
from transformers.utils import logging
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
logging.set_verbosity_info()
|
| 29 |
+
logger = logging.get_logger(__name__)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def get_dpt_config(model_name):
|
| 33 |
+
hidden_size = 768
|
| 34 |
+
num_hidden_layers = 12
|
| 35 |
+
num_attention_heads = 12
|
| 36 |
+
intermediate_size = 3072
|
| 37 |
+
out_features = ["stage3", "stage6", "stage9", "stage12"] # beit-base-384 uses [2, 5, 8, 11]
|
| 38 |
+
|
| 39 |
+
if "large" in model_name:
|
| 40 |
+
hidden_size = 1024
|
| 41 |
+
num_hidden_layers = 24
|
| 42 |
+
num_attention_heads = 16
|
| 43 |
+
intermediate_size = 4096
|
| 44 |
+
out_features = ["stage6", "stage12", "stage18", "stage24"] # beit-large-512 uses [5, 11, 17, 23]
|
| 45 |
+
|
| 46 |
+
if "512" in model_name:
|
| 47 |
+
image_size = 512
|
| 48 |
+
elif "384" in model_name:
|
| 49 |
+
image_size = 384
|
| 50 |
+
else:
|
| 51 |
+
raise ValueError("Model not supported")
|
| 52 |
+
|
| 53 |
+
backbone_config = BeitConfig(
|
| 54 |
+
image_size=image_size,
|
| 55 |
+
num_hidden_layers=num_hidden_layers,
|
| 56 |
+
hidden_size=hidden_size,
|
| 57 |
+
intermediate_size=intermediate_size,
|
| 58 |
+
num_attention_heads=num_attention_heads,
|
| 59 |
+
use_relative_position_bias=True,
|
| 60 |
+
reshape_hidden_states=False,
|
| 61 |
+
out_features=out_features,
|
| 62 |
+
)
|
| 63 |
+
|
| 64 |
+
neck_hidden_sizes = [256, 512, 1024, 1024] if "large" in model_name else [96, 192, 384, 768]
|
| 65 |
+
config = DPTConfig(backbone_config=backbone_config, neck_hidden_sizes=neck_hidden_sizes)
|
| 66 |
+
|
| 67 |
+
return config, image_size
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
# here we list all keys to be renamed (original name on the left, our name on the right)
|
| 71 |
+
def create_rename_keys(config):
|
| 72 |
+
rename_keys = []
|
| 73 |
+
|
| 74 |
+
# fmt: off
|
| 75 |
+
# stem
|
| 76 |
+
rename_keys.append(("pretrained.model.cls_token", "backbone.embeddings.cls_token"))
|
| 77 |
+
rename_keys.append(("pretrained.model.patch_embed.proj.weight", "backbone.embeddings.patch_embeddings.projection.weight"))
|
| 78 |
+
rename_keys.append(("pretrained.model.patch_embed.proj.bias", "backbone.embeddings.patch_embeddings.projection.bias"))
|
| 79 |
+
|
| 80 |
+
# Transformer encoder
|
| 81 |
+
for i in range(config.backbone_config.num_hidden_layers):
|
| 82 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.gamma_1", f"backbone.encoder.layer.{i}.lambda_1"))
|
| 83 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.gamma_2", f"backbone.encoder.layer.{i}.lambda_2"))
|
| 84 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.norm1.weight", f"backbone.encoder.layer.{i}.layernorm_before.weight"))
|
| 85 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.norm1.bias", f"backbone.encoder.layer.{i}.layernorm_before.bias"))
|
| 86 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.norm2.weight", f"backbone.encoder.layer.{i}.layernorm_after.weight"))
|
| 87 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.norm2.bias", f"backbone.encoder.layer.{i}.layernorm_after.bias"))
|
| 88 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.mlp.fc1.weight", f"backbone.encoder.layer.{i}.intermediate.dense.weight"))
|
| 89 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.mlp.fc1.bias", f"backbone.encoder.layer.{i}.intermediate.dense.bias"))
|
| 90 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.mlp.fc2.weight", f"backbone.encoder.layer.{i}.output.dense.weight"))
|
| 91 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.mlp.fc2.bias", f"backbone.encoder.layer.{i}.output.dense.bias"))
|
| 92 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.attn.proj.weight", f"backbone.encoder.layer.{i}.attention.output.dense.weight"))
|
| 93 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.attn.proj.bias", f"backbone.encoder.layer.{i}.attention.output.dense.bias"))
|
| 94 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.attn.relative_position_bias_table", f"backbone.encoder.layer.{i}.attention.attention.relative_position_bias.relative_position_bias_table"))
|
| 95 |
+
rename_keys.append((f"pretrained.model.blocks.{i}.attn.relative_position_index", f"backbone.encoder.layer.{i}.attention.attention.relative_position_bias.relative_position_index"))
|
| 96 |
+
|
| 97 |
+
# activation postprocessing (readout projections + resize blocks)
|
| 98 |
+
for i in range(4):
|
| 99 |
+
rename_keys.append((f"pretrained.act_postprocess{i+1}.0.project.0.weight", f"neck.reassemble_stage.readout_projects.{i}.0.weight"))
|
| 100 |
+
rename_keys.append((f"pretrained.act_postprocess{i+1}.0.project.0.bias", f"neck.reassemble_stage.readout_projects.{i}.0.bias"))
|
| 101 |
+
|
| 102 |
+
rename_keys.append((f"pretrained.act_postprocess{i+1}.3.weight", f"neck.reassemble_stage.layers.{i}.projection.weight"))
|
| 103 |
+
rename_keys.append((f"pretrained.act_postprocess{i+1}.3.bias", f"neck.reassemble_stage.layers.{i}.projection.bias"))
|
| 104 |
+
|
| 105 |
+
if i != 2:
|
| 106 |
+
rename_keys.append((f"pretrained.act_postprocess{i+1}.4.weight", f"neck.reassemble_stage.layers.{i}.resize.weight"))
|
| 107 |
+
rename_keys.append((f"pretrained.act_postprocess{i+1}.4.bias", f"neck.reassemble_stage.layers.{i}.resize.bias"))
|
| 108 |
+
|
| 109 |
+
# refinenet (tricky here)
|
| 110 |
+
mapping = {1:3, 2:2, 3:1, 4:0}
|
| 111 |
+
|
| 112 |
+
for i in range(1, 5):
|
| 113 |
+
j = mapping[i]
|
| 114 |
+
rename_keys.append((f"scratch.refinenet{i}.out_conv.weight", f"neck.fusion_stage.layers.{j}.projection.weight"))
|
| 115 |
+
rename_keys.append((f"scratch.refinenet{i}.out_conv.bias", f"neck.fusion_stage.layers.{j}.projection.bias"))
|
| 116 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit1.conv1.weight", f"neck.fusion_stage.layers.{j}.residual_layer1.convolution1.weight"))
|
| 117 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit1.conv1.bias", f"neck.fusion_stage.layers.{j}.residual_layer1.convolution1.bias"))
|
| 118 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit1.conv2.weight", f"neck.fusion_stage.layers.{j}.residual_layer1.convolution2.weight"))
|
| 119 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit1.conv2.bias", f"neck.fusion_stage.layers.{j}.residual_layer1.convolution2.bias"))
|
| 120 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit2.conv1.weight", f"neck.fusion_stage.layers.{j}.residual_layer2.convolution1.weight"))
|
| 121 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit2.conv1.bias", f"neck.fusion_stage.layers.{j}.residual_layer2.convolution1.bias"))
|
| 122 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit2.conv2.weight", f"neck.fusion_stage.layers.{j}.residual_layer2.convolution2.weight"))
|
| 123 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit2.conv2.bias", f"neck.fusion_stage.layers.{j}.residual_layer2.convolution2.bias"))
|
| 124 |
+
|
| 125 |
+
# scratch convolutions
|
| 126 |
+
for i in range(4):
|
| 127 |
+
rename_keys.append((f"scratch.layer{i+1}_rn.weight", f"neck.convs.{i}.weight"))
|
| 128 |
+
|
| 129 |
+
# head
|
| 130 |
+
for i in range(0, 5, 2):
|
| 131 |
+
rename_keys.append((f"scratch.output_conv.{i}.weight", f"head.head.{i}.weight"))
|
| 132 |
+
rename_keys.append((f"scratch.output_conv.{i}.bias", f"head.head.{i}.bias"))
|
| 133 |
+
|
| 134 |
+
return rename_keys
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
def remove_ignore_keys_(state_dict):
|
| 138 |
+
ignore_keys = ["pretrained.model.head.weight", "pretrained.model.head.bias"]
|
| 139 |
+
for k in ignore_keys:
|
| 140 |
+
state_dict.pop(k, None)
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
# we split up the matrix of each encoder layer into queries, keys and values
|
| 144 |
+
def read_in_q_k_v(state_dict, config):
|
| 145 |
+
hidden_size = config.backbone_config.hidden_size
|
| 146 |
+
for i in range(config.backbone_config.num_hidden_layers):
|
| 147 |
+
# read in weights + bias of input projection layer (in original implementation, this is a single matrix + bias)
|
| 148 |
+
in_proj_weight = state_dict.pop(f"pretrained.model.blocks.{i}.attn.qkv.weight")
|
| 149 |
+
q_bias = state_dict.pop(f"pretrained.model.blocks.{i}.attn.q_bias")
|
| 150 |
+
v_bias = state_dict.pop(f"pretrained.model.blocks.{i}.attn.v_bias")
|
| 151 |
+
# next, add query, keys and values (in that order) to the state dict
|
| 152 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.query.weight"] = in_proj_weight[:hidden_size, :]
|
| 153 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.query.bias"] = q_bias
|
| 154 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.key.weight"] = in_proj_weight[
|
| 155 |
+
hidden_size : hidden_size * 2, :
|
| 156 |
+
]
|
| 157 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.value.weight"] = in_proj_weight[-hidden_size:, :]
|
| 158 |
+
state_dict[f"backbone.encoder.layer.{i}.attention.attention.value.bias"] = v_bias
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
def rename_key(dct, old, new):
|
| 162 |
+
val = dct.pop(old)
|
| 163 |
+
dct[new] = val
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
# We will verify our results on an image of cute cats
|
| 167 |
+
def prepare_img():
|
| 168 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 169 |
+
with httpx.stream("GET", url) as response:
|
| 170 |
+
image = Image.open(BytesIO(response.read()))
|
| 171 |
+
return image
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
@torch.no_grad()
|
| 175 |
+
def convert_dpt_checkpoint(model_name, pytorch_dump_folder_path, push_to_hub):
|
| 176 |
+
"""
|
| 177 |
+
Copy/paste/tweak model's weights to our DPT structure.
|
| 178 |
+
"""
|
| 179 |
+
|
| 180 |
+
name_to_url = {
|
| 181 |
+
"dpt-beit-large-512": "https://github.com/isl-org/MiDaS/releases/download/v3_1/dpt_beit_large_512.pt",
|
| 182 |
+
"dpt-beit-large-384": "https://github.com/isl-org/MiDaS/releases/download/v3_1/dpt_beit_large_384.pt",
|
| 183 |
+
"dpt-beit-base-384": "https://github.com/isl-org/MiDaS/releases/download/v3_1/dpt_beit_base_384.pt",
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
# define DPT configuration based on URL
|
| 187 |
+
checkpoint_url = name_to_url[model_name]
|
| 188 |
+
config, image_size = get_dpt_config(model_name)
|
| 189 |
+
# load original state_dict from URL
|
| 190 |
+
state_dict = torch.hub.load_state_dict_from_url(checkpoint_url, map_location="cpu")
|
| 191 |
+
# remove certain keys
|
| 192 |
+
remove_ignore_keys_(state_dict)
|
| 193 |
+
# rename keys
|
| 194 |
+
rename_keys = create_rename_keys(config)
|
| 195 |
+
for src, dest in rename_keys:
|
| 196 |
+
rename_key(state_dict, src, dest)
|
| 197 |
+
# read in qkv matrices
|
| 198 |
+
read_in_q_k_v(state_dict, config)
|
| 199 |
+
|
| 200 |
+
# load HuggingFace model
|
| 201 |
+
model = DPTForDepthEstimation(config)
|
| 202 |
+
missing_keys, unexpected_keys = model.load_state_dict(state_dict, strict=False)
|
| 203 |
+
print("Missing keys:", missing_keys)
|
| 204 |
+
print("Unexpected keys:", unexpected_keys)
|
| 205 |
+
assert missing_keys == []
|
| 206 |
+
# assert unexpected_keys == ["pretrained.model.fc_norm.weight", "pretrained.model.fc_norm.bias"]
|
| 207 |
+
model.eval()
|
| 208 |
+
|
| 209 |
+
# Check outputs on an image
|
| 210 |
+
# We set `keep_aspect_ratio=False` as our current BEiT does not support arbitrary window sizes
|
| 211 |
+
processor = DPTImageProcessor(
|
| 212 |
+
size={"height": image_size, "width": image_size}, keep_aspect_ratio=False, ensure_multiple_of=32
|
| 213 |
+
)
|
| 214 |
+
|
| 215 |
+
image = prepare_img()
|
| 216 |
+
pixel_values = processor(image, return_tensors="pt").pixel_values
|
| 217 |
+
|
| 218 |
+
print("First values of pixel values:", pixel_values[0, 0, :3, :3])
|
| 219 |
+
print("Mean of pixel values:", pixel_values.mean().item())
|
| 220 |
+
print("Shape of pixel values:", pixel_values.shape)
|
| 221 |
+
|
| 222 |
+
from PIL import Image
|
| 223 |
+
from torchvision import transforms
|
| 224 |
+
|
| 225 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 226 |
+
with httpx.stream("GET", url) as response:
|
| 227 |
+
image = Image.open(BytesIO(response.read()))
|
| 228 |
+
|
| 229 |
+
transforms = transforms.Compose(
|
| 230 |
+
[
|
| 231 |
+
transforms.Resize((image_size, image_size)),
|
| 232 |
+
transforms.ToTensor(),
|
| 233 |
+
]
|
| 234 |
+
)
|
| 235 |
+
pixel_values = transforms(image).unsqueeze(0)
|
| 236 |
+
|
| 237 |
+
# forward pass
|
| 238 |
+
with torch.no_grad():
|
| 239 |
+
outputs = model(pixel_values)
|
| 240 |
+
|
| 241 |
+
predicted_depth = outputs.predicted_depth
|
| 242 |
+
|
| 243 |
+
print("Shape of predicted depth:", predicted_depth.shape)
|
| 244 |
+
print("First values of predicted depth:", predicted_depth[0, :3, :3])
|
| 245 |
+
|
| 246 |
+
# assert logits
|
| 247 |
+
# TODO there's still a small difference with the original logits
|
| 248 |
+
if model_name == "dpt-beit-large-512":
|
| 249 |
+
# OK, checked
|
| 250 |
+
expected_shape = torch.Size([1, 512, 512])
|
| 251 |
+
expected_slice = torch.tensor(
|
| 252 |
+
[[2804.6260, 2792.5708, 2812.9263], [2772.0288, 2780.1118, 2796.2529], [2748.1094, 2766.6558, 2766.9834]]
|
| 253 |
+
)
|
| 254 |
+
elif model_name == "dpt-beit-large-384":
|
| 255 |
+
# OK, checked
|
| 256 |
+
expected_shape = torch.Size([1, 384, 384])
|
| 257 |
+
expected_slice = torch.tensor(
|
| 258 |
+
[[1783.2273, 1780.5729, 1792.6453], [1759.9817, 1765.5359, 1778.5002], [1739.1633, 1754.7903, 1757.1990]],
|
| 259 |
+
)
|
| 260 |
+
elif model_name == "dpt-beit-base-384":
|
| 261 |
+
# OK, checked
|
| 262 |
+
expected_shape = torch.Size([1, 384, 384])
|
| 263 |
+
expected_slice = torch.tensor(
|
| 264 |
+
[[2898.4482, 2891.3750, 2904.8079], [2858.6685, 2877.2615, 2894.4507], [2842.1235, 2854.1023, 2861.6328]],
|
| 265 |
+
)
|
| 266 |
+
|
| 267 |
+
assert predicted_depth.shape == torch.Size(expected_shape)
|
| 268 |
+
assert torch.allclose(predicted_depth[0, :3, :3], expected_slice)
|
| 269 |
+
print("Looks ok!")
|
| 270 |
+
|
| 271 |
+
if pytorch_dump_folder_path is not None:
|
| 272 |
+
Path(pytorch_dump_folder_path).mkdir(exist_ok=True)
|
| 273 |
+
print(f"Saving model and processor to {pytorch_dump_folder_path}")
|
| 274 |
+
model.save_pretrained(pytorch_dump_folder_path)
|
| 275 |
+
processor.save_pretrained(pytorch_dump_folder_path)
|
| 276 |
+
|
| 277 |
+
if push_to_hub:
|
| 278 |
+
print("Pushing model and processor to hub...")
|
| 279 |
+
model.push_to_hub(repo_id=f"nielsr/{model_name}")
|
| 280 |
+
processor.push_to_hub(repo_id=f"nielsr/{model_name}")
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
if __name__ == "__main__":
|
| 284 |
+
parser = argparse.ArgumentParser()
|
| 285 |
+
# Required parameters
|
| 286 |
+
parser.add_argument(
|
| 287 |
+
"--model_name",
|
| 288 |
+
default="dpt-beit-large-512",
|
| 289 |
+
type=str,
|
| 290 |
+
choices=["dpt-beit-large-512", "dpt-beit-large-384", "dpt-beit-base-384"],
|
| 291 |
+
help="Name of the model you'd like to convert.",
|
| 292 |
+
)
|
| 293 |
+
parser.add_argument(
|
| 294 |
+
"--pytorch_dump_folder_path",
|
| 295 |
+
default=None,
|
| 296 |
+
type=str,
|
| 297 |
+
help="Path to the output PyTorch model directory.",
|
| 298 |
+
)
|
| 299 |
+
parser.add_argument(
|
| 300 |
+
"--push_to_hub",
|
| 301 |
+
action="store_true",
|
| 302 |
+
help="Whether to push the model to the hub after conversion.",
|
| 303 |
+
)
|
| 304 |
+
|
| 305 |
+
args = parser.parse_args()
|
| 306 |
+
convert_dpt_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.push_to_hub)
|
third_party/transformers/src/transformers/models/dpt/convert_dpt_hybrid_to_pytorch.py
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 The HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Convert DPT checkpoints from the original repository. URL: https://github.com/isl-org/DPT"""
|
| 15 |
+
|
| 16 |
+
import argparse
|
| 17 |
+
import json
|
| 18 |
+
from io import BytesIO
|
| 19 |
+
from pathlib import Path
|
| 20 |
+
|
| 21 |
+
import httpx
|
| 22 |
+
import torch
|
| 23 |
+
from huggingface_hub import hf_hub_download
|
| 24 |
+
from PIL import Image
|
| 25 |
+
|
| 26 |
+
from transformers import DPTConfig, DPTForDepthEstimation, DPTForSemanticSegmentation, DPTImageProcessor
|
| 27 |
+
from transformers.utils import logging
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
logging.set_verbosity_info()
|
| 31 |
+
logger = logging.get_logger(__name__)
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def get_dpt_config(checkpoint_url):
|
| 35 |
+
config = DPTConfig(embedding_type="hybrid")
|
| 36 |
+
|
| 37 |
+
if "large" in checkpoint_url:
|
| 38 |
+
config.hidden_size = 1024
|
| 39 |
+
config.intermediate_size = 4096
|
| 40 |
+
config.num_hidden_layers = 24
|
| 41 |
+
config.num_attention_heads = 16
|
| 42 |
+
config.backbone_out_indices = [5, 11, 17, 23]
|
| 43 |
+
config.neck_hidden_sizes = [256, 512, 1024, 1024]
|
| 44 |
+
expected_shape = (1, 384, 384)
|
| 45 |
+
|
| 46 |
+
if "nyu" in checkpoint_url or "midas" in checkpoint_url:
|
| 47 |
+
config.hidden_size = 768
|
| 48 |
+
config.reassemble_factors = [1, 1, 1, 0.5]
|
| 49 |
+
config.neck_hidden_sizes = [256, 512, 768, 768]
|
| 50 |
+
config.num_labels = 150
|
| 51 |
+
config.patch_size = 16
|
| 52 |
+
expected_shape = (1, 384, 384)
|
| 53 |
+
config.use_batch_norm_in_fusion_residual = False
|
| 54 |
+
config.readout_type = "project"
|
| 55 |
+
|
| 56 |
+
if "ade" in checkpoint_url:
|
| 57 |
+
config.use_batch_norm_in_fusion_residual = True
|
| 58 |
+
config.hidden_size = 768
|
| 59 |
+
config.reassemble_stage = [1, 1, 1, 0.5]
|
| 60 |
+
config.num_labels = 150
|
| 61 |
+
config.patch_size = 16
|
| 62 |
+
repo_id = "huggingface/label-files"
|
| 63 |
+
filename = "ade20k-id2label.json"
|
| 64 |
+
id2label = json.loads(Path(hf_hub_download(repo_id, filename, repo_type="dataset")).read_text())
|
| 65 |
+
id2label = {int(k): v for k, v in id2label.items()}
|
| 66 |
+
config.id2label = id2label
|
| 67 |
+
config.label2id = {v: k for k, v in id2label.items()}
|
| 68 |
+
expected_shape = [1, 150, 480, 480]
|
| 69 |
+
|
| 70 |
+
return config, expected_shape
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def remove_ignore_keys_(state_dict):
|
| 74 |
+
ignore_keys = ["pretrained.model.head.weight", "pretrained.model.head.bias"]
|
| 75 |
+
for k in ignore_keys:
|
| 76 |
+
state_dict.pop(k, None)
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def rename_key(name):
|
| 80 |
+
if (
|
| 81 |
+
"pretrained.model" in name
|
| 82 |
+
and "cls_token" not in name
|
| 83 |
+
and "pos_embed" not in name
|
| 84 |
+
and "patch_embed" not in name
|
| 85 |
+
):
|
| 86 |
+
name = name.replace("pretrained.model", "dpt.encoder")
|
| 87 |
+
if "pretrained.model" in name:
|
| 88 |
+
name = name.replace("pretrained.model", "dpt.embeddings")
|
| 89 |
+
if "patch_embed" in name:
|
| 90 |
+
name = name.replace("patch_embed", "")
|
| 91 |
+
if "pos_embed" in name:
|
| 92 |
+
name = name.replace("pos_embed", "position_embeddings")
|
| 93 |
+
if "attn.proj" in name:
|
| 94 |
+
name = name.replace("attn.proj", "attention.output.dense")
|
| 95 |
+
if "proj" in name and "project" not in name:
|
| 96 |
+
name = name.replace("proj", "projection")
|
| 97 |
+
if "blocks" in name:
|
| 98 |
+
name = name.replace("blocks", "layer")
|
| 99 |
+
if "mlp.fc1" in name:
|
| 100 |
+
name = name.replace("mlp.fc1", "intermediate.dense")
|
| 101 |
+
if "mlp.fc2" in name:
|
| 102 |
+
name = name.replace("mlp.fc2", "output.dense")
|
| 103 |
+
if "norm1" in name and "backbone" not in name:
|
| 104 |
+
name = name.replace("norm1", "layernorm_before")
|
| 105 |
+
if "norm2" in name and "backbone" not in name:
|
| 106 |
+
name = name.replace("norm2", "layernorm_after")
|
| 107 |
+
if "scratch.output_conv" in name:
|
| 108 |
+
name = name.replace("scratch.output_conv", "head")
|
| 109 |
+
if "scratch" in name:
|
| 110 |
+
name = name.replace("scratch", "neck")
|
| 111 |
+
if "layer1_rn" in name:
|
| 112 |
+
name = name.replace("layer1_rn", "convs.0")
|
| 113 |
+
if "layer2_rn" in name:
|
| 114 |
+
name = name.replace("layer2_rn", "convs.1")
|
| 115 |
+
if "layer3_rn" in name:
|
| 116 |
+
name = name.replace("layer3_rn", "convs.2")
|
| 117 |
+
if "layer4_rn" in name:
|
| 118 |
+
name = name.replace("layer4_rn", "convs.3")
|
| 119 |
+
if "refinenet" in name:
|
| 120 |
+
layer_idx = int(name[len("neck.refinenet") : len("neck.refinenet") + 1])
|
| 121 |
+
# tricky here: we need to map 4 to 0, 3 to 1, 2 to 2 and 1 to 3
|
| 122 |
+
name = name.replace(f"refinenet{layer_idx}", f"fusion_stage.layers.{abs(layer_idx - 4)}")
|
| 123 |
+
if "out_conv" in name:
|
| 124 |
+
name = name.replace("out_conv", "projection")
|
| 125 |
+
if "resConfUnit1" in name:
|
| 126 |
+
name = name.replace("resConfUnit1", "residual_layer1")
|
| 127 |
+
if "resConfUnit2" in name:
|
| 128 |
+
name = name.replace("resConfUnit2", "residual_layer2")
|
| 129 |
+
if "conv1" in name:
|
| 130 |
+
name = name.replace("conv1", "convolution1")
|
| 131 |
+
if "conv2" in name:
|
| 132 |
+
name = name.replace("conv2", "convolution2")
|
| 133 |
+
# readout blocks
|
| 134 |
+
if "pretrained.act_postprocess1.0.project.0" in name:
|
| 135 |
+
name = name.replace("pretrained.act_postprocess1.0.project.0", "neck.reassemble_stage.readout_projects.0.0")
|
| 136 |
+
if "pretrained.act_postprocess2.0.project.0" in name:
|
| 137 |
+
name = name.replace("pretrained.act_postprocess2.0.project.0", "neck.reassemble_stage.readout_projects.1.0")
|
| 138 |
+
if "pretrained.act_postprocess3.0.project.0" in name:
|
| 139 |
+
name = name.replace("pretrained.act_postprocess3.0.project.0", "neck.reassemble_stage.readout_projects.2.0")
|
| 140 |
+
if "pretrained.act_postprocess4.0.project.0" in name:
|
| 141 |
+
name = name.replace("pretrained.act_postprocess4.0.project.0", "neck.reassemble_stage.readout_projects.3.0")
|
| 142 |
+
|
| 143 |
+
# resize blocks
|
| 144 |
+
if "pretrained.act_postprocess1.3" in name:
|
| 145 |
+
name = name.replace("pretrained.act_postprocess1.3", "neck.reassemble_stage.layers.0.projection")
|
| 146 |
+
if "pretrained.act_postprocess1.4" in name:
|
| 147 |
+
name = name.replace("pretrained.act_postprocess1.4", "neck.reassemble_stage.layers.0.resize")
|
| 148 |
+
if "pretrained.act_postprocess2.3" in name:
|
| 149 |
+
name = name.replace("pretrained.act_postprocess2.3", "neck.reassemble_stage.layers.1.projection")
|
| 150 |
+
if "pretrained.act_postprocess2.4" in name:
|
| 151 |
+
name = name.replace("pretrained.act_postprocess2.4", "neck.reassemble_stage.layers.1.resize")
|
| 152 |
+
if "pretrained.act_postprocess3.3" in name:
|
| 153 |
+
name = name.replace("pretrained.act_postprocess3.3", "neck.reassemble_stage.layers.2.projection")
|
| 154 |
+
if "pretrained.act_postprocess4.3" in name:
|
| 155 |
+
name = name.replace("pretrained.act_postprocess4.3", "neck.reassemble_stage.layers.3.projection")
|
| 156 |
+
if "pretrained.act_postprocess4.4" in name:
|
| 157 |
+
name = name.replace("pretrained.act_postprocess4.4", "neck.reassemble_stage.layers.3.resize")
|
| 158 |
+
if "pretrained" in name:
|
| 159 |
+
name = name.replace("pretrained", "dpt")
|
| 160 |
+
if "bn" in name:
|
| 161 |
+
name = name.replace("bn", "batch_norm")
|
| 162 |
+
if "head" in name:
|
| 163 |
+
name = name.replace("head", "head.head")
|
| 164 |
+
if "encoder.norm" in name:
|
| 165 |
+
name = name.replace("encoder.norm", "layernorm")
|
| 166 |
+
if "auxlayer" in name:
|
| 167 |
+
name = name.replace("auxlayer", "auxiliary_head.head")
|
| 168 |
+
if "backbone" in name:
|
| 169 |
+
name = name.replace("backbone", "backbone.bit.encoder")
|
| 170 |
+
|
| 171 |
+
if ".." in name:
|
| 172 |
+
name = name.replace("..", ".")
|
| 173 |
+
|
| 174 |
+
if "stem.conv" in name:
|
| 175 |
+
name = name.replace("stem.conv", "bit.embedder.convolution")
|
| 176 |
+
if "blocks" in name:
|
| 177 |
+
name = name.replace("blocks", "layers")
|
| 178 |
+
if "convolution" in name and "backbone" in name:
|
| 179 |
+
name = name.replace("convolution", "conv")
|
| 180 |
+
if "layer" in name and "backbone" in name:
|
| 181 |
+
name = name.replace("layer", "layers")
|
| 182 |
+
if "backbone.bit.encoder.bit" in name:
|
| 183 |
+
name = name.replace("backbone.bit.encoder.bit", "backbone.bit")
|
| 184 |
+
if "embedder.conv" in name:
|
| 185 |
+
name = name.replace("embedder.conv", "embedder.convolution")
|
| 186 |
+
if "backbone.bit.encoder.stem.norm" in name:
|
| 187 |
+
name = name.replace("backbone.bit.encoder.stem.norm", "backbone.bit.embedder.norm")
|
| 188 |
+
return name
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
# we split up the matrix of each encoder layer into queries, keys and values
|
| 192 |
+
def read_in_q_k_v(state_dict, config):
|
| 193 |
+
for i in range(config.num_hidden_layers):
|
| 194 |
+
# read in weights + bias of input projection layer (in timm, this is a single matrix + bias)
|
| 195 |
+
in_proj_weight = state_dict.pop(f"dpt.encoder.layer.{i}.attn.qkv.weight")
|
| 196 |
+
in_proj_bias = state_dict.pop(f"dpt.encoder.layer.{i}.attn.qkv.bias")
|
| 197 |
+
# next, add query, keys and values (in that order) to the state dict
|
| 198 |
+
state_dict[f"dpt.encoder.layer.{i}.attention.attention.query.weight"] = in_proj_weight[: config.hidden_size, :]
|
| 199 |
+
state_dict[f"dpt.encoder.layer.{i}.attention.attention.query.bias"] = in_proj_bias[: config.hidden_size]
|
| 200 |
+
state_dict[f"dpt.encoder.layer.{i}.attention.attention.key.weight"] = in_proj_weight[
|
| 201 |
+
config.hidden_size : config.hidden_size * 2, :
|
| 202 |
+
]
|
| 203 |
+
state_dict[f"dpt.encoder.layer.{i}.attention.attention.key.bias"] = in_proj_bias[
|
| 204 |
+
config.hidden_size : config.hidden_size * 2
|
| 205 |
+
]
|
| 206 |
+
state_dict[f"dpt.encoder.layer.{i}.attention.attention.value.weight"] = in_proj_weight[
|
| 207 |
+
-config.hidden_size :, :
|
| 208 |
+
]
|
| 209 |
+
state_dict[f"dpt.encoder.layer.{i}.attention.attention.value.bias"] = in_proj_bias[-config.hidden_size :]
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
# We will verify our results on an image of cute cats
|
| 213 |
+
def prepare_img():
|
| 214 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 215 |
+
with httpx.stream("GET", url) as response:
|
| 216 |
+
image = Image.open(BytesIO(response.read()))
|
| 217 |
+
return image
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
@torch.no_grad()
|
| 221 |
+
def convert_dpt_checkpoint(checkpoint_url, pytorch_dump_folder_path, push_to_hub, model_name, show_prediction):
|
| 222 |
+
"""
|
| 223 |
+
Copy/paste/tweak model's weights to our DPT structure.
|
| 224 |
+
"""
|
| 225 |
+
|
| 226 |
+
# define DPT configuration based on URL
|
| 227 |
+
config, expected_shape = get_dpt_config(checkpoint_url)
|
| 228 |
+
# load original state_dict from URL
|
| 229 |
+
# state_dict = torch.hub.load_state_dict_from_url(checkpoint_url, map_location="cpu")
|
| 230 |
+
state_dict = torch.load(checkpoint_url, map_location="cpu", weights_only=True)
|
| 231 |
+
# remove certain keys
|
| 232 |
+
remove_ignore_keys_(state_dict)
|
| 233 |
+
# rename keys
|
| 234 |
+
for key in state_dict.copy():
|
| 235 |
+
val = state_dict.pop(key)
|
| 236 |
+
state_dict[rename_key(key)] = val
|
| 237 |
+
# read in qkv matrices
|
| 238 |
+
read_in_q_k_v(state_dict, config)
|
| 239 |
+
|
| 240 |
+
# load HuggingFace model
|
| 241 |
+
model = DPTForSemanticSegmentation(config) if "ade" in checkpoint_url else DPTForDepthEstimation(config)
|
| 242 |
+
model.load_state_dict(state_dict)
|
| 243 |
+
model.eval()
|
| 244 |
+
|
| 245 |
+
# Check outputs on an image
|
| 246 |
+
size = 480 if "ade" in checkpoint_url else 384
|
| 247 |
+
image_processor = DPTImageProcessor(size=size)
|
| 248 |
+
|
| 249 |
+
image = prepare_img()
|
| 250 |
+
encoding = image_processor(image, return_tensors="pt")
|
| 251 |
+
|
| 252 |
+
# forward pass
|
| 253 |
+
outputs = model(**encoding).logits if "ade" in checkpoint_url else model(**encoding).predicted_depth
|
| 254 |
+
|
| 255 |
+
if show_prediction:
|
| 256 |
+
prediction = (
|
| 257 |
+
torch.nn.functional.interpolate(
|
| 258 |
+
outputs.unsqueeze(1),
|
| 259 |
+
size=(image.size[1], image.size[0]),
|
| 260 |
+
mode="bicubic",
|
| 261 |
+
align_corners=False,
|
| 262 |
+
)
|
| 263 |
+
.squeeze()
|
| 264 |
+
.cpu()
|
| 265 |
+
.numpy()
|
| 266 |
+
)
|
| 267 |
+
|
| 268 |
+
Image.fromarray((prediction / prediction.max()) * 255).show()
|
| 269 |
+
|
| 270 |
+
if pytorch_dump_folder_path is not None:
|
| 271 |
+
Path(pytorch_dump_folder_path).mkdir(exist_ok=True)
|
| 272 |
+
print(f"Saving model to {pytorch_dump_folder_path}")
|
| 273 |
+
model.save_pretrained(pytorch_dump_folder_path)
|
| 274 |
+
print(f"Saving image processor to {pytorch_dump_folder_path}")
|
| 275 |
+
image_processor.save_pretrained(pytorch_dump_folder_path)
|
| 276 |
+
|
| 277 |
+
if push_to_hub:
|
| 278 |
+
model.push_to_hub("ybelkada/dpt-hybrid-midas")
|
| 279 |
+
image_processor.push_to_hub("ybelkada/dpt-hybrid-midas")
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
if __name__ == "__main__":
|
| 283 |
+
parser = argparse.ArgumentParser()
|
| 284 |
+
# Required parameters
|
| 285 |
+
parser.add_argument(
|
| 286 |
+
"--checkpoint_url",
|
| 287 |
+
default="https://github.com/intel-isl/DPT/releases/download/1_0/dpt_large-midas-2f21e586.pt",
|
| 288 |
+
type=str,
|
| 289 |
+
help="URL of the original DPT checkpoint you'd like to convert.",
|
| 290 |
+
)
|
| 291 |
+
parser.add_argument(
|
| 292 |
+
"--pytorch_dump_folder_path",
|
| 293 |
+
default=None,
|
| 294 |
+
type=str,
|
| 295 |
+
required=False,
|
| 296 |
+
help="Path to the output PyTorch model directory.",
|
| 297 |
+
)
|
| 298 |
+
parser.add_argument(
|
| 299 |
+
"--push_to_hub",
|
| 300 |
+
action="store_true",
|
| 301 |
+
)
|
| 302 |
+
parser.add_argument(
|
| 303 |
+
"--model_name",
|
| 304 |
+
default="dpt-large",
|
| 305 |
+
type=str,
|
| 306 |
+
help="Name of the model, in case you're pushing to the hub.",
|
| 307 |
+
)
|
| 308 |
+
parser.add_argument(
|
| 309 |
+
"--show_prediction",
|
| 310 |
+
action="store_true",
|
| 311 |
+
)
|
| 312 |
+
|
| 313 |
+
args = parser.parse_args()
|
| 314 |
+
convert_dpt_checkpoint(
|
| 315 |
+
args.checkpoint_url, args.pytorch_dump_folder_path, args.push_to_hub, args.model_name, args.show_prediction
|
| 316 |
+
)
|
third_party/transformers/src/transformers/models/dpt/convert_dpt_swinv2_to_hf.py
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023 The HuggingFace Inc. team.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Convert DPT 3.1 checkpoints from the MiDaS repository. URL: https://github.com/isl-org/MiDaS"""
|
| 15 |
+
|
| 16 |
+
import argparse
|
| 17 |
+
from io import BytesIO
|
| 18 |
+
from pathlib import Path
|
| 19 |
+
|
| 20 |
+
import httpx
|
| 21 |
+
import torch
|
| 22 |
+
from PIL import Image
|
| 23 |
+
|
| 24 |
+
from transformers import DPTConfig, DPTForDepthEstimation, DPTImageProcessor, Swinv2Config
|
| 25 |
+
from transformers.utils import logging
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
logging.set_verbosity_info()
|
| 29 |
+
logger = logging.get_logger(__name__)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def get_dpt_config(model_name):
|
| 33 |
+
if "tiny" in model_name:
|
| 34 |
+
embed_dim = 96
|
| 35 |
+
depths = (2, 2, 6, 2)
|
| 36 |
+
num_heads = (3, 6, 12, 24)
|
| 37 |
+
window_size = 16
|
| 38 |
+
# note: for Swinv2-tiny authors used the window_size = 16 variant
|
| 39 |
+
# as seen here: https://github.com/isl-org/MiDaS/blob/bdc4ed64c095e026dc0a2f17cabb14d58263decb/midas/backbones/swin2.py#L26
|
| 40 |
+
pretrained_window_sizes = (0, 0, 0, 0)
|
| 41 |
+
elif "base" in model_name:
|
| 42 |
+
embed_dim = 128
|
| 43 |
+
depths = (2, 2, 18, 2)
|
| 44 |
+
num_heads = (4, 8, 16, 32)
|
| 45 |
+
window_size = 24
|
| 46 |
+
pretrained_window_sizes = (12, 12, 12, 6)
|
| 47 |
+
elif "large" in model_name:
|
| 48 |
+
embed_dim = 192
|
| 49 |
+
depths = (2, 2, 18, 2)
|
| 50 |
+
num_heads = (6, 12, 24, 48)
|
| 51 |
+
window_size = 24
|
| 52 |
+
pretrained_window_sizes = (12, 12, 12, 6)
|
| 53 |
+
|
| 54 |
+
if "384" in model_name:
|
| 55 |
+
image_size = 384
|
| 56 |
+
elif "256" in model_name:
|
| 57 |
+
image_size = 256
|
| 58 |
+
else:
|
| 59 |
+
raise ValueError("Model not supported, to do")
|
| 60 |
+
|
| 61 |
+
backbone_config = Swinv2Config(
|
| 62 |
+
image_size=image_size,
|
| 63 |
+
embed_dim=embed_dim,
|
| 64 |
+
depths=depths,
|
| 65 |
+
window_size=window_size,
|
| 66 |
+
pretrained_window_sizes=pretrained_window_sizes,
|
| 67 |
+
num_heads=num_heads,
|
| 68 |
+
out_features=["stage1", "stage2", "stage3", "stage4"],
|
| 69 |
+
)
|
| 70 |
+
|
| 71 |
+
if model_name == "dpt-swinv2-tiny-256":
|
| 72 |
+
neck_hidden_sizes = [96, 192, 384, 768]
|
| 73 |
+
elif model_name == "dpt-swinv2-base-384":
|
| 74 |
+
neck_hidden_sizes = [128, 256, 512, 1024]
|
| 75 |
+
elif model_name == "dpt-swinv2-large-384":
|
| 76 |
+
neck_hidden_sizes = [192, 384, 768, 1536]
|
| 77 |
+
|
| 78 |
+
config = DPTConfig(backbone_config=backbone_config, neck_hidden_sizes=neck_hidden_sizes)
|
| 79 |
+
|
| 80 |
+
return config, image_size
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
# here we list all keys to be renamed (original name on the left, our name on the right)
|
| 84 |
+
def create_rename_keys(config):
|
| 85 |
+
rename_keys = []
|
| 86 |
+
|
| 87 |
+
# fmt: off
|
| 88 |
+
# stem
|
| 89 |
+
rename_keys.append(("pretrained.model.patch_embed.proj.weight", "backbone.embeddings.patch_embeddings.projection.weight"))
|
| 90 |
+
rename_keys.append(("pretrained.model.patch_embed.proj.bias", "backbone.embeddings.patch_embeddings.projection.bias"))
|
| 91 |
+
rename_keys.append(("pretrained.model.patch_embed.norm.weight", "backbone.embeddings.norm.weight"))
|
| 92 |
+
rename_keys.append(("pretrained.model.patch_embed.norm.bias", "backbone.embeddings.norm.bias"))
|
| 93 |
+
|
| 94 |
+
# transformer encoder
|
| 95 |
+
for i in range(len(config.backbone_config.depths)):
|
| 96 |
+
for j in range(config.backbone_config.depths[i]):
|
| 97 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.attn.logit_scale", f"backbone.encoder.layers.{i}.blocks.{j}.attention.self.logit_scale"))
|
| 98 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.attn.cpb_mlp.0.weight", f"backbone.encoder.layers.{i}.blocks.{j}.attention.self.continuous_position_bias_mlp.0.weight"))
|
| 99 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.attn.cpb_mlp.0.bias", f"backbone.encoder.layers.{i}.blocks.{j}.attention.self.continuous_position_bias_mlp.0.bias"))
|
| 100 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.attn.cpb_mlp.2.weight", f"backbone.encoder.layers.{i}.blocks.{j}.attention.self.continuous_position_bias_mlp.2.weight"))
|
| 101 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.attn.q_bias", f"backbone.encoder.layers.{i}.blocks.{j}.attention.self.query.bias"))
|
| 102 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.attn.v_bias", f"backbone.encoder.layers.{i}.blocks.{j}.attention.self.value.bias"))
|
| 103 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.attn.proj.weight", f"backbone.encoder.layers.{i}.blocks.{j}.attention.output.dense.weight"))
|
| 104 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.attn.proj.bias", f"backbone.encoder.layers.{i}.blocks.{j}.attention.output.dense.bias"))
|
| 105 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.norm1.weight", f"backbone.encoder.layers.{i}.blocks.{j}.layernorm_before.weight"))
|
| 106 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.norm1.bias", f"backbone.encoder.layers.{i}.blocks.{j}.layernorm_before.bias"))
|
| 107 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.mlp.fc1.weight", f"backbone.encoder.layers.{i}.blocks.{j}.intermediate.dense.weight"))
|
| 108 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.mlp.fc1.bias", f"backbone.encoder.layers.{i}.blocks.{j}.intermediate.dense.bias"))
|
| 109 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.mlp.fc2.weight", f"backbone.encoder.layers.{i}.blocks.{j}.output.dense.weight"))
|
| 110 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.mlp.fc2.bias", f"backbone.encoder.layers.{i}.blocks.{j}.output.dense.bias"))
|
| 111 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.norm2.weight", f"backbone.encoder.layers.{i}.blocks.{j}.layernorm_after.weight"))
|
| 112 |
+
rename_keys.append((f"pretrained.model.layers.{i}.blocks.{j}.norm2.bias", f"backbone.encoder.layers.{i}.blocks.{j}.layernorm_after.bias"))
|
| 113 |
+
|
| 114 |
+
# downsample parameters
|
| 115 |
+
if i in [0,1,2]:
|
| 116 |
+
rename_keys.append((f"pretrained.model.layers.{i}.downsample.reduction.weight", f"backbone.encoder.layers.{i}.downsample.reduction.weight"))
|
| 117 |
+
rename_keys.append((f"pretrained.model.layers.{i}.downsample.norm.weight", f"backbone.encoder.layers.{i}.downsample.norm.weight"))
|
| 118 |
+
rename_keys.append((f"pretrained.model.layers.{i}.downsample.norm.bias", f"backbone.encoder.layers.{i}.downsample.norm.bias"))
|
| 119 |
+
|
| 120 |
+
# note: non-Transformer backbones like Swinv2, LeViT et al don't require activation postprocessing (readout projections + resize blocks)
|
| 121 |
+
|
| 122 |
+
# refinenet (tricky here)
|
| 123 |
+
mapping = {1:3, 2:2, 3:1, 4:0}
|
| 124 |
+
|
| 125 |
+
for i in range(1, 5):
|
| 126 |
+
j = mapping[i]
|
| 127 |
+
rename_keys.append((f"scratch.refinenet{i}.out_conv.weight", f"neck.fusion_stage.layers.{j}.projection.weight"))
|
| 128 |
+
rename_keys.append((f"scratch.refinenet{i}.out_conv.bias", f"neck.fusion_stage.layers.{j}.projection.bias"))
|
| 129 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit1.conv1.weight", f"neck.fusion_stage.layers.{j}.residual_layer1.convolution1.weight"))
|
| 130 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit1.conv1.bias", f"neck.fusion_stage.layers.{j}.residual_layer1.convolution1.bias"))
|
| 131 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit1.conv2.weight", f"neck.fusion_stage.layers.{j}.residual_layer1.convolution2.weight"))
|
| 132 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit1.conv2.bias", f"neck.fusion_stage.layers.{j}.residual_layer1.convolution2.bias"))
|
| 133 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit2.conv1.weight", f"neck.fusion_stage.layers.{j}.residual_layer2.convolution1.weight"))
|
| 134 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit2.conv1.bias", f"neck.fusion_stage.layers.{j}.residual_layer2.convolution1.bias"))
|
| 135 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit2.conv2.weight", f"neck.fusion_stage.layers.{j}.residual_layer2.convolution2.weight"))
|
| 136 |
+
rename_keys.append((f"scratch.refinenet{i}.resConfUnit2.conv2.bias", f"neck.fusion_stage.layers.{j}.residual_layer2.convolution2.bias"))
|
| 137 |
+
|
| 138 |
+
# scratch convolutions
|
| 139 |
+
for i in range(4):
|
| 140 |
+
rename_keys.append((f"scratch.layer{i+1}_rn.weight", f"neck.convs.{i}.weight"))
|
| 141 |
+
|
| 142 |
+
# head
|
| 143 |
+
for i in range(0, 5, 2):
|
| 144 |
+
rename_keys.append((f"scratch.output_conv.{i}.weight", f"head.head.{i}.weight"))
|
| 145 |
+
rename_keys.append((f"scratch.output_conv.{i}.bias", f"head.head.{i}.bias"))
|
| 146 |
+
|
| 147 |
+
return rename_keys
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def remove_ignore_keys_(state_dict):
|
| 151 |
+
ignore_keys = ["pretrained.model.head.weight", "pretrained.model.head.bias"]
|
| 152 |
+
for k in ignore_keys:
|
| 153 |
+
state_dict.pop(k, None)
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
# we split up the matrix of each encoder layer into queries, keys and values
|
| 157 |
+
def read_in_q_k_v(state_dict, config, model):
|
| 158 |
+
for i in range(len(config.backbone_config.depths)):
|
| 159 |
+
for j in range(config.backbone_config.depths[i]):
|
| 160 |
+
dim = model.backbone.encoder.layers[i].blocks[j].attention.self.all_head_size
|
| 161 |
+
# read in weights + bias of input projection layer (in original implementation, this is a single matrix + bias)
|
| 162 |
+
in_proj_weight = state_dict.pop(f"pretrained.model.layers.{i}.blocks.{j}.attn.qkv.weight")
|
| 163 |
+
# next, add query, keys and values (in that order) to the state dict
|
| 164 |
+
state_dict[f"backbone.encoder.layers.{i}.blocks.{j}.attention.self.query.weight"] = in_proj_weight[:dim, :]
|
| 165 |
+
state_dict[f"backbone.encoder.layers.{i}.blocks.{j}.attention.self.key.weight"] = in_proj_weight[
|
| 166 |
+
dim : dim * 2, :
|
| 167 |
+
]
|
| 168 |
+
state_dict[f"backbone.encoder.layers.{i}.blocks.{j}.attention.self.value.weight"] = in_proj_weight[
|
| 169 |
+
-dim:, :
|
| 170 |
+
]
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
def rename_key(dct, old, new):
|
| 174 |
+
val = dct.pop(old)
|
| 175 |
+
dct[new] = val
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
# We will verify our results on an image of cute cats
|
| 179 |
+
def prepare_img():
|
| 180 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 181 |
+
with httpx.stream("GET", url) as response:
|
| 182 |
+
image = Image.open(BytesIO(response.read()))
|
| 183 |
+
return image
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
@torch.no_grad()
|
| 187 |
+
def convert_dpt_checkpoint(model_name, pytorch_dump_folder_path, verify_logits, push_to_hub):
|
| 188 |
+
"""
|
| 189 |
+
Copy/paste/tweak model's weights to our DPT structure.
|
| 190 |
+
"""
|
| 191 |
+
|
| 192 |
+
name_to_url = {
|
| 193 |
+
"dpt-swinv2-tiny-256": "https://github.com/isl-org/MiDaS/releases/download/v3_1/dpt_swin2_tiny_256.pt",
|
| 194 |
+
"dpt-swinv2-base-384": "https://github.com/isl-org/MiDaS/releases/download/v3_1/dpt_swin2_base_384.pt",
|
| 195 |
+
"dpt-swinv2-large-384": "https://github.com/isl-org/MiDaS/releases/download/v3_1/dpt_swin2_large_384.pt",
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
# define DPT configuration based on URL
|
| 199 |
+
checkpoint_url = name_to_url[model_name]
|
| 200 |
+
config, image_size = get_dpt_config(model_name)
|
| 201 |
+
# load original state_dict from URL
|
| 202 |
+
state_dict = torch.hub.load_state_dict_from_url(checkpoint_url, map_location="cpu")
|
| 203 |
+
|
| 204 |
+
# load HuggingFace model
|
| 205 |
+
model = DPTForDepthEstimation(config)
|
| 206 |
+
|
| 207 |
+
# remove certain keys
|
| 208 |
+
remove_ignore_keys_(state_dict)
|
| 209 |
+
# rename keys
|
| 210 |
+
rename_keys = create_rename_keys(config)
|
| 211 |
+
for src, dest in rename_keys:
|
| 212 |
+
rename_key(state_dict, src, dest)
|
| 213 |
+
# read in qkv matrices
|
| 214 |
+
read_in_q_k_v(state_dict, config, model)
|
| 215 |
+
|
| 216 |
+
missing_keys, unexpected_keys = model.load_state_dict(state_dict, strict=False)
|
| 217 |
+
print("Missing keys:", missing_keys)
|
| 218 |
+
print("Unexpected keys:", unexpected_keys)
|
| 219 |
+
model.eval()
|
| 220 |
+
|
| 221 |
+
# Check outputs on an image
|
| 222 |
+
processor = DPTImageProcessor(size={"height": image_size, "width": image_size})
|
| 223 |
+
|
| 224 |
+
image = prepare_img()
|
| 225 |
+
processor(image, return_tensors="pt")
|
| 226 |
+
|
| 227 |
+
if verify_logits:
|
| 228 |
+
from torchvision import transforms
|
| 229 |
+
|
| 230 |
+
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
| 231 |
+
with httpx.stream("GET", url) as response:
|
| 232 |
+
image = Image.open(BytesIO(response.read()))
|
| 233 |
+
transforms = transforms.Compose(
|
| 234 |
+
[
|
| 235 |
+
transforms.Resize((image_size, image_size)),
|
| 236 |
+
transforms.ToTensor(),
|
| 237 |
+
]
|
| 238 |
+
)
|
| 239 |
+
pixel_values = transforms(image).unsqueeze(0)
|
| 240 |
+
|
| 241 |
+
# forward pass
|
| 242 |
+
with torch.no_grad():
|
| 243 |
+
outputs = model(pixel_values)
|
| 244 |
+
|
| 245 |
+
predicted_depth = outputs.predicted_depth
|
| 246 |
+
|
| 247 |
+
print("Shape of predicted depth:", predicted_depth.shape)
|
| 248 |
+
print("First values of predicted depth:", predicted_depth[0, :3, :3])
|
| 249 |
+
|
| 250 |
+
# assert logits
|
| 251 |
+
if model_name == "dpt-swinv2-base-384":
|
| 252 |
+
# OK, checked
|
| 253 |
+
expected_shape = torch.Size([1, 384, 384])
|
| 254 |
+
expected_slice = torch.tensor(
|
| 255 |
+
[
|
| 256 |
+
[1998.5575, 1997.3887, 2009.2981],
|
| 257 |
+
[1952.8607, 1979.6488, 2001.0854],
|
| 258 |
+
[1953.7697, 1961.7711, 1968.8904],
|
| 259 |
+
],
|
| 260 |
+
)
|
| 261 |
+
elif model_name == "dpt-swinv2-tiny-256":
|
| 262 |
+
# OK, checked
|
| 263 |
+
expected_shape = torch.Size([1, 256, 256])
|
| 264 |
+
expected_slice = torch.tensor(
|
| 265 |
+
[[978.9163, 976.5215, 978.5349], [974.1859, 971.7249, 975.8046], [971.3419, 970.3118, 971.6830]],
|
| 266 |
+
)
|
| 267 |
+
elif model_name == "dpt-swinv2-large-384":
|
| 268 |
+
# OK, checked
|
| 269 |
+
expected_shape = torch.Size([1, 384, 384])
|
| 270 |
+
expected_slice = torch.tensor(
|
| 271 |
+
[
|
| 272 |
+
[1203.7206, 1200.1495, 1197.8234],
|
| 273 |
+
[1196.2484, 1183.5033, 1186.4640],
|
| 274 |
+
[1178.8131, 1182.3260, 1174.3975],
|
| 275 |
+
],
|
| 276 |
+
)
|
| 277 |
+
|
| 278 |
+
assert predicted_depth.shape == torch.Size(expected_shape)
|
| 279 |
+
assert torch.allclose(predicted_depth[0, :3, :3], expected_slice)
|
| 280 |
+
print("Looks ok!")
|
| 281 |
+
|
| 282 |
+
if pytorch_dump_folder_path is not None:
|
| 283 |
+
Path(pytorch_dump_folder_path).mkdir(exist_ok=True)
|
| 284 |
+
print(f"Saving model and processor to {pytorch_dump_folder_path}")
|
| 285 |
+
model.save_pretrained(pytorch_dump_folder_path)
|
| 286 |
+
processor.save_pretrained(pytorch_dump_folder_path)
|
| 287 |
+
|
| 288 |
+
if push_to_hub:
|
| 289 |
+
print("Pushing model and processor to hub...")
|
| 290 |
+
model.push_to_hub(repo_id=f"Intel/{model_name}")
|
| 291 |
+
processor.push_to_hub(repo_id=f"Intel/{model_name}")
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
if __name__ == "__main__":
|
| 295 |
+
parser = argparse.ArgumentParser()
|
| 296 |
+
# Required parameters
|
| 297 |
+
parser.add_argument(
|
| 298 |
+
"--model_name",
|
| 299 |
+
default="dpt-swinv2-base-384",
|
| 300 |
+
type=str,
|
| 301 |
+
choices=["dpt-swinv2-tiny-256", "dpt-swinv2-base-384", "dpt-swinv2-large-384"],
|
| 302 |
+
help="Name of the model you'd like to convert.",
|
| 303 |
+
)
|
| 304 |
+
parser.add_argument(
|
| 305 |
+
"--pytorch_dump_folder_path",
|
| 306 |
+
default=None,
|
| 307 |
+
type=str,
|
| 308 |
+
help="Path to the output PyTorch model directory.",
|
| 309 |
+
)
|
| 310 |
+
parser.add_argument(
|
| 311 |
+
"--verify_logits",
|
| 312 |
+
action="store_true",
|
| 313 |
+
help="Whether to verify logits after conversion.",
|
| 314 |
+
)
|
| 315 |
+
parser.add_argument(
|
| 316 |
+
"--push_to_hub",
|
| 317 |
+
action="store_true",
|
| 318 |
+
help="Whether to push the model to the hub after conversion.",
|
| 319 |
+
)
|
| 320 |
+
|
| 321 |
+
args = parser.parse_args()
|
| 322 |
+
convert_dpt_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.verify_logits, args.push_to_hub)
|